blob: cce67acacf7091f44cc5c3159ba1e833d6d53653 [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
51 effect of iselSB_S390. This is safe because instructions are selected
52 before they are emitted. */
florianf26994a2012-04-21 03:34:54 +000053UInt s390_host_hwcaps;
sewardj2019a972011-03-07 16:04:07 +000054
florianb4df7682011-07-05 02:09:01 +000055
56/*------------------------------------------------------------*/
57/*--- Forward declarations ---*/
58/*------------------------------------------------------------*/
59
60static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
61static void s390_insn_map_regs(HRegRemap *, s390_insn *);
62static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
florian1c857042012-04-15 04:11:07 +000063static UInt s390_tchain_load64_len(void);
florianb4df7682011-07-05 02:09:01 +000064
65
sewardj2019a972011-03-07 16:04:07 +000066/*------------------------------------------------------------*/
67/*--- Registers ---*/
68/*------------------------------------------------------------*/
69
70/* Decompile the given register into a static buffer and return it */
71const HChar *
72s390_hreg_as_string(HReg reg)
73{
74 static HChar buf[10];
75
76 static const HChar ireg_names[16][5] = {
77 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
78 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
79 };
80
81 static const HChar freg_names[16][5] = {
82 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
83 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
84 };
85
86 UInt r; /* hregNumber() returns an UInt */
87
88 r = hregNumber(reg);
89
90 /* Be generic for all virtual regs. */
91 if (hregIsVirtual(reg)) {
92 buf[0] = '\0';
93 switch (hregClass(reg)) {
94 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
95 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
96 default: goto fail;
97 }
98 return buf;
99 }
100
101 /* But specific for real regs. */
102 vassert(r < 16);
103
104 switch (hregClass(reg)) {
105 case HRcInt64: return ireg_names[r];
106 case HRcFlt64: return freg_names[r];
107 default: goto fail;
108 }
109
110 fail: vpanic("s390_hreg_as_string");
111}
112
113
114/* Tell the register allocator which registers can be allocated. */
florianb4df7682011-07-05 02:09:01 +0000115static void
sewardj2019a972011-03-07 16:04:07 +0000116s390_hreg_get_allocable(Int *nregs, HReg **arr)
117{
118 UInt i;
119
120 /* Total number of allocable registers (all classes) */
121 *nregs = 16 /* GPRs */
122 - 1 /* r0 */
florian8844a632012-04-13 04:04:06 +0000123 - 1 /* r12 scratch register for translation chaining support */
sewardj2019a972011-03-07 16:04:07 +0000124 - 1 /* r13 guest state pointer */
125 - 1 /* r14 link register */
126 - 1 /* r15 stack pointer */
127 + 16 /* FPRs */
128 ;
129
130 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
131
132 i = 0;
133
134 /* GPR0 is not available because it is interpreted as 0, when used
135 as a base or index register. */
136 (*arr)[i++] = mkHReg(1, HRcInt64, False);
137 (*arr)[i++] = mkHReg(2, HRcInt64, False);
138 (*arr)[i++] = mkHReg(3, HRcInt64, False);
139 (*arr)[i++] = mkHReg(4, HRcInt64, False);
140 (*arr)[i++] = mkHReg(5, HRcInt64, False);
141 (*arr)[i++] = mkHReg(6, HRcInt64, False);
142 (*arr)[i++] = mkHReg(7, HRcInt64, False);
143 (*arr)[i++] = mkHReg(8, HRcInt64, False);
144 (*arr)[i++] = mkHReg(9, HRcInt64, False);
145 /* GPR10 and GPR11 are used for instructions that use register pairs.
146 Otherwise, they are available to the allocator */
147 (*arr)[i++] = mkHReg(10, HRcInt64, False);
148 (*arr)[i++] = mkHReg(11, HRcInt64, False);
florian8844a632012-04-13 04:04:06 +0000149 /* GPR12 is not available because it us used as a scratch register
150 in translation chaining. */
sewardj2019a972011-03-07 16:04:07 +0000151 /* GPR13 is not available because it is used as guest state pointer */
152 /* GPR14 is not available because it is used as link register */
153 /* GPR15 is not available because it is used as stack pointer */
154
155 /* Add the available real (non-virtual) FPRs */
156 (*arr)[i++] = mkHReg(0, HRcFlt64, False);
157 (*arr)[i++] = mkHReg(1, HRcFlt64, False);
158 (*arr)[i++] = mkHReg(2, HRcFlt64, False);
159 (*arr)[i++] = mkHReg(3, HRcFlt64, False);
160 (*arr)[i++] = mkHReg(4, HRcFlt64, False);
161 (*arr)[i++] = mkHReg(5, HRcFlt64, False);
162 (*arr)[i++] = mkHReg(6, HRcFlt64, False);
163 (*arr)[i++] = mkHReg(7, HRcFlt64, False);
164 (*arr)[i++] = mkHReg(8, HRcFlt64, False);
165 (*arr)[i++] = mkHReg(9, HRcFlt64, False);
166 (*arr)[i++] = mkHReg(10, HRcFlt64, False);
167 (*arr)[i++] = mkHReg(11, HRcFlt64, False);
168 (*arr)[i++] = mkHReg(12, HRcFlt64, False);
169 (*arr)[i++] = mkHReg(13, HRcFlt64, False);
170 (*arr)[i++] = mkHReg(14, HRcFlt64, False);
171 (*arr)[i++] = mkHReg(15, HRcFlt64, False);
172 /* FPR12 - FPR15 are also used as register pairs for 128-bit
173 floating point operations */
174}
175
176
177/* Return the real register that holds the guest state pointer */
178HReg
179s390_hreg_guest_state_pointer(void)
180{
181 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
182}
183
florian8844a632012-04-13 04:04:06 +0000184
sewardj2019a972011-03-07 16:04:07 +0000185/* Is VALUE within the domain of a 20-bit signed integer. */
186static __inline__ Bool
187fits_signed_20bit(Int value)
188{
189 return ((value << 12) >> 12) == value;
190}
191
192
193/* Is VALUE within the domain of a 12-bit unsigned integer. */
194static __inline__ Bool
195fits_unsigned_12bit(Int value)
196{
197 return (value & 0xFFF) == value;
198}
199
200/*------------------------------------------------------------*/
201/*--- Addressing modes (amodes) ---*/
202/*------------------------------------------------------------*/
203
204/* Construct a b12 amode. */
205s390_amode *
206s390_amode_b12(Int d, HReg b)
207{
208 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
209
210 vassert(fits_unsigned_12bit(d));
211
212 am->tag = S390_AMODE_B12;
213 am->d = d;
214 am->b = b;
florian3123f722013-01-24 15:55:52 +0000215 am->x = mkHReg(0, HRcInt64, False); /* hregNumber(am->x) == 0 */
sewardj2019a972011-03-07 16:04:07 +0000216
217 return am;
218}
219
220
221/* Construct a b20 amode. */
222s390_amode *
223s390_amode_b20(Int d, HReg b)
224{
225 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
226
227 vassert(fits_signed_20bit(d));
228
229 am->tag = S390_AMODE_B20;
230 am->d = d;
231 am->b = b;
florian3123f722013-01-24 15:55:52 +0000232 am->x = mkHReg(0, HRcInt64, False); /* hregNumber(am->x) == 0 */
sewardj2019a972011-03-07 16:04:07 +0000233
234 return am;
235}
236
237
238/* Construct a bx12 amode. */
239s390_amode *
240s390_amode_bx12(Int d, HReg b, HReg x)
241{
242 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
243
244 vassert(fits_unsigned_12bit(d));
florian3123f722013-01-24 15:55:52 +0000245 vassert(hregNumber(b) != 0);
246 vassert(hregNumber(x) != 0);
sewardj2019a972011-03-07 16:04:07 +0000247
248 am->tag = S390_AMODE_BX12;
249 am->d = d;
250 am->b = b;
251 am->x = x;
252
253 return am;
254}
255
256
257/* Construct a bx20 amode. */
258s390_amode *
259s390_amode_bx20(Int d, HReg b, HReg x)
260{
261 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
262
263 vassert(fits_signed_20bit(d));
florian3123f722013-01-24 15:55:52 +0000264 vassert(hregNumber(b) != 0);
265 vassert(hregNumber(x) != 0);
sewardj2019a972011-03-07 16:04:07 +0000266
267 am->tag = S390_AMODE_BX20;
268 am->d = d;
269 am->b = b;
270 am->x = x;
271
272 return am;
273}
274
275
florian08d02cb2014-02-11 09:23:01 +0000276/* Construct an AMODE for accessing the guest state at OFFSET.
277 OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES
278 which may be too large for a B12 addressing mode.
279 Use a B20 amode as a fallback which will be safe for any offset.
280*/
sewardj2019a972011-03-07 16:04:07 +0000281s390_amode *
282s390_amode_for_guest_state(Int offset)
283{
284 if (fits_unsigned_12bit(offset))
285 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
sewardj2019a972011-03-07 16:04:07 +0000286
florian08d02cb2014-02-11 09:23:01 +0000287 if (fits_signed_20bit(offset))
288 return s390_amode_b20(offset, s390_hreg_guest_state_pointer());
289
sewardj2019a972011-03-07 16:04:07 +0000290 vpanic("invalid guest state offset");
291}
292
293
294/* Decompile the given amode into a static buffer and return it. */
295const HChar *
296s390_amode_as_string(const s390_amode *am)
297{
298 static HChar buf[30];
299 HChar *p;
300
301 buf[0] = '\0';
302 p = buf;
303
304 switch (am->tag) {
305 case S390_AMODE_B12:
306 case S390_AMODE_B20:
307 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
308 break;
309
310 case S390_AMODE_BX12:
311 case S390_AMODE_BX20:
312 /* s390_hreg_as_string returns pointer to local buffer. Need to
313 split this into two printfs */
314 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
315 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
316 break;
317
318 default:
319 vpanic("s390_amode_as_string");
320 }
321
322 return buf;
323}
324
325
326/* Helper function for s390_amode_is_sane */
327static __inline__ Bool
328is_virtual_gpr(HReg reg)
329{
330 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
331}
332
333
334/* Sanity check for an amode */
335Bool
336s390_amode_is_sane(const s390_amode *am)
337{
338 switch (am->tag) {
339 case S390_AMODE_B12:
340 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
341
342 case S390_AMODE_B20:
343 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
344
345 case S390_AMODE_BX12:
346 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
347 fits_unsigned_12bit(am->d);
348
349 case S390_AMODE_BX20:
350 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
351 fits_signed_20bit(am->d);
352
353 default:
354 vpanic("s390_amode_is_sane");
355 }
356}
357
358
359/* Record the register use of an amode */
florianb4df7682011-07-05 02:09:01 +0000360static void
sewardj2019a972011-03-07 16:04:07 +0000361s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
362{
363 switch (am->tag) {
364 case S390_AMODE_B12:
365 case S390_AMODE_B20:
366 addHRegUse(u, HRmRead, am->b);
367 return;
368
369 case S390_AMODE_BX12:
370 case S390_AMODE_BX20:
371 addHRegUse(u, HRmRead, am->b);
372 addHRegUse(u, HRmRead, am->x);
373 return;
374
375 default:
376 vpanic("s390_amode_get_reg_usage");
377 }
378}
379
380
florianb4df7682011-07-05 02:09:01 +0000381static void
sewardj2019a972011-03-07 16:04:07 +0000382s390_amode_map_regs(HRegRemap *m, s390_amode *am)
383{
384 switch (am->tag) {
385 case S390_AMODE_B12:
386 case S390_AMODE_B20:
387 am->b = lookupHRegRemap(m, am->b);
388 return;
389
390 case S390_AMODE_BX12:
391 case S390_AMODE_BX20:
392 am->b = lookupHRegRemap(m, am->b);
393 am->x = lookupHRegRemap(m, am->x);
394 return;
395
396 default:
397 vpanic("s390_amode_map_regs");
398 }
399}
400
401
sewardj2019a972011-03-07 16:04:07 +0000402void
florianb4df7682011-07-05 02:09:01 +0000403ppS390AMode(s390_amode *am)
sewardj2019a972011-03-07 16:04:07 +0000404{
405 vex_printf("%s", s390_amode_as_string(am));
406}
407
408void
floriand8c64e02014-10-08 08:54:44 +0000409ppS390Instr(const s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000410{
411 vex_printf("%s", s390_insn_as_string(insn));
412}
413
414void
415ppHRegS390(HReg reg)
416{
417 vex_printf("%s", s390_hreg_as_string(reg));
418}
419
420/*------------------------------------------------------------*/
421/*--- Helpers for register allocation ---*/
422/*------------------------------------------------------------*/
423
424/* Called once per translation. */
425void
426getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
427{
428 s390_hreg_get_allocable(nregs, arr);
429}
430
431
432/* Tell the register allocator how the given instruction uses the registers
433 it refers to. */
434void
floriand8c64e02014-10-08 08:54:44 +0000435getRegUsage_S390Instr(HRegUsage *u, const s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000436{
437 s390_insn_get_reg_usage(u, insn);
438}
439
440
441/* Map the registers of the given instruction */
442void
florianb4df7682011-07-05 02:09:01 +0000443mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000444{
445 s390_insn_map_regs(m, insn);
446}
447
448
449/* Figure out if the given insn represents a reg-reg move, and if so
450 assign the source and destination to *src and *dst. If in doubt say No.
451 Used by the register allocator to do move coalescing. */
452Bool
floriand8c64e02014-10-08 08:54:44 +0000453isMove_S390Instr(const s390_insn *insn, HReg *src, HReg *dst)
sewardj2019a972011-03-07 16:04:07 +0000454{
455 return s390_insn_is_reg_reg_move(insn, src, dst);
456}
457
458
459/* Generate s390 spill/reload instructions under the direction of the
460 register allocator. Note it's critical these don't write the
461 condition codes. This is like an Ist_Put */
462void
463genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
464{
465 s390_amode *am;
466
467 vassert(offsetB >= 0);
sewardj2019a972011-03-07 16:04:07 +0000468 vassert(!hregIsVirtual(rreg));
469
470 *i1 = *i2 = NULL;
471
472 am = s390_amode_for_guest_state(offsetB);
473
474 switch (hregClass(rreg)) {
475 case HRcInt64:
476 case HRcFlt64:
477 *i1 = s390_insn_store(8, am, rreg);
478 return;
479
480 default:
481 ppHRegClass(hregClass(rreg));
482 vpanic("genSpill_S390: unimplemented regclass");
483 }
484}
485
486
487/* This is like an Iex_Get */
488void
489genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
490{
491 s390_amode *am;
492
493 vassert(offsetB >= 0);
sewardj2019a972011-03-07 16:04:07 +0000494 vassert(!hregIsVirtual(rreg));
495
496 *i1 = *i2 = NULL;
497
498 am = s390_amode_for_guest_state(offsetB);
499
500 switch (hregClass(rreg)) {
501 case HRcInt64:
502 case HRcFlt64:
503 *i1 = s390_insn_load(8, rreg, am);
504 return;
505
506 default:
507 ppHRegClass(hregClass(rreg));
508 vpanic("genReload_S390: unimplemented regclass");
509 }
510}
511
512/* Helper function for s390_insn_get_reg_usage */
513static void
514s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
515{
516 switch (op.tag) {
517 case S390_OPND_REG:
518 addHRegUse(u, HRmRead, op.variant.reg);
519 break;
520
521 case S390_OPND_AMODE:
522 s390_amode_get_reg_usage(u, op.variant.am);
523 break;
524
525 case S390_OPND_IMMEDIATE:
526 break;
527
528 default:
529 vpanic("s390_opnd_RMI_get_reg_usage");
530 }
531}
532
533
534/* Tell the register allocator how the given insn uses the registers */
florianb4df7682011-07-05 02:09:01 +0000535static void
sewardj2019a972011-03-07 16:04:07 +0000536s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
537{
538 initHRegUsage(u);
539
540 switch (insn->tag) {
541 case S390_INSN_LOAD:
542 addHRegUse(u, HRmWrite, insn->variant.load.dst);
543 s390_amode_get_reg_usage(u, insn->variant.load.src);
544 break;
545
546 case S390_INSN_LOAD_IMMEDIATE:
547 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
548 break;
549
550 case S390_INSN_STORE:
551 addHRegUse(u, HRmRead, insn->variant.store.src);
552 s390_amode_get_reg_usage(u, insn->variant.store.dst);
553 break;
554
555 case S390_INSN_MOVE:
556 addHRegUse(u, HRmRead, insn->variant.move.src);
557 addHRegUse(u, HRmWrite, insn->variant.move.dst);
558 break;
559
floriancec3a8a2013-02-02 00:16:58 +0000560 case S390_INSN_MEMCPY:
561 s390_amode_get_reg_usage(u, insn->variant.memcpy.src);
562 s390_amode_get_reg_usage(u, insn->variant.memcpy.dst);
563 break;
564
sewardj2019a972011-03-07 16:04:07 +0000565 case S390_INSN_COND_MOVE:
566 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
567 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
568 break;
569
570 case S390_INSN_ALU:
571 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
572 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
573 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
574 break;
575
florianc4aa7ed2012-12-22 15:01:04 +0000576 case S390_INSN_SMUL:
577 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +0000578 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
579 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
580 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
581 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
582 break;
583
florianc4aa7ed2012-12-22 15:01:04 +0000584 case S390_INSN_SDIV:
585 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +0000586 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
587 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
588 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
589 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
590 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
591 break;
592
593 case S390_INSN_DIVS:
594 addHRegUse(u, HRmRead, insn->variant.divs.op1);
595 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
596 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
597 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
598 break;
599
sewardj611b06e2011-03-24 08:57:29 +0000600 case S390_INSN_CLZ:
601 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
602 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
603 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000604 break;
605
606 case S390_INSN_UNOP:
607 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
608 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
609 break;
610
611 case S390_INSN_TEST:
612 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
613 break;
614
615 case S390_INSN_CC2BOOL:
616 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
617 break;
618
619 case S390_INSN_CAS:
620 addHRegUse(u, HRmRead, insn->variant.cas.op1);
621 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
622 addHRegUse(u, HRmRead, insn->variant.cas.op3);
623 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
624 break;
625
florianc4aa7ed2012-12-22 15:01:04 +0000626 case S390_INSN_CDAS: {
627 s390_cdas *cdas = insn->variant.cdas.details;
628
629 addHRegUse(u, HRmRead, cdas->op1_high);
630 addHRegUse(u, HRmRead, cdas->op1_low);
631 s390_amode_get_reg_usage(u, cdas->op2);
632 addHRegUse(u, HRmRead, cdas->op3_high);
633 addHRegUse(u, HRmRead, cdas->op3_low);
634 addHRegUse(u, HRmWrite, cdas->old_mem_high);
635 addHRegUse(u, HRmWrite, cdas->old_mem_low);
636 addHRegUse(u, HRmWrite, cdas->scratch);
florian448cbba2012-06-06 02:26:01 +0000637 break;
florianc4aa7ed2012-12-22 15:01:04 +0000638 }
florian448cbba2012-06-06 02:26:01 +0000639
sewardj2019a972011-03-07 16:04:07 +0000640 case S390_INSN_COMPARE:
641 addHRegUse(u, HRmRead, insn->variant.compare.src1);
642 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
643 break;
644
sewardj2019a972011-03-07 16:04:07 +0000645 case S390_INSN_HELPER_CALL: {
646 UInt i;
647
648 /* Assume that all volatile registers are clobbered. ABI says,
649 volatile registers are: r0 - r5. Valgrind's register allocator
650 does not know about r0, so we can leave that out */
651 for (i = 1; i <= 5; ++i) {
652 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
653 }
654
655 /* Ditto for floating point registers. f0 - f7 are volatile */
656 for (i = 0; i <= 7; ++i) {
657 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
658 }
659
660 /* The registers that are used for passing arguments will be read.
661 Not all of them may, but in general we need to assume that. */
sewardj74142b82013-08-08 10:28:59 +0000662 for (i = 0; i < insn->variant.helper_call.details->num_args; ++i) {
sewardj2019a972011-03-07 16:04:07 +0000663 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
664 HRcInt64, False));
665 }
666
667 /* s390_insn_helper_call_emit also reads / writes the link register
668 and stack pointer. But those registers are not visible to the
669 register allocator. So we don't need to do anything for them. */
670 break;
671 }
672
673 case S390_INSN_BFP_TRIOP:
674 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
675 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
676 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
677 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
678 break;
679
680 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000681 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_hi);
682 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_hi); /* left */
683 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_hi); /* right */
684 if (insn->size == 16) {
685 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_lo);
686 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_lo); /* left */
687 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_lo); /* right */
688 }
sewardj2019a972011-03-07 16:04:07 +0000689 break;
690
691 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +0000692 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi);
693 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_hi); /* operand */
694 if (insn->size == 16) {
695 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo);
696 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_lo); /* operand */
697 }
sewardj2019a972011-03-07 16:04:07 +0000698 break;
699
700 case S390_INSN_BFP_COMPARE:
701 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +0000702 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_hi); /* left */
703 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_hi); /* right */
704 if (insn->size == 16) {
705 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_lo); /* left */
706 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_lo); /* right */
707 }
sewardj2019a972011-03-07 16:04:07 +0000708 break;
709
florian9fcff4c2012-09-10 03:09:04 +0000710 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +0000711 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +0000712 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
floriancc491a62012-09-10 23:44:37 +0000713 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo);
714 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +0000715 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
floriancc491a62012-09-10 23:44:37 +0000716 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +0000717 break;
718
florianc4aa7ed2012-12-22 15:01:04 +0000719 case S390_INSN_DFP_BINOP: {
720 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
721
722 addHRegUse(u, HRmWrite, dfp_binop->dst_hi);
723 addHRegUse(u, HRmRead, dfp_binop->op2_hi); /* left */
724 addHRegUse(u, HRmRead, dfp_binop->op3_hi); /* right */
florian12390202012-11-10 22:34:14 +0000725 if (insn->size == 16) {
florianc4aa7ed2012-12-22 15:01:04 +0000726 addHRegUse(u, HRmWrite, dfp_binop->dst_lo);
727 addHRegUse(u, HRmRead, dfp_binop->op2_lo); /* left */
728 addHRegUse(u, HRmRead, dfp_binop->op3_lo); /* right */
florian12390202012-11-10 22:34:14 +0000729 }
730 break;
florianc4aa7ed2012-12-22 15:01:04 +0000731 }
florian12390202012-11-10 22:34:14 +0000732
floriance9e3db2012-12-27 20:14:03 +0000733 case S390_INSN_DFP_UNOP:
734 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_hi);
735 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_hi); /* operand */
736 if (insn->size == 16) {
737 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_lo);
738 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_lo); /* operand */
739 }
740 break;
741
florian1b901d42013-01-01 22:19:24 +0000742 case S390_INSN_DFP_INTOP:
743 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_hi);
744 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op2);
745 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_hi);
746 if (insn->size == 16) {
747 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_lo);
748 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_lo);
749 }
750 break;
751
floriane38f6412012-12-21 17:32:12 +0000752 case S390_INSN_DFP_COMPARE:
753 addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst);
754 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_hi); /* left */
755 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_hi); /* right */
756 if (insn->size == 16) {
757 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_lo); /* left */
758 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_lo); /* right */
759 }
760 break;
761
762 case S390_INSN_DFP_CONVERT:
763 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +0000764 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
floriane38f6412012-12-21 17:32:12 +0000765 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_lo);
766 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_hi); /* operand */
florian79efdc62013-02-11 00:47:35 +0000767 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
floriane38f6412012-12-21 17:32:12 +0000768 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_lo); /* operand */
769 break;
770
florian5c539732013-02-14 14:27:12 +0000771 case S390_INSN_DFP_REROUND:
772 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_hi);
773 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op2); /* left */
774 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_hi); /* right */
775 if (insn->size == 16) {
776 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_lo);
777 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_lo); /* right */
778 }
779 break;
780
florian78d5ef72013-05-11 15:02:58 +0000781 case S390_INSN_FP_CONVERT: {
782 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
783
784 addHRegUse(u, HRmWrite, fp_convert->dst_hi);
785 if (! hregIsInvalid(fp_convert->dst_lo))
786 addHRegUse(u, HRmWrite, fp_convert->dst_lo);
787 addHRegUse(u, HRmRead, fp_convert->op_hi);
788 if (! hregIsInvalid(fp_convert->op_lo))
789 addHRegUse(u, HRmRead, fp_convert->op_lo);
790 addHRegUse(u, HRmWrite, fp_convert->r1);
791 break;
792 }
793
florianb93348d2012-12-27 00:59:43 +0000794 case S390_INSN_MIMM:
795 s390_amode_get_reg_usage(u, insn->variant.mimm.dst);
florian09bbba82012-12-11 04:09:43 +0000796 break;
797
florianf85fe3e2012-12-22 02:28:25 +0000798 case S390_INSN_MADD:
799 s390_amode_get_reg_usage(u, insn->variant.madd.dst);
800 break;
801
sewardja52e37e2011-04-28 18:48:06 +0000802 case S390_INSN_MFENCE:
803 break;
804
florian125e20d2012-10-07 15:42:37 +0000805 case S390_INSN_SET_FPC_BFPRM:
806 addHRegUse(u, HRmRead, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +0000807 break;
808
florianc8e4f562012-10-27 16:19:31 +0000809 case S390_INSN_SET_FPC_DFPRM:
810 addHRegUse(u, HRmRead, insn->variant.set_fpc_dfprm.mode);
811 break;
812
florian8844a632012-04-13 04:04:06 +0000813 case S390_INSN_EVCHECK:
814 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
815 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
816 break;
817
818 case S390_INSN_PROFINC:
819 /* Does not use any register visible to the register allocator */
820 break;
821
822 case S390_INSN_XDIRECT:
823 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
824 break;
825
826 case S390_INSN_XINDIR:
827 addHRegUse(u, HRmRead, insn->variant.xindir.dst);
828 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
829 break;
830
831 case S390_INSN_XASSISTED:
832 addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
833 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
834 break;
835
sewardj2019a972011-03-07 16:04:07 +0000836 default:
837 vpanic("s390_insn_get_reg_usage");
838 }
839}
840
841
842/* Helper function for s390_insn_map_regs */
843static void
844s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
845{
846 switch (op->tag) {
847 case S390_OPND_REG:
848 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
849 break;
850
851 case S390_OPND_IMMEDIATE:
852 break;
853
854 case S390_OPND_AMODE:
855 s390_amode_map_regs(m, op->variant.am);
856 break;
857
858 default:
859 vpanic("s390_opnd_RMI_map_regs");
860 }
861}
862
863
florianb4df7682011-07-05 02:09:01 +0000864static void
sewardj2019a972011-03-07 16:04:07 +0000865s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
866{
867 switch (insn->tag) {
868 case S390_INSN_LOAD:
869 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
870 s390_amode_map_regs(m, insn->variant.load.src);
871 break;
872
873 case S390_INSN_STORE:
874 s390_amode_map_regs(m, insn->variant.store.dst);
875 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
876 break;
877
878 case S390_INSN_MOVE:
879 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
880 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
881 break;
882
floriancec3a8a2013-02-02 00:16:58 +0000883 case S390_INSN_MEMCPY:
884 s390_amode_map_regs(m, insn->variant.memcpy.dst);
885 s390_amode_map_regs(m, insn->variant.memcpy.src);
886 break;
887
sewardj2019a972011-03-07 16:04:07 +0000888 case S390_INSN_COND_MOVE:
889 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
890 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
891 break;
892
893 case S390_INSN_LOAD_IMMEDIATE:
894 insn->variant.load_immediate.dst =
895 lookupHRegRemap(m, insn->variant.load_immediate.dst);
896 break;
897
898 case S390_INSN_ALU:
899 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
900 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
901 break;
902
florianc4aa7ed2012-12-22 15:01:04 +0000903 case S390_INSN_SMUL:
904 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +0000905 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
906 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
907 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
908 break;
909
florianc4aa7ed2012-12-22 15:01:04 +0000910 case S390_INSN_SDIV:
911 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +0000912 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
913 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
914 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
915 break;
916
917 case S390_INSN_DIVS:
918 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
919 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
920 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
921 break;
922
sewardj611b06e2011-03-24 08:57:29 +0000923 case S390_INSN_CLZ:
924 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
925 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
926 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000927 break;
928
929 case S390_INSN_UNOP:
930 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
931 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
932 break;
933
934 case S390_INSN_TEST:
935 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
936 break;
937
938 case S390_INSN_CC2BOOL:
939 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
940 break;
941
942 case S390_INSN_CAS:
943 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
944 s390_amode_map_regs(m, insn->variant.cas.op2);
945 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
946 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
947 break;
948
florianc4aa7ed2012-12-22 15:01:04 +0000949 case S390_INSN_CDAS: {
950 s390_cdas *cdas = insn->variant.cdas.details;
951
952 cdas->op1_high = lookupHRegRemap(m, cdas->op1_high);
953 cdas->op1_low = lookupHRegRemap(m, cdas->op1_low);
954 s390_amode_map_regs(m, cdas->op2);
955 cdas->op3_high = lookupHRegRemap(m, cdas->op3_high);
956 cdas->op3_low = lookupHRegRemap(m, cdas->op3_low);
957 cdas->old_mem_high = lookupHRegRemap(m, cdas->old_mem_high);
958 cdas->old_mem_low = lookupHRegRemap(m, cdas->old_mem_low);
959 cdas->scratch = lookupHRegRemap(m, cdas->scratch);
florian448cbba2012-06-06 02:26:01 +0000960 break;
florianc4aa7ed2012-12-22 15:01:04 +0000961 }
florian448cbba2012-06-06 02:26:01 +0000962
sewardj2019a972011-03-07 16:04:07 +0000963 case S390_INSN_COMPARE:
964 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
965 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
966 break;
967
sewardj2019a972011-03-07 16:04:07 +0000968 case S390_INSN_HELPER_CALL:
969 /* s390_insn_helper_call_emit also reads / writes the link register
970 and stack pointer. But those registers are not visible to the
971 register allocator. So we don't need to do anything for them.
972 As for the arguments of the helper call -- they will be loaded into
973 non-virtual registers. Again, we don't need to do anything for those
974 here. */
975 break;
976
977 case S390_INSN_BFP_TRIOP:
floriancc491a62012-09-10 23:44:37 +0000978 insn->variant.bfp_triop.dst =
979 lookupHRegRemap(m, insn->variant.bfp_triop.dst);
980 insn->variant.bfp_triop.op2 =
981 lookupHRegRemap(m, insn->variant.bfp_triop.op2);
982 insn->variant.bfp_triop.op3 =
983 lookupHRegRemap(m, insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +0000984 break;
985
986 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000987 insn->variant.bfp_binop.dst_hi =
988 lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi);
989 insn->variant.bfp_binop.op2_hi =
990 lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi);
991 if (insn->size == 16) {
floriana1659202012-09-19 16:01:21 +0000992 insn->variant.bfp_binop.dst_lo =
floriancc491a62012-09-10 23:44:37 +0000993 lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo);
floriana1659202012-09-19 16:01:21 +0000994 insn->variant.bfp_binop.op2_lo =
floriancc491a62012-09-10 23:44:37 +0000995 lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo);
996 }
sewardj2019a972011-03-07 16:04:07 +0000997 break;
998
999 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +00001000 insn->variant.bfp_unop.dst_hi =
1001 lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi);
1002 insn->variant.bfp_unop.op_hi =
1003 lookupHRegRemap(m, insn->variant.bfp_unop.op_hi);
1004 if (insn->size == 16) {
1005 insn->variant.bfp_unop.dst_lo =
1006 lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo);
1007 insn->variant.bfp_unop.op_lo =
1008 lookupHRegRemap(m, insn->variant.bfp_unop.op_lo);
1009 }
sewardj2019a972011-03-07 16:04:07 +00001010 break;
1011
1012 case S390_INSN_BFP_COMPARE:
floriancc491a62012-09-10 23:44:37 +00001013 insn->variant.bfp_compare.dst =
1014 lookupHRegRemap(m, insn->variant.bfp_compare.dst);
1015 insn->variant.bfp_compare.op1_hi =
1016 lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi);
1017 insn->variant.bfp_compare.op2_hi =
1018 lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi);
1019 if (insn->size == 16) {
1020 insn->variant.bfp_compare.op1_lo =
1021 lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo);
1022 insn->variant.bfp_compare.op2_lo =
1023 lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo);
1024 }
sewardj2019a972011-03-07 16:04:07 +00001025 break;
1026
florian9fcff4c2012-09-10 03:09:04 +00001027 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +00001028 insn->variant.bfp_convert.dst_hi =
1029 lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +00001030 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
floriancc491a62012-09-10 23:44:37 +00001031 insn->variant.bfp_convert.dst_lo =
1032 lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo);
1033 insn->variant.bfp_convert.op_hi =
1034 lookupHRegRemap(m, insn->variant.bfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +00001035 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
floriancc491a62012-09-10 23:44:37 +00001036 insn->variant.bfp_convert.op_lo =
1037 lookupHRegRemap(m, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +00001038 break;
1039
florianc4aa7ed2012-12-22 15:01:04 +00001040 case S390_INSN_DFP_BINOP: {
1041 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
1042
1043 dfp_binop->dst_hi = lookupHRegRemap(m, dfp_binop->dst_hi);
1044 dfp_binop->op2_hi = lookupHRegRemap(m, dfp_binop->op2_hi);
1045 dfp_binop->op3_hi = lookupHRegRemap(m, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +00001046 if (insn->size == 16) {
florianc4aa7ed2012-12-22 15:01:04 +00001047 dfp_binop->dst_lo = lookupHRegRemap(m, dfp_binop->dst_lo);
1048 dfp_binop->op2_lo = lookupHRegRemap(m, dfp_binop->op2_lo);
1049 dfp_binop->op3_lo = lookupHRegRemap(m, dfp_binop->op3_lo);
florian12390202012-11-10 22:34:14 +00001050 }
1051 break;
florianc4aa7ed2012-12-22 15:01:04 +00001052 }
florian12390202012-11-10 22:34:14 +00001053
floriance9e3db2012-12-27 20:14:03 +00001054 case S390_INSN_DFP_UNOP:
1055 insn->variant.dfp_unop.dst_hi =
1056 lookupHRegRemap(m, insn->variant.dfp_unop.dst_hi);
1057 insn->variant.dfp_unop.op_hi =
1058 lookupHRegRemap(m, insn->variant.dfp_unop.op_hi);
1059 if (insn->size == 16) {
1060 insn->variant.dfp_unop.dst_lo =
1061 lookupHRegRemap(m, insn->variant.dfp_unop.dst_lo);
1062 insn->variant.dfp_unop.op_lo =
1063 lookupHRegRemap(m, insn->variant.dfp_unop.op_lo);
1064 }
1065 break;
1066
florian1b901d42013-01-01 22:19:24 +00001067 case S390_INSN_DFP_INTOP:
1068 insn->variant.dfp_intop.dst_hi =
1069 lookupHRegRemap(m, insn->variant.dfp_intop.dst_hi);
1070 insn->variant.dfp_intop.op2 =
1071 lookupHRegRemap(m, insn->variant.dfp_intop.op2);
1072 insn->variant.dfp_intop.op3_hi =
1073 lookupHRegRemap(m, insn->variant.dfp_intop.op3_hi);
1074 if (insn->size == 16) {
1075 insn->variant.dfp_intop.dst_lo =
1076 lookupHRegRemap(m, insn->variant.dfp_intop.dst_lo);
1077 insn->variant.dfp_intop.op3_lo =
1078 lookupHRegRemap(m, insn->variant.dfp_intop.op3_lo);
1079 }
1080 break;
1081
floriane38f6412012-12-21 17:32:12 +00001082 case S390_INSN_DFP_COMPARE:
1083 insn->variant.dfp_compare.dst =
1084 lookupHRegRemap(m, insn->variant.dfp_compare.dst);
1085 insn->variant.dfp_compare.op1_hi =
1086 lookupHRegRemap(m, insn->variant.dfp_compare.op1_hi);
1087 insn->variant.dfp_compare.op2_hi =
1088 lookupHRegRemap(m, insn->variant.dfp_compare.op2_hi);
1089 if (insn->size == 16) {
1090 insn->variant.dfp_compare.op1_lo =
1091 lookupHRegRemap(m, insn->variant.dfp_compare.op1_lo);
1092 insn->variant.dfp_compare.op2_lo =
1093 lookupHRegRemap(m, insn->variant.dfp_compare.op2_lo);
1094 }
1095 break;
1096
1097 case S390_INSN_DFP_CONVERT:
1098 insn->variant.dfp_convert.dst_hi =
1099 lookupHRegRemap(m, insn->variant.dfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +00001100 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
floriane38f6412012-12-21 17:32:12 +00001101 insn->variant.dfp_convert.dst_lo =
1102 lookupHRegRemap(m, insn->variant.dfp_convert.dst_lo);
1103 insn->variant.dfp_convert.op_hi =
1104 lookupHRegRemap(m, insn->variant.dfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +00001105 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
floriane38f6412012-12-21 17:32:12 +00001106 insn->variant.dfp_convert.op_lo =
1107 lookupHRegRemap(m, insn->variant.dfp_convert.op_lo);
1108 break;
1109
florian5c539732013-02-14 14:27:12 +00001110 case S390_INSN_DFP_REROUND:
1111 insn->variant.dfp_reround.dst_hi =
1112 lookupHRegRemap(m, insn->variant.dfp_reround.dst_hi);
1113 insn->variant.dfp_reround.op2 =
1114 lookupHRegRemap(m, insn->variant.dfp_reround.op2);
1115 insn->variant.dfp_reround.op3_hi =
1116 lookupHRegRemap(m, insn->variant.dfp_reround.op3_hi);
1117 if (insn->size == 16) {
1118 insn->variant.dfp_reround.dst_lo =
1119 lookupHRegRemap(m, insn->variant.dfp_reround.dst_lo);
1120 insn->variant.dfp_reround.op3_lo =
1121 lookupHRegRemap(m, insn->variant.dfp_reround.op3_lo);
1122 }
1123 break;
1124
florian78d5ef72013-05-11 15:02:58 +00001125 case S390_INSN_FP_CONVERT: {
1126 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
1127
1128 fp_convert->dst_hi = lookupHRegRemap(m, fp_convert->dst_hi);
1129 if (! hregIsInvalid(fp_convert->dst_lo))
1130 fp_convert->dst_lo = lookupHRegRemap(m, fp_convert->dst_lo);
1131 fp_convert->op_hi = lookupHRegRemap(m, fp_convert->op_hi);
1132 if (! hregIsInvalid(fp_convert->op_lo))
1133 fp_convert->op_lo = lookupHRegRemap(m, fp_convert->op_lo);
1134 fp_convert->r1 = lookupHRegRemap(m, fp_convert->r1);
1135 break;
1136 }
1137
florianb93348d2012-12-27 00:59:43 +00001138 case S390_INSN_MIMM:
1139 s390_amode_map_regs(m, insn->variant.mimm.dst);
florian09bbba82012-12-11 04:09:43 +00001140 break;
1141
florianf85fe3e2012-12-22 02:28:25 +00001142 case S390_INSN_MADD:
1143 s390_amode_map_regs(m, insn->variant.madd.dst);
1144 break;
1145
sewardja52e37e2011-04-28 18:48:06 +00001146 case S390_INSN_MFENCE:
1147 break;
1148
florian125e20d2012-10-07 15:42:37 +00001149 case S390_INSN_SET_FPC_BFPRM:
1150 insn->variant.set_fpc_bfprm.mode =
1151 lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00001152 break;
1153
florianc8e4f562012-10-27 16:19:31 +00001154 case S390_INSN_SET_FPC_DFPRM:
1155 insn->variant.set_fpc_dfprm.mode =
1156 lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode);
1157 break;
1158
florian8844a632012-04-13 04:04:06 +00001159 case S390_INSN_EVCHECK:
1160 s390_amode_map_regs(m, insn->variant.evcheck.counter);
1161 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
1162 break;
1163
1164 case S390_INSN_PROFINC:
1165 /* Does not use any register visible to the register allocator */
1166 break;
1167
1168 case S390_INSN_XDIRECT:
1169 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
1170 break;
1171
1172 case S390_INSN_XINDIR:
1173 s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
1174 insn->variant.xindir.dst =
1175 lookupHRegRemap(m, insn->variant.xindir.dst);
1176 break;
1177
1178 case S390_INSN_XASSISTED:
1179 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
1180 insn->variant.xassisted.dst =
1181 lookupHRegRemap(m, insn->variant.xassisted.dst);
1182 break;
1183
sewardj2019a972011-03-07 16:04:07 +00001184 default:
1185 vpanic("s390_insn_map_regs");
1186 }
1187}
1188
1189
1190/* Return True, if INSN is a move between two registers of the same class.
1191 In that case assign the source and destination registers to SRC and DST,
1192 respectively. */
florianb4df7682011-07-05 02:09:01 +00001193static Bool
sewardj2019a972011-03-07 16:04:07 +00001194s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
1195{
1196 if (insn->tag == S390_INSN_MOVE &&
1197 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
1198 *src = insn->variant.move.src;
1199 *dst = insn->variant.move.dst;
1200 return True;
1201 }
1202
1203 return False;
1204}
1205
1206
sewardj2019a972011-03-07 16:04:07 +00001207/*------------------------------------------------------------*/
1208/*--- Functions to emit a sequence of bytes ---*/
1209/*------------------------------------------------------------*/
1210
sewardj2019a972011-03-07 16:04:07 +00001211static __inline__ UChar *
1212emit_2bytes(UChar *p, ULong val)
1213{
1214 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1215}
1216
1217
1218static __inline__ UChar *
1219emit_4bytes(UChar *p, ULong val)
1220{
1221 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1222}
1223
1224
1225static __inline__ UChar *
1226emit_6bytes(UChar *p, ULong val)
1227{
1228 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1229}
1230
1231
1232/*------------------------------------------------------------*/
1233/*--- Functions to emit various instruction formats ---*/
1234/*------------------------------------------------------------*/
1235
sewardj2019a972011-03-07 16:04:07 +00001236static UChar *
1237emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1238{
1239 ULong the_insn = op;
1240
1241 the_insn |= ((ULong)r1) << 20;
1242 the_insn |= ((ULong)i2) << 0;
1243
1244 return emit_4bytes(p, the_insn);
1245}
1246
1247
1248static UChar *
1249emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1250{
1251 ULong the_insn = op;
1252
1253 the_insn |= ((ULong)r1) << 36;
1254 the_insn |= ((ULong)i2) << 0;
1255
1256 return emit_6bytes(p, the_insn);
1257}
1258
1259
1260static UChar *
1261emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1262{
1263 ULong the_insn = op;
1264
1265 the_insn |= ((ULong)r1) << 4;
1266 the_insn |= ((ULong)r2) << 0;
1267
1268 return emit_2bytes(p, the_insn);
1269}
1270
1271
1272static UChar *
1273emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1274{
1275 ULong the_insn = op;
1276
1277 the_insn |= ((ULong)r1) << 4;
1278 the_insn |= ((ULong)r2) << 0;
1279
1280 return emit_4bytes(p, the_insn);
1281}
1282
1283
1284static UChar *
1285emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1286{
1287 ULong the_insn = op;
1288
1289 the_insn |= ((ULong)r1) << 12;
1290 the_insn |= ((ULong)r3) << 4;
1291 the_insn |= ((ULong)r2) << 0;
1292
1293 return emit_4bytes(p, the_insn);
1294}
1295
1296
1297static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00001298emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
1299{
1300 ULong the_insn = op;
1301
1302 the_insn |= ((ULong)m3) << 12;
1303 the_insn |= ((ULong)m4) << 8;
1304 the_insn |= ((ULong)r1) << 4;
1305 the_insn |= ((ULong)r2) << 0;
1306
1307 return emit_4bytes(p, the_insn);
1308}
1309
1310
1311static UChar *
sewardj2019a972011-03-07 16:04:07 +00001312emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1313{
1314 ULong the_insn = op;
1315
1316 the_insn |= ((ULong)r3) << 12;
1317 the_insn |= ((ULong)r1) << 4;
1318 the_insn |= ((ULong)r2) << 0;
1319
1320 return emit_4bytes(p, the_insn);
1321}
1322
1323
1324static UChar *
florian12390202012-11-10 22:34:14 +00001325emit_RRF4(UChar *p, UInt op, UChar r3, UChar m4, UChar r1, UChar r2)
1326{
1327 ULong the_insn = op;
1328
1329 the_insn |= ((ULong)r3) << 12;
1330 the_insn |= ((ULong)m4) << 8;
1331 the_insn |= ((ULong)r1) << 4;
1332 the_insn |= ((ULong)r2) << 0;
1333
1334 return emit_4bytes(p, the_insn);
1335}
1336
1337
1338static UChar *
floriane38f6412012-12-21 17:32:12 +00001339emit_RRF5(UChar *p, UInt op, UChar m4, UChar r1, UChar r2)
1340{
1341 ULong the_insn = op;
1342
1343 the_insn |= ((ULong)m4) << 8;
1344 the_insn |= ((ULong)r1) << 4;
1345 the_insn |= ((ULong)r2) << 0;
1346
1347 return emit_4bytes(p, the_insn);
1348}
1349
1350
1351static UChar *
sewardj2019a972011-03-07 16:04:07 +00001352emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1353{
1354 ULong the_insn = op;
1355
1356 the_insn |= ((ULong)r1) << 20;
1357 the_insn |= ((ULong)r3) << 16;
1358 the_insn |= ((ULong)b2) << 12;
1359 the_insn |= ((ULong)d2) << 0;
1360
1361 return emit_4bytes(p, the_insn);
1362}
1363
1364
1365static UChar *
1366emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1367{
1368 ULong the_insn = op;
1369
1370 the_insn |= ((ULong)r1) << 36;
1371 the_insn |= ((ULong)r3) << 32;
1372 the_insn |= ((ULong)b2) << 28;
1373 the_insn |= ((ULong)dl2) << 16;
1374 the_insn |= ((ULong)dh2) << 8;
1375
1376 return emit_6bytes(p, the_insn);
1377}
1378
1379
1380static UChar *
1381emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1382{
1383 ULong the_insn = op;
1384
1385 the_insn |= ((ULong)r1) << 20;
1386 the_insn |= ((ULong)x2) << 16;
1387 the_insn |= ((ULong)b2) << 12;
1388 the_insn |= ((ULong)d2) << 0;
1389
1390 return emit_4bytes(p, the_insn);
1391}
1392
1393
1394static UChar *
florian1b901d42013-01-01 22:19:24 +00001395emit_RXF(UChar *p, ULong op, UChar r3, UChar x2, UChar b2, UShort d2, UChar r1)
1396{
1397 ULong the_insn = op;
1398
1399 the_insn |= ((ULong)r3) << 36;
1400 the_insn |= ((ULong)x2) << 32;
1401 the_insn |= ((ULong)b2) << 28;
1402 the_insn |= ((ULong)d2) << 16;
1403 the_insn |= ((ULong)r1) << 12;
1404
1405 return emit_6bytes(p, the_insn);
1406}
1407
1408
1409static UChar *
sewardj2019a972011-03-07 16:04:07 +00001410emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1411{
1412 ULong the_insn = op;
1413
1414 the_insn |= ((ULong)r1) << 36;
1415 the_insn |= ((ULong)x2) << 32;
1416 the_insn |= ((ULong)b2) << 28;
1417 the_insn |= ((ULong)dl2) << 16;
1418 the_insn |= ((ULong)dh2) << 8;
1419
1420 return emit_6bytes(p, the_insn);
1421}
1422
1423
1424static UChar *
1425emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1426{
1427 ULong the_insn = op;
1428
1429 the_insn |= ((ULong)b2) << 12;
1430 the_insn |= ((ULong)d2) << 0;
1431
1432 return emit_4bytes(p, the_insn);
1433}
1434
1435
florianad43b3a2012-02-20 15:01:14 +00001436static UChar *
florianb93348d2012-12-27 00:59:43 +00001437emit_SI(UChar *p, UInt op, UChar i2, UChar b1, UShort d1)
1438{
1439 ULong the_insn = op;
1440
1441 the_insn |= ((ULong)i2) << 16;
1442 the_insn |= ((ULong)b1) << 12;
1443 the_insn |= ((ULong)d1) << 0;
1444
1445 return emit_4bytes(p, the_insn);
1446}
1447
1448
1449static UChar *
1450emit_SIL(UChar *p, ULong op, UChar b1, UShort d1, UShort i2)
1451{
1452 ULong the_insn = op;
1453
1454 the_insn |= ((ULong)b1) << 28;
1455 the_insn |= ((ULong)d1) << 16;
1456 the_insn |= ((ULong)i2) << 0;
1457
1458 return emit_6bytes(p, the_insn);
1459}
1460
1461
1462static UChar *
florianad43b3a2012-02-20 15:01:14 +00001463emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1464{
1465 ULong the_insn = op;
1466
1467 the_insn |= ((ULong)i2) << 32;
1468 the_insn |= ((ULong)b1) << 28;
1469 the_insn |= ((ULong)dl1) << 16;
1470 the_insn |= ((ULong)dh1) << 8;
1471
1472 return emit_6bytes(p, the_insn);
1473}
1474
1475
1476static UChar *
1477emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1478{
1479 ULong the_insn = op;
1480
1481 the_insn |= ((ULong)l) << 32;
1482 the_insn |= ((ULong)b1) << 28;
1483 the_insn |= ((ULong)d1) << 16;
1484 the_insn |= ((ULong)b2) << 12;
1485 the_insn |= ((ULong)d2) << 0;
1486
1487 return emit_6bytes(p, the_insn);
1488}
1489
1490
sewardj2019a972011-03-07 16:04:07 +00001491/*------------------------------------------------------------*/
1492/*--- Functions to emit particular instructions ---*/
1493/*------------------------------------------------------------*/
1494
sewardj9d31dfd2011-03-15 12:36:44 +00001495static UChar *
sewardj2019a972011-03-07 16:04:07 +00001496s390_emit_AR(UChar *p, UChar r1, UChar r2)
1497{
sewardj7ee97522011-05-09 21:45:04 +00001498 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001499 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1500
1501 return emit_RR(p, 0x1a00, r1, r2);
1502}
1503
1504
sewardj9d31dfd2011-03-15 12:36:44 +00001505static UChar *
sewardj2019a972011-03-07 16:04:07 +00001506s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1507{
sewardj7ee97522011-05-09 21:45:04 +00001508 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001509 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1510
1511 return emit_RRE(p, 0xb9080000, r1, r2);
1512}
1513
1514
sewardj9d31dfd2011-03-15 12:36:44 +00001515static UChar *
sewardj2019a972011-03-07 16:04:07 +00001516s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1517{
sewardj7ee97522011-05-09 21:45:04 +00001518 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001519 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1520
1521 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1522}
1523
1524
sewardj9d31dfd2011-03-15 12:36:44 +00001525static UChar *
sewardj2019a972011-03-07 16:04:07 +00001526s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1527{
sewardj652b56a2011-04-13 15:38:17 +00001528 vassert(s390_host_has_ldisp);
1529
sewardj7ee97522011-05-09 21:45:04 +00001530 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001531 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1532
1533 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1534}
1535
1536
sewardj9d31dfd2011-03-15 12:36:44 +00001537static UChar *
sewardj2019a972011-03-07 16:04:07 +00001538s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1539{
sewardj652b56a2011-04-13 15:38:17 +00001540 vassert(s390_host_has_ldisp || dh2 == 0);
1541
sewardj7ee97522011-05-09 21:45:04 +00001542 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001543 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1544
1545 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1546}
1547
1548
sewardj9d31dfd2011-03-15 12:36:44 +00001549static UChar *
sewardj2019a972011-03-07 16:04:07 +00001550s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1551{
sewardj652b56a2011-04-13 15:38:17 +00001552 vassert(s390_host_has_eimm);
1553
sewardj7ee97522011-05-09 21:45:04 +00001554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001555 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1556
1557 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1558}
1559
1560
sewardj9d31dfd2011-03-15 12:36:44 +00001561static UChar *
sewardj2019a972011-03-07 16:04:07 +00001562s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1563{
sewardj652b56a2011-04-13 15:38:17 +00001564 vassert(s390_host_has_eimm);
1565
sewardj7ee97522011-05-09 21:45:04 +00001566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001567 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1568
1569 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1570}
1571
1572
sewardj9d31dfd2011-03-15 12:36:44 +00001573static UChar *
sewardj2019a972011-03-07 16:04:07 +00001574s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1575{
sewardj7ee97522011-05-09 21:45:04 +00001576 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001577 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1578
1579 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1580}
1581
1582
sewardj9d31dfd2011-03-15 12:36:44 +00001583static UChar *
sewardj2019a972011-03-07 16:04:07 +00001584s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1585{
sewardj652b56a2011-04-13 15:38:17 +00001586 vassert(s390_host_has_ldisp);
1587
sewardj7ee97522011-05-09 21:45:04 +00001588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001589 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1590
1591 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1592}
1593
1594
sewardj9d31dfd2011-03-15 12:36:44 +00001595static UChar *
sewardj2019a972011-03-07 16:04:07 +00001596s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1597{
sewardj7ee97522011-05-09 21:45:04 +00001598 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001599 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1600
1601 return emit_RI(p, 0xa70a0000, r1, i2);
1602}
1603
1604
sewardj9d31dfd2011-03-15 12:36:44 +00001605static UChar *
sewardj2019a972011-03-07 16:04:07 +00001606s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1607{
sewardj7ee97522011-05-09 21:45:04 +00001608 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001609 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1610
1611 return emit_RI(p, 0xa70b0000, r1, i2);
1612}
1613
1614
sewardj9d31dfd2011-03-15 12:36:44 +00001615static UChar *
florianad43b3a2012-02-20 15:01:14 +00001616s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1617{
1618 vassert(s390_host_has_gie);
1619
1620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001621 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
florianad43b3a2012-02-20 15:01:14 +00001622
1623 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
1624}
1625
1626
1627static UChar *
florian0e047d62012-04-21 16:06:04 +00001628s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1629{
1630 vassert(s390_host_has_gie);
1631
1632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001633 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
florian0e047d62012-04-21 16:06:04 +00001634
1635 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
1636}
1637
1638
1639static UChar *
sewardj2019a972011-03-07 16:04:07 +00001640s390_emit_NR(UChar *p, UChar r1, UChar r2)
1641{
sewardj7ee97522011-05-09 21:45:04 +00001642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001643 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1644
1645 return emit_RR(p, 0x1400, r1, r2);
1646}
1647
1648
sewardj9d31dfd2011-03-15 12:36:44 +00001649static UChar *
sewardj2019a972011-03-07 16:04:07 +00001650s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1651{
sewardj7ee97522011-05-09 21:45:04 +00001652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001653 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1654
1655 return emit_RRE(p, 0xb9800000, r1, r2);
1656}
1657
1658
sewardj9d31dfd2011-03-15 12:36:44 +00001659static UChar *
sewardj2019a972011-03-07 16:04:07 +00001660s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1661{
sewardj7ee97522011-05-09 21:45:04 +00001662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001663 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1664
1665 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1666}
1667
1668
sewardj9d31dfd2011-03-15 12:36:44 +00001669static UChar *
sewardj2019a972011-03-07 16:04:07 +00001670s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1671{
sewardj652b56a2011-04-13 15:38:17 +00001672 vassert(s390_host_has_ldisp);
1673
sewardj7ee97522011-05-09 21:45:04 +00001674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001675 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1676
1677 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1678}
1679
1680
sewardj9d31dfd2011-03-15 12:36:44 +00001681static UChar *
sewardj2019a972011-03-07 16:04:07 +00001682s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1683{
sewardj652b56a2011-04-13 15:38:17 +00001684 vassert(s390_host_has_ldisp || dh2 == 0);
1685
sewardj7ee97522011-05-09 21:45:04 +00001686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001687 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1688
1689 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1690}
1691
1692
sewardj9d31dfd2011-03-15 12:36:44 +00001693static UChar *
sewardj2019a972011-03-07 16:04:07 +00001694s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1695{
sewardj652b56a2011-04-13 15:38:17 +00001696 vassert(s390_host_has_eimm);
1697
sewardj7ee97522011-05-09 21:45:04 +00001698 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001699 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1700
1701 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1702}
1703
1704
sewardj9d31dfd2011-03-15 12:36:44 +00001705static UChar *
sewardj2019a972011-03-07 16:04:07 +00001706s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1707{
sewardj652b56a2011-04-13 15:38:17 +00001708 vassert(s390_host_has_eimm);
1709
sewardj7ee97522011-05-09 21:45:04 +00001710 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001711 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1712
1713 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1714}
1715
1716
sewardj9d31dfd2011-03-15 12:36:44 +00001717static UChar *
sewardj2019a972011-03-07 16:04:07 +00001718s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1719{
sewardj7ee97522011-05-09 21:45:04 +00001720 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001721 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1722
1723 return emit_RI(p, 0xa5070000, r1, i2);
1724}
1725
1726
sewardj9d31dfd2011-03-15 12:36:44 +00001727static UChar *
sewardj2019a972011-03-07 16:04:07 +00001728s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1729{
sewardj7ee97522011-05-09 21:45:04 +00001730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001731 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1732
1733 return emit_RR(p, 0x0d00, r1, r2);
1734}
1735
1736
sewardj9d31dfd2011-03-15 12:36:44 +00001737static UChar *
sewardj2019a972011-03-07 16:04:07 +00001738s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1739{
sewardj7ee97522011-05-09 21:45:04 +00001740 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001741 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1742
1743 return emit_RR(p, 0x0700, r1, r2);
1744}
1745
1746
sewardj9d31dfd2011-03-15 12:36:44 +00001747static UChar *
sewardj2019a972011-03-07 16:04:07 +00001748s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1749{
sewardj7ee97522011-05-09 21:45:04 +00001750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001751 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1752
1753 return emit_RI(p, 0xa7040000, r1, i2);
1754}
1755
1756
sewardj9d31dfd2011-03-15 12:36:44 +00001757static UChar *
florian8844a632012-04-13 04:04:06 +00001758s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
1759{
1760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1761 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
1762
1763 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
1764}
1765
1766
1767static UChar *
sewardj2019a972011-03-07 16:04:07 +00001768s390_emit_CR(UChar *p, UChar r1, UChar r2)
1769{
sewardj7ee97522011-05-09 21:45:04 +00001770 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001771 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1772
1773 return emit_RR(p, 0x1900, r1, r2);
1774}
1775
1776
sewardj9d31dfd2011-03-15 12:36:44 +00001777static UChar *
sewardj2019a972011-03-07 16:04:07 +00001778s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1779{
sewardj7ee97522011-05-09 21:45:04 +00001780 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001781 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1782
1783 return emit_RRE(p, 0xb9200000, r1, r2);
1784}
1785
1786
sewardj9d31dfd2011-03-15 12:36:44 +00001787static UChar *
sewardj2019a972011-03-07 16:04:07 +00001788s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1789{
sewardj7ee97522011-05-09 21:45:04 +00001790 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001791 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1792
1793 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1794}
1795
1796
sewardj9d31dfd2011-03-15 12:36:44 +00001797static UChar *
sewardj2019a972011-03-07 16:04:07 +00001798s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1799{
sewardj652b56a2011-04-13 15:38:17 +00001800 vassert(s390_host_has_ldisp);
1801
sewardj7ee97522011-05-09 21:45:04 +00001802 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001803 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1804
1805 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1806}
1807
1808
sewardj9d31dfd2011-03-15 12:36:44 +00001809static UChar *
sewardj2019a972011-03-07 16:04:07 +00001810s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1811{
sewardj652b56a2011-04-13 15:38:17 +00001812 vassert(s390_host_has_ldisp || dh2 == 0);
1813
sewardj7ee97522011-05-09 21:45:04 +00001814 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001815 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1816
1817 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1818}
1819
1820
sewardj9d31dfd2011-03-15 12:36:44 +00001821static UChar *
sewardj2019a972011-03-07 16:04:07 +00001822s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1823{
sewardj652b56a2011-04-13 15:38:17 +00001824 vassert(s390_host_has_eimm);
1825
sewardj7ee97522011-05-09 21:45:04 +00001826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001827 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1828
1829 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1830}
1831
1832
sewardj9d31dfd2011-03-15 12:36:44 +00001833static UChar *
florian07d34552012-05-26 01:59:21 +00001834s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
1835{
1836 vassert(s390_host_has_eimm);
1837
1838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1839 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
1840
1841 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
1842}
1843
1844
1845static UChar *
sewardj2019a972011-03-07 16:04:07 +00001846s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1847{
sewardj7ee97522011-05-09 21:45:04 +00001848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001849 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1850
1851 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1852}
1853
1854
sewardj9d31dfd2011-03-15 12:36:44 +00001855static UChar *
sewardj2019a972011-03-07 16:04:07 +00001856s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1857{
sewardj652b56a2011-04-13 15:38:17 +00001858 vassert(s390_host_has_ldisp);
1859
sewardj7ee97522011-05-09 21:45:04 +00001860 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001861 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1862
1863 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1864}
1865
1866
sewardj9d31dfd2011-03-15 12:36:44 +00001867static UChar *
sewardj2019a972011-03-07 16:04:07 +00001868s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1869{
sewardj652b56a2011-04-13 15:38:17 +00001870 vassert(s390_host_has_ldisp || dh2 == 0);
1871
sewardj7ee97522011-05-09 21:45:04 +00001872 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001873 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1874
1875 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1876}
1877
1878
sewardj9d31dfd2011-03-15 12:36:44 +00001879static UChar *
florian448cbba2012-06-06 02:26:01 +00001880s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1881{
1882 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1883 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
1884
1885 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
1886}
1887
1888
1889static UChar *
1890s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1891{
1892 vassert(s390_host_has_ldisp);
1893
1894 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1895 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
1896
1897 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
1898}
1899
1900
1901static UChar *
1902s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1903{
1904 vassert(s390_host_has_ldisp || dh2 == 0);
1905
1906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1907 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
1908
1909 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
1910}
1911
1912
1913static UChar *
sewardj2019a972011-03-07 16:04:07 +00001914s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1915{
sewardj7ee97522011-05-09 21:45:04 +00001916 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001917 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1918
1919 return emit_RR(p, 0x1500, r1, r2);
1920}
1921
1922
sewardj9d31dfd2011-03-15 12:36:44 +00001923static UChar *
sewardj2019a972011-03-07 16:04:07 +00001924s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1925{
sewardj7ee97522011-05-09 21:45:04 +00001926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001927 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1928
1929 return emit_RRE(p, 0xb9210000, r1, r2);
1930}
1931
1932
sewardj9d31dfd2011-03-15 12:36:44 +00001933static UChar *
sewardj2019a972011-03-07 16:04:07 +00001934s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1935{
sewardj7ee97522011-05-09 21:45:04 +00001936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001937 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1938
1939 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1940}
1941
1942
sewardj9d31dfd2011-03-15 12:36:44 +00001943static UChar *
sewardj2019a972011-03-07 16:04:07 +00001944s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1945{
sewardj652b56a2011-04-13 15:38:17 +00001946 vassert(s390_host_has_ldisp);
1947
sewardj7ee97522011-05-09 21:45:04 +00001948 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001949 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1950
1951 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1952}
1953
1954
sewardj9d31dfd2011-03-15 12:36:44 +00001955static UChar *
sewardj2019a972011-03-07 16:04:07 +00001956s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1957{
sewardj652b56a2011-04-13 15:38:17 +00001958 vassert(s390_host_has_ldisp || dh2 == 0);
1959
sewardj7ee97522011-05-09 21:45:04 +00001960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001961 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1962
1963 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1964}
1965
1966
sewardj9d31dfd2011-03-15 12:36:44 +00001967static UChar *
sewardj2019a972011-03-07 16:04:07 +00001968s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1969{
sewardj652b56a2011-04-13 15:38:17 +00001970 vassert(s390_host_has_eimm);
1971
sewardj7ee97522011-05-09 21:45:04 +00001972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001973 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1974
1975 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1976}
1977
1978
sewardj9d31dfd2011-03-15 12:36:44 +00001979static UChar *
florian07d34552012-05-26 01:59:21 +00001980s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
1981{
1982 vassert(s390_host_has_eimm);
1983
1984 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1985 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
1986
1987 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
1988}
1989
1990
1991static UChar *
sewardj2019a972011-03-07 16:04:07 +00001992s390_emit_DR(UChar *p, UChar r1, UChar r2)
1993{
sewardj7ee97522011-05-09 21:45:04 +00001994 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001995 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1996
1997 return emit_RR(p, 0x1d00, r1, r2);
1998}
1999
2000
sewardj9d31dfd2011-03-15 12:36:44 +00002001static UChar *
sewardj2019a972011-03-07 16:04:07 +00002002s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2003{
sewardj7ee97522011-05-09 21:45:04 +00002004 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002005 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
2006
2007 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
2008}
2009
2010
sewardj9d31dfd2011-03-15 12:36:44 +00002011static UChar *
sewardj2019a972011-03-07 16:04:07 +00002012s390_emit_DLR(UChar *p, UChar r1, UChar r2)
2013{
sewardj7ee97522011-05-09 21:45:04 +00002014 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002015 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
2016
2017 return emit_RRE(p, 0xb9970000, r1, r2);
2018}
2019
2020
sewardj9d31dfd2011-03-15 12:36:44 +00002021static UChar *
sewardj2019a972011-03-07 16:04:07 +00002022s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
2023{
sewardj7ee97522011-05-09 21:45:04 +00002024 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002025 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
2026
2027 return emit_RRE(p, 0xb9870000, r1, r2);
2028}
2029
2030
sewardj9d31dfd2011-03-15 12:36:44 +00002031static UChar *
sewardj2019a972011-03-07 16:04:07 +00002032s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2033{
sewardj652b56a2011-04-13 15:38:17 +00002034 vassert(s390_host_has_ldisp || dh2 == 0);
2035
sewardj7ee97522011-05-09 21:45:04 +00002036 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002037 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
2038
2039 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
2040}
2041
2042
sewardj9d31dfd2011-03-15 12:36:44 +00002043static UChar *
sewardj2019a972011-03-07 16:04:07 +00002044s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2045{
sewardj652b56a2011-04-13 15:38:17 +00002046 vassert(s390_host_has_ldisp || dh2 == 0);
2047
sewardj7ee97522011-05-09 21:45:04 +00002048 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002049 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
2050
2051 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
2052}
2053
2054
sewardj9d31dfd2011-03-15 12:36:44 +00002055static UChar *
sewardj2019a972011-03-07 16:04:07 +00002056s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
2057{
sewardj7ee97522011-05-09 21:45:04 +00002058 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002059 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
2060
2061 return emit_RRE(p, 0xb90d0000, r1, r2);
2062}
2063
2064
sewardj9d31dfd2011-03-15 12:36:44 +00002065static UChar *
sewardj2019a972011-03-07 16:04:07 +00002066s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2067{
sewardj652b56a2011-04-13 15:38:17 +00002068 vassert(s390_host_has_ldisp || dh2 == 0);
2069
sewardj7ee97522011-05-09 21:45:04 +00002070 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002071 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
2072
2073 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
2074}
2075
2076
sewardj9d31dfd2011-03-15 12:36:44 +00002077static UChar *
sewardj2019a972011-03-07 16:04:07 +00002078s390_emit_XR(UChar *p, UChar r1, UChar r2)
2079{
sewardj7ee97522011-05-09 21:45:04 +00002080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002081 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
2082
2083 return emit_RR(p, 0x1700, r1, r2);
2084}
2085
2086
sewardj9d31dfd2011-03-15 12:36:44 +00002087static UChar *
sewardj2019a972011-03-07 16:04:07 +00002088s390_emit_XGR(UChar *p, UChar r1, UChar r2)
2089{
sewardj7ee97522011-05-09 21:45:04 +00002090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002091 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
2092
2093 return emit_RRE(p, 0xb9820000, r1, r2);
2094}
2095
2096
sewardj9d31dfd2011-03-15 12:36:44 +00002097static UChar *
sewardj2019a972011-03-07 16:04:07 +00002098s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2099{
sewardj7ee97522011-05-09 21:45:04 +00002100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002101 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
2102
2103 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
2104}
2105
2106
sewardj9d31dfd2011-03-15 12:36:44 +00002107static UChar *
sewardj2019a972011-03-07 16:04:07 +00002108s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2109{
sewardj652b56a2011-04-13 15:38:17 +00002110 vassert(s390_host_has_ldisp);
2111
sewardj7ee97522011-05-09 21:45:04 +00002112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002113 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
2114
2115 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
2116}
2117
2118
sewardj9d31dfd2011-03-15 12:36:44 +00002119static UChar *
sewardj2019a972011-03-07 16:04:07 +00002120s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2121{
sewardj652b56a2011-04-13 15:38:17 +00002122 vassert(s390_host_has_ldisp || dh2 == 0);
2123
sewardj7ee97522011-05-09 21:45:04 +00002124 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002125 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
2126
2127 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
2128}
2129
2130
sewardj9d31dfd2011-03-15 12:36:44 +00002131static UChar *
sewardj2019a972011-03-07 16:04:07 +00002132s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
2133{
sewardj652b56a2011-04-13 15:38:17 +00002134 vassert(s390_host_has_eimm);
2135
sewardj7ee97522011-05-09 21:45:04 +00002136 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002137 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
2138
2139 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
2140}
2141
2142
sewardj9d31dfd2011-03-15 12:36:44 +00002143static UChar *
sewardj2019a972011-03-07 16:04:07 +00002144s390_emit_XILF(UChar *p, UChar r1, UInt i2)
2145{
sewardj652b56a2011-04-13 15:38:17 +00002146 vassert(s390_host_has_eimm);
2147
sewardj7ee97522011-05-09 21:45:04 +00002148 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002149 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
2150
2151 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
2152}
2153
2154
sewardj9d31dfd2011-03-15 12:36:44 +00002155static UChar *
florianad43b3a2012-02-20 15:01:14 +00002156s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2157{
2158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2159 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
2160
2161 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
2162}
2163
2164
2165static UChar *
sewardj2019a972011-03-07 16:04:07 +00002166s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
2167{
sewardj652b56a2011-04-13 15:38:17 +00002168 vassert(s390_host_has_eimm);
2169
sewardj7ee97522011-05-09 21:45:04 +00002170 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002171 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
2172
2173 return emit_RRE(p, 0xb9830000, r1, r2);
2174}
2175
2176
sewardj9d31dfd2011-03-15 12:36:44 +00002177static UChar *
sewardj2019a972011-03-07 16:04:07 +00002178s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2179{
sewardj7ee97522011-05-09 21:45:04 +00002180 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002181 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
2182
2183 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
2184}
2185
2186
sewardj9d31dfd2011-03-15 12:36:44 +00002187static UChar *
sewardj2019a972011-03-07 16:04:07 +00002188s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2189{
sewardj652b56a2011-04-13 15:38:17 +00002190 vassert(s390_host_has_ldisp);
2191
sewardj7ee97522011-05-09 21:45:04 +00002192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002193 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
2194
2195 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
2196}
2197
2198
sewardj9d31dfd2011-03-15 12:36:44 +00002199static UChar *
sewardj2019a972011-03-07 16:04:07 +00002200s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
2201{
sewardj652b56a2011-04-13 15:38:17 +00002202 vassert(s390_host_has_eimm);
2203
sewardj7ee97522011-05-09 21:45:04 +00002204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002205 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
2206
2207 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
2208}
2209
2210
sewardj9d31dfd2011-03-15 12:36:44 +00002211static UChar *
sewardj2019a972011-03-07 16:04:07 +00002212s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
2213{
sewardj7ee97522011-05-09 21:45:04 +00002214 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002215 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
2216
2217 return emit_RI(p, 0xa5000000, r1, i2);
2218}
2219
2220
sewardj9d31dfd2011-03-15 12:36:44 +00002221static UChar *
sewardj2019a972011-03-07 16:04:07 +00002222s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
2223{
sewardj7ee97522011-05-09 21:45:04 +00002224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002225 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
2226
2227 return emit_RI(p, 0xa5010000, r1, i2);
2228}
2229
2230
sewardj9d31dfd2011-03-15 12:36:44 +00002231static UChar *
sewardj2019a972011-03-07 16:04:07 +00002232s390_emit_IILF(UChar *p, UChar r1, UInt i2)
2233{
sewardj652b56a2011-04-13 15:38:17 +00002234 vassert(s390_host_has_eimm);
2235
sewardj7ee97522011-05-09 21:45:04 +00002236 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002237 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
2238
2239 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
2240}
2241
2242
sewardj9d31dfd2011-03-15 12:36:44 +00002243static UChar *
sewardj2019a972011-03-07 16:04:07 +00002244s390_emit_IILH(UChar *p, UChar r1, UShort i2)
2245{
sewardj7ee97522011-05-09 21:45:04 +00002246 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002247 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
2248
2249 return emit_RI(p, 0xa5020000, r1, i2);
2250}
2251
2252
sewardj9d31dfd2011-03-15 12:36:44 +00002253static UChar *
sewardj2019a972011-03-07 16:04:07 +00002254s390_emit_IILL(UChar *p, UChar r1, UShort i2)
2255{
sewardj7ee97522011-05-09 21:45:04 +00002256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002257 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
2258
2259 return emit_RI(p, 0xa5030000, r1, i2);
2260}
2261
2262
sewardj9d31dfd2011-03-15 12:36:44 +00002263static UChar *
sewardj2019a972011-03-07 16:04:07 +00002264s390_emit_IPM(UChar *p, UChar r1, UChar r2)
2265{
sewardj7ee97522011-05-09 21:45:04 +00002266 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002267 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
2268
2269 return emit_RRE(p, 0xb2220000, r1, r2);
2270}
2271
2272
sewardj9d31dfd2011-03-15 12:36:44 +00002273static UChar *
sewardj2019a972011-03-07 16:04:07 +00002274s390_emit_LR(UChar *p, UChar r1, UChar r2)
2275{
sewardj7ee97522011-05-09 21:45:04 +00002276 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002277 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
2278
2279 return emit_RR(p, 0x1800, r1, r2);
2280}
2281
2282
sewardj9d31dfd2011-03-15 12:36:44 +00002283static UChar *
sewardj2019a972011-03-07 16:04:07 +00002284s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2285{
sewardj7ee97522011-05-09 21:45:04 +00002286 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002287 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2288
2289 return emit_RRE(p, 0xb9040000, r1, r2);
2290}
2291
2292
sewardj9d31dfd2011-03-15 12:36:44 +00002293static UChar *
sewardj2019a972011-03-07 16:04:07 +00002294s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2295{
sewardj7ee97522011-05-09 21:45:04 +00002296 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002297 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2298
2299 return emit_RRE(p, 0xb9140000, r1, r2);
2300}
2301
2302
sewardj9d31dfd2011-03-15 12:36:44 +00002303static UChar *
sewardj2019a972011-03-07 16:04:07 +00002304s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2305{
sewardj7ee97522011-05-09 21:45:04 +00002306 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002307 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2308
2309 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2310}
2311
2312
sewardj9d31dfd2011-03-15 12:36:44 +00002313static UChar *
sewardj2019a972011-03-07 16:04:07 +00002314s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2315{
sewardj652b56a2011-04-13 15:38:17 +00002316 vassert(s390_host_has_ldisp);
2317
sewardj7ee97522011-05-09 21:45:04 +00002318 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002319 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2320
2321 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2322}
2323
2324
sewardj9d31dfd2011-03-15 12:36:44 +00002325static UChar *
sewardj2019a972011-03-07 16:04:07 +00002326s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2327{
sewardj652b56a2011-04-13 15:38:17 +00002328 vassert(s390_host_has_ldisp || dh2 == 0);
2329
sewardj7ee97522011-05-09 21:45:04 +00002330 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002331 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2332
2333 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2334}
2335
2336
sewardj9d31dfd2011-03-15 12:36:44 +00002337static UChar *
sewardj2019a972011-03-07 16:04:07 +00002338s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2339{
sewardj652b56a2011-04-13 15:38:17 +00002340 vassert(s390_host_has_ldisp || dh2 == 0);
2341
sewardj7ee97522011-05-09 21:45:04 +00002342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002343 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2344
2345 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2346}
2347
2348
sewardj9d31dfd2011-03-15 12:36:44 +00002349static UChar *
sewardj2019a972011-03-07 16:04:07 +00002350s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2351{
sewardj652b56a2011-04-13 15:38:17 +00002352 vassert(s390_host_has_eimm);
2353
sewardj7ee97522011-05-09 21:45:04 +00002354 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002355 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2356
2357 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2358}
2359
2360
sewardj9d31dfd2011-03-15 12:36:44 +00002361static UChar *
sewardj2019a972011-03-07 16:04:07 +00002362s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2363{
sewardj7ee97522011-05-09 21:45:04 +00002364 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002365 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2366
2367 return emit_RR(p, 0x1200, r1, r2);
2368}
2369
2370
sewardj9d31dfd2011-03-15 12:36:44 +00002371static UChar *
sewardj2019a972011-03-07 16:04:07 +00002372s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2373{
sewardj7ee97522011-05-09 21:45:04 +00002374 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002375 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2376
2377 return emit_RRE(p, 0xb9020000, r1, r2);
2378}
2379
2380
sewardj9d31dfd2011-03-15 12:36:44 +00002381static UChar *
sewardj2019a972011-03-07 16:04:07 +00002382s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2383{
sewardj652b56a2011-04-13 15:38:17 +00002384 vassert(s390_host_has_eimm);
2385
sewardj7ee97522011-05-09 21:45:04 +00002386 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002387 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2388
2389 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2390}
2391
2392
sewardj9d31dfd2011-03-15 12:36:44 +00002393static UChar *
sewardj2019a972011-03-07 16:04:07 +00002394s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2395{
sewardj652b56a2011-04-13 15:38:17 +00002396 vassert(s390_host_has_eimm);
2397
sewardj7ee97522011-05-09 21:45:04 +00002398 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002399 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2400
2401 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2402}
2403
2404
sewardj9d31dfd2011-03-15 12:36:44 +00002405static UChar *
sewardj2019a972011-03-07 16:04:07 +00002406s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2407{
sewardj652b56a2011-04-13 15:38:17 +00002408 vassert(s390_host_has_eimm);
2409
sewardj7ee97522011-05-09 21:45:04 +00002410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002411 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2412
2413 return emit_RRE(p, 0xb9260000, r1, r2);
2414}
2415
2416
sewardj9d31dfd2011-03-15 12:36:44 +00002417static UChar *
sewardj2019a972011-03-07 16:04:07 +00002418s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2419{
sewardj652b56a2011-04-13 15:38:17 +00002420 vassert(s390_host_has_eimm);
2421
sewardj7ee97522011-05-09 21:45:04 +00002422 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002423 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2424
2425 return emit_RRE(p, 0xb9060000, r1, r2);
2426}
2427
2428
sewardj9d31dfd2011-03-15 12:36:44 +00002429static UChar *
sewardj2019a972011-03-07 16:04:07 +00002430s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2431{
sewardj652b56a2011-04-13 15:38:17 +00002432 vassert(s390_host_has_ldisp);
2433
sewardj7ee97522011-05-09 21:45:04 +00002434 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002435 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2436
2437 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2438}
2439
2440
sewardj9d31dfd2011-03-15 12:36:44 +00002441static UChar *
sewardj2019a972011-03-07 16:04:07 +00002442s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2443{
sewardj652b56a2011-04-13 15:38:17 +00002444 vassert(s390_host_has_ldisp);
2445
sewardj7ee97522011-05-09 21:45:04 +00002446 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002447 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2448
2449 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2450}
2451
2452
sewardj9d31dfd2011-03-15 12:36:44 +00002453static UChar *
sewardj2019a972011-03-07 16:04:07 +00002454s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2455{
sewardj7ee97522011-05-09 21:45:04 +00002456 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002457 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2458
2459 return emit_RR(p, 0x1300, r1, r2);
2460}
2461
2462
sewardj9d31dfd2011-03-15 12:36:44 +00002463static UChar *
sewardj2019a972011-03-07 16:04:07 +00002464s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2465{
sewardj7ee97522011-05-09 21:45:04 +00002466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002467 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2468
2469 return emit_RRE(p, 0xb9030000, r1, r2);
2470}
2471
2472
sewardj9d31dfd2011-03-15 12:36:44 +00002473static UChar *
sewardj2019a972011-03-07 16:04:07 +00002474s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2475{
sewardj652b56a2011-04-13 15:38:17 +00002476 vassert(s390_host_has_eimm);
2477
sewardj7ee97522011-05-09 21:45:04 +00002478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002479 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2480
2481 return emit_RRE(p, 0xb9270000, r1, r2);
2482}
2483
2484
sewardj9d31dfd2011-03-15 12:36:44 +00002485static UChar *
sewardj2019a972011-03-07 16:04:07 +00002486s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2487{
sewardj652b56a2011-04-13 15:38:17 +00002488 vassert(s390_host_has_eimm);
2489
sewardj7ee97522011-05-09 21:45:04 +00002490 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002491 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2492
2493 return emit_RRE(p, 0xb9070000, r1, r2);
2494}
2495
2496
sewardj9d31dfd2011-03-15 12:36:44 +00002497static UChar *
sewardj2019a972011-03-07 16:04:07 +00002498s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2499{
sewardj7ee97522011-05-09 21:45:04 +00002500 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002501 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2502
2503 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2504}
2505
2506
sewardj9d31dfd2011-03-15 12:36:44 +00002507static UChar *
sewardj2019a972011-03-07 16:04:07 +00002508s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2509{
sewardj652b56a2011-04-13 15:38:17 +00002510 vassert(s390_host_has_ldisp);
2511
sewardj7ee97522011-05-09 21:45:04 +00002512 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002513 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2514
2515 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2516}
2517
2518
sewardj9d31dfd2011-03-15 12:36:44 +00002519static UChar *
sewardj2019a972011-03-07 16:04:07 +00002520s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2521{
sewardj652b56a2011-04-13 15:38:17 +00002522 vassert(s390_host_has_ldisp || dh2 == 0);
2523
sewardj7ee97522011-05-09 21:45:04 +00002524 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002525 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2526
2527 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2528}
2529
2530
sewardj9d31dfd2011-03-15 12:36:44 +00002531static UChar *
sewardj2019a972011-03-07 16:04:07 +00002532s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2533{
sewardj7ee97522011-05-09 21:45:04 +00002534 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002535 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2536
2537 return emit_RI(p, 0xa7080000, r1, i2);
2538}
2539
2540
sewardj9d31dfd2011-03-15 12:36:44 +00002541static UChar *
sewardj2019a972011-03-07 16:04:07 +00002542s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2543{
sewardj7ee97522011-05-09 21:45:04 +00002544 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002545 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2546
2547 return emit_RI(p, 0xa7090000, r1, i2);
2548}
2549
2550
sewardj9d31dfd2011-03-15 12:36:44 +00002551static UChar *
sewardj2019a972011-03-07 16:04:07 +00002552s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2553{
sewardj7ee97522011-05-09 21:45:04 +00002554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002555 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2556
2557 return emit_RRE(p, 0xb9160000, r1, r2);
2558}
2559
2560
sewardj9d31dfd2011-03-15 12:36:44 +00002561static UChar *
sewardj2019a972011-03-07 16:04:07 +00002562s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2563{
sewardj652b56a2011-04-13 15:38:17 +00002564 vassert(s390_host_has_ldisp || dh2 == 0);
2565
sewardj7ee97522011-05-09 21:45:04 +00002566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002567 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2568
2569 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2570}
2571
2572
sewardj9d31dfd2011-03-15 12:36:44 +00002573static UChar *
sewardj2019a972011-03-07 16:04:07 +00002574s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2575{
sewardj652b56a2011-04-13 15:38:17 +00002576 vassert(s390_host_has_eimm);
2577
sewardj7ee97522011-05-09 21:45:04 +00002578 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002579 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2580
2581 return emit_RRE(p, 0xb9940000, r1, r2);
2582}
2583
2584
sewardj9d31dfd2011-03-15 12:36:44 +00002585static UChar *
sewardj2019a972011-03-07 16:04:07 +00002586s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2587{
sewardj652b56a2011-04-13 15:38:17 +00002588 vassert(s390_host_has_eimm);
2589
sewardj7ee97522011-05-09 21:45:04 +00002590 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002591 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2592
2593 return emit_RRE(p, 0xb9840000, r1, r2);
2594}
2595
2596
sewardj9d31dfd2011-03-15 12:36:44 +00002597static UChar *
sewardj2019a972011-03-07 16:04:07 +00002598s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2599{
sewardj652b56a2011-04-13 15:38:17 +00002600 vassert(s390_host_has_eimm);
2601
sewardj7ee97522011-05-09 21:45:04 +00002602 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002603 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2604
2605 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2606}
2607
2608
sewardj9d31dfd2011-03-15 12:36:44 +00002609static UChar *
sewardj2019a972011-03-07 16:04:07 +00002610s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2611{
sewardj652b56a2011-04-13 15:38:17 +00002612 vassert(s390_host_has_ldisp || dh2 == 0);
2613
sewardj7ee97522011-05-09 21:45:04 +00002614 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002615 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2616
2617 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2618}
2619
2620
sewardj9d31dfd2011-03-15 12:36:44 +00002621static UChar *
sewardj2019a972011-03-07 16:04:07 +00002622s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2623{
sewardj652b56a2011-04-13 15:38:17 +00002624 vassert(s390_host_has_eimm);
2625
sewardj7ee97522011-05-09 21:45:04 +00002626 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002627 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2628
2629 return emit_RRE(p, 0xb9950000, r1, r2);
2630}
2631
2632
sewardj9d31dfd2011-03-15 12:36:44 +00002633static UChar *
sewardj2019a972011-03-07 16:04:07 +00002634s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2635{
sewardj652b56a2011-04-13 15:38:17 +00002636 vassert(s390_host_has_eimm);
2637
sewardj7ee97522011-05-09 21:45:04 +00002638 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002639 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2640
2641 return emit_RRE(p, 0xb9850000, r1, r2);
2642}
2643
2644
sewardj9d31dfd2011-03-15 12:36:44 +00002645static UChar *
sewardj2019a972011-03-07 16:04:07 +00002646s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2647{
sewardj652b56a2011-04-13 15:38:17 +00002648 vassert(s390_host_has_eimm);
2649
sewardj7ee97522011-05-09 21:45:04 +00002650 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002651 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2652
2653 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2654}
2655
2656
sewardj9d31dfd2011-03-15 12:36:44 +00002657static UChar *
sewardj2019a972011-03-07 16:04:07 +00002658s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2659{
sewardj652b56a2011-04-13 15:38:17 +00002660 vassert(s390_host_has_ldisp || dh2 == 0);
2661
sewardj7ee97522011-05-09 21:45:04 +00002662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002663 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2664
2665 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2666}
2667
2668
sewardj9d31dfd2011-03-15 12:36:44 +00002669static UChar *
sewardj2019a972011-03-07 16:04:07 +00002670s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2671{
sewardj652b56a2011-04-13 15:38:17 +00002672 vassert(s390_host_has_eimm);
2673
sewardj7ee97522011-05-09 21:45:04 +00002674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002675 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2676
2677 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2678}
2679
2680
sewardj9d31dfd2011-03-15 12:36:44 +00002681static UChar *
sewardj2019a972011-03-07 16:04:07 +00002682s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2683{
sewardj7ee97522011-05-09 21:45:04 +00002684 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002685 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2686
2687 return emit_RI(p, 0xa50e0000, r1, i2);
2688}
2689
2690
sewardj9d31dfd2011-03-15 12:36:44 +00002691static UChar *
sewardj2019a972011-03-07 16:04:07 +00002692s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2693{
sewardj7ee97522011-05-09 21:45:04 +00002694 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002695 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2696
2697 return emit_RI(p, 0xa50f0000, r1, i2);
2698}
2699
2700
sewardj9d31dfd2011-03-15 12:36:44 +00002701static UChar *
sewardj2019a972011-03-07 16:04:07 +00002702s390_emit_MR(UChar *p, UChar r1, UChar r2)
2703{
sewardj7ee97522011-05-09 21:45:04 +00002704 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002705 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2706
2707 return emit_RR(p, 0x1c00, r1, r2);
2708}
2709
2710
sewardj9d31dfd2011-03-15 12:36:44 +00002711static UChar *
sewardj2019a972011-03-07 16:04:07 +00002712s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2713{
sewardj7ee97522011-05-09 21:45:04 +00002714 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002715 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2716
2717 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2718}
2719
2720
sewardj9d31dfd2011-03-15 12:36:44 +00002721static UChar *
sewardj2019a972011-03-07 16:04:07 +00002722s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2723{
sewardj652b56a2011-04-13 15:38:17 +00002724 vassert(s390_host_has_gie);
2725
sewardj7ee97522011-05-09 21:45:04 +00002726 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002727 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2728
2729 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2730}
2731
2732
sewardj9d31dfd2011-03-15 12:36:44 +00002733static UChar *
sewardj2019a972011-03-07 16:04:07 +00002734s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2735{
sewardj7ee97522011-05-09 21:45:04 +00002736 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002737 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2738
2739 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2740}
2741
2742
sewardj9d31dfd2011-03-15 12:36:44 +00002743static UChar *
sewardj2019a972011-03-07 16:04:07 +00002744s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2745{
sewardj652b56a2011-04-13 15:38:17 +00002746 vassert(s390_host_has_gie);
2747
sewardj7ee97522011-05-09 21:45:04 +00002748 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002749 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2750
2751 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2752}
2753
2754
sewardj9d31dfd2011-03-15 12:36:44 +00002755static UChar *
sewardj2019a972011-03-07 16:04:07 +00002756s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2757{
sewardj7ee97522011-05-09 21:45:04 +00002758 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002759 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2760
2761 return emit_RI(p, 0xa70c0000, r1, i2);
2762}
2763
2764
sewardj9d31dfd2011-03-15 12:36:44 +00002765static UChar *
sewardj2019a972011-03-07 16:04:07 +00002766s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2767{
sewardj7ee97522011-05-09 21:45:04 +00002768 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002769 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2770
2771 return emit_RRE(p, 0xb9960000, r1, r2);
2772}
2773
2774
sewardj9d31dfd2011-03-15 12:36:44 +00002775static UChar *
sewardj2019a972011-03-07 16:04:07 +00002776s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2777{
sewardj7ee97522011-05-09 21:45:04 +00002778 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002779 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2780
2781 return emit_RRE(p, 0xb9860000, r1, r2);
2782}
2783
2784
sewardj9d31dfd2011-03-15 12:36:44 +00002785static UChar *
sewardj2019a972011-03-07 16:04:07 +00002786s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2787{
sewardj652b56a2011-04-13 15:38:17 +00002788 vassert(s390_host_has_ldisp || dh2 == 0);
2789
sewardj7ee97522011-05-09 21:45:04 +00002790 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002791 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2792
2793 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2794}
2795
2796
sewardj9d31dfd2011-03-15 12:36:44 +00002797static UChar *
sewardj2019a972011-03-07 16:04:07 +00002798s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2799{
sewardj652b56a2011-04-13 15:38:17 +00002800 vassert(s390_host_has_ldisp || dh2 == 0);
2801
sewardj7ee97522011-05-09 21:45:04 +00002802 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002803 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2804
2805 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2806}
2807
2808
sewardj9d31dfd2011-03-15 12:36:44 +00002809static UChar *
sewardj2019a972011-03-07 16:04:07 +00002810s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2811{
sewardj7ee97522011-05-09 21:45:04 +00002812 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002813 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2814
2815 return emit_RRE(p, 0xb2520000, r1, r2);
2816}
2817
2818
sewardj9d31dfd2011-03-15 12:36:44 +00002819static UChar *
sewardj2019a972011-03-07 16:04:07 +00002820s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2821{
sewardj7ee97522011-05-09 21:45:04 +00002822 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002823 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2824
2825 return emit_RRE(p, 0xb90c0000, r1, r2);
2826}
2827
2828
sewardj9d31dfd2011-03-15 12:36:44 +00002829static UChar *
sewardj2019a972011-03-07 16:04:07 +00002830s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2831{
sewardj7ee97522011-05-09 21:45:04 +00002832 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002833 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2834
2835 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2836}
2837
2838
sewardj9d31dfd2011-03-15 12:36:44 +00002839static UChar *
sewardj2019a972011-03-07 16:04:07 +00002840s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2841{
sewardj652b56a2011-04-13 15:38:17 +00002842 vassert(s390_host_has_ldisp);
2843
sewardj7ee97522011-05-09 21:45:04 +00002844 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002845 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2846
2847 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2848}
2849
2850
sewardj9d31dfd2011-03-15 12:36:44 +00002851static UChar *
sewardj2019a972011-03-07 16:04:07 +00002852s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2853{
sewardj652b56a2011-04-13 15:38:17 +00002854 vassert(s390_host_has_ldisp || dh2 == 0);
2855
sewardj7ee97522011-05-09 21:45:04 +00002856 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002857 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2858
2859 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2860}
2861
2862
sewardj9d31dfd2011-03-15 12:36:44 +00002863static UChar *
sewardj2019a972011-03-07 16:04:07 +00002864s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2865{
sewardj652b56a2011-04-13 15:38:17 +00002866 vassert(s390_host_has_gie);
2867
sewardj7ee97522011-05-09 21:45:04 +00002868 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002869 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2870
2871 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2872}
2873
2874
sewardj9d31dfd2011-03-15 12:36:44 +00002875static UChar *
sewardj2019a972011-03-07 16:04:07 +00002876s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2877{
sewardj652b56a2011-04-13 15:38:17 +00002878 vassert(s390_host_has_gie);
2879
sewardj7ee97522011-05-09 21:45:04 +00002880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002881 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2882
2883 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2884}
2885
2886
sewardj9d31dfd2011-03-15 12:36:44 +00002887static UChar *
floriancec3a8a2013-02-02 00:16:58 +00002888s390_emit_MVC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2889{
2890 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2891 s390_disasm(ENC3(MNM, UDLB, UDXB), "mvc", d1, l, b1, d2, 0, b2);
2892
2893 return emit_SSa(p, 0xd20000000000ULL, l, b1, d1, b2, d2);
2894}
2895
2896
2897static UChar *
florianb93348d2012-12-27 00:59:43 +00002898s390_emit_MVI(UChar *p, UChar i2, UChar b1, UShort d1)
2899{
2900 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002901 s390_disasm(ENC3(MNM, UDXB, INT), "mvi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002902
2903 return emit_SI(p, 0x92000000, i2, b1, d1);
2904}
2905
2906
2907static UChar *
2908s390_emit_MVHHI(UChar *p, UChar b1, UShort d1, UShort i2)
2909{
2910 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002911 s390_disasm(ENC3(MNM, UDXB, INT), "mvhhi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002912
2913 return emit_SIL(p, 0xe54400000000ULL, b1, d1, i2);
2914}
2915
2916
2917static UChar *
2918s390_emit_MVHI(UChar *p, UChar b1, UShort d1, UShort i2)
2919{
2920 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002921 s390_disasm(ENC3(MNM, UDXB, INT), "mvhi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002922
2923 return emit_SIL(p, 0xe54c00000000ULL, b1, d1, i2);
2924}
2925
2926
2927static UChar *
2928s390_emit_MVGHI(UChar *p, UChar b1, UShort d1, UShort i2)
2929{
2930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002931 s390_disasm(ENC3(MNM, UDXB, INT), "mvghi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002932
2933 return emit_SIL(p, 0xe54800000000ULL, b1, d1, i2);
2934}
2935
2936
2937static UChar *
sewardj2019a972011-03-07 16:04:07 +00002938s390_emit_OR(UChar *p, UChar r1, UChar r2)
2939{
sewardj7ee97522011-05-09 21:45:04 +00002940 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002941 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2942
2943 return emit_RR(p, 0x1600, r1, r2);
2944}
2945
2946
sewardj9d31dfd2011-03-15 12:36:44 +00002947static UChar *
sewardj2019a972011-03-07 16:04:07 +00002948s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2949{
sewardj7ee97522011-05-09 21:45:04 +00002950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002951 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2952
2953 return emit_RRE(p, 0xb9810000, r1, r2);
2954}
2955
2956
sewardj9d31dfd2011-03-15 12:36:44 +00002957static UChar *
sewardj2019a972011-03-07 16:04:07 +00002958s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2959{
sewardj7ee97522011-05-09 21:45:04 +00002960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002961 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2962
2963 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2964}
2965
2966
sewardj9d31dfd2011-03-15 12:36:44 +00002967static UChar *
sewardj2019a972011-03-07 16:04:07 +00002968s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2969{
sewardj652b56a2011-04-13 15:38:17 +00002970 vassert(s390_host_has_ldisp);
2971
sewardj7ee97522011-05-09 21:45:04 +00002972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002973 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2974
2975 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2976}
2977
2978
sewardj9d31dfd2011-03-15 12:36:44 +00002979static UChar *
sewardj2019a972011-03-07 16:04:07 +00002980s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2981{
sewardj652b56a2011-04-13 15:38:17 +00002982 vassert(s390_host_has_ldisp || dh2 == 0);
2983
sewardj7ee97522011-05-09 21:45:04 +00002984 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002985 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2986
2987 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2988}
2989
2990
sewardj9d31dfd2011-03-15 12:36:44 +00002991static UChar *
sewardj2019a972011-03-07 16:04:07 +00002992s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2993{
sewardj652b56a2011-04-13 15:38:17 +00002994 vassert(s390_host_has_eimm);
2995
sewardj7ee97522011-05-09 21:45:04 +00002996 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002997 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2998
2999 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
3000}
3001
3002
sewardj9d31dfd2011-03-15 12:36:44 +00003003static UChar *
sewardj2019a972011-03-07 16:04:07 +00003004s390_emit_OILF(UChar *p, UChar r1, UInt i2)
3005{
sewardj652b56a2011-04-13 15:38:17 +00003006 vassert(s390_host_has_eimm);
3007
sewardj7ee97522011-05-09 21:45:04 +00003008 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003009 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
3010
3011 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
3012}
3013
3014
sewardj9d31dfd2011-03-15 12:36:44 +00003015static UChar *
sewardj2019a972011-03-07 16:04:07 +00003016s390_emit_OILL(UChar *p, UChar r1, UShort i2)
3017{
sewardj7ee97522011-05-09 21:45:04 +00003018 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003019 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
3020
3021 return emit_RI(p, 0xa50b0000, r1, i2);
3022}
3023
3024
sewardj9d31dfd2011-03-15 12:36:44 +00003025static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00003026s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00003027{
sewardj7ee97522011-05-09 21:45:04 +00003028 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003029 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
3030
sewardj3c49aaa2011-04-05 14:00:37 +00003031 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00003032}
3033
3034
sewardj9d31dfd2011-03-15 12:36:44 +00003035static UChar *
sewardj2019a972011-03-07 16:04:07 +00003036s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3037{
sewardj652b56a2011-04-13 15:38:17 +00003038 vassert(s390_host_has_ldisp || dh2 == 0);
3039
sewardj7ee97522011-05-09 21:45:04 +00003040 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003041 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
3042
3043 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
3044}
3045
3046
sewardj9d31dfd2011-03-15 12:36:44 +00003047static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00003048s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00003049{
sewardj7ee97522011-05-09 21:45:04 +00003050 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003051 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
3052
sewardj3c49aaa2011-04-05 14:00:37 +00003053 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00003054}
3055
3056
sewardj9d31dfd2011-03-15 12:36:44 +00003057static UChar *
sewardj2019a972011-03-07 16:04:07 +00003058s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3059{
sewardj652b56a2011-04-13 15:38:17 +00003060 vassert(s390_host_has_ldisp || dh2 == 0);
3061
sewardj7ee97522011-05-09 21:45:04 +00003062 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003063 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
3064
3065 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
3066}
3067
3068
sewardj9d31dfd2011-03-15 12:36:44 +00003069static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00003070s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00003071{
sewardj7ee97522011-05-09 21:45:04 +00003072 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003073 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
3074
sewardj3c49aaa2011-04-05 14:00:37 +00003075 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00003076}
3077
3078
sewardj9d31dfd2011-03-15 12:36:44 +00003079static UChar *
sewardj2019a972011-03-07 16:04:07 +00003080s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3081{
sewardj652b56a2011-04-13 15:38:17 +00003082 vassert(s390_host_has_ldisp || dh2 == 0);
3083
sewardj7ee97522011-05-09 21:45:04 +00003084 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003085 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
3086
3087 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
3088}
3089
3090
sewardj9d31dfd2011-03-15 12:36:44 +00003091static UChar *
sewardj2019a972011-03-07 16:04:07 +00003092s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3093{
sewardj7ee97522011-05-09 21:45:04 +00003094 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003095 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
3096
3097 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
3098}
3099
3100
sewardj9d31dfd2011-03-15 12:36:44 +00003101static UChar *
sewardj2019a972011-03-07 16:04:07 +00003102s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3103{
sewardj652b56a2011-04-13 15:38:17 +00003104 vassert(s390_host_has_ldisp);
3105
sewardj7ee97522011-05-09 21:45:04 +00003106 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003107 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
3108
3109 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
3110}
3111
3112
sewardj9d31dfd2011-03-15 12:36:44 +00003113static UChar *
sewardj2019a972011-03-07 16:04:07 +00003114s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3115{
sewardj652b56a2011-04-13 15:38:17 +00003116 vassert(s390_host_has_ldisp || dh2 == 0);
3117
sewardj7ee97522011-05-09 21:45:04 +00003118 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003119 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
3120
3121 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
3122}
3123
3124
sewardj9d31dfd2011-03-15 12:36:44 +00003125static UChar *
sewardj2019a972011-03-07 16:04:07 +00003126s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3127{
sewardj7ee97522011-05-09 21:45:04 +00003128 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003129 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
3130
3131 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
3132}
3133
3134
sewardj9d31dfd2011-03-15 12:36:44 +00003135static UChar *
sewardj2019a972011-03-07 16:04:07 +00003136s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3137{
sewardj652b56a2011-04-13 15:38:17 +00003138 vassert(s390_host_has_ldisp);
3139
sewardj7ee97522011-05-09 21:45:04 +00003140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003141 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
3142
3143 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
3144}
3145
3146
sewardj9d31dfd2011-03-15 12:36:44 +00003147static UChar *
sewardj2019a972011-03-07 16:04:07 +00003148s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3149{
sewardj7ee97522011-05-09 21:45:04 +00003150 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003151 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
3152
3153 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
3154}
3155
3156
sewardj9d31dfd2011-03-15 12:36:44 +00003157static UChar *
sewardj2019a972011-03-07 16:04:07 +00003158s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3159{
sewardj652b56a2011-04-13 15:38:17 +00003160 vassert(s390_host_has_ldisp);
3161
sewardj7ee97522011-05-09 21:45:04 +00003162 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003163 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
3164
3165 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
3166}
3167
3168
sewardj9d31dfd2011-03-15 12:36:44 +00003169static UChar *
sewardj2019a972011-03-07 16:04:07 +00003170s390_emit_SR(UChar *p, UChar r1, UChar r2)
3171{
sewardj7ee97522011-05-09 21:45:04 +00003172 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003173 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
3174
3175 return emit_RR(p, 0x1b00, r1, r2);
3176}
3177
3178
sewardj9d31dfd2011-03-15 12:36:44 +00003179static UChar *
sewardj2019a972011-03-07 16:04:07 +00003180s390_emit_SGR(UChar *p, UChar r1, UChar r2)
3181{
sewardj7ee97522011-05-09 21:45:04 +00003182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003183 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
3184
3185 return emit_RRE(p, 0xb9090000, r1, r2);
3186}
3187
3188
sewardj9d31dfd2011-03-15 12:36:44 +00003189static UChar *
sewardj2019a972011-03-07 16:04:07 +00003190s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3191{
sewardj7ee97522011-05-09 21:45:04 +00003192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003193 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
3194
3195 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
3196}
3197
3198
sewardj9d31dfd2011-03-15 12:36:44 +00003199static UChar *
sewardj2019a972011-03-07 16:04:07 +00003200s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3201{
sewardj652b56a2011-04-13 15:38:17 +00003202 vassert(s390_host_has_ldisp);
3203
sewardj7ee97522011-05-09 21:45:04 +00003204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003205 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
3206
3207 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
3208}
3209
3210
sewardj9d31dfd2011-03-15 12:36:44 +00003211static UChar *
sewardj2019a972011-03-07 16:04:07 +00003212s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3213{
sewardj652b56a2011-04-13 15:38:17 +00003214 vassert(s390_host_has_ldisp || dh2 == 0);
3215
sewardj7ee97522011-05-09 21:45:04 +00003216 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003217 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
3218
3219 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
3220}
3221
3222
sewardj9d31dfd2011-03-15 12:36:44 +00003223static UChar *
sewardj2019a972011-03-07 16:04:07 +00003224s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3225{
sewardj7ee97522011-05-09 21:45:04 +00003226 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003227 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
3228
3229 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
3230}
3231
3232
sewardj9d31dfd2011-03-15 12:36:44 +00003233static UChar *
sewardj2019a972011-03-07 16:04:07 +00003234s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3235{
sewardj652b56a2011-04-13 15:38:17 +00003236 vassert(s390_host_has_ldisp);
3237
sewardj7ee97522011-05-09 21:45:04 +00003238 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003239 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
3240
3241 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
3242}
3243
3244
sewardj9d31dfd2011-03-15 12:36:44 +00003245static UChar *
sewardj2019a972011-03-07 16:04:07 +00003246s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
3247{
sewardj652b56a2011-04-13 15:38:17 +00003248 vassert(s390_host_has_eimm);
3249
sewardj7ee97522011-05-09 21:45:04 +00003250 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003251 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
3252
3253 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
3254}
3255
3256
sewardj9d31dfd2011-03-15 12:36:44 +00003257static UChar *
sewardjb13a92a2011-04-13 14:44:29 +00003258s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
3259{
sewardj7ee97522011-05-09 21:45:04 +00003260 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardjb13a92a2011-04-13 14:44:29 +00003261 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
3262
3263 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
3264}
3265
3266
3267static UChar *
sewardj2019a972011-03-07 16:04:07 +00003268s390_emit_LDR(UChar *p, UChar r1, UChar r2)
3269{
sewardj7ee97522011-05-09 21:45:04 +00003270 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003271 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
3272
3273 return emit_RR(p, 0x2800, r1, r2);
3274}
3275
3276
sewardj9d31dfd2011-03-15 12:36:44 +00003277static UChar *
sewardj2019a972011-03-07 16:04:07 +00003278s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3279{
sewardj7ee97522011-05-09 21:45:04 +00003280 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003281 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
3282
3283 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
3284}
3285
3286
sewardj9d31dfd2011-03-15 12:36:44 +00003287static UChar *
sewardj2019a972011-03-07 16:04:07 +00003288s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3289{
sewardj7ee97522011-05-09 21:45:04 +00003290 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003291 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
3292
3293 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
3294}
3295
3296
sewardj9d31dfd2011-03-15 12:36:44 +00003297static UChar *
sewardj2019a972011-03-07 16:04:07 +00003298s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3299{
sewardj652b56a2011-04-13 15:38:17 +00003300 vassert(s390_host_has_ldisp);
3301
sewardj7ee97522011-05-09 21:45:04 +00003302 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003303 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
3304
3305 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
3306}
3307
3308
sewardj9d31dfd2011-03-15 12:36:44 +00003309static UChar *
sewardj2019a972011-03-07 16:04:07 +00003310s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3311{
sewardj652b56a2011-04-13 15:38:17 +00003312 vassert(s390_host_has_ldisp);
3313
sewardj7ee97522011-05-09 21:45:04 +00003314 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003315 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
3316
3317 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
3318}
3319
3320
sewardj9d31dfd2011-03-15 12:36:44 +00003321static UChar *
sewardj2019a972011-03-07 16:04:07 +00003322s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
3323{
sewardj7ee97522011-05-09 21:45:04 +00003324 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003325 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
3326
3327 return emit_S(p, 0xb29d0000, b2, d2);
3328}
3329
3330
sewardj9d31dfd2011-03-15 12:36:44 +00003331static UChar *
sewardj2019a972011-03-07 16:04:07 +00003332s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3333{
sewardjd07b8562011-04-27 11:58:22 +00003334 vassert(s390_host_has_fgx);
3335
sewardj7ee97522011-05-09 21:45:04 +00003336 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003337 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
3338
3339 return emit_RRE(p, 0xb3c10000, r1, r2);
3340}
3341
3342
sewardj9d31dfd2011-03-15 12:36:44 +00003343static UChar *
sewardj2019a972011-03-07 16:04:07 +00003344s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3345{
sewardjd07b8562011-04-27 11:58:22 +00003346 vassert(s390_host_has_fgx);
3347
sewardj7ee97522011-05-09 21:45:04 +00003348 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003349 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3350
3351 return emit_RRE(p, 0xb3cd0000, r1, r2);
3352}
3353
3354
sewardj9d31dfd2011-03-15 12:36:44 +00003355static UChar *
sewardj2019a972011-03-07 16:04:07 +00003356s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3357{
sewardj7ee97522011-05-09 21:45:04 +00003358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003359 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3360
3361 return emit_RRE(p, 0xb3740000, r1, r2);
3362}
3363
3364
sewardj9d31dfd2011-03-15 12:36:44 +00003365static UChar *
sewardj2019a972011-03-07 16:04:07 +00003366s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3367{
sewardj7ee97522011-05-09 21:45:04 +00003368 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003369 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3370
3371 return emit_RRE(p, 0xb3750000, r1, r2);
3372}
3373
3374
sewardj9d31dfd2011-03-15 12:36:44 +00003375static UChar *
florian6d8e26e2012-09-12 19:52:16 +00003376s390_emit_SFPC(UChar *p, UChar r1)
sewardj2019a972011-03-07 16:04:07 +00003377{
sewardj7ee97522011-05-09 21:45:04 +00003378 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003379 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3380
florian6d8e26e2012-09-12 19:52:16 +00003381 return emit_RRE(p, 0xb3840000, r1, 0);
sewardj2019a972011-03-07 16:04:07 +00003382}
3383
3384
sewardj9d31dfd2011-03-15 12:36:44 +00003385static UChar *
sewardj2019a972011-03-07 16:04:07 +00003386s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3387{
sewardj7ee97522011-05-09 21:45:04 +00003388 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003389 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3390
3391 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3392}
3393
3394
sewardj9d31dfd2011-03-15 12:36:44 +00003395static UChar *
sewardj2019a972011-03-07 16:04:07 +00003396s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3397{
sewardj7ee97522011-05-09 21:45:04 +00003398 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003399 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3400
3401 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3402}
3403
3404
sewardj9d31dfd2011-03-15 12:36:44 +00003405static UChar *
sewardj2019a972011-03-07 16:04:07 +00003406s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3407{
sewardj652b56a2011-04-13 15:38:17 +00003408 vassert(s390_host_has_ldisp);
3409
sewardj7ee97522011-05-09 21:45:04 +00003410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003411 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3412
3413 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3414}
3415
3416
sewardj9d31dfd2011-03-15 12:36:44 +00003417static UChar *
sewardj2019a972011-03-07 16:04:07 +00003418s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3419{
sewardj652b56a2011-04-13 15:38:17 +00003420 vassert(s390_host_has_ldisp);
3421
sewardj7ee97522011-05-09 21:45:04 +00003422 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003423 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3424
3425 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3426}
3427
3428
sewardj9d31dfd2011-03-15 12:36:44 +00003429static UChar *
sewardj2019a972011-03-07 16:04:07 +00003430s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3431{
sewardj7ee97522011-05-09 21:45:04 +00003432 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003433 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3434
3435 return emit_S(p, 0xb29c0000, b2, d2);
3436}
3437
3438
sewardj9d31dfd2011-03-15 12:36:44 +00003439static UChar *
sewardj2019a972011-03-07 16:04:07 +00003440s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3441{
sewardj7ee97522011-05-09 21:45:04 +00003442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003443 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3444
3445 return emit_RRE(p, 0xb30a0000, r1, r2);
3446}
3447
3448
sewardj9d31dfd2011-03-15 12:36:44 +00003449static UChar *
sewardj2019a972011-03-07 16:04:07 +00003450s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3451{
sewardj7ee97522011-05-09 21:45:04 +00003452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003453 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3454
3455 return emit_RRE(p, 0xb31a0000, r1, r2);
3456}
3457
3458
sewardj9d31dfd2011-03-15 12:36:44 +00003459static UChar *
sewardj2019a972011-03-07 16:04:07 +00003460s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3461{
sewardj7ee97522011-05-09 21:45:04 +00003462 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003463 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3464
3465 return emit_RRE(p, 0xb34a0000, r1, r2);
3466}
3467
3468
sewardj9d31dfd2011-03-15 12:36:44 +00003469static UChar *
sewardj2019a972011-03-07 16:04:07 +00003470s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3471{
sewardj7ee97522011-05-09 21:45:04 +00003472 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003473 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3474
3475 return emit_RRE(p, 0xb3090000, r1, r2);
3476}
3477
3478
sewardj9d31dfd2011-03-15 12:36:44 +00003479static UChar *
sewardj2019a972011-03-07 16:04:07 +00003480s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3481{
sewardj7ee97522011-05-09 21:45:04 +00003482 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003483 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3484
3485 return emit_RRE(p, 0xb3190000, r1, r2);
3486}
3487
3488
sewardj9d31dfd2011-03-15 12:36:44 +00003489static UChar *
sewardj2019a972011-03-07 16:04:07 +00003490s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3491{
sewardj7ee97522011-05-09 21:45:04 +00003492 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003493 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3494
3495 return emit_RRE(p, 0xb3490000, r1, r2);
3496}
3497
3498
sewardj9d31dfd2011-03-15 12:36:44 +00003499static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003500s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003501{
florian8c3ccaf2012-09-09 18:18:25 +00003502 vassert(m4 == 0);
3503 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003504
florian8c3ccaf2012-09-09 18:18:25 +00003505 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3506 if (m3 == 0)
3507 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3508 else
3509 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3510 "cefbra", r1, m3, r2, m4);
3511 }
3512
3513 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003514}
3515
3516
sewardj9d31dfd2011-03-15 12:36:44 +00003517static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003518s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003519{
florian8c3ccaf2012-09-09 18:18:25 +00003520 vassert(m4 == 0);
3521 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003522
florian8c3ccaf2012-09-09 18:18:25 +00003523 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3524 if (m3 == 0)
3525 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3526 else
3527 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3528 "cdfbra", r1, m3, r2, m4);
3529 }
3530
3531 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003532}
3533
3534
sewardj9d31dfd2011-03-15 12:36:44 +00003535static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003536s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003537{
florian8c3ccaf2012-09-09 18:18:25 +00003538 vassert(m4 == 0);
3539 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003540
florian8c3ccaf2012-09-09 18:18:25 +00003541 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3542 if (m3 == 0)
3543 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3544 else
3545 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3546 "cxfbra", r1, m3, r2, m4);
3547 }
3548
3549 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003550}
3551
3552
sewardj9d31dfd2011-03-15 12:36:44 +00003553static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003554s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003555{
florian8c3ccaf2012-09-09 18:18:25 +00003556 vassert(m4 == 0);
3557 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003558
florian8c3ccaf2012-09-09 18:18:25 +00003559 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3560 if (m3 == 0)
3561 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3562 else
3563 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3564 "cegbra", r1, m3, r2, m4);
3565 }
3566
3567 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003568}
3569
3570
sewardj9d31dfd2011-03-15 12:36:44 +00003571static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003572s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003573{
florian8c3ccaf2012-09-09 18:18:25 +00003574 vassert(m4 == 0);
3575 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003576
florian8c3ccaf2012-09-09 18:18:25 +00003577 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3578 if (m3 == 0)
3579 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3580 else
3581 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3582 "cdgbra", r1, m3, r2, m4);
3583 }
3584
3585 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003586}
3587
3588
sewardj9d31dfd2011-03-15 12:36:44 +00003589static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003590s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003591{
florian8c3ccaf2012-09-09 18:18:25 +00003592 vassert(m4 == 0);
3593 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003594
florian8c3ccaf2012-09-09 18:18:25 +00003595 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3596 if (m3 == 0)
3597 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3598 else
3599 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3600 "cxgbra", r1, m3, r2, m4);
3601 }
3602
3603 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003604}
3605
3606
sewardj9d31dfd2011-03-15 12:36:44 +00003607static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00003608s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3609{
florian606dbeb2012-09-09 18:12:28 +00003610 vassert(m4 == 0);
3611 vassert(s390_host_has_fpext);
3612
florian1c8f7ff2012-09-01 00:12:11 +00003613 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3614 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
3615
3616 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
3617}
3618
3619
3620static UChar *
3621s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3622{
florian606dbeb2012-09-09 18:12:28 +00003623 vassert(m4 == 0);
3624 vassert(s390_host_has_fpext);
3625
florian1c8f7ff2012-09-01 00:12:11 +00003626 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3627 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
3628
3629 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
3630}
3631
3632
3633static UChar *
3634s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3635{
florian606dbeb2012-09-09 18:12:28 +00003636 vassert(m4 == 0);
3637 vassert(s390_host_has_fpext);
3638
florian1c8f7ff2012-09-01 00:12:11 +00003639 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3640 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
3641
3642 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
3643}
3644
3645
3646static UChar *
3647s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3648{
florian606dbeb2012-09-09 18:12:28 +00003649 vassert(m4 == 0);
3650 vassert(s390_host_has_fpext);
3651
florian1c8f7ff2012-09-01 00:12:11 +00003652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3653 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
3654
3655 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
3656}
3657
3658
3659static UChar *
3660s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3661{
florian606dbeb2012-09-09 18:12:28 +00003662 vassert(m4 == 0);
3663 vassert(s390_host_has_fpext);
3664
florian1c8f7ff2012-09-01 00:12:11 +00003665 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3666 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
3667
3668 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
3669}
3670
3671
3672static UChar *
3673s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3674{
florian606dbeb2012-09-09 18:12:28 +00003675 vassert(m4 == 0);
3676 vassert(s390_host_has_fpext);
3677
florian1c8f7ff2012-09-01 00:12:11 +00003678 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3679 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
3680
3681 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
3682}
3683
3684
3685static UChar *
3686s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3687{
florian606dbeb2012-09-09 18:12:28 +00003688 vassert(m4 == 0);
3689 vassert(s390_host_has_fpext);
3690
florian1c8f7ff2012-09-01 00:12:11 +00003691 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3692 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
3693
3694 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
3695}
3696
3697
3698static UChar *
3699s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3700{
florian606dbeb2012-09-09 18:12:28 +00003701 vassert(m4 == 0);
3702 vassert(s390_host_has_fpext);
3703
florian1c8f7ff2012-09-01 00:12:11 +00003704 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3705 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
3706
3707 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
3708}
3709
3710
3711static UChar *
3712s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3713{
florian606dbeb2012-09-09 18:12:28 +00003714 vassert(m4 == 0);
3715 vassert(s390_host_has_fpext);
3716
florian1c8f7ff2012-09-01 00:12:11 +00003717 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3718 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
3719
3720 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
3721}
3722
3723
3724static UChar *
3725s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3726{
florian606dbeb2012-09-09 18:12:28 +00003727 vassert(m4 == 0);
3728 vassert(s390_host_has_fpext);
3729
florian1c8f7ff2012-09-01 00:12:11 +00003730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3731 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
3732
3733 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
3734}
3735
3736
3737static UChar *
3738s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3739{
florian606dbeb2012-09-09 18:12:28 +00003740 vassert(m4 == 0);
3741 vassert(s390_host_has_fpext);
3742
florian1c8f7ff2012-09-01 00:12:11 +00003743 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3744 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
3745
3746 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
3747}
3748
3749
3750static UChar *
3751s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3752{
florian606dbeb2012-09-09 18:12:28 +00003753 vassert(m4 == 0);
3754 vassert(s390_host_has_fpext);
3755
florian1c8f7ff2012-09-01 00:12:11 +00003756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3757 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
3758
3759 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
3760}
3761
3762
3763static UChar *
sewardj2019a972011-03-07 16:04:07 +00003764s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3765{
sewardj7ee97522011-05-09 21:45:04 +00003766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003767 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3768
3769 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3770}
3771
3772
sewardj9d31dfd2011-03-15 12:36:44 +00003773static UChar *
sewardj2019a972011-03-07 16:04:07 +00003774s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3775{
sewardj7ee97522011-05-09 21:45:04 +00003776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003777 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3778
3779 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3780}
3781
3782
sewardj9d31dfd2011-03-15 12:36:44 +00003783static UChar *
sewardj2019a972011-03-07 16:04:07 +00003784s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3785{
sewardj7ee97522011-05-09 21:45:04 +00003786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003787 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3788
3789 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3790}
3791
3792
sewardj9d31dfd2011-03-15 12:36:44 +00003793static UChar *
sewardj2019a972011-03-07 16:04:07 +00003794s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3795{
sewardj7ee97522011-05-09 21:45:04 +00003796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003797 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3798
3799 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3800}
3801
3802
sewardj9d31dfd2011-03-15 12:36:44 +00003803static UChar *
sewardj2019a972011-03-07 16:04:07 +00003804s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3805{
sewardj7ee97522011-05-09 21:45:04 +00003806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003807 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3808
3809 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3810}
3811
3812
sewardj9d31dfd2011-03-15 12:36:44 +00003813static UChar *
sewardj2019a972011-03-07 16:04:07 +00003814s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3815{
sewardj7ee97522011-05-09 21:45:04 +00003816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003817 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3818
3819 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3820}
3821
3822
sewardj9d31dfd2011-03-15 12:36:44 +00003823static UChar *
sewardj2019a972011-03-07 16:04:07 +00003824s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3825{
sewardj7ee97522011-05-09 21:45:04 +00003826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003827 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3828
3829 return emit_RRE(p, 0xb30d0000, r1, r2);
3830}
3831
3832
sewardj9d31dfd2011-03-15 12:36:44 +00003833static UChar *
sewardj2019a972011-03-07 16:04:07 +00003834s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3835{
sewardj7ee97522011-05-09 21:45:04 +00003836 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003837 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3838
3839 return emit_RRE(p, 0xb31d0000, r1, r2);
3840}
3841
3842
sewardj9d31dfd2011-03-15 12:36:44 +00003843static UChar *
sewardj2019a972011-03-07 16:04:07 +00003844s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3845{
sewardj7ee97522011-05-09 21:45:04 +00003846 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003847 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3848
3849 return emit_RRE(p, 0xb34d0000, r1, r2);
3850}
3851
3852
sewardj9d31dfd2011-03-15 12:36:44 +00003853static UChar *
sewardj2019a972011-03-07 16:04:07 +00003854s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3855{
sewardj7ee97522011-05-09 21:45:04 +00003856 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003857 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3858
3859 return emit_RRE(p, 0xb3030000, r1, r2);
3860}
3861
3862
sewardj9d31dfd2011-03-15 12:36:44 +00003863static UChar *
sewardj2019a972011-03-07 16:04:07 +00003864s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3865{
sewardj7ee97522011-05-09 21:45:04 +00003866 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003867 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3868
3869 return emit_RRE(p, 0xb3130000, r1, r2);
3870}
3871
3872
sewardj9d31dfd2011-03-15 12:36:44 +00003873static UChar *
sewardj2019a972011-03-07 16:04:07 +00003874s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3875{
sewardj7ee97522011-05-09 21:45:04 +00003876 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003877 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3878
3879 return emit_RRE(p, 0xb3430000, r1, r2);
3880}
3881
3882
sewardj9d31dfd2011-03-15 12:36:44 +00003883static UChar *
sewardj2019a972011-03-07 16:04:07 +00003884s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3885{
sewardj7ee97522011-05-09 21:45:04 +00003886 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003887 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3888
3889 return emit_RRE(p, 0xb3040000, r1, r2);
3890}
3891
3892
sewardj9d31dfd2011-03-15 12:36:44 +00003893static UChar *
sewardj2019a972011-03-07 16:04:07 +00003894s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3895{
sewardj7ee97522011-05-09 21:45:04 +00003896 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003897 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3898
3899 return emit_RRE(p, 0xb3050000, r1, r2);
3900}
3901
3902
sewardj9d31dfd2011-03-15 12:36:44 +00003903static UChar *
sewardj2019a972011-03-07 16:04:07 +00003904s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3905{
sewardj7ee97522011-05-09 21:45:04 +00003906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003907 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3908
3909 return emit_RRE(p, 0xb3060000, r1, r2);
3910}
3911
3912
sewardj9d31dfd2011-03-15 12:36:44 +00003913static UChar *
sewardj2019a972011-03-07 16:04:07 +00003914s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3915{
sewardj7ee97522011-05-09 21:45:04 +00003916 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003917 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3918
3919 return emit_RRE(p, 0xb3010000, r1, r2);
3920}
3921
3922
sewardj9d31dfd2011-03-15 12:36:44 +00003923static UChar *
sewardj2019a972011-03-07 16:04:07 +00003924s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3925{
sewardj7ee97522011-05-09 21:45:04 +00003926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003927 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3928
3929 return emit_RRE(p, 0xb3110000, r1, r2);
3930}
3931
3932
sewardj9d31dfd2011-03-15 12:36:44 +00003933static UChar *
sewardj2019a972011-03-07 16:04:07 +00003934s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3935{
sewardj7ee97522011-05-09 21:45:04 +00003936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003937 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3938
3939 return emit_RRE(p, 0xb3410000, r1, r2);
3940}
3941
3942
sewardj9d31dfd2011-03-15 12:36:44 +00003943static UChar *
sewardj2019a972011-03-07 16:04:07 +00003944s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3945{
sewardj7ee97522011-05-09 21:45:04 +00003946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003947 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3948
3949 return emit_RRE(p, 0xb3000000, r1, r2);
3950}
3951
3952
sewardj9d31dfd2011-03-15 12:36:44 +00003953static UChar *
sewardj2019a972011-03-07 16:04:07 +00003954s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3955{
sewardj7ee97522011-05-09 21:45:04 +00003956 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003957 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3958
3959 return emit_RRE(p, 0xb3100000, r1, r2);
3960}
3961
3962
sewardj9d31dfd2011-03-15 12:36:44 +00003963static UChar *
sewardj2019a972011-03-07 16:04:07 +00003964s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3965{
sewardj7ee97522011-05-09 21:45:04 +00003966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003967 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3968
3969 return emit_RRE(p, 0xb3400000, r1, r2);
3970}
3971
3972
sewardj9d31dfd2011-03-15 12:36:44 +00003973static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003974s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003975{
florian8c3ccaf2012-09-09 18:18:25 +00003976 vassert(m4 == 0);
3977 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003978
florian8c3ccaf2012-09-09 18:18:25 +00003979 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3980 if (m3 == 0)
3981 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3982 else
3983 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3984 "ledbra", r1, m3, r2, m4);
3985 }
3986
3987 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003988}
3989
3990
sewardj9d31dfd2011-03-15 12:36:44 +00003991static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003992s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003993{
florian8c3ccaf2012-09-09 18:18:25 +00003994 vassert(m4 == 0);
3995 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003996
florian8c3ccaf2012-09-09 18:18:25 +00003997 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3998 if (m3 == 0)
3999 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
4000 else
4001 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4002 "ldxbra", r1, m3, r2, m4);
4003 }
4004
4005 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00004006}
4007
4008
sewardj9d31dfd2011-03-15 12:36:44 +00004009static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00004010s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00004011{
florian8c3ccaf2012-09-09 18:18:25 +00004012 vassert(m4 == 0);
4013 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00004014
florian8c3ccaf2012-09-09 18:18:25 +00004015 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4016 if (m3 == 0)
4017 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
4018 else
4019 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4020 "lexbra", r1, m3, r2, m4);
4021 }
4022
4023 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00004024}
4025
4026
sewardj9d31dfd2011-03-15 12:36:44 +00004027static UChar *
sewardj2019a972011-03-07 16:04:07 +00004028s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
4029{
sewardj7ee97522011-05-09 21:45:04 +00004030 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004031 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
4032
4033 return emit_RRE(p, 0xb3170000, r1, r2);
4034}
4035
4036
sewardj9d31dfd2011-03-15 12:36:44 +00004037static UChar *
sewardj2019a972011-03-07 16:04:07 +00004038s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
4039{
sewardj7ee97522011-05-09 21:45:04 +00004040 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004041 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
4042
4043 return emit_RRE(p, 0xb31c0000, r1, r2);
4044}
4045
4046
sewardj9d31dfd2011-03-15 12:36:44 +00004047static UChar *
sewardj2019a972011-03-07 16:04:07 +00004048s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
4049{
sewardj7ee97522011-05-09 21:45:04 +00004050 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004051 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
4052
4053 return emit_RRE(p, 0xb34c0000, r1, r2);
4054}
4055
4056
sewardj9d31dfd2011-03-15 12:36:44 +00004057static UChar *
sewardj2019a972011-03-07 16:04:07 +00004058s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4059{
sewardj7ee97522011-05-09 21:45:04 +00004060 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004061 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
4062
4063 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
4064}
4065
4066
sewardj9d31dfd2011-03-15 12:36:44 +00004067static UChar *
sewardj2019a972011-03-07 16:04:07 +00004068s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
4069{
sewardj7ee97522011-05-09 21:45:04 +00004070 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004071 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
4072
4073 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
4074}
4075
4076
sewardj9d31dfd2011-03-15 12:36:44 +00004077static UChar *
sewardj2019a972011-03-07 16:04:07 +00004078s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4079{
sewardj7ee97522011-05-09 21:45:04 +00004080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004081 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
4082
4083 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
4084}
4085
4086
sewardj9d31dfd2011-03-15 12:36:44 +00004087static UChar *
sewardj2019a972011-03-07 16:04:07 +00004088s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
4089{
sewardj7ee97522011-05-09 21:45:04 +00004090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004091 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
4092
4093 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
4094}
4095
4096
sewardj9d31dfd2011-03-15 12:36:44 +00004097static UChar *
sewardj2019a972011-03-07 16:04:07 +00004098s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
4099{
sewardj7ee97522011-05-09 21:45:04 +00004100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004101 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
4102
4103 return emit_RRE(p, 0xb3140000, r1, r2);
4104}
4105
4106
sewardj9d31dfd2011-03-15 12:36:44 +00004107static UChar *
sewardj2019a972011-03-07 16:04:07 +00004108s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
4109{
sewardj7ee97522011-05-09 21:45:04 +00004110 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004111 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
4112
4113 return emit_RRE(p, 0xb3150000, r1, r2);
4114}
4115
4116
sewardj9d31dfd2011-03-15 12:36:44 +00004117static UChar *
sewardj2019a972011-03-07 16:04:07 +00004118s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
4119{
sewardj7ee97522011-05-09 21:45:04 +00004120 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004121 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
4122
4123 return emit_RRE(p, 0xb3160000, r1, r2);
4124}
4125
4126
sewardj9d31dfd2011-03-15 12:36:44 +00004127static UChar *
sewardj2019a972011-03-07 16:04:07 +00004128s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
4129{
sewardj7ee97522011-05-09 21:45:04 +00004130 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004131 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
4132
4133 return emit_RRE(p, 0xb30b0000, r1, r2);
4134}
4135
4136
sewardj9d31dfd2011-03-15 12:36:44 +00004137static UChar *
sewardj2019a972011-03-07 16:04:07 +00004138s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
4139{
sewardj7ee97522011-05-09 21:45:04 +00004140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004141 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
4142
4143 return emit_RRE(p, 0xb31b0000, r1, r2);
4144}
4145
4146
sewardj9d31dfd2011-03-15 12:36:44 +00004147static UChar *
sewardj2019a972011-03-07 16:04:07 +00004148s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
4149{
sewardj7ee97522011-05-09 21:45:04 +00004150 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004151 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
4152
4153 return emit_RRE(p, 0xb34b0000, r1, r2);
4154}
4155
sewardj2019a972011-03-07 16:04:07 +00004156
florian12390202012-11-10 22:34:14 +00004157static UChar *
4158s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4159{
4160 vassert(s390_host_has_dfp);
4161 vassert(m4 == 0 || s390_host_has_fpext);
4162 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4163 if (m4 == 0)
4164 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
4165 else
florianb3764a92012-12-20 14:44:42 +00004166 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004167 }
4168
4169 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
4170}
4171
4172
4173static UChar *
floriane38f6412012-12-21 17:32:12 +00004174s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4175{
4176 vassert(s390_host_has_dfp);
4177 vassert(m4 == 0 || s390_host_has_fpext);
4178 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4179 if (m4 == 0)
4180 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
4181 else
4182 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
4183 }
4184
4185 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
4186}
4187
4188
4189static UChar *
4190s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
4191{
4192 vassert(s390_host_has_dfp);
4193 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4194 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
4195
4196 return emit_RRE(p, 0xb3e40000, r1, r2);
4197}
4198
4199
4200static UChar *
4201s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
4202{
4203 vassert(s390_host_has_dfp);
4204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4205 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
4206
4207 return emit_RRE(p, 0xb3ec0000, r1, r2);
4208}
4209
4210
4211static UChar *
floriana887acd2013-02-08 23:32:54 +00004212s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4213{
4214 vassert(s390_host_has_dfp);
4215 vassert(m4 == 0);
4216 vassert(m3 == 0 || s390_host_has_fpext);
4217
4218 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4219 if (m3 == 0)
4220 s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2);
4221 else
4222 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4);
4223 }
4224
4225 return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2);
4226}
4227
4228
4229static UChar *
4230s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4231{
4232 vassert(s390_host_has_dfp);
4233 vassert(m4 == 0);
4234 /* rounding mode m3 is not considered, as the corresponding
4235 IRop (Iop_I64StoD128) does not take rounding mode. */
4236 vassert(m3 == 0);
4237
florian08f65d92013-02-22 03:40:22 +00004238 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004239 s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2);
floriana887acd2013-02-08 23:32:54 +00004240
4241 return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2);
4242}
4243
4244
4245static UChar *
florian5f034622013-01-13 02:29:05 +00004246s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4247{
4248 vassert(m4 == 0);
4249 vassert(s390_host_has_dfp);
4250 vassert(s390_host_has_fpext);
4251
florian08f65d92013-02-22 03:40:22 +00004252 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004253 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004254
4255 return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2);
4256}
4257
4258
4259static UChar *
4260s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4261{
4262 vassert(m4 == 0);
4263 vassert(s390_host_has_dfp);
4264 vassert(s390_host_has_fpext);
4265
florian08f65d92013-02-22 03:40:22 +00004266 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004267 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004268
4269 return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2);
4270}
4271
4272
4273static UChar *
4274s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4275{
4276 vassert(m4 == 0);
4277 vassert(s390_host_has_dfp);
4278 vassert(s390_host_has_fpext);
4279
4280 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4281 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4);
4282
4283 return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2);
4284}
4285
4286
4287static UChar *
4288s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4289{
4290 vassert(m4 == 0);
4291 vassert(s390_host_has_dfp);
4292 vassert(s390_host_has_fpext);
4293
4294 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4295 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4);
4296
4297 return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2);
4298}
4299
4300
4301static UChar *
4302s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4303{
4304 vassert(m4 == 0);
4305 vassert(s390_host_has_dfp);
4306 vassert(s390_host_has_fpext);
4307
4308 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4309 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4);
4310
4311 return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2);
4312}
4313
4314
4315static UChar *
4316s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4317{
4318 vassert(m4 == 0);
4319 vassert(s390_host_has_dfp);
4320 vassert(s390_host_has_fpext);
4321
4322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4323 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4);
4324
4325 return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2);
4326}
4327
4328
4329static UChar *
florian20c6bca2012-12-26 17:47:19 +00004330s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
4331{
4332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4333 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
4334
4335 return emit_RRE(p, 0xb3f40000, r1, r2);
4336}
4337
4338
4339static UChar *
4340s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
4341{
4342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4343 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
4344
4345 return emit_RRE(p, 0xb3fc0000, r1, r2);
4346}
4347
4348
4349static UChar *
florian5f034622013-01-13 02:29:05 +00004350s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4351{
4352 vassert(m4 == 0);
4353 vassert(s390_host_has_dfp);
4354 vassert(s390_host_has_fpext);
4355
florian08f65d92013-02-22 03:40:22 +00004356 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004357 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004358
4359 return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2);
4360}
4361
4362
4363static UChar *
4364s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4365{
4366 vassert(m4 == 0);
4367 vassert(s390_host_has_dfp);
4368 vassert(s390_host_has_fpext);
4369
florian08f65d92013-02-22 03:40:22 +00004370 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004371 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004372
4373 return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2);
4374}
4375
4376
4377static UChar *
floriana887acd2013-02-08 23:32:54 +00004378s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4379{
4380 vassert(s390_host_has_dfp);
4381 vassert(m4 == 0);
4382 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4383
florian08f65d92013-02-22 03:40:22 +00004384 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004385 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2);
floriana887acd2013-02-08 23:32:54 +00004386
4387 return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2);
4388}
4389
4390
4391static UChar *
4392s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4393{
4394 vassert(s390_host_has_dfp);
4395 vassert(m4 == 0);
4396 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4397
florian08f65d92013-02-22 03:40:22 +00004398 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004399 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2);
floriana887acd2013-02-08 23:32:54 +00004400
4401 return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2);
4402}
4403
4404
4405static UChar *
florian5f034622013-01-13 02:29:05 +00004406s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4407{
4408 vassert(m4 == 0);
4409 vassert(s390_host_has_dfp);
4410 vassert(s390_host_has_fpext);
4411
4412 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4413 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4);
4414
4415 return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2);
4416}
4417
4418
4419static UChar *
4420s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4421{
4422 vassert(m4 == 0);
4423 vassert(s390_host_has_dfp);
4424 vassert(s390_host_has_fpext);
4425
4426 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4427 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4);
4428
4429 return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2);
4430}
4431
4432
4433static UChar *
4434s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4435{
4436 vassert(m4 == 0);
4437 vassert(s390_host_has_dfp);
4438 vassert(s390_host_has_fpext);
4439
4440 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4441 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4);
4442
4443 return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2);
4444}
4445
4446
4447static UChar *
4448s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4449{
4450 vassert(m4 == 0);
4451 vassert(s390_host_has_dfp);
4452 vassert(s390_host_has_fpext);
4453
4454 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4455 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4);
4456
4457 return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2);
4458}
4459
4460
4461static UChar *
florian12390202012-11-10 22:34:14 +00004462s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4463{
4464 vassert(s390_host_has_dfp);
4465 vassert(m4 == 0 || s390_host_has_fpext);
4466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4467 if (m4 == 0)
4468 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
4469 else
florianb3764a92012-12-20 14:44:42 +00004470 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004471 }
4472
4473 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
4474}
4475
4476
4477static UChar *
floriane38f6412012-12-21 17:32:12 +00004478s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4479{
4480 vassert(s390_host_has_dfp);
4481 vassert(m4 == 0 || s390_host_has_fpext);
4482 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4483 if (m4 == 0)
4484 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
4485 else
4486 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
4487 }
4488
4489 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
4490}
4491
4492
4493static UChar *
florian5c539732013-02-14 14:27:12 +00004494s390_emit_EEDTR(UChar *p, UChar r1, UChar r2)
4495{
4496 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4497 s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2);
4498
4499 return emit_RRE(p, 0xb3e50000, r1, r2);
4500}
4501
4502
4503static UChar *
4504s390_emit_EEXTR(UChar *p, UChar r1, UChar r2)
4505{
4506 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4507 s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2);
4508
4509 return emit_RRE(p, 0xb3ed0000, r1, r2);
4510}
4511
4512
4513static UChar *
floriance9e3db2012-12-27 20:14:03 +00004514s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
4515{
4516 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4517 s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
4518
4519 return emit_RRE(p, 0xb3e70000, r1, r2);
4520}
4521
4522
4523static UChar *
4524s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
4525{
4526 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4527 s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
4528
4529 return emit_RRE(p, 0xb3ef0000, r1, r2);
4530}
4531
4532
4533static UChar *
florian5c539732013-02-14 14:27:12 +00004534s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2)
4535{
4536 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4537 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2);
4538
4539 return emit_RRF(p, 0xb3f60000, r3, r1, r2);
4540}
4541
4542
4543static UChar *
4544s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2)
4545{
4546 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4547 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2);
4548
4549 return emit_RRF(p, 0xb3fe0000, r3, r1, r2);
4550}
4551
4552
4553static UChar *
floriane38f6412012-12-21 17:32:12 +00004554s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
4555{
4556 vassert(s390_host_has_dfp);
4557 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4558 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
4559
4560 return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
4561}
4562
4563
4564static UChar *
4565s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
4566{
4567 vassert(s390_host_has_dfp);
4568 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4569 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
4570
4571 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
4572}
4573
4574
4575static UChar *
4576s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4577{
4578 vassert(s390_host_has_dfp);
4579 vassert(m4 == 0);
florian1bb7f6f2013-02-11 00:03:27 +00004580 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
floriane38f6412012-12-21 17:32:12 +00004581
florian08f65d92013-02-22 03:40:22 +00004582 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4583 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4);
floriane38f6412012-12-21 17:32:12 +00004584
4585 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
4586}
4587
4588
4589static UChar *
4590s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4591{
4592 vassert(s390_host_has_dfp);
4593 vassert(m4 == 0);
florian1bb7f6f2013-02-11 00:03:27 +00004594 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
floriane38f6412012-12-21 17:32:12 +00004595
florian08f65d92013-02-22 03:40:22 +00004596 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4597 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4);
floriane38f6412012-12-21 17:32:12 +00004598
4599 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
4600}
4601
4602
4603static UChar *
florian12390202012-11-10 22:34:14 +00004604s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4605{
4606 vassert(s390_host_has_dfp);
4607 vassert(m4 == 0 || s390_host_has_fpext);
4608 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4609 if (m4 == 0)
4610 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
4611 else
florianb3764a92012-12-20 14:44:42 +00004612 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004613 }
4614
4615 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
4616}
4617
4618
4619static UChar *
floriane38f6412012-12-21 17:32:12 +00004620s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4621{
4622 vassert(s390_host_has_dfp);
4623 vassert(m4 == 0 || s390_host_has_fpext);
4624 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4625 if (m4 == 0)
4626 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
4627 else
4628 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
4629 }
4630
4631 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
4632}
4633
4634
4635static UChar *
florian78d5ef72013-05-11 15:02:58 +00004636emit_E(UChar *p, UInt op)
4637{
4638 ULong the_insn = op;
4639
4640 return emit_2bytes(p, the_insn);
4641}
4642
4643
4644static UChar *
4645s390_emit_PFPO(UChar *p)
4646{
4647 vassert(s390_host_has_pfpo);
4648 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4649 s390_disasm(ENC1(MNM), "pfpo");
4650 }
4651
4652 return emit_E(p, 0x010a);
4653}
4654
4655
4656static UChar *
florian5c539732013-02-14 14:27:12 +00004657s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4658{
4659 vassert(s390_host_has_dfp);
4660 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4661 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4);
4662
4663 return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2);
4664}
4665
4666
4667static UChar *
4668s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4669{
4670 vassert(s390_host_has_dfp);
4671 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4672 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4);
4673
4674 return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2);
4675}
4676
4677
4678static UChar *
4679s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4680{
4681 vassert(s390_host_has_dfp);
4682 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4683 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4);
4684
4685 return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2);
4686}
4687
4688
4689static UChar *
4690s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4691{
4692 vassert(s390_host_has_dfp);
4693 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4694 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4);
4695
4696 return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2);
4697}
4698
4699
4700static UChar *
florian12390202012-11-10 22:34:14 +00004701s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4702{
4703 vassert(s390_host_has_dfp);
4704 vassert(m4 == 0 || s390_host_has_fpext);
4705 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4706 if (m4 == 0)
4707 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
4708 else
florianb3764a92012-12-20 14:44:42 +00004709 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004710 }
4711
4712 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
4713}
4714
florian3a3d7f12012-12-03 13:32:05 +00004715
4716static UChar *
floriane38f6412012-12-21 17:32:12 +00004717s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4718{
4719 vassert(s390_host_has_dfp);
4720 vassert(m4 == 0 || s390_host_has_fpext);
4721 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4722 if (m4 == 0)
4723 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
4724 else
4725 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
4726 }
4727
4728 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
4729}
4730
4731
4732static UChar *
florian1b901d42013-01-01 22:19:24 +00004733s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2)
4734{
4735 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004736 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004737 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004738
sewardj6938b9d2013-02-11 16:06:03 +00004739 return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004740}
4741
4742
4743static UChar *
4744s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2)
4745{
4746 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004747 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004748 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004749
sewardj6938b9d2013-02-11 16:06:03 +00004750 return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004751}
4752
4753
4754static UChar *
4755s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2)
4756{
4757 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004758 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004759 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004760
sewardj6938b9d2013-02-11 16:06:03 +00004761 return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004762}
4763
4764
4765static UChar *
4766s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2)
4767{
4768 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004769 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004770 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004771
sewardj6938b9d2013-02-11 16:06:03 +00004772 return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004773}
4774
4775
4776static UChar *
florian3a3d7f12012-12-03 13:32:05 +00004777s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
4778{
florianaec8e052012-12-09 17:26:32 +00004779 vassert(s390_host_has_lsc);
florian08f65d92013-02-22 03:40:22 +00004780 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian3a3d7f12012-12-03 13:32:05 +00004781 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
florian3a3d7f12012-12-03 13:32:05 +00004782
4783 return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
4784}
4785
4786
4787static UChar *
4788s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4789{
4790 vassert(s390_host_has_ldisp || dh2 == 0);
4791
4792 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4793 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
4794
4795 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
4796}
4797
4798
4799static UChar *
4800s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4801{
4802 vassert(s390_host_has_ldisp || dh2 == 0);
4803
4804 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4805 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
4806
4807 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
4808}
4809
4810
sewardj2019a972011-03-07 16:04:07 +00004811/* Provide a symbolic name for register "R0" */
4812#define R0 0
4813
4814/* Split up a 20-bit displacement into its high and low piece
4815 suitable for passing as function arguments */
sewardjcd2b0252011-05-09 20:35:41 +00004816#define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
sewardj2019a972011-03-07 16:04:07 +00004817
4818/*---------------------------------------------------------------*/
4819/*--- Helper functions ---*/
4820/*---------------------------------------------------------------*/
4821
4822static __inline__ Bool
4823uint_fits_signed_16bit(UInt val)
4824{
florianffbd84d2012-12-09 02:06:29 +00004825 Int v = val & 0xFFFFu;
sewardj2019a972011-03-07 16:04:07 +00004826
4827 /* sign extend */
4828 v = (v << 16) >> 16;
4829
4830 return val == (UInt)v;
4831}
4832
4833
4834static __inline__ Bool
4835ulong_fits_signed_16bit(ULong val)
4836{
4837 Long v = val & 0xFFFFu;
4838
4839 /* sign extend */
4840 v = (v << 48) >> 48;
4841
4842 return val == (ULong)v;
4843}
4844
4845
4846static __inline__ Bool
4847ulong_fits_signed_32bit(ULong val)
4848{
4849 Long v = val & 0xFFFFFFFFu;
4850
4851 /* sign extend */
4852 v = (v << 32) >> 32;
4853
4854 return val == (ULong)v;
4855}
4856
4857
4858static __inline__ Bool
4859ulong_fits_unsigned_32bit(ULong val)
4860{
4861 return (val & 0xFFFFFFFFu) == val;
4862}
4863
4864
4865/* Load a 64-bit immediate VAL into register REG. */
4866static UChar *
4867s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
4868{
4869 if (ulong_fits_signed_16bit(val)) {
4870 return s390_emit_LGHI(p, reg, val);
4871 }
4872
4873 if (s390_host_has_eimm) {
4874 if (ulong_fits_unsigned_32bit(val)) {
4875 return s390_emit_LLILF(p, reg, val);
4876 }
4877 if (ulong_fits_signed_32bit(val)) {
4878 /* LGFI's sign extension will recreate the correct 64-bit value */
4879 return s390_emit_LGFI(p, reg, val);
4880 }
4881 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
4882 p = s390_emit_IIHF(p, reg, val >> 32);
4883 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
4884 }
4885
4886 /* Fall back */
4887 if (ulong_fits_unsigned_32bit(val)) {
4888 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
4889 val[0:31] = 0 */
4890 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
4891 return p;
4892 }
4893
4894 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
4895 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
4896 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4897 p = s390_emit_IILL(p, reg, val & 0xFFFF);
4898
4899 return p;
4900}
4901
4902/* Load a 32-bit immediate VAL into register REG. */
4903static UChar *
4904s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
4905{
4906 if (uint_fits_signed_16bit(val)) {
4907 /* LHI's sign extension will recreate the correct 32-bit value */
4908 return s390_emit_LHI(p, reg, val);
4909 }
4910 if (s390_host_has_eimm) {
4911 return s390_emit_IILF(p, reg, val);
4912 }
4913 /* val[0:15] --> (val >> 16) & 0xFFFF
4914 val[16:31] --> val & 0xFFFF */
4915 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4916 return s390_emit_IILL(p, reg, val & 0xFFFF);
4917}
4918
4919/*------------------------------------------------------------*/
4920/*--- Wrapper functions ---*/
4921/*------------------------------------------------------------*/
4922
sewardjeae8db52011-03-24 09:01:50 +00004923/* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
sewardj2019a972011-03-07 16:04:07 +00004924static UChar *
4925s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4926{
4927 if (s390_host_has_gie) {
4928 return s390_emit_MFY(p, r1, x, b, dl, dh);
4929 }
4930
4931 /* Load from memory into R0, then MULTIPLY with R1 */
4932 p = s390_emit_LY(p, R0, x, b, dl, dh);
4933 return s390_emit_MR(p, r1, R0);
4934}
4935
sewardjeae8db52011-03-24 09:01:50 +00004936/* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
4937static UChar *
4938s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4939{
4940 if (s390_host_has_gie) {
4941 return s390_emit_MHY(p, r1, x, b, dl, dh);
4942 }
4943
4944 /* Load from memory into R0, then MULTIPLY with R1 */
4945 p = s390_emit_LHY(p, R0, x, b, dl, dh);
4946 return s390_emit_MSR(p, r1, R0);
4947}
4948
sewardj2019a972011-03-07 16:04:07 +00004949/* r1[32:63] = r1[32:63] * i2 */
4950static UChar *
4951s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
4952{
4953 if (s390_host_has_gie) {
4954 return s390_emit_MSFI(p, r1, i2);
4955 }
4956
4957 /* Load I2 into R0; then MULTIPLY R0 with R1 */
4958 p = s390_emit_load_32imm(p, R0, i2);
4959 return s390_emit_MSR(p, r1, R0);
4960}
4961
4962
4963/* r1[32:63] = r1[32:63] & i2 */
4964static UChar *
4965s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
4966{
4967 if (s390_host_has_eimm) {
4968 return s390_emit_NILF(p, r1, i2);
4969 }
4970
4971 /* Load I2 into R0; then AND R0 with R1 */
4972 p = s390_emit_load_32imm(p, R0, i2);
4973 return s390_emit_NR(p, r1, R0);
4974}
4975
4976
4977/* r1[32:63] = r1[32:63] | i2 */
4978static UChar *
4979s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
4980{
4981 if (s390_host_has_eimm) {
4982 return s390_emit_OILF(p, r1, i2);
4983 }
4984
4985 /* Load I2 into R0; then AND R0 with R1 */
4986 p = s390_emit_load_32imm(p, R0, i2);
4987 return s390_emit_OR(p, r1, R0);
4988}
4989
4990
4991/* r1[32:63] = r1[32:63] ^ i2 */
4992static UChar *
4993s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
4994{
4995 if (s390_host_has_eimm) {
4996 return s390_emit_XILF(p, r1, i2);
4997 }
4998
4999 /* Load I2 into R0; then AND R0 with R1 */
5000 p = s390_emit_load_32imm(p, R0, i2);
5001 return s390_emit_XR(p, r1, R0);
5002}
5003
5004
sewardj652b56a2011-04-13 15:38:17 +00005005/* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
5006static UChar *
5007s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
5008{
5009 vassert(s390_host_has_ldisp || dh2 == 0);
5010
5011 if (s390_host_has_ldisp) {
5012 return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
5013 }
5014
5015 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
5016 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
5017 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
5018}
5019
5020
sewardj2019a972011-03-07 16:04:07 +00005021/* r1[32:63] = sign_extend(r2[56:63]) */
5022static UChar *
5023s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
5024{
5025 if (s390_host_has_eimm) {
5026 return s390_emit_LBR(p, r1, r2);
5027 }
5028
5029 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00005030 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
5031 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
sewardj2019a972011-03-07 16:04:07 +00005032}
5033
5034
sewardj652b56a2011-04-13 15:38:17 +00005035/* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
5036static UChar *
5037s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
5038{
5039 vassert(s390_host_has_ldisp || dh2 == 0);
5040
5041 if (s390_host_has_ldisp) {
5042 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
5043 }
5044
5045 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
5046 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
5047 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
5048}
5049
5050
sewardj2019a972011-03-07 16:04:07 +00005051/* r1[0:63] = sign_extend(r2[56:63]) */
5052static UChar *
5053s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
5054{
5055 if (s390_host_has_eimm) {
5056 return s390_emit_LGBR(p, r1, r2);
5057 }
5058
5059 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5060 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
5061 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
5062}
5063
5064
5065/* r1[32:63] = sign_extend(r2[48:63]) */
5066static UChar *
5067s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
5068{
5069 if (s390_host_has_eimm) {
5070 return s390_emit_LHR(p, r1, r2);
5071 }
5072
5073 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00005074 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
5075 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
sewardj2019a972011-03-07 16:04:07 +00005076}
5077
5078
5079/* r1[0:63] = sign_extend(r2[48:63]) */
5080static UChar *
5081s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
5082{
5083 if (s390_host_has_eimm) {
5084 return s390_emit_LGHR(p, r1, r2);
5085 }
5086
5087 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5088 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
5089 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
5090}
5091
5092
5093/* r1[0:63] = sign_extend(i2) */
5094static UChar *
5095s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
5096{
5097 if (s390_host_has_eimm) {
5098 return s390_emit_LGFI(p, r1, i2);
5099 }
5100
5101 p = s390_emit_load_32imm(p, R0, i2);
5102 return s390_emit_LGFR(p, r1, R0);
5103}
5104
5105
5106/* r1[32:63] = zero_extend($r2[56:63]) */
5107static UChar *
5108s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
5109{
5110 if (s390_host_has_eimm) {
5111 return s390_emit_LLCR(p, r1, r2);
5112 }
5113
5114 p = s390_emit_LR(p, r1, r2);
5115 p = s390_emit_LHI(p, R0, 0xFF);
5116 return s390_emit_NR(p, r1, R0);
5117}
5118
5119
5120/* r1[0:63] = zero_extend($r2[56:63]) */
5121static UChar *
5122s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
5123{
5124 if (s390_host_has_eimm) {
5125 return s390_emit_LLGCR(p, r1, r2);
5126 }
5127
5128 p = s390_emit_LR(p, r1, r2);
5129 p = s390_emit_LLILL(p, R0, 0xFF);
5130 return s390_emit_NGR(p, r1, R0);
5131}
5132
5133
5134/* r1[32:63] = zero_extend(r2[48:63]) */
5135static UChar *
5136s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
5137{
5138 if (s390_host_has_eimm) {
5139 return s390_emit_LLHR(p, r1, r2);
5140 }
5141
5142 p = s390_emit_LR(p, r1, r2);
5143 p = s390_emit_LLILL(p, R0, 0xFFFF);
5144 return s390_emit_NR(p, r1, R0);
5145}
5146
5147
5148/* r1[0:63] = zero_extend(r2[48:63]) */
5149static UChar *
5150s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
5151{
5152 if (s390_host_has_eimm) {
5153 return s390_emit_LLGHR(p, r1, r2);
5154 }
5155
5156 p = s390_emit_LR(p, r1, r2);
5157 p = s390_emit_LLILL(p, R0, 0xFFFF);
5158 return s390_emit_NGR(p, r1, R0);
5159}
5160
5161
5162/* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
5163static UChar *
5164s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5165{
5166 if (s390_host_has_eimm) {
5167 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
5168 }
5169
5170 if (dh == 0) {
5171 p = s390_emit_IC(p, r1, x2, b2, dl);
5172 } else {
5173 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
5174 }
5175 p = s390_emit_LLILL(p, R0, 0xFF);
5176 return s390_emit_NR(p, r1, R0);
5177}
5178
5179
5180/* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
5181static UChar *
5182s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5183{
5184 if (s390_host_has_eimm) {
5185 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
5186 }
5187
5188 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
5189 p = s390_emit_LLILL(p, R0, 0xFFFF);
5190 return s390_emit_NR(p, r1, R0);
5191}
5192
5193
5194/* r1[0:63] = zero_extend(i2) */
5195static UChar *
5196s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
5197{
5198 if (s390_host_has_eimm) {
5199 return s390_emit_LLILF(p, r1, i2);
5200 }
5201
5202 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
5203 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
5204}
5205
5206
5207/* r1[32:63] = r1[32:63] + i2 */
5208static UChar *
5209s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
5210{
5211 if (s390_host_has_eimm) {
5212 return s390_emit_AFI(p, r1, i2);
5213 }
5214 /* Load 32 bit immediate to R0 then add */
5215 p = s390_emit_load_32imm(p, R0, i2);
5216 return s390_emit_AR(p, r1, R0);
5217}
5218
5219
5220/* r1[32:63] = r1[32:63] - i2 */
5221static UChar *
5222s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
5223{
5224 if (s390_host_has_eimm) {
5225 return s390_emit_SLFI(p, r1, i2);
5226 }
5227
5228 /* Load 32 bit immediate to R0 then subtract */
5229 p = s390_emit_load_32imm(p, R0, i2);
5230 return s390_emit_SR(p, r1, R0);
5231}
5232
5233
sewardjb13a92a2011-04-13 14:44:29 +00005234/* r1[0:63] = r1[0:63] - zero_extend(i2) */
5235static UChar *
5236s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
5237{
5238 if (s390_host_has_eimm) {
5239 return s390_emit_SLGFI(p, r1, i2);
5240 }
5241
5242 /* Load zero-extended 32 bit immediate to R0 then subtract */
5243 p = s390_emit_load_64imm(p, R0, i2);
5244 return s390_emit_SGR(p, r1, R0);
5245}
5246
5247
sewardj2019a972011-03-07 16:04:07 +00005248static UChar *
5249s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5250{
5251 if (s390_host_has_eimm) {
5252 return s390_emit_LT(p, r1, x2, b2, dl, dh);
5253 }
5254 /* Load 32 bit from memory to R0 then compare */
5255 if (dh == 0) {
5256 p = s390_emit_L(p, R0, x2, b2, dl);
5257 } else {
5258 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
5259 }
5260 return s390_emit_LTR(p, r1, R0);
5261}
5262
5263
5264static UChar *
5265s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5266{
5267 if (s390_host_has_eimm) {
5268 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
5269 }
5270 /* Load 64 bit from memory to R0 then compare */
5271 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
5272 return s390_emit_LTGR(p, r1, R0);
5273}
5274
5275
5276static UChar *
5277s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
5278{
5279 if (s390_host_has_eimm) {
5280 return s390_emit_CFI(p, r1, i2);
5281 }
5282 /* Load 32 bit immediate to R0 then compare */
5283 p = s390_emit_load_32imm(p, R0, i2);
5284 return s390_emit_CR(p, r1, R0);
5285}
5286
5287
5288static UChar *
5289s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
5290{
5291 if (s390_host_has_eimm) {
5292 return s390_emit_CLFI(p, r1, i2);
5293 }
5294 /* Load 32 bit immediate to R0 then compare */
5295 p = s390_emit_load_32imm(p, R0, i2);
5296 return s390_emit_CLR(p, r1, R0);
5297}
5298
sewardjd07b8562011-04-27 11:58:22 +00005299
5300static UChar *
5301s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
5302{
5303 if (s390_host_has_fgx) {
5304 return s390_emit_LGDR(p, r1, r2);
5305 }
5306
5307 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
5308 smaller addresses and is 8-byte aligned. Then load the GPR from that
5309 memory location/ */
5310 if (s390_host_has_ldisp) {
5311 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5312 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5313 }
5314
5315 /* No long displacement. Need to adjust SP explicitly as to avoid negative
5316 displacements. */
5317 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
5318 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
5319 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
5320 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
5321}
5322
5323
5324static UChar *
5325s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
5326{
5327 if (s390_host_has_fgx) {
5328 return s390_emit_LDGR(p, r1, r2);
5329 }
5330
5331 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
5332 smaller addresses and is 8-byte aligned. Then load the FPR from that
5333 memory location/ */
5334 if (s390_host_has_ldisp) {
5335 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5336 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5337 }
5338
5339 /* No long displacement. Need to adjust SP explicitly as to avoid negative
5340 displacements. */
5341 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
5342 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
5343 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
5344 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
5345}
5346
5347
sewardj2019a972011-03-07 16:04:07 +00005348/*---------------------------------------------------------------*/
5349/*--- Constructors for the various s390_insn kinds ---*/
5350/*---------------------------------------------------------------*/
5351
5352s390_insn *
5353s390_insn_load(UChar size, HReg dst, s390_amode *src)
5354{
5355 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5356
5357 insn->tag = S390_INSN_LOAD;
5358 insn->size = size;
5359 insn->variant.load.src = src;
5360 insn->variant.load.dst = dst;
5361
5362 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5363
5364 return insn;
5365}
5366
5367
5368s390_insn *
5369s390_insn_store(UChar size, s390_amode *dst, HReg src)
5370{
5371 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5372
5373 insn->tag = S390_INSN_STORE;
5374 insn->size = size;
5375 insn->variant.store.src = src;
5376 insn->variant.store.dst = dst;
5377
5378 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5379
5380 return insn;
5381}
5382
5383
5384s390_insn *
5385s390_insn_move(UChar size, HReg dst, HReg src)
5386{
5387 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5388
5389 insn->tag = S390_INSN_MOVE;
5390 insn->size = size;
5391 insn->variant.move.src = src;
5392 insn->variant.move.dst = dst;
5393
5394 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5395
5396 return insn;
5397}
5398
5399
5400s390_insn *
floriancec3a8a2013-02-02 00:16:58 +00005401s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src)
5402{
5403 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5404
5405 /* This insn will be mapped to MVC which requires base register
5406 plus 12-bit displacement */
5407 vassert(src->tag == S390_AMODE_B12);
5408 vassert(dst->tag == S390_AMODE_B12);
5409
5410 insn->tag = S390_INSN_MEMCPY;
5411 insn->size = size;
5412 insn->variant.memcpy.src = src;
5413 insn->variant.memcpy.dst = dst;
5414
5415 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5416
5417 return insn;
5418}
5419
5420
5421s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005422s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
5423{
5424 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5425
5426 insn->tag = S390_INSN_COND_MOVE;
5427 insn->size = size;
5428 insn->variant.cond_move.cond = cond;
5429 insn->variant.cond_move.src = src;
5430 insn->variant.cond_move.dst = dst;
5431
5432 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5433
5434 return insn;
5435}
5436
5437
5438s390_insn *
5439s390_insn_load_immediate(UChar size, HReg dst, ULong value)
5440{
5441 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5442
5443 insn->tag = S390_INSN_LOAD_IMMEDIATE;
5444 insn->size = size;
5445 insn->variant.load_immediate.dst = dst;
5446 insn->variant.load_immediate.value = value;
5447
5448 return insn;
5449}
5450
5451
5452s390_insn *
5453s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
5454{
5455 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5456
5457 insn->tag = S390_INSN_ALU;
5458 insn->size = size;
5459 insn->variant.alu.tag = tag;
5460 insn->variant.alu.dst = dst;
5461 insn->variant.alu.op2 = op2;
5462
5463 return insn;
5464}
5465
5466
5467s390_insn *
5468s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
5469 Bool signed_multiply)
5470{
5471 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5472
5473 vassert(! hregIsVirtual(dst_hi));
5474 vassert(! hregIsVirtual(dst_lo));
5475
florianc4aa7ed2012-12-22 15:01:04 +00005476 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
sewardj2019a972011-03-07 16:04:07 +00005477 insn->size = size;
5478 insn->variant.mul.dst_hi = dst_hi;
5479 insn->variant.mul.dst_lo = dst_lo;
5480 insn->variant.mul.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00005481
5482 return insn;
5483}
5484
5485
5486s390_insn *
5487s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
5488 Bool signed_divide)
5489{
5490 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5491
5492 vassert(size == 4 || size == 8);
5493 vassert(! hregIsVirtual(op1_hi));
5494 vassert(! hregIsVirtual(op1_lo));
5495
florianc4aa7ed2012-12-22 15:01:04 +00005496 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
sewardj2019a972011-03-07 16:04:07 +00005497 insn->size = size;
5498 insn->variant.div.op1_hi = op1_hi;
5499 insn->variant.div.op1_lo = op1_lo;
5500 insn->variant.div.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00005501
5502 return insn;
5503}
5504
5505
5506s390_insn *
5507s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
5508{
5509 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5510
5511 vassert(size == 8);
5512 vassert(! hregIsVirtual(op1));
5513 vassert(! hregIsVirtual(rem));
5514
5515 insn->tag = S390_INSN_DIVS;
5516 insn->size = size;
5517 insn->variant.divs.rem = rem; /* remainder */
5518 insn->variant.divs.op1 = op1; /* also quotient */
5519 insn->variant.divs.op2 = op2;
5520
5521 return insn;
5522}
5523
5524
5525s390_insn *
sewardj611b06e2011-03-24 08:57:29 +00005526s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
sewardj2019a972011-03-07 16:04:07 +00005527{
5528 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5529
5530 vassert(size == 8);
sewardj611b06e2011-03-24 08:57:29 +00005531 vassert(! hregIsVirtual(num_bits));
5532 vassert(! hregIsVirtual(clobber));
sewardj2019a972011-03-07 16:04:07 +00005533
sewardj611b06e2011-03-24 08:57:29 +00005534 insn->tag = S390_INSN_CLZ;
sewardj2019a972011-03-07 16:04:07 +00005535 insn->size = size;
sewardj611b06e2011-03-24 08:57:29 +00005536 insn->variant.clz.num_bits = num_bits;
5537 insn->variant.clz.clobber = clobber;
5538 insn->variant.clz.src = src;
sewardj2019a972011-03-07 16:04:07 +00005539
5540 return insn;
5541}
5542
5543
5544s390_insn *
5545s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
5546{
5547 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5548
5549 insn->tag = S390_INSN_UNOP;
5550 insn->size = size;
5551 insn->variant.unop.tag = tag;
5552 insn->variant.unop.dst = dst;
5553 insn->variant.unop.src = opnd;
5554
5555 return insn;
5556}
5557
5558
5559s390_insn *
5560s390_insn_test(UChar size, s390_opnd_RMI src)
5561{
5562 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5563
5564 vassert(size == 4 || size == 8);
5565
5566 insn->tag = S390_INSN_TEST;
5567 insn->size = size;
5568 insn->variant.test.src = src;
5569
5570 return insn;
5571}
5572
5573
5574s390_insn *
5575s390_insn_cc2bool(HReg dst, s390_cc_t cond)
5576{
5577 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5578
5579 insn->tag = S390_INSN_CC2BOOL;
5580 insn->size = 0; /* does not matter */
5581 insn->variant.cc2bool.cond = cond;
5582 insn->variant.cc2bool.dst = dst;
5583
5584 return insn;
5585}
5586
5587
5588s390_insn *
5589s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
5590{
5591 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5592
5593 vassert(size == 4 || size == 8);
florian3123f722013-01-24 15:55:52 +00005594 vassert(hregNumber(op2->x) == 0);
florian406ac942014-11-22 20:10:21 +00005595 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
sewardj2019a972011-03-07 16:04:07 +00005596
5597 insn->tag = S390_INSN_CAS;
5598 insn->size = size;
5599 insn->variant.cas.op1 = op1;
5600 insn->variant.cas.op2 = op2;
5601 insn->variant.cas.op3 = op3;
5602 insn->variant.cas.old_mem = old_mem;
5603
5604 return insn;
5605}
5606
5607
5608s390_insn *
florian448cbba2012-06-06 02:26:01 +00005609s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
5610 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
5611 HReg scratch)
5612{
5613 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005614 s390_cdas *cdas = LibVEX_Alloc(sizeof(s390_cdas));
florian448cbba2012-06-06 02:26:01 +00005615
5616 vassert(size == 4 || size == 8);
florian3123f722013-01-24 15:55:52 +00005617 vassert(hregNumber(op2->x) == 0);
florian448cbba2012-06-06 02:26:01 +00005618 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
florian406ac942014-11-22 20:10:21 +00005619 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
florian448cbba2012-06-06 02:26:01 +00005620
5621 insn->tag = S390_INSN_CDAS;
5622 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005623 insn->variant.cdas.details = cdas;
5624
5625 cdas->op1_high = op1_high;
5626 cdas->op1_low = op1_low;
5627 cdas->op2 = op2;
5628 cdas->op3_high = op3_high;
5629 cdas->op3_low = op3_low;
5630 cdas->old_mem_high = old_mem_high;
5631 cdas->old_mem_low = old_mem_low;
5632 cdas->scratch = scratch;
florian448cbba2012-06-06 02:26:01 +00005633
5634 return insn;
5635}
5636
5637
5638s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005639s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
5640 Bool signed_comparison)
5641{
5642 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5643
5644 vassert(size == 4 || size == 8);
5645
5646 insn->tag = S390_INSN_COMPARE;
5647 insn->size = size;
5648 insn->variant.compare.src1 = src1;
5649 insn->variant.compare.src2 = src2;
5650 insn->variant.compare.signed_comparison = signed_comparison;
5651
5652 return insn;
5653}
5654
5655
5656s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005657s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
sewardj74142b82013-08-08 10:28:59 +00005658 const HChar *name, RetLoc rloc)
sewardj2019a972011-03-07 16:04:07 +00005659{
5660 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
sewardj74142b82013-08-08 10:28:59 +00005661 s390_helper_call *helper_call = LibVEX_Alloc(sizeof(s390_helper_call));
sewardj2019a972011-03-07 16:04:07 +00005662
5663 insn->tag = S390_INSN_HELPER_CALL;
5664 insn->size = 0; /* does not matter */
sewardj74142b82013-08-08 10:28:59 +00005665 insn->variant.helper_call.details = helper_call;
5666
5667 helper_call->cond = cond;
5668 helper_call->target = target;
5669 helper_call->num_args = num_args;
5670 helper_call->name = name;
5671 helper_call->rloc = rloc;
5672
5673 vassert(is_sane_RetLoc(rloc));
sewardj2019a972011-03-07 16:04:07 +00005674
5675 return insn;
5676}
5677
5678
5679s390_insn *
5680s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
florian2c74d242012-09-12 19:38:42 +00005681 HReg op3)
sewardj2019a972011-03-07 16:04:07 +00005682{
5683 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5684
floriancc491a62012-09-10 23:44:37 +00005685 vassert(size == 4 || size == 8);
5686
sewardj2019a972011-03-07 16:04:07 +00005687 insn->tag = S390_INSN_BFP_TRIOP;
5688 insn->size = size;
5689 insn->variant.bfp_triop.tag = tag;
5690 insn->variant.bfp_triop.dst = dst;
5691 insn->variant.bfp_triop.op2 = op2;
5692 insn->variant.bfp_triop.op3 = op3;
sewardj2019a972011-03-07 16:04:07 +00005693
5694 return insn;
5695}
5696
5697
5698s390_insn *
florian2c74d242012-09-12 19:38:42 +00005699s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
sewardj2019a972011-03-07 16:04:07 +00005700{
5701 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5702
floriancc491a62012-09-10 23:44:37 +00005703 vassert(size == 4 || size == 8);
5704
sewardj2019a972011-03-07 16:04:07 +00005705 insn->tag = S390_INSN_BFP_BINOP;
5706 insn->size = size;
5707 insn->variant.bfp_binop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005708 insn->variant.bfp_binop.dst_hi = dst;
5709 insn->variant.bfp_binop.op2_hi = op2;
5710 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
5711 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005712
5713 return insn;
5714}
5715
5716
5717s390_insn *
florian2c74d242012-09-12 19:38:42 +00005718s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
sewardj2019a972011-03-07 16:04:07 +00005719{
5720 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5721
floriancc491a62012-09-10 23:44:37 +00005722 vassert(size == 4 || size == 8);
5723
sewardj2019a972011-03-07 16:04:07 +00005724 insn->tag = S390_INSN_BFP_UNOP;
5725 insn->size = size;
5726 insn->variant.bfp_unop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005727 insn->variant.bfp_unop.dst_hi = dst;
5728 insn->variant.bfp_unop.op_hi = op;
5729 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
5730 insn->variant.bfp_unop.op_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005731
5732 return insn;
5733}
5734
5735
5736s390_insn *
5737s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
5738{
5739 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5740
5741 vassert(size == 4 || size == 8);
5742
5743 insn->tag = S390_INSN_BFP_COMPARE;
5744 insn->size = size;
5745 insn->variant.bfp_compare.dst = dst;
floriancc491a62012-09-10 23:44:37 +00005746 insn->variant.bfp_compare.op1_hi = op1;
5747 insn->variant.bfp_compare.op2_hi = op2;
5748 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
5749 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005750
5751 return insn;
5752}
5753
5754
5755s390_insn *
florian6dc90242012-12-21 21:43:00 +00005756s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
florian125e20d2012-10-07 15:42:37 +00005757 s390_bfp_round_t rounding_mode)
florian9fcff4c2012-09-10 03:09:04 +00005758{
5759 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5760
floriancc491a62012-09-10 23:44:37 +00005761 vassert(size == 4 || size == 8);
5762
florian9fcff4c2012-09-10 03:09:04 +00005763 insn->tag = S390_INSN_BFP_CONVERT;
5764 insn->size = size;
5765 insn->variant.bfp_convert.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005766 insn->variant.bfp_convert.dst_hi = dst;
5767 insn->variant.bfp_convert.op_hi = op;
5768 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
5769 insn->variant.bfp_convert.op_lo = INVALID_HREG;
florian9fcff4c2012-09-10 03:09:04 +00005770 insn->variant.bfp_convert.rounding_mode = rounding_mode;
5771
5772 return insn;
5773}
5774
5775
floriane38f6412012-12-21 17:32:12 +00005776/* Check validity of a register pair for 128-bit FP. Valid register
floriancc491a62012-09-10 23:44:37 +00005777 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
5778 and (13, 15). */
5779static Bool
floriane38f6412012-12-21 17:32:12 +00005780is_valid_fp128_regpair(HReg hi, HReg lo)
floriancc491a62012-09-10 23:44:37 +00005781{
5782 UInt hi_regno = hregNumber(hi);
5783 UInt lo_regno = hregNumber(lo);
5784
5785 if (lo_regno != hi_regno + 2) return False;
5786 if ((hi_regno & 0x2) != 0) return False;
5787
5788 return True;
5789}
5790
florian9fcff4c2012-09-10 03:09:04 +00005791s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005792s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005793 HReg dst_lo, HReg op2_hi, HReg op2_lo)
sewardj2019a972011-03-07 16:04:07 +00005794{
5795 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5796
floriancc491a62012-09-10 23:44:37 +00005797 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005798 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5799 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005800
5801 insn->tag = S390_INSN_BFP_BINOP;
sewardj2019a972011-03-07 16:04:07 +00005802 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005803 insn->variant.bfp_binop.tag = tag;
5804 insn->variant.bfp_binop.dst_hi = dst_hi;
5805 insn->variant.bfp_binop.dst_lo = dst_lo;
5806 insn->variant.bfp_binop.op2_hi = op2_hi;
5807 insn->variant.bfp_binop.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005808
5809 return insn;
5810}
5811
5812
5813s390_insn *
sewardja970c402011-04-28 18:38:42 +00005814s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005815 HReg dst_lo, HReg op_hi, HReg op_lo)
sewardj2019a972011-03-07 16:04:07 +00005816{
5817 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5818
floriancc491a62012-09-10 23:44:37 +00005819 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005820 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5821 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005822
5823 insn->tag = S390_INSN_BFP_UNOP;
sewardj2019a972011-03-07 16:04:07 +00005824 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005825 insn->variant.bfp_unop.tag = tag;
5826 insn->variant.bfp_unop.dst_hi = dst_hi;
5827 insn->variant.bfp_unop.dst_lo = dst_lo;
5828 insn->variant.bfp_unop.op_hi = op_hi;
5829 insn->variant.bfp_unop.op_lo = op_lo;
sewardj2019a972011-03-07 16:04:07 +00005830
5831 return insn;
5832}
5833
5834
5835s390_insn *
5836s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
5837 HReg op2_hi, HReg op2_lo)
5838{
5839 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5840
floriancc491a62012-09-10 23:44:37 +00005841 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005842 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
5843 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005844
5845 insn->tag = S390_INSN_BFP_COMPARE;
sewardj2019a972011-03-07 16:04:07 +00005846 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005847 insn->variant.bfp_compare.dst = dst;
5848 insn->variant.bfp_compare.op1_hi = op1_hi;
5849 insn->variant.bfp_compare.op1_lo = op1_lo;
5850 insn->variant.bfp_compare.op2_hi = op2_hi;
5851 insn->variant.bfp_compare.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005852
5853 return insn;
5854}
5855
5856
florian9fcff4c2012-09-10 03:09:04 +00005857static s390_insn *
florian6dc90242012-12-21 21:43:00 +00005858s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005859 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005860 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005861{
5862 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5863
floriancc491a62012-09-10 23:44:37 +00005864 if (size == 16) {
5865 /* From smaller size to 16 bytes */
floriane38f6412012-12-21 17:32:12 +00005866 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
florian79efdc62013-02-11 00:47:35 +00005867 vassert(hregIsInvalid(op_lo));
floriancc491a62012-09-10 23:44:37 +00005868 } else {
5869 /* From 16 bytes to smaller size */
floriane38f6412012-12-21 17:32:12 +00005870 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005871 }
5872
5873 insn->tag = S390_INSN_BFP_CONVERT;
sewardj2019a972011-03-07 16:04:07 +00005874 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005875 insn->variant.bfp_convert.tag = tag;
5876 insn->variant.bfp_convert.dst_hi = dst_hi;
5877 insn->variant.bfp_convert.dst_lo = dst_lo;
5878 insn->variant.bfp_convert.op_hi = op_hi;
5879 insn->variant.bfp_convert.op_lo = op_lo;
5880 insn->variant.bfp_convert.rounding_mode = rounding_mode;
sewardj2019a972011-03-07 16:04:07 +00005881
5882 return insn;
5883}
5884
5885
5886s390_insn *
florian6dc90242012-12-21 21:43:00 +00005887s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005888 HReg dst_lo, HReg op)
5889{
5890 /* Conversion to bfp128 never requires a rounding mode. Provide default
5891 rounding mode. It will not be used when emitting insns. */
florian125e20d2012-10-07 15:42:37 +00005892 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
florian9fcff4c2012-09-10 03:09:04 +00005893
5894 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
5895 INVALID_HREG, rounding_mode);
5896}
5897
5898
5899s390_insn *
floriana2039c52013-12-10 16:51:15 +00005900s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
5901 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005902 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005903{
floriana2039c52013-12-10 16:51:15 +00005904 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
florian9fcff4c2012-09-10 03:09:04 +00005905 rounding_mode);
sewardj2019a972011-03-07 16:04:07 +00005906}
5907
5908
sewardja52e37e2011-04-28 18:48:06 +00005909s390_insn *
florian12390202012-11-10 22:34:14 +00005910s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
5911 HReg op3, s390_dfp_round_t rounding_mode)
5912{
5913 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005914 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop));
florian12390202012-11-10 22:34:14 +00005915
5916 vassert(size == 8);
5917
5918 insn->tag = S390_INSN_DFP_BINOP;
5919 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005920 insn->variant.dfp_binop.details = dfp_binop;
5921
5922 dfp_binop->tag = tag;
5923 dfp_binop->dst_hi = dst;
5924 dfp_binop->op2_hi = op2;
5925 dfp_binop->op3_hi = op3;
5926 dfp_binop->dst_lo = INVALID_HREG;
5927 dfp_binop->op2_lo = INVALID_HREG;
5928 dfp_binop->op3_lo = INVALID_HREG;
5929 dfp_binop->rounding_mode = rounding_mode;
florian12390202012-11-10 22:34:14 +00005930
5931 return insn;
5932}
5933
5934
5935s390_insn *
floriance9e3db2012-12-27 20:14:03 +00005936s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
5937{
5938 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5939
5940 vassert(size == 8);
5941
5942 insn->tag = S390_INSN_DFP_UNOP;
5943 insn->size = size;
5944 insn->variant.dfp_unop.tag = tag;
5945 insn->variant.dfp_unop.dst_hi = dst;
5946 insn->variant.dfp_unop.op_hi = op;
5947 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
5948 insn->variant.dfp_unop.op_lo = INVALID_HREG;
5949
5950 return insn;
5951}
5952
5953
5954s390_insn *
florian1b901d42013-01-01 22:19:24 +00005955s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2,
5956 HReg op3)
5957{
5958 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5959
5960 vassert(size == 8);
5961
5962 insn->tag = S390_INSN_DFP_INTOP;
5963 insn->size = size;
5964 insn->variant.dfp_intop.tag = tag;
5965 insn->variant.dfp_intop.dst_hi = dst;
5966 insn->variant.dfp_intop.op2 = op2;
5967 insn->variant.dfp_intop.op3_hi = op3;
5968 insn->variant.dfp_intop.dst_lo = INVALID_HREG;
5969 insn->variant.dfp_intop.op3_lo = INVALID_HREG;
5970
5971 return insn;
5972}
5973
5974
5975s390_insn *
florian20c6bca2012-12-26 17:47:19 +00005976s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
5977 HReg op1, HReg op2)
floriane38f6412012-12-21 17:32:12 +00005978{
5979 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5980
5981 vassert(size == 8);
5982
5983 insn->tag = S390_INSN_DFP_COMPARE;
5984 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00005985 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00005986 insn->variant.dfp_compare.dst = dst;
5987 insn->variant.dfp_compare.op1_hi = op1;
5988 insn->variant.dfp_compare.op2_hi = op2;
5989 insn->variant.dfp_compare.op1_lo = INVALID_HREG;
5990 insn->variant.dfp_compare.op2_lo = INVALID_HREG;
5991
5992 return insn;
5993}
5994
5995
5996s390_insn *
5997s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
5998 s390_dfp_round_t rounding_mode)
5999{
6000 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6001
florian06dfe212012-12-22 02:09:40 +00006002 vassert(size == 4 || size == 8);
floriane38f6412012-12-21 17:32:12 +00006003
6004 insn->tag = S390_INSN_DFP_CONVERT;
6005 insn->size = size;
6006 insn->variant.dfp_convert.tag = tag;
6007 insn->variant.dfp_convert.dst_hi = dst;
6008 insn->variant.dfp_convert.op_hi = op;
6009 insn->variant.dfp_convert.dst_lo = INVALID_HREG;
6010 insn->variant.dfp_convert.op_lo = INVALID_HREG;
6011 insn->variant.dfp_convert.rounding_mode = rounding_mode;
6012
6013 return insn;
6014}
6015
6016
6017s390_insn *
florian5c539732013-02-14 14:27:12 +00006018s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3,
6019 s390_dfp_round_t rounding_mode)
6020{
6021 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6022
6023 vassert(size == 8);
6024
6025 insn->tag = S390_INSN_DFP_REROUND;
6026 insn->size = size;
6027 insn->variant.dfp_reround.dst_hi = dst;
6028 insn->variant.dfp_reround.op2 = op2;
6029 insn->variant.dfp_reround.op3_hi = op3;
6030 insn->variant.dfp_reround.dst_lo = INVALID_HREG;
6031 insn->variant.dfp_reround.op3_lo = INVALID_HREG;
6032 insn->variant.dfp_reround.rounding_mode = rounding_mode;
6033
6034 return insn;
6035}
6036
6037
6038s390_insn *
florian78d5ef72013-05-11 15:02:58 +00006039s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op,
6040 HReg r1, s390_dfp_round_t rounding_mode)
6041{
6042 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6043 s390_fp_convert *fp_convert = LibVEX_Alloc(sizeof(s390_fp_convert));
6044
6045 vassert(size == 4 || size == 8);
6046
6047 insn->tag = S390_INSN_FP_CONVERT;
6048 insn->size = size;
6049 insn->variant.fp_convert.details = fp_convert;
6050
6051 fp_convert->tag = tag;
6052 fp_convert->dst_hi = dst;
6053 fp_convert->op_hi = op;
6054 fp_convert->r1 = r1;
6055 fp_convert->dst_lo = INVALID_HREG;
6056 fp_convert->op_lo = INVALID_HREG;
6057 fp_convert->rounding_mode = rounding_mode;
6058
6059 return insn;
6060}
6061
6062
6063s390_insn *
6064s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi,
6065 HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1,
6066 s390_dfp_round_t rounding_mode)
6067{
6068 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6069 s390_fp_convert *fp_convert = LibVEX_Alloc(sizeof(s390_fp_convert));
6070
6071 vassert(size == 16);
6072
6073 insn->tag = S390_INSN_FP_CONVERT;
6074 insn->size = size;
6075 insn->variant.fp_convert.details = fp_convert;
6076
6077 fp_convert->tag = tag;
6078 fp_convert->dst_hi = dst_hi;
6079 fp_convert->dst_lo = dst_lo;
6080 fp_convert->op_hi = op_hi;
6081 fp_convert->r1 = r1;
6082 fp_convert->op_lo = op_lo;
6083 fp_convert->rounding_mode = rounding_mode;
6084
6085 return insn;
6086}
6087
6088
6089s390_insn *
floriane38f6412012-12-21 17:32:12 +00006090s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
6091 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
6092 HReg op3_lo, s390_dfp_round_t rounding_mode)
6093{
6094 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00006095 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop));
floriane38f6412012-12-21 17:32:12 +00006096
6097 vassert(size == 16);
6098 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6099 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6100 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6101
floriane38f6412012-12-21 17:32:12 +00006102 insn->tag = S390_INSN_DFP_BINOP;
6103 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00006104 insn->variant.dfp_binop.details = dfp_binop;
6105
6106 dfp_binop->tag = tag;
6107 dfp_binop->dst_hi = dst_hi;
6108 dfp_binop->dst_lo = dst_lo;
6109 dfp_binop->op2_hi = op2_hi;
6110 dfp_binop->op2_lo = op2_lo;
6111 dfp_binop->op3_hi = op3_hi;
6112 dfp_binop->op3_lo = op3_lo;
6113 dfp_binop->rounding_mode = rounding_mode;
floriane38f6412012-12-21 17:32:12 +00006114
6115 return insn;
6116}
6117
6118
6119s390_insn *
floriance9e3db2012-12-27 20:14:03 +00006120s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
6121 HReg op_hi, HReg op_lo)
6122{
6123 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6124
6125 /* destination is an 8 byte integer value */
6126 vassert(size == 8);
6127 vassert(is_valid_fp128_regpair(op_hi, op_lo));
6128
6129 insn->tag = S390_INSN_DFP_UNOP;
6130 insn->size = size;
6131 insn->variant.dfp_unop.tag = tag;
6132 insn->variant.dfp_unop.dst_hi = dst;
6133 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
6134 insn->variant.dfp_unop.op_hi = op_hi;
6135 insn->variant.dfp_unop.op_lo = op_lo;
6136
6137 return insn;
6138}
6139
6140
6141s390_insn *
florian1b901d42013-01-01 22:19:24 +00006142s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi,
6143 HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo)
6144{
6145 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6146
6147 vassert(size == 16);
6148 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6149 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6150
6151 insn->tag = S390_INSN_DFP_INTOP;
6152 insn->size = size;
6153 insn->variant.dfp_intop.tag = tag;
6154 insn->variant.dfp_intop.dst_hi = dst_hi;
6155 insn->variant.dfp_intop.dst_lo = dst_lo;
6156 insn->variant.dfp_intop.op2 = op2;
6157 insn->variant.dfp_intop.op3_hi = op3_hi;
6158 insn->variant.dfp_intop.op3_lo = op3_lo;
6159
6160 return insn;
6161}
6162
6163
6164s390_insn *
florian20c6bca2012-12-26 17:47:19 +00006165s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
6166 HReg op1_lo, HReg op2_hi, HReg op2_lo)
floriane38f6412012-12-21 17:32:12 +00006167{
6168 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6169
6170 vassert(size == 16);
6171 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
6172 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6173
6174 insn->tag = S390_INSN_DFP_COMPARE;
6175 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00006176 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00006177 insn->variant.dfp_compare.dst = dst;
6178 insn->variant.dfp_compare.op1_hi = op1_hi;
6179 insn->variant.dfp_compare.op1_lo = op1_lo;
6180 insn->variant.dfp_compare.op2_hi = op2_hi;
6181 insn->variant.dfp_compare.op2_lo = op2_lo;
6182
6183 return insn;
6184}
6185
6186
6187static s390_insn *
6188s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6189 HReg dst_lo, HReg op_hi, HReg op_lo,
6190 s390_dfp_round_t rounding_mode)
6191{
6192 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6193
6194 if (size == 16) {
6195 /* From smaller size to 16 bytes */
6196 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
florian79efdc62013-02-11 00:47:35 +00006197 vassert(hregIsInvalid(op_lo));
floriane38f6412012-12-21 17:32:12 +00006198 } else {
6199 /* From 16 bytes to smaller size */
6200 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriane38f6412012-12-21 17:32:12 +00006201 }
6202
6203 insn->tag = S390_INSN_DFP_CONVERT;
6204 insn->size = size;
6205 insn->variant.dfp_convert.tag = tag;
6206 insn->variant.dfp_convert.dst_hi = dst_hi;
6207 insn->variant.dfp_convert.dst_lo = dst_lo;
6208 insn->variant.dfp_convert.op_hi = op_hi;
6209 insn->variant.dfp_convert.op_lo = op_lo;
6210 insn->variant.dfp_convert.rounding_mode = rounding_mode;
6211
6212 return insn;
6213}
6214
6215
6216s390_insn *
6217s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6218 HReg dst_lo, HReg op)
6219{
6220 /* Conversion to dfp128 never requires a rounding mode. Provide default
6221 rounding mode. It will not be used when emitting insns. */
6222 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
6223
6224 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
6225 INVALID_HREG, rounding_mode);
6226}
6227
6228
6229s390_insn *
floriana2039c52013-12-10 16:51:15 +00006230s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6231 HReg dst_lo, HReg op_hi, HReg op_lo,
floriane38f6412012-12-21 17:32:12 +00006232 s390_dfp_round_t rounding_mode)
6233{
floriana2039c52013-12-10 16:51:15 +00006234 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
floriane38f6412012-12-21 17:32:12 +00006235 rounding_mode);
6236}
6237
6238
6239s390_insn *
florian5c539732013-02-14 14:27:12 +00006240s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2,
6241 HReg op3_hi, HReg op3_lo,
6242 s390_dfp_round_t rounding_mode)
6243{
6244 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6245
6246 vassert(size == 16);
6247 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6248 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6249
6250 insn->tag = S390_INSN_DFP_REROUND;
6251 insn->size = size;
6252 insn->variant.dfp_reround.dst_hi = dst_hi;
6253 insn->variant.dfp_reround.dst_lo = dst_lo;
6254 insn->variant.dfp_reround.op2 = op2;
6255 insn->variant.dfp_reround.op3_hi = op3_hi;
6256 insn->variant.dfp_reround.op3_lo = op3_lo;
6257 insn->variant.dfp_reround.rounding_mode = rounding_mode;
6258
6259 return insn;
6260}
6261
6262
6263s390_insn *
sewardja52e37e2011-04-28 18:48:06 +00006264s390_insn_mfence(void)
6265{
6266 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6267
6268 insn->tag = S390_INSN_MFENCE;
6269 insn->size = 0; /* not needed */
6270
6271 return insn;
6272}
6273
6274
florianad43b3a2012-02-20 15:01:14 +00006275s390_insn *
florianb93348d2012-12-27 00:59:43 +00006276s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
florianad43b3a2012-02-20 15:01:14 +00006277{
6278 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6279
florianb93348d2012-12-27 00:59:43 +00006280 /* This insn will be mapped to insns that require base register
florian09bbba82012-12-11 04:09:43 +00006281 plus 12-bit displacement */
6282 vassert(dst->tag == S390_AMODE_B12);
6283
florianb93348d2012-12-27 00:59:43 +00006284 insn->tag = S390_INSN_MIMM;
florianad43b3a2012-02-20 15:01:14 +00006285 insn->size = size;
florianb93348d2012-12-27 00:59:43 +00006286 insn->variant.mimm.dst = dst;
6287 insn->variant.mimm.value = value;
florianad43b3a2012-02-20 15:01:14 +00006288
6289 return insn;
6290}
6291
6292
6293s390_insn *
florianf85fe3e2012-12-22 02:28:25 +00006294s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
florianad43b3a2012-02-20 15:01:14 +00006295{
6296 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6297
florianf85fe3e2012-12-22 02:28:25 +00006298 vassert(size == 4 || size == 8);
6299
6300 /* This insn will be mapped to an ASI or AGSI so we can only allow base
6301 register plus 12-bit / 20-bit displacement. */
6302 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
6303
6304 insn->tag = S390_INSN_MADD;
florianad43b3a2012-02-20 15:01:14 +00006305 insn->size = size;
florianf85fe3e2012-12-22 02:28:25 +00006306 insn->variant.madd.dst = dst;
6307 insn->variant.madd.delta = delta;
6308 insn->variant.madd.value = value;
florianad43b3a2012-02-20 15:01:14 +00006309
6310 return insn;
6311}
6312
6313
florian8844a632012-04-13 04:04:06 +00006314s390_insn *
florian125e20d2012-10-07 15:42:37 +00006315s390_insn_set_fpc_bfprm(UChar size, HReg mode)
florian2c74d242012-09-12 19:38:42 +00006316{
6317 vassert(size == 4);
6318
6319 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6320
florian125e20d2012-10-07 15:42:37 +00006321 insn->tag = S390_INSN_SET_FPC_BFPRM;
florian2c74d242012-09-12 19:38:42 +00006322 insn->size = size;
florian125e20d2012-10-07 15:42:37 +00006323 insn->variant.set_fpc_bfprm.mode = mode;
florian2c74d242012-09-12 19:38:42 +00006324
6325 return insn;
6326}
6327
6328
6329s390_insn *
florianc8e4f562012-10-27 16:19:31 +00006330s390_insn_set_fpc_dfprm(UChar size, HReg mode)
6331{
6332 vassert(size == 4);
6333
6334 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6335
6336 insn->tag = S390_INSN_SET_FPC_DFPRM;
6337 insn->size = size;
6338 insn->variant.set_fpc_dfprm.mode = mode;
6339
6340 return insn;
6341}
6342
6343
6344s390_insn *
florian8844a632012-04-13 04:04:06 +00006345s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
6346 Bool to_fast_entry)
6347{
6348 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6349
florian406ac942014-11-22 20:10:21 +00006350 vassert(guest_IA->tag == S390_AMODE_B12);
6351
florian8844a632012-04-13 04:04:06 +00006352 insn->tag = S390_INSN_XDIRECT;
6353 insn->size = 0; /* does not matter */
6354
6355 insn->variant.xdirect.cond = cond;
6356 insn->variant.xdirect.dst = dst;
6357 insn->variant.xdirect.guest_IA = guest_IA;
6358 insn->variant.xdirect.to_fast_entry = to_fast_entry;
6359
6360 return insn;
6361}
6362
6363
6364s390_insn *
6365s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
6366{
6367 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6368
florian406ac942014-11-22 20:10:21 +00006369 vassert(guest_IA->tag == S390_AMODE_B12);
6370
florian7346c7a2012-04-13 21:14:24 +00006371 insn->tag = S390_INSN_XINDIR;
florian8844a632012-04-13 04:04:06 +00006372 insn->size = 0; /* does not matter */
6373
florian7346c7a2012-04-13 21:14:24 +00006374 insn->variant.xindir.cond = cond;
6375 insn->variant.xindir.dst = dst;
6376 insn->variant.xindir.guest_IA = guest_IA;
florian8844a632012-04-13 04:04:06 +00006377
6378 return insn;
6379}
6380
6381
6382s390_insn *
6383s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
6384 IRJumpKind kind)
6385{
6386 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6387
florian406ac942014-11-22 20:10:21 +00006388 vassert(guest_IA->tag == S390_AMODE_B12);
6389
florian8844a632012-04-13 04:04:06 +00006390 insn->tag = S390_INSN_XASSISTED;
6391 insn->size = 0; /* does not matter */
6392
6393 insn->variant.xassisted.cond = cond;
6394 insn->variant.xassisted.dst = dst;
6395 insn->variant.xassisted.guest_IA = guest_IA;
6396 insn->variant.xassisted.kind = kind;
6397
6398 return insn;
6399}
6400
6401
6402s390_insn *
6403s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
6404{
6405 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6406
florianbf516d12012-04-21 15:53:13 +00006407 vassert(counter->tag == S390_AMODE_B12);
6408 vassert(fail_addr->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00006409
6410 insn->tag = S390_INSN_EVCHECK;
6411 insn->size = 0; /* does not matter */
6412
6413 insn->variant.evcheck.counter = counter;
6414 insn->variant.evcheck.fail_addr = fail_addr;
6415
6416 return insn;
6417}
6418
6419
6420s390_insn *
6421s390_insn_profinc(void)
6422{
6423 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6424
6425 insn->tag = S390_INSN_PROFINC;
6426 insn->size = 0; /* does not matter */
6427
6428 return insn;
6429}
6430
6431
sewardj2019a972011-03-07 16:04:07 +00006432/*---------------------------------------------------------------*/
6433/*--- Debug print ---*/
6434/*---------------------------------------------------------------*/
6435
6436static const HChar *
6437s390_cc_as_string(s390_cc_t cc)
6438{
6439 switch (cc) {
6440 case S390_CC_NEVER: return "never";
6441 case S390_CC_OVFL: return "overflow";
6442 case S390_CC_H: return "greater than"; /* A > B ; high */
6443 case S390_CC_NLE: return "not low or equal";
6444 case S390_CC_L: return "less than"; /* A < B ; low */
6445 case S390_CC_NHE: return "not high or equal";
6446 case S390_CC_LH: return "low or high";
6447 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
6448 case S390_CC_E: return "equal"; /* A == B ; zero */
6449 case S390_CC_NLH: return "not low or high";
6450 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
6451 case S390_CC_NL: return "not low"; /* not low */
6452 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
6453 case S390_CC_NH: return "not high";
6454 case S390_CC_NO: return "not overflow";
6455 case S390_CC_ALWAYS: return "always";
6456 default:
6457 vpanic("s390_cc_as_string");
6458 }
6459}
6460
6461
florian8844a632012-04-13 04:04:06 +00006462static const HChar *
6463s390_jump_kind_as_string(IRJumpKind kind)
6464{
6465 switch (kind) {
6466 case Ijk_Boring: return "Boring";
6467 case Ijk_Call: return "Call";
6468 case Ijk_Ret: return "Return";
6469 case Ijk_ClientReq: return "ClientReq";
6470 case Ijk_Yield: return "Yield";
6471 case Ijk_EmWarn: return "EmWarn";
6472 case Ijk_EmFail: return "EmFail";
6473 case Ijk_NoDecode: return "NoDecode";
6474 case Ijk_MapFail: return "MapFail";
sewardj05f5e012014-05-04 10:52:11 +00006475 case Ijk_InvalICache: return "Invalidate";
florian8844a632012-04-13 04:04:06 +00006476 case Ijk_NoRedir: return "NoRedir";
6477 case Ijk_SigTRAP: return "SigTRAP";
6478 case Ijk_SigSEGV: return "SigSEGV";
6479 case Ijk_SigBUS: return "SigBUS";
6480 case Ijk_Sys_syscall: return "Sys_syscall";
6481 default:
6482 vpanic("s390_jump_kind_as_string");
6483 }
6484}
6485
6486
sewardj2019a972011-03-07 16:04:07 +00006487/* Helper function for writing out a V insn */
6488static void
florian55085f82012-11-21 00:36:55 +00006489s390_sprintf(HChar *buf, const HChar *fmt, ...)
sewardj2019a972011-03-07 16:04:07 +00006490{
6491 HChar *p;
6492 ULong value;
6493 va_list args;
6494 va_start(args, fmt);
6495
6496 p = buf;
6497 for ( ; *fmt; ++fmt) {
6498 Int c = *fmt;
6499
6500 if (c != '%') {
6501 *p++ = c;
6502 continue;
6503 }
6504
6505 c = *++fmt; /* next char */
6506 switch (c) {
6507 case '%':
6508 *p++ = c; /* %% */
6509 continue;
6510
6511 case 's': /* %s */
6512 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
6513 continue;
6514
6515 case 'M': /* %M = mnemonic */
6516 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
6517 continue;
6518
6519 case 'R': /* %R = register */
6520 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
6521 continue;
6522
6523 case 'A': /* %A = amode */
6524 p += vex_sprintf(p, "%s",
6525 s390_amode_as_string(va_arg(args, s390_amode *)));
6526 continue;
6527
florianad43b3a2012-02-20 15:01:14 +00006528 case 'G': /* %G = guest state @ offset */
6529 p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt));
6530 continue;
6531
sewardj2019a972011-03-07 16:04:07 +00006532 case 'C': /* %C = condition code */
6533 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
6534 continue;
6535
florian8844a632012-04-13 04:04:06 +00006536 case 'J': /* &J = jump kind */
6537 p += vex_sprintf(p, "%s",
6538 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
6539 continue;
6540
sewardj2019a972011-03-07 16:04:07 +00006541 case 'L': { /* %L = argument list in helper call*/
6542 UInt i, num_args;
6543
6544 num_args = va_arg(args, UInt);
6545
6546 for (i = 0; i < num_args; ++i) {
6547 if (i != 0) p += vex_sprintf(p, ", ");
6548 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
6549 }
6550 continue;
6551 }
6552
6553 case 'O': { /* %O = RMI operand */
6554 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
6555
6556 switch (op->tag) {
6557 case S390_OPND_REG:
6558 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
6559 continue;
6560
6561 case S390_OPND_AMODE:
6562 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
6563 continue;
6564
6565 case S390_OPND_IMMEDIATE:
6566 value = op->variant.imm;
6567 goto print_value;
6568
6569 default:
6570 goto fail;
6571 }
6572 }
6573
6574 case 'I': /* %I = immediate value */
6575 value = va_arg(args, ULong);
6576 goto print_value;
6577
6578 print_value:
6579 if ((Long)value < 0)
6580 p += vex_sprintf(p, "%lld", (Long)value);
6581 else if (value < 100)
6582 p += vex_sprintf(p, "%llu", value);
6583 else
6584 p += vex_sprintf(p, "0x%llx", value);
6585 continue;
6586
6587 default:
6588 goto fail;
6589 }
6590 }
6591 *p = '\0';
6592 va_end(args);
6593
6594 return;
6595
6596 fail: vpanic("s390_printf");
6597}
6598
6599
6600/* Decompile the given insn into a static buffer and return it */
6601const HChar *
6602s390_insn_as_string(const s390_insn *insn)
6603{
6604 static HChar buf[300];
6605 const HChar *op;
6606 HChar *p;
6607
6608 buf[0] = '\0';
6609
6610 switch (insn->tag) {
6611 case S390_INSN_LOAD:
6612 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
6613 insn->variant.load.src);
6614 break;
6615
6616 case S390_INSN_STORE:
6617 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
6618 insn->variant.store.dst);
6619 break;
6620
6621 case S390_INSN_MOVE:
6622 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
6623 insn->variant.move.src);
6624 break;
6625
floriancec3a8a2013-02-02 00:16:58 +00006626 case S390_INSN_MEMCPY:
6627 s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst,
6628 insn->variant.memcpy.src);
6629 break;
6630
sewardj2019a972011-03-07 16:04:07 +00006631 case S390_INSN_COND_MOVE:
6632 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
6633 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
6634 &insn->variant.cond_move.src);
6635 break;
6636
6637 case S390_INSN_LOAD_IMMEDIATE:
6638 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
6639 insn->variant.load_immediate.value);
6640 break;
6641
6642 case S390_INSN_ALU:
6643 switch (insn->variant.alu.tag) {
6644 case S390_ALU_ADD: op = "v-add"; break;
6645 case S390_ALU_SUB: op = "v-sub"; break;
6646 case S390_ALU_MUL: op = "v-mul"; break;
6647 case S390_ALU_AND: op = "v-and"; break;
6648 case S390_ALU_OR: op = "v-or"; break;
6649 case S390_ALU_XOR: op = "v-xor"; break;
6650 case S390_ALU_LSH: op = "v-lsh"; break;
6651 case S390_ALU_RSH: op = "v-rsh"; break;
6652 case S390_ALU_RSHA: op = "v-rsha"; break;
6653 default: goto fail;
6654 }
florian043af212012-06-06 02:44:53 +00006655 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
sewardj2019a972011-03-07 16:04:07 +00006656 &insn->variant.alu.op2);
6657 break;
6658
florianc4aa7ed2012-12-22 15:01:04 +00006659 case S390_INSN_SMUL:
6660 case S390_INSN_UMUL:
6661 if (insn->tag == S390_INSN_SMUL) {
sewardj2019a972011-03-07 16:04:07 +00006662 op = "v-muls";
6663 } else {
6664 op = "v-mulu";
6665 }
6666 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
6667 &insn->variant.mul.op2);
6668 break;
6669
florianc4aa7ed2012-12-22 15:01:04 +00006670 case S390_INSN_SDIV:
6671 case S390_INSN_UDIV:
6672 if (insn->tag == S390_INSN_SDIV) {
sewardj2019a972011-03-07 16:04:07 +00006673 op = "v-divs";
6674 } else {
6675 op = "v-divu";
6676 }
6677 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
6678 &insn->variant.div.op2);
6679 break;
6680
6681 case S390_INSN_DIVS:
6682 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
6683 &insn->variant.divs.op2);
6684 break;
6685
sewardj611b06e2011-03-24 08:57:29 +00006686 case S390_INSN_CLZ:
6687 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
6688 &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +00006689 break;
6690
6691 case S390_INSN_UNOP:
6692 switch (insn->variant.unop.tag) {
6693 case S390_ZERO_EXTEND_8:
6694 case S390_ZERO_EXTEND_16:
6695 case S390_ZERO_EXTEND_32:
6696 op = "v-zerox";
6697 break;
6698
6699 case S390_SIGN_EXTEND_8:
6700 case S390_SIGN_EXTEND_16:
6701 case S390_SIGN_EXTEND_32:
6702 op = "v-signx";
6703 break;
6704
6705 case S390_NEGATE:
6706 op = "v-neg";
6707 break;
6708
6709 default:
6710 goto fail;
6711 }
6712 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
6713 &insn->variant.unop.src);
6714 break;
6715
6716 case S390_INSN_TEST:
6717 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
6718 break;
6719
6720 case S390_INSN_CC2BOOL:
6721 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
6722 insn->variant.cc2bool.cond);
6723 break;
6724
6725 case S390_INSN_CAS:
6726 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
6727 insn->variant.cas.op2, insn->variant.cas.op3,
6728 insn->variant.cas.old_mem);
6729 break;
6730
florianc4aa7ed2012-12-22 15:01:04 +00006731 case S390_INSN_CDAS: {
6732 s390_cdas *cdas = insn->variant.cdas.details;
6733
florian448cbba2012-06-06 02:26:01 +00006734 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
florianc4aa7ed2012-12-22 15:01:04 +00006735 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
6736 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
florian448cbba2012-06-06 02:26:01 +00006737 break;
florianc4aa7ed2012-12-22 15:01:04 +00006738 }
florian448cbba2012-06-06 02:26:01 +00006739
sewardj2019a972011-03-07 16:04:07 +00006740 case S390_INSN_COMPARE:
6741 if (insn->variant.compare.signed_comparison) {
6742 op = "v-cmps";
6743 } else {
6744 op = "v-cmpu";
6745 }
6746 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
6747 &insn->variant.compare.src2);
6748 break;
6749
sewardj2019a972011-03-07 16:04:07 +00006750 case S390_INSN_HELPER_CALL: {
sewardj74142b82013-08-08 10:28:59 +00006751 s390_helper_call *helper_call = insn->variant.helper_call.details;
6752 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
6753 helper_call->cond,
6754 helper_call->name,
6755 helper_call->target,
6756 helper_call->num_args);
florian8844a632012-04-13 04:04:06 +00006757 return buf; /* avoid printing "size = ..." which is meaningless */
sewardj2019a972011-03-07 16:04:07 +00006758 }
6759
6760 case S390_INSN_BFP_TRIOP:
6761 switch (insn->variant.bfp_triop.tag) {
6762 case S390_BFP_MADD: op = "v-fmadd"; break;
6763 case S390_BFP_MSUB: op = "v-fmsub"; break;
6764 default: goto fail;
6765 }
florian043af212012-06-06 02:44:53 +00006766 s390_sprintf(buf, "%M %R,%R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00006767 insn->variant.bfp_triop.dst /* op1 same as dst */,
6768 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
6769 break;
6770
6771 case S390_INSN_BFP_BINOP:
6772 switch (insn->variant.bfp_binop.tag) {
6773 case S390_BFP_ADD: op = "v-fadd"; break;
6774 case S390_BFP_SUB: op = "v-fsub"; break;
6775 case S390_BFP_MUL: op = "v-fmul"; break;
6776 case S390_BFP_DIV: op = "v-fdiv"; break;
6777 default: goto fail;
6778 }
florian043af212012-06-06 02:44:53 +00006779 s390_sprintf(buf, "%M %R,%R", op,
floriancc491a62012-09-10 23:44:37 +00006780 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
6781 insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00006782 break;
6783
6784 case S390_INSN_BFP_COMPARE:
6785 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
floriancc491a62012-09-10 23:44:37 +00006786 insn->variant.bfp_compare.op1_hi,
6787 insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00006788 break;
6789
6790 case S390_INSN_BFP_UNOP:
6791 switch (insn->variant.bfp_unop.tag) {
6792 case S390_BFP_ABS: op = "v-fabs"; break;
6793 case S390_BFP_NABS: op = "v-fnabs"; break;
6794 case S390_BFP_NEG: op = "v-fneg"; break;
6795 case S390_BFP_SQRT: op = "v-fsqrt"; break;
florian9fcff4c2012-09-10 03:09:04 +00006796 default: goto fail;
6797 }
floriancc491a62012-09-10 23:44:37 +00006798 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
6799 insn->variant.bfp_unop.op_hi);
florian9fcff4c2012-09-10 03:09:04 +00006800 break;
6801
6802 case S390_INSN_BFP_CONVERT:
6803 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00006804 case S390_BFP_I32_TO_F32:
6805 case S390_BFP_I32_TO_F64:
6806 case S390_BFP_I32_TO_F128:
6807 case S390_BFP_I64_TO_F32:
6808 case S390_BFP_I64_TO_F64:
6809 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006810 case S390_BFP_U32_TO_F32:
6811 case S390_BFP_U32_TO_F64:
6812 case S390_BFP_U32_TO_F128:
6813 case S390_BFP_U64_TO_F32:
6814 case S390_BFP_U64_TO_F64:
6815 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
sewardj2019a972011-03-07 16:04:07 +00006816 case S390_BFP_F32_TO_I32:
6817 case S390_BFP_F32_TO_I64:
6818 case S390_BFP_F64_TO_I32:
6819 case S390_BFP_F64_TO_I64:
6820 case S390_BFP_F128_TO_I32:
6821 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006822 case S390_BFP_F32_TO_U32:
6823 case S390_BFP_F32_TO_U64:
6824 case S390_BFP_F64_TO_U32:
6825 case S390_BFP_F64_TO_U64:
6826 case S390_BFP_F128_TO_U32:
6827 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
sewardj2019a972011-03-07 16:04:07 +00006828 case S390_BFP_F32_TO_F64:
6829 case S390_BFP_F32_TO_F128:
6830 case S390_BFP_F64_TO_F32:
6831 case S390_BFP_F64_TO_F128:
6832 case S390_BFP_F128_TO_F32:
6833 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
6834 default: goto fail;
6835 }
floriancc491a62012-09-10 23:44:37 +00006836 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
6837 insn->variant.bfp_convert.op_hi);
sewardj2019a972011-03-07 16:04:07 +00006838 break;
6839
florianc4aa7ed2012-12-22 15:01:04 +00006840 case S390_INSN_DFP_BINOP: {
6841 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
6842
6843 switch (dfp_binop->tag) {
florian12390202012-11-10 22:34:14 +00006844 case S390_DFP_ADD: op = "v-dadd"; break;
6845 case S390_DFP_SUB: op = "v-dsub"; break;
6846 case S390_DFP_MUL: op = "v-dmul"; break;
6847 case S390_DFP_DIV: op = "v-ddiv"; break;
florian5c539732013-02-14 14:27:12 +00006848 case S390_DFP_QUANTIZE: op = "v-dqua"; break;
florian12390202012-11-10 22:34:14 +00006849 default: goto fail;
6850 }
florianc4aa7ed2012-12-22 15:01:04 +00006851 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
6852 dfp_binop->op2_hi, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +00006853 break;
florianc4aa7ed2012-12-22 15:01:04 +00006854 }
florian12390202012-11-10 22:34:14 +00006855
floriance9e3db2012-12-27 20:14:03 +00006856 case S390_INSN_DFP_UNOP:
6857 switch (insn->variant.dfp_unop.tag) {
florian5c539732013-02-14 14:27:12 +00006858 case S390_DFP_EXTRACT_EXP_D64:
6859 case S390_DFP_EXTRACT_EXP_D128: op = "v-d2exp"; break;
floriance9e3db2012-12-27 20:14:03 +00006860 case S390_DFP_EXTRACT_SIG_D64:
6861 case S390_DFP_EXTRACT_SIG_D128: op = "v-d2sig"; break;
6862 default: goto fail;
6863 }
6864 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
6865 insn->variant.dfp_unop.op_hi);
6866 break;
6867
florian1b901d42013-01-01 22:19:24 +00006868 case S390_INSN_DFP_INTOP:
6869 switch (insn->variant.dfp_intop.tag) {
6870 case S390_DFP_SHIFT_LEFT: op = "v-dshl"; break;
6871 case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break;
florian5c539732013-02-14 14:27:12 +00006872 case S390_DFP_INSERT_EXP: op = "v-diexp"; break;
florian1b901d42013-01-01 22:19:24 +00006873 default: goto fail;
6874 }
6875 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi,
6876 insn->variant.dfp_intop.op2,
6877 insn->variant.dfp_intop.op3_hi);
6878 break;
6879
floriane38f6412012-12-21 17:32:12 +00006880 case S390_INSN_DFP_COMPARE:
florian20c6bca2012-12-26 17:47:19 +00006881 switch (insn->variant.dfp_compare.tag) {
6882 case S390_DFP_COMPARE: op = "v-dcmp"; break;
6883 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
6884 default: goto fail;
6885 }
6886 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
floriane38f6412012-12-21 17:32:12 +00006887 insn->variant.dfp_compare.op1_hi,
6888 insn->variant.dfp_compare.op2_hi);
6889 break;
6890
6891 case S390_INSN_DFP_CONVERT:
6892 switch (insn->variant.dfp_convert.tag) {
6893 case S390_DFP_D32_TO_D64:
6894 case S390_DFP_D64_TO_D32:
6895 case S390_DFP_D64_TO_D128:
6896 case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
florian5f034622013-01-13 02:29:05 +00006897 case S390_DFP_I32_TO_D64:
floriana887acd2013-02-08 23:32:54 +00006898 case S390_DFP_I32_TO_D128:
6899 case S390_DFP_I64_TO_D64:
6900 case S390_DFP_I64_TO_D128: op = "v-i2d"; break;
florian5f034622013-01-13 02:29:05 +00006901 case S390_DFP_U32_TO_D64:
6902 case S390_DFP_U32_TO_D128:
6903 case S390_DFP_U64_TO_D64:
6904 case S390_DFP_U64_TO_D128: op = "v-u2d"; break;
6905 case S390_DFP_D64_TO_I32:
floriana887acd2013-02-08 23:32:54 +00006906 case S390_DFP_D128_TO_I32:
6907 case S390_DFP_D64_TO_I64:
6908 case S390_DFP_D128_TO_I64: op = "v-d2i"; break;
florian5f034622013-01-13 02:29:05 +00006909 case S390_DFP_D64_TO_U32:
6910 case S390_DFP_D64_TO_U64:
6911 case S390_DFP_D128_TO_U32:
6912 case S390_DFP_D128_TO_U64: op = "v-d2u"; break;
floriane38f6412012-12-21 17:32:12 +00006913 default: goto fail;
6914 }
6915 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
6916 insn->variant.dfp_convert.op_hi);
6917 break;
6918
florian5c539732013-02-14 14:27:12 +00006919 case S390_INSN_DFP_REROUND:
6920 s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd",
6921 insn->variant.dfp_reround.dst_hi,
6922 insn->variant.dfp_reround.op2,
6923 insn->variant.dfp_reround.op3_hi);
6924 break;
6925
florian78d5ef72013-05-11 15:02:58 +00006926 case S390_INSN_FP_CONVERT: {
6927 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
6928
6929 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00006930 case S390_FP_F32_TO_D32:
6931 case S390_FP_F32_TO_D64:
6932 case S390_FP_F32_TO_D128:
6933 case S390_FP_F64_TO_D32:
6934 case S390_FP_F64_TO_D64:
6935 case S390_FP_F64_TO_D128:
6936 case S390_FP_F128_TO_D32:
6937 case S390_FP_F128_TO_D64:
florian78d5ef72013-05-11 15:02:58 +00006938 case S390_FP_F128_TO_D128: op = "v-f2d"; break;
florian7ab421d2013-06-17 21:03:56 +00006939 case S390_FP_D32_TO_F32:
6940 case S390_FP_D32_TO_F64:
6941 case S390_FP_D32_TO_F128:
6942 case S390_FP_D64_TO_F32:
6943 case S390_FP_D64_TO_F64:
6944 case S390_FP_D64_TO_F128:
6945 case S390_FP_D128_TO_F32:
6946 case S390_FP_D128_TO_F64:
florian78d5ef72013-05-11 15:02:58 +00006947 case S390_FP_D128_TO_F128: op = "v-d2f"; break;
6948 default: goto fail;
6949 }
6950 s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi,
6951 fp_convert->op_hi);
6952 break;
6953 }
6954
sewardja52e37e2011-04-28 18:48:06 +00006955 case S390_INSN_MFENCE:
6956 s390_sprintf(buf, "%M", "v-mfence");
6957 return buf; /* avoid printing "size = ..." which is meaningless */
6958
florianb93348d2012-12-27 00:59:43 +00006959 case S390_INSN_MIMM:
6960 s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
6961 insn->variant.mimm.value);
florianad43b3a2012-02-20 15:01:14 +00006962 break;
6963
florianf85fe3e2012-12-22 02:28:25 +00006964 case S390_INSN_MADD:
6965 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd",
6966 insn->variant.madd.dst,
6967 (Long)(Char)insn->variant.madd.delta,
6968 insn->variant.madd.value);
florianad43b3a2012-02-20 15:01:14 +00006969 break;
6970
florian125e20d2012-10-07 15:42:37 +00006971 case S390_INSN_SET_FPC_BFPRM:
6972 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
6973 insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00006974 break;
6975
florianc8e4f562012-10-27 16:19:31 +00006976 case S390_INSN_SET_FPC_DFPRM:
6977 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
6978 insn->variant.set_fpc_dfprm.mode);
6979 break;
6980
florian8844a632012-04-13 04:04:06 +00006981 case S390_INSN_EVCHECK:
6982 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
6983 insn->variant.evcheck.counter,
6984 insn->variant.evcheck.fail_addr);
6985 return buf; /* avoid printing "size = ..." which is meaningless */
6986
6987 case S390_INSN_PROFINC:
6988 s390_sprintf(buf, "%M", "v-profinc");
6989 return buf; /* avoid printing "size = ..." which is meaningless */
6990
6991 case S390_INSN_XDIRECT:
6992 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
6993 insn->variant.xdirect.cond,
6994 insn->variant.xdirect.guest_IA,
6995 insn->variant.xdirect.dst,
6996 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
6997 return buf; /* avoid printing "size = ..." which is meaningless */
6998
6999 case S390_INSN_XINDIR:
7000 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
7001 insn->variant.xindir.cond,
7002 insn->variant.xindir.guest_IA,
7003 insn->variant.xindir.dst);
7004 return buf; /* avoid printing "size = ..." which is meaningless */
7005
7006 case S390_INSN_XASSISTED:
7007 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
7008 insn->variant.xassisted.cond,
7009 insn->variant.xassisted.kind,
7010 insn->variant.xassisted.guest_IA,
7011 insn->variant.xassisted.dst);
7012 return buf; /* avoid printing "size = ..." which is meaningless */
7013
sewardj2019a972011-03-07 16:04:07 +00007014 default: goto fail;
7015 }
7016
7017 /* Write out how many bytes are involved in the operation */
7018
7019 {
7020 UInt len, i;
7021
7022 for (p = buf; *p; ++p)
7023 continue;
7024
7025 len = p - buf;
7026
7027 if (len < 32) {
7028 for (i = len; i < 32; ++i)
7029 p += vex_sprintf(p, " ");
7030 } else {
7031 p += vex_sprintf(p, "\t");
7032 }
7033 }
7034
7035 /* Special cases first */
7036 switch (insn->tag) {
7037 case S390_INSN_UNOP:
7038 switch (insn->variant.unop.tag) {
7039 case S390_SIGN_EXTEND_8:
7040 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
7041 case S390_SIGN_EXTEND_16:
7042 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
7043 case S390_SIGN_EXTEND_32:
7044 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
7045 default:
7046 goto common;
7047 }
7048
floriancc491a62012-09-10 23:44:37 +00007049 case S390_INSN_BFP_CONVERT:
7050 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00007051 case S390_BFP_I32_TO_F32:
7052 case S390_BFP_I32_TO_F64:
7053 case S390_BFP_I32_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00007054 case S390_BFP_U32_TO_F32:
7055 case S390_BFP_U32_TO_F64:
7056 case S390_BFP_U32_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00007057 case S390_BFP_F32_TO_I32:
7058 case S390_BFP_F32_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00007059 case S390_BFP_F32_TO_U32:
7060 case S390_BFP_F32_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00007061 case S390_BFP_F32_TO_F64:
7062 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
7063 case S390_BFP_I64_TO_F32:
7064 case S390_BFP_I64_TO_F64:
7065 case S390_BFP_I64_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00007066 case S390_BFP_U64_TO_F32:
7067 case S390_BFP_U64_TO_F64:
7068 case S390_BFP_U64_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00007069 case S390_BFP_F64_TO_I32:
7070 case S390_BFP_F64_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00007071 case S390_BFP_F64_TO_U32:
7072 case S390_BFP_F64_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00007073 case S390_BFP_F64_TO_F32:
7074 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
7075 case S390_BFP_F128_TO_I32:
7076 case S390_BFP_F128_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00007077 case S390_BFP_F128_TO_U32:
7078 case S390_BFP_F128_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00007079 case S390_BFP_F128_TO_F32:
7080 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
7081 default:
7082 goto common;
7083 }
7084
floriane38f6412012-12-21 17:32:12 +00007085 case S390_INSN_DFP_CONVERT:
7086 switch (insn->variant.dfp_convert.tag) {
florian5f034622013-01-13 02:29:05 +00007087 case S390_DFP_D32_TO_D64:
7088 case S390_DFP_I32_TO_D64:
7089 case S390_DFP_I32_TO_D128:
7090 case S390_DFP_U32_TO_D64:
7091 case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common;
floriane38f6412012-12-21 17:32:12 +00007092 case S390_DFP_D64_TO_D32:
florian5f034622013-01-13 02:29:05 +00007093 case S390_DFP_D64_TO_D128:
floriana887acd2013-02-08 23:32:54 +00007094 case S390_DFP_I64_TO_D64:
7095 case S390_DFP_I64_TO_D128:
florian5f034622013-01-13 02:29:05 +00007096 case S390_DFP_U64_TO_D64:
7097 case S390_DFP_U64_TO_D128:
7098 case S390_DFP_D64_TO_I32:
floriana887acd2013-02-08 23:32:54 +00007099 case S390_DFP_D64_TO_I64:
florian5f034622013-01-13 02:29:05 +00007100 case S390_DFP_D64_TO_U32:
7101 case S390_DFP_D64_TO_U64: p += vex_sprintf(p, "8 -> "); goto common;
7102 case S390_DFP_D128_TO_D64:
7103 case S390_DFP_D128_TO_I32:
floriana887acd2013-02-08 23:32:54 +00007104 case S390_DFP_D128_TO_I64:
florian5f034622013-01-13 02:29:05 +00007105 case S390_DFP_D128_TO_U32:
7106 case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common;
floriane38f6412012-12-21 17:32:12 +00007107 default:
7108 goto common;
7109 }
7110
florian78d5ef72013-05-11 15:02:58 +00007111 case S390_INSN_FP_CONVERT: {
7112 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
7113
7114 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00007115 case S390_FP_F32_TO_D32:
7116 case S390_FP_F32_TO_D64:
7117 case S390_FP_F32_TO_D128:
7118 case S390_FP_D32_TO_F32:
7119 case S390_FP_D32_TO_F64:
7120 case S390_FP_D32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
7121 case S390_FP_F64_TO_D32:
florian78d5ef72013-05-11 15:02:58 +00007122 case S390_FP_F64_TO_D64:
florian7ab421d2013-06-17 21:03:56 +00007123 case S390_FP_F64_TO_D128:
7124 case S390_FP_D64_TO_F32:
florian78d5ef72013-05-11 15:02:58 +00007125 case S390_FP_D64_TO_F64:
florian7ab421d2013-06-17 21:03:56 +00007126 case S390_FP_D64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
7127 case S390_FP_F128_TO_D32:
7128 case S390_FP_F128_TO_D64:
florian78d5ef72013-05-11 15:02:58 +00007129 case S390_FP_F128_TO_D128:
florian7ab421d2013-06-17 21:03:56 +00007130 case S390_FP_D128_TO_F32:
7131 case S390_FP_D128_TO_F64:
florian78d5ef72013-05-11 15:02:58 +00007132 case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
7133 default:
7134 goto common;
7135 }
7136 }
7137
sewardj2019a972011-03-07 16:04:07 +00007138 default:
7139 goto common;
7140 }
7141
7142 /* Common case */
7143 common:
7144 vex_sprintf(p, "%u bytes", (UInt)insn->size);
7145
7146 return buf;
7147
7148 fail: vpanic("s390_insn_as_string");
7149}
7150
7151
7152
7153/* Load NUM bytes from memory into register REG using addressing mode AM. */
7154static UChar *
7155s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
7156{
7157 UInt b = hregNumber(am->b);
7158 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
7159 UInt d = am->d;
7160
7161 switch (am->tag) {
7162 case S390_AMODE_B12:
7163 case S390_AMODE_BX12:
7164 switch (num) {
7165 case 1: return s390_emit_IC(p, reg, x, b, d);
7166 case 2: return s390_emit_LH(p, reg, x, b, d);
7167 case 4: return s390_emit_L(p, reg, x, b, d);
7168 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
7169 default: goto fail;
7170 }
7171 break;
7172
7173 case S390_AMODE_B20:
7174 case S390_AMODE_BX20:
7175 switch (num) {
7176 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
7177 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
7178 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
7179 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
7180 default: goto fail;
7181 }
7182 break;
7183
7184 default: goto fail;
7185 }
7186
7187 fail:
7188 vpanic("s390_emit_load_mem");
7189}
7190
7191
7192/* Load condition code into register REG */
7193static UChar *
7194s390_emit_load_cc(UChar *p, UChar reg)
7195{
7196 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
7197 p = s390_emit_IPM(p, reg, reg);
7198 /* Shift 28 bits to the right --> [0,1,2,3] */
sewardjf74c86f2011-04-05 14:04:53 +00007199 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
sewardj2019a972011-03-07 16:04:07 +00007200}
7201
7202
7203/*---------------------------------------------------------------*/
7204/*--- Code generation ---*/
7205/*---------------------------------------------------------------*/
7206
7207/* Do not load more bytes than requested. */
7208static UChar *
7209s390_insn_load_emit(UChar *buf, const s390_insn *insn)
7210{
7211 UInt r, x, b, d;
7212 const s390_amode *src;
7213
7214 src = insn->variant.load.src;
7215
7216 r = hregNumber(insn->variant.load.dst);
7217
7218 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
7219 b = hregNumber(src->b);
7220 x = hregNumber(src->x); /* 0 for B12 and B20 */
7221 d = src->d;
7222
7223 switch (insn->size) {
7224
7225 case 4:
7226 switch (src->tag) {
7227 case S390_AMODE_B12:
7228 case S390_AMODE_BX12:
7229 return s390_emit_LE(buf, r, x, b, d);
7230
7231 case S390_AMODE_B20:
7232 case S390_AMODE_BX20:
7233 return s390_emit_LEY(buf, r, x, b, DISP20(d));
7234 }
7235 break;
7236
7237 case 8:
7238 switch (src->tag) {
7239 case S390_AMODE_B12:
7240 case S390_AMODE_BX12:
7241 return s390_emit_LD(buf, r, x, b, d);
7242
7243 case S390_AMODE_B20:
7244 case S390_AMODE_BX20:
7245 return s390_emit_LDY(buf, r, x, b, DISP20(d));
7246 }
7247 break;
7248 }
7249 vpanic("s390_insn_load_emit");
7250 }
7251
7252 /* Integer stuff */
7253 return s390_emit_load_mem(buf, insn->size, r, src);
7254}
7255
7256
7257static UChar *
7258s390_insn_store_emit(UChar *buf, const s390_insn *insn)
7259{
7260 UInt r, x, b, d;
7261 const s390_amode *dst;
7262
7263 dst = insn->variant.store.dst;
7264
7265 r = hregNumber(insn->variant.store.src);
7266 b = hregNumber(dst->b);
7267 x = hregNumber(dst->x); /* 0 for B12 and B20 */
7268 d = dst->d;
7269
7270 if (hregClass(insn->variant.store.src) == HRcFlt64) {
7271 switch (insn->size) {
7272
7273 case 4:
7274 switch (dst->tag) {
7275 case S390_AMODE_B12:
7276 case S390_AMODE_BX12:
7277 return s390_emit_STE(buf, r, x, b, d);
7278
7279 case S390_AMODE_B20:
7280 case S390_AMODE_BX20:
7281 return s390_emit_STEY(buf, r, x, b, DISP20(d));
7282 }
7283 break;
7284
7285 case 8:
7286 switch (dst->tag) {
7287 case S390_AMODE_B12:
7288 case S390_AMODE_BX12:
7289 return s390_emit_STD(buf, r, x, b, d);
7290
7291 case S390_AMODE_B20:
7292 case S390_AMODE_BX20:
7293 return s390_emit_STDY(buf, r, x, b, DISP20(d));
7294 }
7295 break;
7296 }
7297 vpanic("s390_insn_store_emit");
7298 }
7299
7300 /* Integer stuff */
7301 switch (insn->size) {
7302 case 1:
7303 switch (dst->tag) {
7304 case S390_AMODE_B12:
7305 case S390_AMODE_BX12:
7306 return s390_emit_STC(buf, r, x, b, d);
7307
7308 case S390_AMODE_B20:
7309 case S390_AMODE_BX20:
7310 return s390_emit_STCY(buf, r, x, b, DISP20(d));
7311 }
7312 break;
7313
7314 case 2:
7315 switch (dst->tag) {
7316 case S390_AMODE_B12:
7317 case S390_AMODE_BX12:
7318 return s390_emit_STH(buf, r, x, b, d);
7319
7320 case S390_AMODE_B20:
7321 case S390_AMODE_BX20:
7322 return s390_emit_STHY(buf, r, x, b, DISP20(d));
7323 }
7324 break;
7325
7326 case 4:
7327 switch (dst->tag) {
7328 case S390_AMODE_B12:
7329 case S390_AMODE_BX12:
7330 return s390_emit_ST(buf, r, x, b, d);
7331
7332 case S390_AMODE_B20:
7333 case S390_AMODE_BX20:
7334 return s390_emit_STY(buf, r, x, b, DISP20(d));
7335 }
7336 break;
7337
7338 case 8:
7339 return s390_emit_STG(buf, r, x, b, DISP20(d));
7340
7341 default:
7342 break;
7343 }
7344
7345 vpanic("s390_insn_store_emit");
7346}
7347
7348
7349static UChar *
7350s390_insn_move_emit(UChar *buf, const s390_insn *insn)
7351{
7352 UInt dst, src;
7353 HRegClass dst_class, src_class;
7354
7355 dst = hregNumber(insn->variant.move.dst);
7356 src = hregNumber(insn->variant.move.src);
7357
7358 dst_class = hregClass(insn->variant.move.dst);
7359 src_class = hregClass(insn->variant.move.src);
7360
7361 if (dst_class == src_class) {
7362 if (dst_class == HRcInt64)
7363 return s390_emit_LGR(buf, dst, src);
7364 if (dst_class == HRcFlt64)
7365 return s390_emit_LDR(buf, dst, src);
7366 } else {
floriana782a172011-12-18 15:51:54 +00007367 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
7368 if (insn->size == 4) {
7369 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
7370 return s390_emit_LDGRw(buf, dst, R0);
7371 } else {
7372 return s390_emit_LDGRw(buf, dst, src);
7373 }
7374 }
7375 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
7376 if (insn->size == 4) {
7377 buf = s390_emit_LGDRw(buf, dst, src);
7378 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
7379 } else {
7380 return s390_emit_LGDRw(buf, dst, src);
7381 }
7382 }
sewardj2019a972011-03-07 16:04:07 +00007383 /* A move between floating point registers and general purpose
7384 registers of different size should never occur and indicates
7385 an error elsewhere. */
7386 }
7387
7388 vpanic("s390_insn_move_emit");
7389}
7390
7391
7392static UChar *
floriancec3a8a2013-02-02 00:16:58 +00007393s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn)
7394{
7395 s390_amode *dst = insn->variant.memcpy.dst;
7396 s390_amode *src = insn->variant.memcpy.src;
7397
7398 return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d,
7399 hregNumber(src->b), src->d);
7400}
7401
7402
7403static UChar *
sewardj2019a972011-03-07 16:04:07 +00007404s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
7405{
7406 UInt r;
7407 ULong value = insn->variant.load_immediate.value;
7408
7409 r = hregNumber(insn->variant.load_immediate.dst);
7410
7411 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
7412 vassert(value == 0);
7413 switch (insn->size) {
7414 case 4: return s390_emit_LZER(buf, r, value);
7415 case 8: return s390_emit_LZDR(buf, r, value);
7416 }
7417 vpanic("s390_insn_load_immediate_emit");
7418 }
7419
7420 switch (insn->size) {
7421 case 1:
7422 case 2:
7423 /* Load the immediate values as a 4 byte value. That does not hurt as
7424 those extra bytes will not be looked at. Fall through .... */
7425 case 4:
7426 return s390_emit_load_32imm(buf, r, value);
7427
7428 case 8:
7429 return s390_emit_load_64imm(buf, r, value);
7430 }
7431
7432 vpanic("s390_insn_load_immediate_emit");
7433}
7434
7435
7436/* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
7437 So we simply perform a 4-byte operation. Doing so uses possibly undefined
7438 bits and produces an undefined result in those extra bit positions. But
7439 upstream does not look at those positions, so this is OK. */
7440static UChar *
7441s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
7442{
7443 s390_opnd_RMI op2;
7444 UInt dst;
7445
7446 dst = hregNumber(insn->variant.alu.dst);
7447 op2 = insn->variant.alu.op2;
7448
7449 /* Second operand is in a register */
7450 if (op2.tag == S390_OPND_REG) {
7451 UInt r2 = hregNumber(op2.variant.reg);
7452
7453 switch (insn->size) {
7454 case 1:
7455 case 2:
7456 case 4:
7457 switch (insn->variant.alu.tag) {
7458 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
7459 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
7460 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
7461 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
7462 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
7463 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
sewardj3c49aaa2011-04-05 14:00:37 +00007464 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
7465 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
7466 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
sewardj2019a972011-03-07 16:04:07 +00007467 }
7468 goto fail;
7469
7470 case 8:
7471 switch (insn->variant.alu.tag) {
7472 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
7473 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
7474 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
7475 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
7476 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
7477 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
7478 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
7479 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
7480 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
7481 }
7482 goto fail;
7483 }
7484 goto fail;
7485 }
7486
7487 /* 2nd operand is in memory */
7488 if (op2.tag == S390_OPND_AMODE) {
7489 UInt b, x, d;
7490 const s390_amode *src = op2.variant.am;
7491
7492 b = hregNumber(src->b);
7493 x = hregNumber(src->x); /* 0 for B12 and B20 */
7494 d = src->d;
7495
7496 /* Shift operands are special here as there are no opcodes that
sewardje0dd77e2011-04-27 12:07:01 +00007497 allow a memory operand. So we first load the 2nd operand into
7498 some register. R0 is used to save restore the contents of the
7499 chosen register.. */
sewardj652b56a2011-04-13 15:38:17 +00007500
sewardj2019a972011-03-07 16:04:07 +00007501 if (insn->variant.alu.tag == S390_ALU_LSH ||
7502 insn->variant.alu.tag == S390_ALU_RSH ||
7503 insn->variant.alu.tag == S390_ALU_RSHA) {
sewardje0dd77e2011-04-27 12:07:01 +00007504 UInt b2;
sewardj2019a972011-03-07 16:04:07 +00007505
sewardje0dd77e2011-04-27 12:07:01 +00007506 /* Choose a register (other than DST or R0) into which to stick the
7507 shift amount. The following works because r15 is reserved and
7508 thusly dst != 15. */
7509 vassert(dst != 15); /* extra paranoia */
7510 b2 = (dst + 1) % 16;
7511
7512 buf = s390_emit_LGR(buf, R0, b2); /* save */
7513
7514 /* Loading SRC to B2 does not modify R0. */
7515 buf = s390_emit_load_mem(buf, insn->size, b2, src);
sewardj2019a972011-03-07 16:04:07 +00007516
7517 if (insn->size == 8) {
sewardje0dd77e2011-04-27 12:07:01 +00007518 switch (insn->variant.alu.tag) {
7519 case S390_ALU_LSH:
7520 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
7521 break;
7522 case S390_ALU_RSH:
7523 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
7524 break;
7525 case S390_ALU_RSHA:
7526 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
7527 break;
7528 default: /* unreachable */
7529 goto fail;
7530 }
sewardj2019a972011-03-07 16:04:07 +00007531 } else {
sewardje0dd77e2011-04-27 12:07:01 +00007532 switch (insn->variant.alu.tag) {
7533 case S390_ALU_LSH:
7534 buf = s390_emit_SLL(buf, dst, b2, 0);
7535 break;
7536 case S390_ALU_RSH:
7537 buf = s390_emit_SRL(buf, dst, b2, 0);
7538 break;
7539 case S390_ALU_RSHA:
7540 buf = s390_emit_SRA(buf, dst, b2, 0);
7541 break;
7542 default: /* unreachable */
7543 goto fail;
7544 }
sewardj2019a972011-03-07 16:04:07 +00007545 }
sewardje0dd77e2011-04-27 12:07:01 +00007546 return s390_emit_LGR(buf, b2, R0); /* restore */
sewardj2019a972011-03-07 16:04:07 +00007547 }
7548
7549 switch (insn->size) {
7550 case 1:
7551 /* Move the byte from memory into scratch register r0 */
7552 buf = s390_emit_load_mem(buf, 1, R0, src);
7553
7554 switch (insn->variant.alu.tag) {
7555 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
7556 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
7557 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
7558 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
7559 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
7560 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
7561 case S390_ALU_LSH:
7562 case S390_ALU_RSH:
7563 case S390_ALU_RSHA: ; /* avoid GCC warning */
7564 }
7565 goto fail;
7566
7567 case 2:
7568 switch (src->tag) {
7569 case S390_AMODE_B12:
7570 case S390_AMODE_BX12:
7571 switch (insn->variant.alu.tag) {
7572 case S390_ALU_ADD:
7573 return s390_emit_AH(buf, dst, x, b, d);
7574
7575 case S390_ALU_SUB:
7576 return s390_emit_SH(buf, dst, x, b, d);
7577
7578 case S390_ALU_MUL:
7579 return s390_emit_MH(buf, dst, x, b, d);
7580
7581 /* For bitwise operations: Move two bytes from memory into scratch
7582 register r0; then perform operation */
7583 case S390_ALU_AND:
7584 buf = s390_emit_LH(buf, R0, x, b, d);
7585 return s390_emit_NR(buf, dst, R0);
7586
7587 case S390_ALU_OR:
7588 buf = s390_emit_LH(buf, R0, x, b, d);
7589 return s390_emit_OR(buf, dst, R0);
7590
7591 case S390_ALU_XOR:
7592 buf = s390_emit_LH(buf, R0, x, b, d);
7593 return s390_emit_XR(buf, dst, R0);
7594
7595 case S390_ALU_LSH:
7596 case S390_ALU_RSH:
7597 case S390_ALU_RSHA: ; /* avoid GCC warning */
7598 }
7599 goto fail;
7600
7601 case S390_AMODE_B20:
7602 case S390_AMODE_BX20:
7603 switch (insn->variant.alu.tag) {
7604 case S390_ALU_ADD:
7605 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
7606
7607 case S390_ALU_SUB:
7608 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
7609
7610 case S390_ALU_MUL:
sewardjeae8db52011-03-24 09:01:50 +00007611 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007612
7613 /* For bitwise operations: Move two bytes from memory into scratch
7614 register r0; then perform operation */
7615 case S390_ALU_AND:
7616 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7617 return s390_emit_NR(buf, dst, R0);
7618
7619 case S390_ALU_OR:
7620 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7621 return s390_emit_OR(buf, dst, R0);
7622
7623 case S390_ALU_XOR:
7624 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7625 return s390_emit_XR(buf, dst, R0);
7626
7627 case S390_ALU_LSH:
7628 case S390_ALU_RSH:
7629 case S390_ALU_RSHA: ; /* avoid GCC warning */
7630 }
7631 goto fail;
7632 }
7633 goto fail;
7634
7635 case 4:
7636 switch (src->tag) {
7637 case S390_AMODE_B12:
7638 case S390_AMODE_BX12:
7639 switch (insn->variant.alu.tag) {
7640 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
7641 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
7642 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
7643 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
7644 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
7645 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
7646 case S390_ALU_LSH:
7647 case S390_ALU_RSH:
7648 case S390_ALU_RSHA: ; /* avoid GCC warning */
7649 }
7650 goto fail;
7651
7652 case S390_AMODE_B20:
7653 case S390_AMODE_BX20:
7654 switch (insn->variant.alu.tag) {
7655 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
7656 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
7657 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
7658 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
7659 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
7660 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
7661 case S390_ALU_LSH:
7662 case S390_ALU_RSH:
7663 case S390_ALU_RSHA: ; /* avoid GCC warning */
7664 }
7665 goto fail;
7666 }
7667 goto fail;
7668
7669 case 8:
7670 switch (insn->variant.alu.tag) {
7671 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
7672 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
7673 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
7674 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
7675 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
7676 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
7677 case S390_ALU_LSH:
7678 case S390_ALU_RSH:
7679 case S390_ALU_RSHA: ; /* avoid GCC warning */
7680 }
7681 goto fail;
7682 }
7683 goto fail;
7684 }
7685
7686 /* 2nd operand is an immediate value */
7687 if (op2.tag == S390_OPND_IMMEDIATE) {
7688 ULong value;
7689
7690 /* No masking of the value is required as it is not sign extended */
7691 value = op2.variant.imm;
7692
7693 switch (insn->size) {
7694 case 1:
7695 case 2:
7696 /* There is no 1-byte opcode. Do the computation in
7697 2 bytes. The extra byte will be ignored. */
7698 switch (insn->variant.alu.tag) {
7699 case S390_ALU_ADD:
7700 return s390_emit_AHI(buf, dst, value);
7701
7702 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00007703 return s390_emit_SLFIw(buf, dst, value);
sewardj2019a972011-03-07 16:04:07 +00007704
7705 case S390_ALU_MUL:
7706 return s390_emit_MHI(buf, dst, value);
7707
7708 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
7709 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
7710 case S390_ALU_XOR:
7711 /* There is no XILL instruction. Load the immediate value into
7712 R0 and combine with the destination register. */
7713 buf = s390_emit_LHI(buf, R0, value);
7714 return s390_emit_XR(buf, dst, R0);
7715
7716 case S390_ALU_LSH:
sewardj3c49aaa2011-04-05 14:00:37 +00007717 return s390_emit_SLL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007718
7719 case S390_ALU_RSH:
sewardj3c49aaa2011-04-05 14:00:37 +00007720 return s390_emit_SRL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007721
7722 case S390_ALU_RSHA:
sewardj3c49aaa2011-04-05 14:00:37 +00007723 return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007724 }
7725 goto fail;
7726
7727 case 4:
7728 switch (insn->variant.alu.tag) {
7729 case S390_ALU_ADD:
7730 if (uint_fits_signed_16bit(value)) {
7731 return s390_emit_AHI(buf, dst, value);
7732 }
7733 return s390_emit_AFIw(buf, dst, value);
7734
7735 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
7736 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
7737 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
7738 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
7739 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
sewardj3c49aaa2011-04-05 14:00:37 +00007740 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
7741 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
7742 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007743 }
7744 goto fail;
7745
7746 case 8:
7747 switch (insn->variant.alu.tag) {
7748 case S390_ALU_ADD:
7749 if (ulong_fits_signed_16bit(value)) {
7750 return s390_emit_AGHI(buf, dst, value);
7751 }
7752 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
7753 return s390_emit_AGFI(buf, dst, value);
7754 }
7755 /* Load constant into R0 then add */
7756 buf = s390_emit_load_64imm(buf, R0, value);
7757 return s390_emit_AGR(buf, dst, R0);
7758
7759 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00007760 if (ulong_fits_unsigned_32bit(value)) {
7761 return s390_emit_SLGFIw(buf, dst, value);
7762 }
sewardj2019a972011-03-07 16:04:07 +00007763 /* Load value into R0; then subtract from destination reg */
7764 buf = s390_emit_load_64imm(buf, R0, value);
7765 return s390_emit_SGR(buf, dst, R0);
7766
7767 case S390_ALU_MUL:
7768 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
7769 return s390_emit_MSGFI(buf, dst, value);
7770 }
7771 /* Load constant into R0 then add */
7772 buf = s390_emit_load_64imm(buf, R0, value);
7773 return s390_emit_MSGR(buf, dst, R0);
7774
7775 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
7776 case S390_ALU_AND:
7777 if (s390_host_has_eimm) {
7778 buf = s390_emit_NIHF(buf, dst, value >> 32);
7779 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
7780 }
7781 /* Load value into R0; then combine with destination reg */
7782 buf = s390_emit_load_64imm(buf, R0, value);
7783 return s390_emit_NGR(buf, dst, R0);
7784
7785 case S390_ALU_OR:
7786 if (s390_host_has_eimm) {
7787 buf = s390_emit_OIHF(buf, dst, value >> 32);
7788 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
7789 }
7790 /* Load value into R0; then combine with destination reg */
7791 buf = s390_emit_load_64imm(buf, R0, value);
7792 return s390_emit_OGR(buf, dst, R0);
7793
7794 case S390_ALU_XOR:
7795 if (s390_host_has_eimm) {
7796 buf = s390_emit_XIHF(buf, dst, value >> 32);
7797 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
7798 }
7799 /* Load value into R0; then combine with destination reg */
7800 buf = s390_emit_load_64imm(buf, R0, value);
7801 return s390_emit_XGR(buf, dst, R0);
7802
sewardj652b56a2011-04-13 15:38:17 +00007803 /* No special considerations for long displacement here. Only the six
7804 least significant bits of VALUE will be taken; all other bits are
7805 ignored. So the DH2 bits are irrelevant and do not influence the
7806 shift operation, independent of whether long-displacement is available
7807 or not. */
sewardj2019a972011-03-07 16:04:07 +00007808 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
7809 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
7810 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
7811 }
7812 goto fail;
7813 }
7814 goto fail;
7815 }
7816
7817 fail:
7818 vpanic("s390_insn_alu_emit");
7819}
7820
7821
7822static UChar *
7823s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
7824 Bool sign_extend)
7825{
sewardj06122e72011-03-28 12:14:48 +00007826 s390_opnd_RMI opnd = insn->variant.unop.src;
sewardj2019a972011-03-07 16:04:07 +00007827
7828 switch (opnd.tag) {
7829 case S390_OPND_REG: {
7830 UChar r1 = hregNumber(insn->variant.unop.dst);
7831 UChar r2 = hregNumber(opnd.variant.reg);
7832
7833 switch (from_size) {
7834 case 1:
7835 /* Widening to a half-word is implemented like widening to a word
7836 because the upper half-word will not be looked at. */
7837 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7838 if (sign_extend)
7839 return s390_emit_LBRw(buf, r1, r2);
7840 else
7841 return s390_emit_LLCRw(buf, r1, r2);
7842 }
7843 if (insn->size == 8) { /* 8 --> 64 */
7844 if (sign_extend)
7845 return s390_emit_LGBRw(buf, r1, r2);
7846 else
7847 return s390_emit_LLGCRw(buf, r1, r2);
7848 }
7849 goto fail;
7850
7851 case 2:
7852 if (insn->size == 4) { /* 16 --> 32 */
7853 if (sign_extend)
7854 return s390_emit_LHRw(buf, r1, r2);
7855 else
7856 return s390_emit_LLHRw(buf, r1, r2);
7857 }
7858 if (insn->size == 8) { /* 16 --> 64 */
7859 if (sign_extend)
7860 return s390_emit_LGHRw(buf, r1, r2);
7861 else
7862 return s390_emit_LLGHRw(buf, r1, r2);
7863 }
7864 goto fail;
7865
7866 case 4:
7867 if (insn->size == 8) { /* 32 --> 64 */
7868 if (sign_extend)
7869 return s390_emit_LGFR(buf, r1, r2);
7870 else
7871 return s390_emit_LLGFR(buf, r1, r2);
7872 }
7873 goto fail;
7874
7875 default: /* unexpected "from" size */
7876 goto fail;
7877 }
7878 }
7879
7880 case S390_OPND_AMODE: {
7881 UChar r1 = hregNumber(insn->variant.unop.dst);
7882 const s390_amode *src = opnd.variant.am;
7883 UChar b = hregNumber(src->b);
7884 UChar x = hregNumber(src->x);
7885 Int d = src->d;
7886
7887 switch (from_size) {
7888 case 1:
7889 if (insn->size == 4 || insn->size == 2) {
7890 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00007891 return s390_emit_LBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007892 else
7893 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
7894 }
7895 if (insn->size == 8) {
7896 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00007897 return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007898 else
sewardj2019a972011-03-07 16:04:07 +00007899 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
7900 }
7901 goto fail;
7902
7903 case 2:
7904 if (insn->size == 4) { /* 16 --> 32 */
7905 if (sign_extend == 0)
7906 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
7907
7908 switch (src->tag) {
7909 case S390_AMODE_B12:
7910 case S390_AMODE_BX12:
7911 return s390_emit_LH(buf, r1, x, b, d);
7912
7913 case S390_AMODE_B20:
7914 case S390_AMODE_BX20:
7915 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
7916 }
7917 goto fail;
7918 }
7919 if (insn->size == 8) { /* 16 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00007920 if (sign_extend)
7921 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
7922 else
7923 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
7924 }
7925 goto fail;
7926
7927 case 4:
7928 if (insn->size == 8) { /* 32 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00007929 if (sign_extend)
7930 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
7931 else
7932 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
7933 }
7934 goto fail;
7935
7936 default: /* unexpected "from" size */
7937 goto fail;
7938 }
7939 }
7940
7941 case S390_OPND_IMMEDIATE: {
7942 UChar r1 = hregNumber(insn->variant.unop.dst);
7943 ULong value = opnd.variant.imm;
7944
7945 switch (from_size) {
7946 case 1:
7947 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7948 if (sign_extend) {
7949 /* host can do the sign extension to 16-bit; LHI does the rest */
7950 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
7951 } else {
7952 return s390_emit_LHI(buf, r1, value);
7953 }
7954 }
7955 if (insn->size == 8) { /* 8 --> 64 */
7956 if (sign_extend) {
7957 /* host can do the sign extension to 16-bit; LGHI does the rest */
7958 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
7959 } else {
7960 return s390_emit_LGHI(buf, r1, value);
7961 }
7962 }
7963 goto fail;
7964
7965 case 2:
7966 if (insn->size == 4) { /* 16 --> 32 */
7967 return s390_emit_LHI(buf, r1, value);
7968 }
7969 if (insn->size == 8) { /* 16 --> 64 */
7970 if (sign_extend)
7971 return s390_emit_LGHI(buf, r1, value);
7972 else
7973 return s390_emit_LLILL(buf, r1, value);
7974 }
7975 goto fail;
7976
7977 case 4:
7978 if (insn->size == 8) { /* 32 --> 64 */
7979 if (sign_extend)
7980 return s390_emit_LGFIw(buf, r1, value);
7981 else
7982 return s390_emit_LLILFw(buf, r1, value);
7983 }
7984 goto fail;
7985
7986 default: /* unexpected "from" size */
7987 goto fail;
7988 }
7989 }
7990 }
7991
7992 fail:
7993 vpanic("s390_widen_emit");
7994}
7995
7996
7997static UChar *
7998s390_negate_emit(UChar *buf, const s390_insn *insn)
7999{
8000 s390_opnd_RMI opnd;
8001
8002 opnd = insn->variant.unop.src;
8003
8004 switch (opnd.tag) {
8005 case S390_OPND_REG: {
8006 UChar r1 = hregNumber(insn->variant.unop.dst);
8007 UChar r2 = hregNumber(opnd.variant.reg);
8008
8009 switch (insn->size) {
8010 case 1:
8011 case 2:
8012 case 4:
8013 return s390_emit_LCR(buf, r1, r2);
8014
8015 case 8:
8016 return s390_emit_LCGR(buf, r1, r2);
8017
8018 default:
8019 goto fail;
8020 }
8021 }
8022
8023 case S390_OPND_AMODE: {
8024 UChar r1 = hregNumber(insn->variant.unop.dst);
8025
8026 /* Load bytes into scratch register R0, then negate */
8027 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
8028
8029 switch (insn->size) {
8030 case 1:
8031 case 2:
8032 case 4:
8033 return s390_emit_LCR(buf, r1, R0);
8034
8035 case 8:
8036 return s390_emit_LCGR(buf, r1, R0);
8037
8038 default:
8039 goto fail;
8040 }
8041 }
8042
8043 case S390_OPND_IMMEDIATE: {
8044 UChar r1 = hregNumber(insn->variant.unop.dst);
8045 ULong value = opnd.variant.imm;
8046
8047 value = ~value + 1; /* two's complement */
8048
8049 switch (insn->size) {
8050 case 1:
8051 case 2:
8052 /* Load the immediate values as a 4 byte value. That does not hurt as
8053 those extra bytes will not be looked at. Fall through .... */
8054 case 4:
8055 return s390_emit_load_32imm(buf, r1, value);
8056
8057 case 8:
8058 return s390_emit_load_64imm(buf, r1, value);
8059
8060 default:
8061 goto fail;
8062 }
8063 }
8064 }
8065
8066 fail:
8067 vpanic("s390_negate_emit");
8068}
8069
8070
8071static UChar *
8072s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
8073{
8074 switch (insn->variant.unop.tag) {
8075 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
8076 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
8077 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
8078
8079 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
8080 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
8081 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
8082
8083 case S390_NEGATE: return s390_negate_emit(buf, insn);
8084 }
8085
8086 vpanic("s390_insn_unop_emit");
8087}
8088
8089
8090/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
8091 comparisons will have been converted to 4-byte comparisons in
8092 s390_isel_cc and should not occur here. */
8093static UChar *
8094s390_insn_test_emit(UChar *buf, const s390_insn *insn)
8095{
8096 s390_opnd_RMI opnd;
8097
8098 opnd = insn->variant.test.src;
8099
8100 switch (opnd.tag) {
8101 case S390_OPND_REG: {
8102 UInt reg = hregNumber(opnd.variant.reg);
8103
8104 switch (insn->size) {
8105 case 4:
8106 return s390_emit_LTR(buf, reg, reg);
8107
8108 case 8:
8109 return s390_emit_LTGR(buf, reg, reg);
8110
8111 default:
8112 goto fail;
8113 }
8114 }
8115
8116 case S390_OPND_AMODE: {
8117 const s390_amode *am = opnd.variant.am;
8118 UChar b = hregNumber(am->b);
8119 UChar x = hregNumber(am->x);
8120 Int d = am->d;
8121
8122 switch (insn->size) {
8123 case 4:
8124 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
8125
8126 case 8:
8127 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
8128
8129 default:
8130 goto fail;
8131 }
8132 }
8133
8134 case S390_OPND_IMMEDIATE: {
8135 ULong value = opnd.variant.imm;
8136
8137 switch (insn->size) {
8138 case 4:
8139 buf = s390_emit_load_32imm(buf, R0, value);
8140 return s390_emit_LTR(buf, R0, R0);
8141
8142 case 8:
8143 buf = s390_emit_load_64imm(buf, R0, value);
8144 return s390_emit_LTGR(buf, R0, R0);
8145
8146 default:
8147 goto fail;
8148 }
8149 }
8150
8151 default:
8152 goto fail;
8153 }
8154
8155 fail:
8156 vpanic("s390_insn_test_emit");
8157}
8158
8159
8160static UChar *
8161s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
8162{
8163 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
8164 s390_cc_t cond = insn->variant.cc2bool.cond;
8165
8166 /* Make the destination register be 1 or 0, depending on whether
8167 the relevant condition holds. A 64-bit value is computed. */
8168 if (cond == S390_CC_ALWAYS)
8169 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
8170
8171 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
8172 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
8173 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
8174 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
8175 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
8176
8177 return buf;
8178}
8179
8180
8181/* Only 4-byte and 8-byte operands are handled. */
8182static UChar *
8183s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
8184{
8185 UChar r1, r3, b, old;
8186 Int d;
8187 s390_amode *am;
8188
8189 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
8190 r3 = hregNumber(insn->variant.cas.op3);
8191 old= hregNumber(insn->variant.cas.old_mem);
8192 am = insn->variant.cas.op2;
8193 b = hregNumber(am->b);
8194 d = am->d;
8195
florian406ac942014-11-22 20:10:21 +00008196 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8197
sewardj2019a972011-03-07 16:04:07 +00008198 switch (insn->size) {
8199 case 4:
florian406ac942014-11-22 20:10:21 +00008200 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
sewardj2019a972011-03-07 16:04:07 +00008201 buf = s390_emit_LR(buf, R0, r1);
8202 if (am->tag == S390_AMODE_B12)
8203 buf = s390_emit_CS(buf, R0, r3, b, d);
8204 else
8205 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
8206 /* Now copy R0 which has the old memory value to OLD */
8207 return s390_emit_LR(buf, old, R0);
8208
8209 case 8:
florian406ac942014-11-22 20:10:21 +00008210 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
sewardj2019a972011-03-07 16:04:07 +00008211 buf = s390_emit_LGR(buf, R0, r1);
8212 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
8213 /* Now copy R0 which has the old memory value to OLD */
8214 return s390_emit_LGR(buf, old, R0);
8215
8216 default:
8217 goto fail;
8218 }
8219
8220 fail:
8221 vpanic("s390_insn_cas_emit");
8222}
8223
8224
florian448cbba2012-06-06 02:26:01 +00008225/* Only 4-byte and 8-byte operands are handled. */
8226static UChar *
8227s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
8228{
sewardja90622a2012-06-19 13:29:00 +00008229 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
florian448cbba2012-06-06 02:26:01 +00008230 Int d;
8231 s390_amode *am;
florianc4aa7ed2012-12-22 15:01:04 +00008232 s390_cdas *cdas = insn->variant.cdas.details;
florian448cbba2012-06-06 02:26:01 +00008233
florianc4aa7ed2012-12-22 15:01:04 +00008234 r1 = hregNumber(cdas->op1_high); /* expected value */
8235 r1p1 = hregNumber(cdas->op1_low); /* expected value */
8236 r3 = hregNumber(cdas->op3_high);
8237 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
8238 old_high = hregNumber(cdas->old_mem_high);
8239 old_low = hregNumber(cdas->old_mem_low);
8240 scratch = hregNumber(cdas->scratch);
8241 am = cdas->op2;
florian448cbba2012-06-06 02:26:01 +00008242 b = hregNumber(am->b);
8243 d = am->d;
8244
8245 vassert(scratch == 1);
florian406ac942014-11-22 20:10:21 +00008246 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
florian448cbba2012-06-06 02:26:01 +00008247
8248 switch (insn->size) {
8249 case 4:
8250 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
8251 and let CDS/CDSY clobber it */
8252 buf = s390_emit_LR(buf, R0, r1);
8253 buf = s390_emit_LR(buf, scratch, r1p1);
8254
8255 if (am->tag == S390_AMODE_B12)
8256 buf = s390_emit_CDS(buf, R0, r3, b, d);
8257 else
8258 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
8259
8260 /* Now copy R0,scratch which has the old memory value to OLD */
8261 buf = s390_emit_LR(buf, old_high, R0);
8262 buf = s390_emit_LR(buf, old_low, scratch);
8263 return buf;
8264
8265 case 8:
8266 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
8267 and let CDSG clobber it */
8268 buf = s390_emit_LGR(buf, R0, r1);
8269 buf = s390_emit_LGR(buf, scratch, r1p1);
8270
8271 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
8272
8273 /* Now copy R0,scratch which has the old memory value to OLD */
8274 buf = s390_emit_LGR(buf, old_high, R0);
8275 buf = s390_emit_LGR(buf, old_low, scratch);
8276 return buf;
8277
8278 default:
8279 goto fail;
8280 }
8281
8282 fail:
florianbb5aa782012-12-01 21:29:07 +00008283 vpanic("s390_insn_cdas_emit");
florian448cbba2012-06-06 02:26:01 +00008284}
8285
8286
sewardj2019a972011-03-07 16:04:07 +00008287/* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
8288 comparisons will have been converted to 4-byte comparisons in
8289 s390_isel_cc and should not occur here. */
8290static UChar *
8291s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
8292{
8293 s390_opnd_RMI op2;
8294 HReg op1;
8295 Bool signed_comparison;
8296
8297 op1 = insn->variant.compare.src1;
8298 op2 = insn->variant.compare.src2;
8299 signed_comparison = insn->variant.compare.signed_comparison;
8300
8301 switch (op2.tag) {
8302 case S390_OPND_REG: {
8303 UInt r1 = hregNumber(op1);
8304 UInt r2 = hregNumber(op2.variant.reg);
8305
8306 switch (insn->size) {
8307 case 4:
8308 if (signed_comparison)
8309 return s390_emit_CR(buf, r1, r2);
8310 else
8311 return s390_emit_CLR(buf, r1, r2);
8312
8313 case 8:
8314 if (signed_comparison)
8315 return s390_emit_CGR(buf, r1, r2);
8316 else
8317 return s390_emit_CLGR(buf, r1, r2);
8318
8319 default:
8320 goto fail;
8321 }
8322 }
8323
8324 case S390_OPND_AMODE: {
8325 UChar r1 = hregNumber(op1);
8326 const s390_amode *am = op2.variant.am;
8327 UChar b = hregNumber(am->b);
8328 UChar x = hregNumber(am->x);
8329 Int d = am->d;
8330
8331 switch (insn->size) {
8332 case 4:
8333 switch (am->tag) {
8334 case S390_AMODE_B12:
8335 case S390_AMODE_BX12:
8336 if (signed_comparison)
8337 return s390_emit_C(buf, r1, x, b, d);
8338 else
8339 return s390_emit_CL(buf, r1, x, b, d);
8340
8341 case S390_AMODE_B20:
8342 case S390_AMODE_BX20:
8343 if (signed_comparison)
8344 return s390_emit_CY(buf, r1, x, b, DISP20(d));
8345 else
8346 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
8347 }
8348 goto fail;
8349
8350 case 8:
8351 if (signed_comparison)
8352 return s390_emit_CG(buf, r1, x, b, DISP20(d));
8353 else
8354 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
8355
8356 default:
8357 goto fail;
8358 }
8359 }
8360
8361 case S390_OPND_IMMEDIATE: {
8362 UChar r1 = hregNumber(op1);
8363 ULong value = op2.variant.imm;
8364
8365 switch (insn->size) {
8366 case 4:
8367 if (signed_comparison)
8368 return s390_emit_CFIw(buf, r1, value);
8369 else
8370 return s390_emit_CLFIw(buf, r1, value);
8371
8372 case 8:
florian07d34552012-05-26 01:59:21 +00008373 if (s390_host_has_eimm) {
8374 if (signed_comparison) {
8375 if (ulong_fits_signed_32bit(value))
8376 return s390_emit_CGFI(buf, r1, value);
8377 } else {
8378 if (ulong_fits_unsigned_32bit(value))
8379 return s390_emit_CLGFI(buf, r1, value);
8380 }
8381 }
sewardj2019a972011-03-07 16:04:07 +00008382 buf = s390_emit_load_64imm(buf, R0, value);
8383 if (signed_comparison)
8384 return s390_emit_CGR(buf, r1, R0);
8385 else
8386 return s390_emit_CLGR(buf, r1, R0);
8387
8388 default:
8389 goto fail;
8390 }
8391 }
8392
8393 default:
8394 goto fail;
8395 }
8396
8397 fail:
8398 vpanic("s390_insn_compare_emit");
8399}
8400
8401
8402static UChar *
8403s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
8404{
8405 s390_opnd_RMI op2;
8406 UChar r1;
8407 Bool signed_multiply;
8408
8409 /* The register number identifying the register pair */
8410 r1 = hregNumber(insn->variant.mul.dst_hi);
8411
8412 op2 = insn->variant.mul.op2;
florianc4aa7ed2012-12-22 15:01:04 +00008413 signed_multiply = insn->tag == S390_INSN_SMUL;
sewardj2019a972011-03-07 16:04:07 +00008414
8415 switch (op2.tag) {
8416 case S390_OPND_REG: {
8417 UInt r2 = hregNumber(op2.variant.reg);
8418
8419 switch (insn->size) {
8420 case 1:
8421 case 2:
8422 case 4:
8423 if (signed_multiply)
8424 return s390_emit_MR(buf, r1, r2);
8425 else
8426 return s390_emit_MLR(buf, r1, r2);
8427
8428 case 8:
8429 if (signed_multiply)
8430 vpanic("s390_insn_mul_emit");
8431 else
8432 return s390_emit_MLGR(buf, r1, r2);
8433
8434 default:
8435 goto fail;
8436 }
8437 }
8438
8439 case S390_OPND_AMODE: {
8440 const s390_amode *am = op2.variant.am;
8441 UChar b = hregNumber(am->b);
8442 UChar x = hregNumber(am->x);
8443 Int d = am->d;
8444
8445 switch (insn->size) {
8446 case 1:
8447 case 2:
8448 /* Load bytes into scratch register R0, then multiply */
8449 buf = s390_emit_load_mem(buf, insn->size, R0, am);
8450 if (signed_multiply)
8451 return s390_emit_MR(buf, r1, R0);
8452 else
8453 return s390_emit_MLR(buf, r1, R0);
8454
8455 case 4:
8456 switch (am->tag) {
8457 case S390_AMODE_B12:
8458 case S390_AMODE_BX12:
8459 if (signed_multiply)
8460 return s390_emit_M(buf, r1, x, b, d);
8461 else
8462 return s390_emit_ML(buf, r1, x, b, DISP20(d));
8463
8464 case S390_AMODE_B20:
8465 case S390_AMODE_BX20:
8466 if (signed_multiply)
8467 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
8468 else
sewardjb13a92a2011-04-13 14:44:29 +00008469 return s390_emit_ML(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008470 }
8471 goto fail;
8472
8473 case 8:
8474 if (signed_multiply)
8475 vpanic("s390_insn_mul_emit");
8476 else
8477 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
8478
8479 default:
8480 goto fail;
8481 }
8482 }
8483
8484 case S390_OPND_IMMEDIATE: {
8485 ULong value = op2.variant.imm;
8486
8487 switch (insn->size) {
8488 case 1:
8489 case 2:
8490 case 4:
8491 buf = s390_emit_load_32imm(buf, R0, value);
8492 if (signed_multiply)
8493 return s390_emit_MR(buf, r1, R0);
8494 else
8495 return s390_emit_MLR(buf, r1, R0);
8496
8497 case 8:
8498 buf = s390_emit_load_64imm(buf, R0, value);
8499 if (signed_multiply)
8500 vpanic("s390_insn_mul_emit");
8501 else
8502 return s390_emit_MLGR(buf, r1, R0);
8503
8504 default:
8505 goto fail;
8506 }
8507 }
8508
8509 default:
8510 goto fail;
8511 }
8512
8513 fail:
8514 vpanic("s390_insn_mul_emit");
8515}
8516
8517
8518static UChar *
8519s390_insn_div_emit(UChar *buf, const s390_insn *insn)
8520{
8521 s390_opnd_RMI op2;
8522 UChar r1;
8523 Bool signed_divide;
8524
8525 r1 = hregNumber(insn->variant.div.op1_hi);
8526 op2 = insn->variant.div.op2;
florianc4aa7ed2012-12-22 15:01:04 +00008527 signed_divide = insn->tag == S390_INSN_SDIV;
sewardj2019a972011-03-07 16:04:07 +00008528
8529 switch (op2.tag) {
8530 case S390_OPND_REG: {
8531 UInt r2 = hregNumber(op2.variant.reg);
8532
8533 switch (insn->size) {
8534 case 4:
8535 if (signed_divide)
8536 return s390_emit_DR(buf, r1, r2);
8537 else
8538 return s390_emit_DLR(buf, r1, r2);
8539
8540 case 8:
8541 if (signed_divide)
8542 vpanic("s390_insn_div_emit");
8543 else
8544 return s390_emit_DLGR(buf, r1, r2);
8545
8546 default:
8547 goto fail;
8548 }
8549 }
8550
8551 case S390_OPND_AMODE: {
8552 const s390_amode *am = op2.variant.am;
8553 UChar b = hregNumber(am->b);
8554 UChar x = hregNumber(am->x);
8555 Int d = am->d;
8556
8557 switch (insn->size) {
8558 case 4:
8559 switch (am->tag) {
8560 case S390_AMODE_B12:
8561 case S390_AMODE_BX12:
8562 if (signed_divide)
8563 return s390_emit_D(buf, r1, x, b, d);
8564 else
8565 return s390_emit_DL(buf, r1, x, b, DISP20(d));
8566
8567 case S390_AMODE_B20:
8568 case S390_AMODE_BX20:
sewardjb13a92a2011-04-13 14:44:29 +00008569 if (signed_divide) {
8570 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008571 return s390_emit_DR(buf, r1, R0);
sewardjb13a92a2011-04-13 14:44:29 +00008572 } else
8573 return s390_emit_DL(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008574 }
8575 goto fail;
8576
8577 case 8:
8578 if (signed_divide)
8579 vpanic("s390_insn_div_emit");
8580 else
8581 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
8582
8583 default:
8584 goto fail;
8585 }
8586 }
8587
8588 case S390_OPND_IMMEDIATE: {
8589 ULong value = op2.variant.imm;
8590
8591 switch (insn->size) {
8592 case 4:
8593 buf = s390_emit_load_32imm(buf, R0, value);
8594 if (signed_divide)
8595 return s390_emit_DR(buf, r1, R0);
8596 else
8597 return s390_emit_DLR(buf, r1, R0);
8598
8599 case 8:
8600 buf = s390_emit_load_64imm(buf, R0, value);
8601 if (signed_divide)
8602 vpanic("s390_insn_div_emit");
8603 else
8604 return s390_emit_DLGR(buf, r1, R0);
8605
8606 default:
8607 goto fail;
8608 }
8609 }
8610
8611 default:
8612 goto fail;
8613 }
8614
8615 fail:
8616 vpanic("s390_insn_div_emit");
8617}
8618
8619
8620static UChar *
8621s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
8622{
8623 s390_opnd_RMI op2;
8624 UChar r1;
8625
8626 r1 = hregNumber(insn->variant.divs.rem);
8627 op2 = insn->variant.divs.op2;
8628
8629 switch (op2.tag) {
8630 case S390_OPND_REG: {
8631 UInt r2 = hregNumber(op2.variant.reg);
8632
8633 return s390_emit_DSGR(buf, r1, r2);
8634 }
8635
8636 case S390_OPND_AMODE: {
8637 const s390_amode *am = op2.variant.am;
8638 UChar b = hregNumber(am->b);
8639 UChar x = hregNumber(am->x);
8640 Int d = am->d;
8641
8642 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
8643 }
8644
8645 case S390_OPND_IMMEDIATE: {
8646 ULong value = op2.variant.imm;
8647
8648 buf = s390_emit_load_64imm(buf, R0, value);
8649 return s390_emit_DSGR(buf, r1, R0);
8650 }
8651
8652 default:
8653 goto fail;
8654 }
8655
8656 fail:
8657 vpanic("s390_insn_divs_emit");
8658}
8659
8660
8661static UChar *
sewardj611b06e2011-03-24 08:57:29 +00008662s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
sewardj2019a972011-03-07 16:04:07 +00008663{
8664 s390_opnd_RMI src;
sewardj611b06e2011-03-24 08:57:29 +00008665 UChar r1, r1p1, r2, *p;
sewardj2019a972011-03-07 16:04:07 +00008666
sewardj611b06e2011-03-24 08:57:29 +00008667 r1 = hregNumber(insn->variant.clz.num_bits);
8668 r1p1 = hregNumber(insn->variant.clz.clobber);
sewardj2019a972011-03-07 16:04:07 +00008669
8670 vassert((r1 & 0x1) == 0);
8671 vassert(r1p1 == r1 + 1);
8672
sewardj611b06e2011-03-24 08:57:29 +00008673 p = buf;
8674 src = insn->variant.clz.src;
sewardj2019a972011-03-07 16:04:07 +00008675
sewardj611b06e2011-03-24 08:57:29 +00008676 /* Get operand and move it to r2 */
sewardj2019a972011-03-07 16:04:07 +00008677 switch (src.tag) {
sewardj611b06e2011-03-24 08:57:29 +00008678 case S390_OPND_REG:
8679 r2 = hregNumber(src.variant.reg);
8680 break;
sewardj2019a972011-03-07 16:04:07 +00008681
8682 case S390_OPND_AMODE: {
8683 const s390_amode *am = src.variant.am;
8684 UChar b = hregNumber(am->b);
8685 UChar x = hregNumber(am->x);
8686 Int d = am->d;
8687
sewardj611b06e2011-03-24 08:57:29 +00008688 p = s390_emit_LG(p, R0, x, b, DISP20(d));
8689 r2 = R0;
8690 break;
sewardj2019a972011-03-07 16:04:07 +00008691 }
8692
8693 case S390_OPND_IMMEDIATE: {
8694 ULong value = src.variant.imm;
8695
sewardj611b06e2011-03-24 08:57:29 +00008696 p = s390_emit_load_64imm(p, R0, value);
8697 r2 = R0;
8698 break;
sewardj2019a972011-03-07 16:04:07 +00008699 }
8700
8701 default:
8702 goto fail;
8703 }
8704
sewardj611b06e2011-03-24 08:57:29 +00008705 /* Use FLOGR if you can */
8706 if (s390_host_has_eimm) {
8707 return s390_emit_FLOGR(p, r1, r2);
8708 }
8709
8710 /*
8711 r0 = r2;
8712 r1 = 64;
8713 while (r0 != 0) {
8714 r1 -= 1;
8715 r0 >>= 1;
8716 }
8717 */
8718 p = s390_emit_LTGR(p, R0, r2);
8719 p = s390_emit_LLILL(p, r1, 64);
8720
8721 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
8722 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
8723 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
8724 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
8725 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
8726 (UShort)(-(4 + 6 + 4) / 2));
8727 return p;
8728
sewardj2019a972011-03-07 16:04:07 +00008729 fail:
sewardj611b06e2011-03-24 08:57:29 +00008730 vpanic("s390_insn_clz_emit");
sewardj2019a972011-03-07 16:04:07 +00008731}
8732
8733
sewardjcfe046e2013-01-17 14:23:53 +00008734/* Returns a value == BUF to denote failure, != BUF to denote success. */
sewardj2019a972011-03-07 16:04:07 +00008735static UChar *
sewardj2019a972011-03-07 16:04:07 +00008736s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
8737{
8738 s390_cc_t cond;
8739 ULong target;
8740 UChar *ptmp = buf;
sewardj74142b82013-08-08 10:28:59 +00008741 s390_helper_call *helper_call = insn->variant.helper_call.details;
sewardj2019a972011-03-07 16:04:07 +00008742
sewardj74142b82013-08-08 10:28:59 +00008743 cond = helper_call->cond;
8744 target = helper_call->target;
sewardj2019a972011-03-07 16:04:07 +00008745
sewardjcfe046e2013-01-17 14:23:53 +00008746 if (cond != S390_CC_ALWAYS
sewardj74142b82013-08-08 10:28:59 +00008747 && helper_call->rloc.pri != RLPri_None) {
sewardjcfe046e2013-01-17 14:23:53 +00008748 /* The call might not happen (it isn't unconditional) and it
8749 returns a result. In this case we will need to generate a
8750 control flow diamond to put 0x555..555 in the return
8751 register(s) in the case where the call doesn't happen. If
8752 this ever becomes necessary, maybe copy code from the ARM
8753 equivalent. Until that day, just give up. */
floriandff20412014-09-25 20:33:50 +00008754 return buf; /* To denote failure. */
sewardjcfe046e2013-01-17 14:23:53 +00008755 }
8756
sewardj2019a972011-03-07 16:04:07 +00008757 if (cond != S390_CC_ALWAYS) {
8758 /* So we have something like this
8759 if (cond) call X;
8760 Y: ...
8761 We convert this into
8762 if (! cond) goto Y; // BRC opcode; 4 bytes
8763 call X;
8764 Y:
8765 */
8766 /* 4 bytes (a BRC insn) to be filled in here */
8767 buf += 4;
8768 }
8769
8770 /* Load the target address into a register, that
8771 (a) is not used for passing parameters to the helper and
8772 (b) can be clobbered by the callee
florianc9e90e52012-05-27 17:20:47 +00008773 (c) is not special to the BASR insn
8774 r1 is the only choice.
sewardj2019a972011-03-07 16:04:07 +00008775 Also, need to arrange for the return address be put into the
8776 link-register */
8777 buf = s390_emit_load_64imm(buf, 1, target);
8778
8779 /* Stash away the client's FPC register because the helper might change it. */
8780 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
8781
sewardj2019a972011-03-07 16:04:07 +00008782 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
florian01ed6e72012-05-27 16:52:43 +00008783
sewardj2019a972011-03-07 16:04:07 +00008784 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
8785 S390_OFFSET_SAVED_FPC_C);
8786
8787 if (cond != S390_CC_ALWAYS) {
8788 Int delta = buf - ptmp;
8789
8790 delta >>= 1; /* immediate constant is #half-words */
8791 vassert(delta > 0 && delta < (1 << 16));
8792 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8793 }
8794
8795 return buf;
8796}
8797
8798
8799static UChar *
8800s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
8801{
8802 HReg dst;
8803 s390_opnd_RMI src;
8804 s390_cc_t cond;
8805 UChar *p, *ptmp = 0; /* avoid compiler warnings */
8806
8807 cond = insn->variant.cond_move.cond;
8808 dst = insn->variant.cond_move.dst;
8809 src = insn->variant.cond_move.src;
8810
florian3a3d7f12012-12-03 13:32:05 +00008811 if (cond == S390_CC_NEVER) return buf;
8812
sewardj2019a972011-03-07 16:04:07 +00008813 p = buf;
8814
florianaec8e052012-12-09 17:26:32 +00008815 if (s390_host_has_lsc) {
florian3a3d7f12012-12-03 13:32:05 +00008816 /* LOCx is not the preferred way to implement an unconditional load. */
8817 if (cond != S390_CC_ALWAYS) goto use_branch_insn;
8818
8819 switch (src.tag) {
8820 case S390_OPND_REG:
8821 return s390_emit_LOCGR(p, cond, hregNumber(dst),
8822 hregNumber(src.variant.reg));
8823
8824 case S390_OPND_AMODE: {
8825 const s390_amode *am = src.variant.am;
8826
8827 /* We cannot use LOCx for loads less than 4 bytes. In that case
8828 load into R0 and then use LOCGR. Do the same if the amode uses
8829 an index register. */
8830 if (insn->size < 4 ||
8831 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
8832 p = s390_emit_load_mem(p, insn->size, R0, am);
8833 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8834 return p;
8835 }
8836
8837 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8838 vassert(insn->size == 4 || insn->size == 8);
8839
8840 UInt b = hregNumber(am->b);
8841 UInt d = am->d;
8842
8843 if (insn->size == 4) {
8844 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
8845 }
8846 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
8847 }
8848
8849 case S390_OPND_IMMEDIATE: {
8850 ULong value = src.variant.imm;
8851
8852 /* Load value into R0, then use LOCGR */
8853 if (insn->size <= 4) {
8854 p = s390_emit_load_32imm(p, R0, value);
8855 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8856 }
8857
8858 vassert(insn->size == 8);
8859 p = s390_emit_load_64imm(p, R0, value);
8860 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8861 }
8862 }
8863 }
8864
8865use_branch_insn:
sewardj2019a972011-03-07 16:04:07 +00008866 /* Branch (if cond fails) over move instrs */
8867 if (cond != S390_CC_ALWAYS) {
8868 /* Don't know how many bytes to jump over yet.
8869 Make space for a BRC instruction (4 bytes) and fill in later. */
8870 ptmp = p; /* to be filled in here */
8871 p += 4;
8872 }
8873
8874 // cond true: move src => dst
8875
8876 switch (src.tag) {
8877 case S390_OPND_REG:
8878 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
8879 break;
8880
8881 case S390_OPND_AMODE:
8882 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
8883 break;
8884
8885 case S390_OPND_IMMEDIATE: {
8886 ULong value = src.variant.imm;
8887 UInt r = hregNumber(dst);
8888
8889 switch (insn->size) {
8890 case 1:
8891 case 2:
8892 /* Load the immediate values as a 4 byte value. That does not hurt as
8893 those extra bytes will not be looked at. Fall through .... */
8894 case 4:
8895 p = s390_emit_load_32imm(p, r, value);
8896 break;
8897
8898 case 8:
8899 p = s390_emit_load_64imm(p, r, value);
8900 break;
8901 }
8902 break;
8903 }
8904
8905 default:
8906 goto fail;
8907 }
8908
8909 if (cond != S390_CC_ALWAYS) {
8910 Int delta = p - ptmp;
8911
8912 delta >>= 1; /* immediate constant is #half-words */
8913 vassert(delta > 0 && delta < (1 << 16));
8914 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8915 }
8916
8917 return p;
8918
8919 fail:
8920 vpanic("s390_insn_cond_move_emit");
8921}
8922
8923
sewardj2019a972011-03-07 16:04:07 +00008924static UChar *
8925s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
8926{
8927 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
8928 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
8929 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +00008930
8931 switch (insn->size) {
8932 case 4:
8933 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008934 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
8935 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008936 default: goto fail;
8937 }
8938 break;
8939
8940 case 8:
8941 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008942 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
8943 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008944 default: goto fail;
8945 }
8946 break;
8947
8948 default: goto fail;
8949 }
8950
sewardj2019a972011-03-07 16:04:07 +00008951 fail:
8952 vpanic("s390_insn_bfp_triop_emit");
8953}
8954
8955
8956static UChar *
8957s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
8958{
floriancc491a62012-09-10 23:44:37 +00008959 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
8960 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00008961
8962 switch (insn->size) {
8963 case 4:
8964 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008965 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
8966 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
8967 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
8968 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008969 default: goto fail;
8970 }
8971 break;
8972
8973 case 8:
8974 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008975 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
8976 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
8977 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
8978 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008979 default: goto fail;
8980 }
8981 break;
8982
floriancc491a62012-09-10 23:44:37 +00008983 case 16:
8984 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008985 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
8986 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
8987 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
8988 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008989 default: goto fail;
8990 }
8991 break;
8992
sewardj2019a972011-03-07 16:04:07 +00008993 default: goto fail;
8994 }
8995
sewardj2019a972011-03-07 16:04:07 +00008996 fail:
8997 vpanic("s390_insn_bfp_binop_emit");
8998}
8999
9000
9001static UChar *
9002s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
9003{
floriancc491a62012-09-10 23:44:37 +00009004 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
9005 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
sewardj2019a972011-03-07 16:04:07 +00009006
9007 switch (insn->variant.bfp_unop.tag) {
9008 case S390_BFP_ABS:
9009 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00009010 case 4: return s390_emit_LPEBR(buf, r1, r2);
9011 case 8: return s390_emit_LPDBR(buf, r1, r2);
9012 case 16: return s390_emit_LPXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00009013 default: goto fail;
9014 }
9015 break;
9016
9017 case S390_BFP_NABS:
9018 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00009019 case 4: return s390_emit_LNEBR(buf, r1, r2);
9020 case 8: return s390_emit_LNDBR(buf, r1, r2);
9021 case 16: return s390_emit_LNXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00009022 default: goto fail;
9023 }
9024 break;
9025
9026 case S390_BFP_NEG:
9027 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00009028 case 4: return s390_emit_LCEBR(buf, r1, r2);
9029 case 8: return s390_emit_LCDBR(buf, r1, r2);
9030 case 16: return s390_emit_LCXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00009031 default: goto fail;
9032 }
9033 break;
9034
9035 case S390_BFP_SQRT:
9036 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00009037 case 4: return s390_emit_SQEBR(buf, r1, r2);
9038 case 8: return s390_emit_SQDBR(buf, r1, r2);
9039 case 16: return s390_emit_SQXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00009040 default: goto fail;
9041 }
9042 break;
9043
florian9fcff4c2012-09-10 03:09:04 +00009044 default: goto fail;
9045 }
9046
florian9fcff4c2012-09-10 03:09:04 +00009047 fail:
9048 vpanic("s390_insn_bfp_unop_emit");
9049}
9050
9051
9052static UChar *
9053s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
9054{
floriancc491a62012-09-10 23:44:37 +00009055 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
9056 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
florian125e20d2012-10-07 15:42:37 +00009057 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
florian2c74d242012-09-12 19:38:42 +00009058 /* The IEEE-inexact-exception control is not modelled. So the
9059 m4 field is 0 (which is what GCC does, too) */
9060 const UInt m4 = 0;
florian9fcff4c2012-09-10 03:09:04 +00009061
florian9fcff4c2012-09-10 03:09:04 +00009062 switch (insn->variant.bfp_convert.tag) {
floriancc491a62012-09-10 23:44:37 +00009063 /* Convert to fixed */
florian9fcff4c2012-09-10 03:09:04 +00009064 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
9065 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00009066 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00009067 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
9068 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00009069 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00009070
floriancc491a62012-09-10 23:44:37 +00009071 /* Convert to logical */
florian2c74d242012-09-12 19:38:42 +00009072 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
9073 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
9074 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
9075 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
9076 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
9077 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00009078
florian2c74d242012-09-12 19:38:42 +00009079 /* Convert from fixed */
9080 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
9081 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
9082 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
9083 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
9084 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
9085 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
9086
9087 /* Convert from logical */
9088 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
9089 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
9090 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
9091 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
9092 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
9093 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
9094
9095 /* Load lengthened */
9096 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00009097 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
9098 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00009099
florian2c74d242012-09-12 19:38:42 +00009100 /* Load rounded */
9101 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
9102 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
9103 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
floriancc491a62012-09-10 23:44:37 +00009104
sewardj2019a972011-03-07 16:04:07 +00009105 default: goto fail;
9106 }
9107
sewardj2019a972011-03-07 16:04:07 +00009108 fail:
florian9fcff4c2012-09-10 03:09:04 +00009109 vpanic("s390_insn_bfp_convert_emit");
sewardj2019a972011-03-07 16:04:07 +00009110}
9111
9112
9113static UChar *
9114s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
9115{
9116 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +00009117 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
9118 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00009119
9120 switch (insn->size) {
floriancc491a62012-09-10 23:44:37 +00009121 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
9122 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
9123 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
sewardj2019a972011-03-07 16:04:07 +00009124 default: goto fail;
9125 }
9126
9127 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
9128
9129 fail:
9130 vpanic("s390_insn_bfp_compare_emit");
9131}
9132
9133
9134static UChar *
florian12390202012-11-10 22:34:14 +00009135s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
9136{
florianc4aa7ed2012-12-22 15:01:04 +00009137 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
9138
9139 UInt r1 = hregNumber(dfp_binop->dst_hi);
9140 UInt r2 = hregNumber(dfp_binop->op2_hi);
9141 UInt r3 = hregNumber(dfp_binop->op3_hi);
florian89bb1a92013-01-10 15:41:46 +00009142 s390_dfp_round_t m4 = dfp_binop->rounding_mode;
florian12390202012-11-10 22:34:14 +00009143
9144 switch (insn->size) {
9145 case 8:
florianc4aa7ed2012-12-22 15:01:04 +00009146 switch (dfp_binop->tag) {
florian362e2712013-01-22 14:02:05 +00009147 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2);
9148 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2);
9149 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2);
9150 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2);
florian5c539732013-02-14 14:27:12 +00009151 case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2);
florian12390202012-11-10 22:34:14 +00009152 default: goto fail;
9153 }
9154 break;
floriane38f6412012-12-21 17:32:12 +00009155
9156 case 16:
florianc4aa7ed2012-12-22 15:01:04 +00009157 switch (dfp_binop->tag) {
floriane38f6412012-12-21 17:32:12 +00009158 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2);
9159 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2);
9160 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2);
9161 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2);
florian5c539732013-02-14 14:27:12 +00009162 case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2);
floriane38f6412012-12-21 17:32:12 +00009163 default: goto fail;
9164 }
9165 break;
9166
florian12390202012-11-10 22:34:14 +00009167 default: goto fail;
9168 }
9169
9170 fail:
9171 vpanic("s390_insn_dfp_binop_emit");
9172}
9173
9174
9175static UChar *
florian5c539732013-02-14 14:27:12 +00009176s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn)
9177{
9178 UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi);
9179 UInt r2 = hregNumber(insn->variant.dfp_reround.op2);
9180 UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi);
9181 s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode;
9182
9183 switch (insn->size) {
9184 case 8:
9185 return s390_emit_RRDTR(buf, r3, m4, r1, r2);
9186
9187 case 16:
9188 return s390_emit_RRXTR(buf, r3, m4, r1, r2);
9189
9190 default: goto fail;
9191 }
9192 fail:
9193 vpanic("s390_insn_dfp_reround_emit");
9194}
9195
9196
9197static UChar *
floriance9e3db2012-12-27 20:14:03 +00009198s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
9199{
9200 UInt r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
9201 UInt r2 = hregNumber(insn->variant.dfp_unop.op_hi);
9202
9203 switch (insn->variant.dfp_unop.tag) {
florian5c539732013-02-14 14:27:12 +00009204 case S390_DFP_EXTRACT_EXP_D64: return s390_emit_EEDTR(buf, r1, r2); break;
9205 case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break;
floriance9e3db2012-12-27 20:14:03 +00009206 case S390_DFP_EXTRACT_SIG_D64: return s390_emit_ESDTR(buf, r1, r2); break;
9207 case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
9208 default: goto fail;
9209 }
9210 fail:
9211 vpanic("s390_insn_dfp_unop_emit");
9212}
9213
9214
9215static UChar *
florian1b901d42013-01-01 22:19:24 +00009216s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn)
9217{
9218 UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi);
9219 UInt r2 = hregNumber(insn->variant.dfp_intop.op2);
9220 UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi);
9221
9222 switch (insn->size) {
9223 case 8:
9224 switch (insn->variant.dfp_intop.tag) {
9225 case S390_DFP_SHIFT_LEFT: return s390_emit_SLDT(buf, r3, r1, r2);
9226 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2);
florian5c539732013-02-14 14:27:12 +00009227 case S390_DFP_INSERT_EXP: return s390_emit_IEDTR(buf, r3, r1, r2);
florian1b901d42013-01-01 22:19:24 +00009228 default: goto fail;
9229 }
9230 break;
9231
9232 case 16:
9233 switch (insn->variant.dfp_intop.tag) {
9234 case S390_DFP_SHIFT_LEFT: return s390_emit_SLXT(buf, r3, r1, r2);
9235 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2);
florian5c539732013-02-14 14:27:12 +00009236 case S390_DFP_INSERT_EXP: return s390_emit_IEXTR(buf, r3, r1, r2);
florian1b901d42013-01-01 22:19:24 +00009237 default: goto fail;
9238 }
9239 break;
9240
9241 default: goto fail;
9242 }
9243
9244 fail:
9245 vpanic("s390_insn_dfp_intop_emit");
9246}
9247
9248
9249static UChar *
floriane38f6412012-12-21 17:32:12 +00009250s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
9251{
9252 UInt dst = hregNumber(insn->variant.dfp_compare.dst);
9253 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi);
9254 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi);
9255
9256 switch (insn->size) {
florian20c6bca2012-12-26 17:47:19 +00009257 case 8:
9258 switch(insn->variant.dfp_compare.tag) {
9259 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break;
9260 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
9261 default: goto fail;
9262 }
9263 break;
9264
9265 case 16:
9266 switch(insn->variant.dfp_compare.tag) {
9267 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break;
9268 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
9269 default: goto fail;
9270 }
9271 break;
9272
floriane38f6412012-12-21 17:32:12 +00009273 default: goto fail;
9274 }
9275
9276 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
9277
9278 fail:
9279 vpanic("s390_insn_dfp_compare_emit");
9280}
9281
9282
9283static UChar *
9284s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
9285{
9286 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
9287 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi);
9288 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
9289 /* The IEEE-inexact-exception control is not modelled. So the
9290 m4 field is 0 (which is what GCC does, too) */
9291 const UInt m4 = 0;
9292
9293 switch (insn->variant.dfp_convert.tag) {
9294
florian5f034622013-01-13 02:29:05 +00009295 /* Convert to fixed */
9296 case S390_DFP_D64_TO_I32: return s390_emit_CFDTR(buf, m3, m4, r1, r2);
9297 case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2);
floriana887acd2013-02-08 23:32:54 +00009298 case S390_DFP_D64_TO_I64: return s390_emit_CGDTR(buf, m3, m4, r1, r2);
9299 case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2);
florian5f034622013-01-13 02:29:05 +00009300
9301 /* Convert to logical */
9302 case S390_DFP_D64_TO_U32: return s390_emit_CLFDTR(buf, m3, m4, r1, r2);
9303 case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2);
9304 case S390_DFP_D64_TO_U64: return s390_emit_CLGDTR(buf, m3, m4, r1, r2);
9305 case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2);
9306
9307 /* Convert from fixed */
9308 case S390_DFP_I32_TO_D64: return s390_emit_CDFTR(buf, 0, m4, r1, r2);
9309 case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2);
floriana887acd2013-02-08 23:32:54 +00009310 case S390_DFP_I64_TO_D64: return s390_emit_CDGTRA(buf, m3, m4, r1, r2);
9311 case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2);
florian5f034622013-01-13 02:29:05 +00009312
9313 /* Convert from logical */
9314 case S390_DFP_U32_TO_D64: return s390_emit_CDLFTR(buf, m3, m4, r1, r2);
9315 case S390_DFP_U64_TO_D64: return s390_emit_CDLGTR(buf, m3, m4, r1, r2);
9316 case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2);
9317 case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2);
9318
floriane38f6412012-12-21 17:32:12 +00009319 /* Load lengthened */
9320 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2);
9321 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2);
9322
9323 /* Load rounded */
9324 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2);
9325 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2);
9326
9327 default: goto fail;
9328 }
9329
9330 fail:
9331 vpanic("s390_insn_dfp_convert_emit");
9332}
9333
9334
9335static UChar *
florian78d5ef72013-05-11 15:02:58 +00009336s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
9337{
9338 UInt pfpo;
9339 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
9340 s390_dfp_round_t rm = fp_convert->rounding_mode;
9341
9342 vassert(rm < 2 || rm > 7);
9343
9344 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00009345 case S390_FP_F32_TO_D32: pfpo = S390_PFPO_F32_TO_D32 << 8; break;
9346 case S390_FP_F32_TO_D64: pfpo = S390_PFPO_F32_TO_D64 << 8; break;
9347 case S390_FP_F32_TO_D128: pfpo = S390_PFPO_F32_TO_D128 << 8; break;
9348 case S390_FP_F64_TO_D32: pfpo = S390_PFPO_F64_TO_D32 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009349 case S390_FP_F64_TO_D64: pfpo = S390_PFPO_F64_TO_D64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009350 case S390_FP_F64_TO_D128: pfpo = S390_PFPO_F64_TO_D128 << 8; break;
florian7ab421d2013-06-17 21:03:56 +00009351 case S390_FP_F128_TO_D32: pfpo = S390_PFPO_F128_TO_D32 << 8; break;
9352 case S390_FP_F128_TO_D64: pfpo = S390_PFPO_F128_TO_D64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009353 case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
florian7ab421d2013-06-17 21:03:56 +00009354 case S390_FP_D32_TO_F32: pfpo = S390_PFPO_D32_TO_F32 << 8; break;
9355 case S390_FP_D32_TO_F64: pfpo = S390_PFPO_D32_TO_F64 << 8; break;
9356 case S390_FP_D32_TO_F128: pfpo = S390_PFPO_D32_TO_F128 << 8; break;
9357 case S390_FP_D64_TO_F32: pfpo = S390_PFPO_D64_TO_F32 << 8; break;
9358 case S390_FP_D64_TO_F64: pfpo = S390_PFPO_D64_TO_F64 << 8; break;
9359 case S390_FP_D64_TO_F128: pfpo = S390_PFPO_D64_TO_F128 << 8; break;
9360 case S390_FP_D128_TO_F32: pfpo = S390_PFPO_D128_TO_F32 << 8; break;
9361 case S390_FP_D128_TO_F64: pfpo = S390_PFPO_D128_TO_F64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009362 case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
9363 default: goto fail;
9364 }
9365
9366 pfpo = pfpo | rm;
9367 buf = s390_emit_load_32imm(buf, R0, pfpo);
9368 buf = s390_emit_PFPO(buf);
9369 return buf;
9370
9371 fail:
9372 vpanic("s390_insn_fp_convert_emit");
9373}
9374
9375
9376static UChar *
sewardja52e37e2011-04-28 18:48:06 +00009377s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
9378{
9379 return s390_emit_BCR(buf, 0xF, 0x0);
9380}
9381
9382
florianad43b3a2012-02-20 15:01:14 +00009383static UChar *
florianb93348d2012-12-27 00:59:43 +00009384s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00009385{
florianb93348d2012-12-27 00:59:43 +00009386 s390_amode *am = insn->variant.mimm.dst;
florian3123f722013-01-24 15:55:52 +00009387 UChar b = hregNumber(am->b);
florian3123f722013-01-24 15:55:52 +00009388 Int d = am->d;
florianb93348d2012-12-27 00:59:43 +00009389 ULong value = insn->variant.mimm.value;
florian09bbba82012-12-11 04:09:43 +00009390
florianb93348d2012-12-27 00:59:43 +00009391 if (value == 0) {
florian3123f722013-01-24 15:55:52 +00009392 return s390_emit_XC(buf, insn->size - 1, b, d, b, d);
florianb93348d2012-12-27 00:59:43 +00009393 }
9394
9395 if (insn->size == 1) {
florian3123f722013-01-24 15:55:52 +00009396 return s390_emit_MVI(buf, value & 0xFF, b, d);
florianb93348d2012-12-27 00:59:43 +00009397 }
9398
9399 if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
9400 value &= 0xFFFF;
9401 switch (insn->size) {
florian3123f722013-01-24 15:55:52 +00009402 case 2: return s390_emit_MVHHI(buf, b, d, value);
9403 case 4: return s390_emit_MVHI(buf, b, d, value);
9404 case 8: return s390_emit_MVGHI(buf, b, d, value);
florianb93348d2012-12-27 00:59:43 +00009405 }
9406 } else {
9407 // Load value to R0, then store.
9408 switch (insn->size) {
9409 case 2:
9410 buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
florian3123f722013-01-24 15:55:52 +00009411 return s390_emit_STH(buf, R0, 0, b, d);
florianb93348d2012-12-27 00:59:43 +00009412 case 4:
9413 buf = s390_emit_load_32imm(buf, R0, value);
florian3123f722013-01-24 15:55:52 +00009414 return s390_emit_ST(buf, R0, 0, b, d);
florianb93348d2012-12-27 00:59:43 +00009415 case 8:
9416 buf = s390_emit_load_64imm(buf, R0, value);
florian3123f722013-01-24 15:55:52 +00009417 return s390_emit_STG(buf, R0, 0, b, DISP20(d));
florianb93348d2012-12-27 00:59:43 +00009418 }
9419 }
9420
9421 vpanic("s390_insn_mimm_emit");
florianad43b3a2012-02-20 15:01:14 +00009422}
9423
9424
9425static UChar *
florianf85fe3e2012-12-22 02:28:25 +00009426s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00009427{
florianf85fe3e2012-12-22 02:28:25 +00009428 s390_amode *am = insn->variant.madd.dst;
florian3123f722013-01-24 15:55:52 +00009429 UChar b = hregNumber(am->b);
florian3123f722013-01-24 15:55:52 +00009430 Int d = am->d;
florianf85fe3e2012-12-22 02:28:25 +00009431
9432 if (insn->size == 4) {
florian3123f722013-01-24 15:55:52 +00009433 return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d));
florianf85fe3e2012-12-22 02:28:25 +00009434 }
9435
florian3123f722013-01-24 15:55:52 +00009436 return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d));
florianad43b3a2012-02-20 15:01:14 +00009437}
9438
9439
florian2c74d242012-09-12 19:38:42 +00009440static UChar *
florian125e20d2012-10-07 15:42:37 +00009441s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
florian2c74d242012-09-12 19:38:42 +00009442{
florian125e20d2012-10-07 15:42:37 +00009443 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00009444
9445 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
9446 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
9447 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
9448
9449 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
9450 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
florian6d8e26e2012-09-12 19:52:16 +00009451 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
florian2c74d242012-09-12 19:38:42 +00009452
9453 return buf;
9454}
9455
9456
florianc8e4f562012-10-27 16:19:31 +00009457static UChar *
9458s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
9459{
9460 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
9461
9462 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
9463 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
9464 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
9465
9466 /* DFP rounding mode is set at bit position 25:27 in FPC register */
9467 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
9468 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
9469 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
9470 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
9471
9472 return buf;
9473}
9474
9475
florian8844a632012-04-13 04:04:06 +00009476/* Define convenience functions needed for translation chaining.
9477 Any changes need to be applied to the functions in concert. */
9478
florian1c857042012-04-15 04:11:07 +00009479static __inline__ Bool
9480s390_insn_is_BRCL(const UChar *p, UChar condition)
9481{
9482 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
9483}
9484
9485static __inline__ Bool
9486s390_insn_is_BR(const UChar *p, UChar reg)
9487{
9488 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
9489}
9490
florianebaf8d92012-04-22 17:38:46 +00009491
9492/* The length of the BASR insn */
9493#define S390_BASR_LEN 2
9494
florian1c857042012-04-15 04:11:07 +00009495
florian8844a632012-04-13 04:04:06 +00009496/* Load the 64-bit VALUE into REG. Note that this function must NOT
9497 optimise the generated code by looking at the value. I.e. using
floriane09e8bb2012-05-07 03:28:18 +00009498 LGHI if value == 0 would be very wrong. */
florian8844a632012-04-13 04:04:06 +00009499static UChar *
9500s390_tchain_load64(UChar *buf, UChar regno, ULong value)
9501{
florian1c857042012-04-15 04:11:07 +00009502 UChar *begin = buf;
9503
florian1c2b4db2012-04-22 17:46:31 +00009504 if (s390_host_has_eimm) {
9505 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
9506 buf = s390_emit_IIHF(buf, regno, value >> 32);
9507 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
9508 } else {
9509 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
9510 value >>= 16;
9511 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
9512 value >>= 16;
9513 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
9514 value >>= 16;
9515 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
9516 }
florian8844a632012-04-13 04:04:06 +00009517
florian1c857042012-04-15 04:11:07 +00009518 vassert(buf - begin == s390_tchain_load64_len());
9519
florian8844a632012-04-13 04:04:06 +00009520 return buf;
9521}
9522
9523/* Return number of bytes generated by s390_tchain_load64 */
9524static UInt
9525s390_tchain_load64_len(void)
9526{
florian1c2b4db2012-04-22 17:46:31 +00009527 if (s390_host_has_eimm) {
9528 return 6 + 6; /* IIHF + IILF */
9529 }
florianebaf8d92012-04-22 17:38:46 +00009530 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
florian8844a632012-04-13 04:04:06 +00009531}
9532
9533/* Verify that CODE is the code sequence generated by s390_tchain_load64
9534 to load VALUE into REGNO. Return pointer to the byte following the
9535 insn sequence. */
9536static const UChar *
9537s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
9538{
9539 UInt regmask = regno << 4;
9540 UInt hw;
9541
florian1c2b4db2012-04-22 17:46:31 +00009542 if (s390_host_has_eimm) {
9543 /* Check for IIHF */
9544 vassert(code[0] == 0xC0);
9545 vassert(code[1] == (0x08 | regmask));
9546 vassert(*(const UInt *)&code[2] == (value >> 32));
9547 /* Check for IILF */
9548 vassert(code[6] == 0xC0);
9549 vassert(code[7] == (0x09 | regmask));
9550 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
9551 } else {
9552 /* Check for IILL */
9553 hw = value & 0xFFFF;
9554 vassert(code[0] == 0xA5);
9555 vassert(code[1] == (0x03 | regmask));
9556 vassert(code[2] == (hw >> 8));
9557 vassert(code[3] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009558
florian1c2b4db2012-04-22 17:46:31 +00009559 /* Check for IILH */
9560 hw = (value >> 16) & 0xFFFF;
9561 vassert(code[4] == 0xA5);
9562 vassert(code[5] == (0x02 | regmask));
9563 vassert(code[6] == (hw >> 8));
9564 vassert(code[7] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009565
florian1c2b4db2012-04-22 17:46:31 +00009566 /* Check for IIHL */
9567 hw = (value >> 32) & 0xFFFF;
9568 vassert(code[8] == 0xA5);
9569 vassert(code[9] == (0x01 | regmask));
9570 vassert(code[10] == (hw >> 8));
9571 vassert(code[11] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009572
florian1c2b4db2012-04-22 17:46:31 +00009573 /* Check for IIHH */
9574 hw = (value >> 48) & 0xFFFF;
9575 vassert(code[12] == 0xA5);
9576 vassert(code[13] == (0x00 | regmask));
9577 vassert(code[14] == (hw >> 8));
9578 vassert(code[15] == (hw & 0xFF));
9579 }
florian8844a632012-04-13 04:04:06 +00009580
florian1c857042012-04-15 04:11:07 +00009581 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00009582}
9583
9584/* CODE points to the code sequence as generated by s390_tchain_load64.
florian5ea257b2012-09-29 17:05:46 +00009585 Change the loaded value to IMM64. Return pointer to the byte following
florian8844a632012-04-13 04:04:06 +00009586 the patched code sequence. */
9587static UChar *
9588s390_tchain_patch_load64(UChar *code, ULong imm64)
9589{
florian1c2b4db2012-04-22 17:46:31 +00009590 if (s390_host_has_eimm) {
9591 /* Patch IIHF */
9592 *(UInt *)&code[2] = imm64 >> 32;
9593 /* Patch IILF */
9594 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
9595 } else {
9596 code[3] = imm64 & 0xFF; imm64 >>= 8;
9597 code[2] = imm64 & 0xFF; imm64 >>= 8;
9598 code[7] = imm64 & 0xFF; imm64 >>= 8;
9599 code[6] = imm64 & 0xFF; imm64 >>= 8;
9600 code[11] = imm64 & 0xFF; imm64 >>= 8;
9601 code[10] = imm64 & 0xFF; imm64 >>= 8;
9602 code[15] = imm64 & 0xFF; imm64 >>= 8;
9603 code[14] = imm64 & 0xFF; imm64 >>= 8;
9604 }
florian8844a632012-04-13 04:04:06 +00009605
florian1c857042012-04-15 04:11:07 +00009606 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00009607}
9608
9609
9610/* NB: what goes on here has to be very closely coordinated with the
9611 chainXDirect_S390 and unchainXDirect_S390 below. */
9612static UChar *
9613s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
florian8462d112014-09-24 15:18:09 +00009614 const void *disp_cp_chain_me_to_slowEP,
9615 const void *disp_cp_chain_me_to_fastEP)
florian8844a632012-04-13 04:04:06 +00009616{
9617 /* We're generating chain-me requests here, so we need to be
9618 sure this is actually allowed -- no-redir translations can't
9619 use chain-me's. Hence: */
9620 vassert(disp_cp_chain_me_to_slowEP != NULL);
9621 vassert(disp_cp_chain_me_to_fastEP != NULL);
9622
9623 /* Use ptmp for backpatching conditional jumps. */
9624 UChar *ptmp = buf;
9625
9626 /* First off, if this is conditional, create a conditional
9627 jump over the rest of it. */
9628 s390_cc_t cond = insn->variant.xdirect.cond;
9629
9630 if (cond != S390_CC_ALWAYS) {
9631 /* So we have something like this
9632 if (cond) do_xdirect;
9633 Y: ...
9634 We convert this into
9635 if (! cond) goto Y; // BRC opcode; 4 bytes
9636 do_xdirect;
9637 Y:
9638 */
9639 /* 4 bytes (a BRC insn) to be filled in here */
9640 buf += 4;
9641 }
9642
9643 /* Update the guest IA. */
9644 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
9645
9646 const s390_amode *amode = insn->variant.xdirect.guest_IA;
florianbf516d12012-04-21 15:53:13 +00009647 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009648 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009649 UInt d = amode->d;
9650
florianbf516d12012-04-21 15:53:13 +00009651 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009652
florian8844a632012-04-13 04:04:06 +00009653 /* Load the chosen entry point into the scratch reg */
florian8462d112014-09-24 15:18:09 +00009654 const void *disp_cp_chain_me;
florian8844a632012-04-13 04:04:06 +00009655
9656 disp_cp_chain_me =
9657 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
9658 : disp_cp_chain_me_to_slowEP;
florianebaf8d92012-04-22 17:38:46 +00009659 /* Get the address of the beginning of the load64 code sequence into %r1.
9660 Do not change the register! This is part of the protocol with the
9661 dispatcher. */
9662 buf = s390_emit_BASR(buf, 1, R0);
florian8844a632012-04-13 04:04:06 +00009663
florianebaf8d92012-04-22 17:38:46 +00009664 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
florian8844a632012-04-13 04:04:06 +00009665 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
9666 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
9667
florianebaf8d92012-04-22 17:38:46 +00009668 /* goto *tchain_scratch */
9669 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00009670
9671 /* --- END of PATCHABLE BYTES --- */
9672
9673 /* Fix up the conditional jump, if there was one. */
9674 if (cond != S390_CC_ALWAYS) {
9675 Int delta = buf - ptmp;
9676
9677 delta >>= 1; /* immediate constant is #half-words */
9678 vassert(delta > 0 && delta < (1 << 16));
9679 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9680 }
9681
9682 return buf;
9683}
9684
9685/* Return the number of patchable bytes from an xdirect insn. */
9686static UInt
9687s390_xdirect_patchable_len(void)
9688{
florianebaf8d92012-04-22 17:38:46 +00009689 return s390_tchain_load64_len() + S390_BASR_LEN;
florian8844a632012-04-13 04:04:06 +00009690}
9691
9692
9693static UChar *
florian8462d112014-09-24 15:18:09 +00009694s390_insn_xindir_emit(UChar *buf, const s390_insn *insn,
9695 const void *disp_cp_xindir)
florian8844a632012-04-13 04:04:06 +00009696{
9697 /* We're generating transfers that could lead indirectly to a
9698 chain-me, so we need to be sure this is actually allowed --
9699 no-redir translations are not allowed to reach normal
9700 translations without going through the scheduler. That means
9701 no XDirects or XIndirs out from no-redir translations.
9702 Hence: */
9703 vassert(disp_cp_xindir != NULL);
9704
9705 /* Use ptmp for backpatching conditional jumps. */
9706 UChar *ptmp = buf;
9707
9708 /* First off, if this is conditional, create a conditional
9709 jump over the rest of it. */
9710 s390_cc_t cond = insn->variant.xdirect.cond;
9711
9712 if (cond != S390_CC_ALWAYS) {
9713 /* So we have something like this
9714 if (cond) do_xdirect;
9715 Y: ...
9716 We convert this into
9717 if (! cond) goto Y; // BRC opcode; 4 bytes
9718 do_xdirect;
9719 Y:
9720 */
9721 /* 4 bytes (a BRC insn) to be filled in here */
9722 buf += 4;
9723 }
9724
9725 /* Update the guest IA with the address in xdirect.dst. */
florian7346c7a2012-04-13 21:14:24 +00009726 const s390_amode *amode = insn->variant.xindir.guest_IA;
florian8844a632012-04-13 04:04:06 +00009727
florianbf516d12012-04-21 15:53:13 +00009728 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009729 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009730 UInt d = amode->d;
florian7346c7a2012-04-13 21:14:24 +00009731 UInt regno = hregNumber(insn->variant.xindir.dst);
florian8844a632012-04-13 04:04:06 +00009732
florianbf516d12012-04-21 15:53:13 +00009733 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009734
9735 /* load tchain_scratch, #disp_indir */
9736 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
9737 Ptr_to_ULong(disp_cp_xindir));
florianebaf8d92012-04-22 17:38:46 +00009738 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00009739 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9740
9741 /* Fix up the conditional jump, if there was one. */
9742 if (cond != S390_CC_ALWAYS) {
9743 Int delta = buf - ptmp;
9744
9745 delta >>= 1; /* immediate constant is #half-words */
9746 vassert(delta > 0 && delta < (1 << 16));
9747 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9748 }
9749
9750 return buf;
9751}
9752
9753static UChar *
9754s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
florian8462d112014-09-24 15:18:09 +00009755 const void *disp_cp_xassisted)
florian8844a632012-04-13 04:04:06 +00009756{
9757 /* Use ptmp for backpatching conditional jumps. */
9758 UChar *ptmp = buf;
9759
9760 /* First off, if this is conditional, create a conditional
9761 jump over the rest of it. */
9762 s390_cc_t cond = insn->variant.xdirect.cond;
9763
9764 if (cond != S390_CC_ALWAYS) {
9765 /* So we have something like this
9766 if (cond) do_xdirect;
9767 Y: ...
9768 We convert this into
9769 if (! cond) goto Y; // BRC opcode; 4 bytes
9770 do_xdirect;
9771 Y:
9772 */
9773 /* 4 bytes (a BRC insn) to be filled in here */
9774 buf += 4;
9775 }
9776
9777 /* Update the guest IA with the address in xassisted.dst. */
9778 const s390_amode *amode = insn->variant.xassisted.guest_IA;
9779
florianbf516d12012-04-21 15:53:13 +00009780 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009781 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009782 UInt d = amode->d;
9783 UInt regno = hregNumber(insn->variant.xassisted.dst);
9784
florianbf516d12012-04-21 15:53:13 +00009785 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009786
9787 UInt trcval = 0;
9788
9789 switch (insn->variant.xassisted.kind) {
9790 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
9791 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
florian8844a632012-04-13 04:04:06 +00009792 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
9793 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
florian4e0083e2012-08-26 03:41:56 +00009794 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
florian8844a632012-04-13 04:04:06 +00009795 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
9796 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
sewardj05f5e012014-05-04 10:52:11 +00009797 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
florian8844a632012-04-13 04:04:06 +00009798 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
9799 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
9800 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
9801 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
9802 /* We don't expect to see the following being assisted. */
9803 case Ijk_Ret:
9804 case Ijk_Call:
9805 /* fallthrough */
9806 default:
9807 ppIRJumpKind(insn->variant.xassisted.kind);
9808 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
9809 }
9810
9811 vassert(trcval != 0);
9812
9813 /* guest_state_pointer = trcval */
9814 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
9815
9816 /* load tchain_scratch, #disp_assisted */
9817 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
9818 Ptr_to_ULong(disp_cp_xassisted));
9819
florianebaf8d92012-04-22 17:38:46 +00009820 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00009821 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9822
9823 /* Fix up the conditional jump, if there was one. */
9824 if (cond != S390_CC_ALWAYS) {
9825 Int delta = buf - ptmp;
9826
9827 delta >>= 1; /* immediate constant is #half-words */
9828 vassert(delta > 0 && delta < (1 << 16));
9829 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9830 }
9831
9832 return buf;
9833}
9834
9835
9836/* Pseudo code:
9837
9838 guest_state[host_EvC_COUNTER] -= 1;
9839 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
9840 goto guest_state[host_EvC_FAILADDR];
9841 nofail: ;
9842
9843 The dispatch counter is a 32-bit value. */
9844static UChar *
sewardj9b769162014-07-24 12:42:03 +00009845s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn,
9846 VexEndness endness_host)
florian8844a632012-04-13 04:04:06 +00009847{
9848 s390_amode *amode;
florianbf516d12012-04-21 15:53:13 +00009849 UInt b, d;
florian8844a632012-04-13 04:04:06 +00009850 UChar *code_begin, *code_end;
9851
9852 code_begin = buf;
9853
9854 amode = insn->variant.evcheck.counter;
florianbf516d12012-04-21 15:53:13 +00009855 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009856 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009857 d = amode->d;
9858
9859 /* Decrement the dispatch counter in the guest state */
florian0e047d62012-04-21 16:06:04 +00009860 if (s390_host_has_gie) {
9861 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
9862 } else {
9863 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
9864 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
9865 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
9866 }
florian8844a632012-04-13 04:04:06 +00009867
9868 /* Jump over the next insn if >= 0 */
9869 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
9870
9871 /* Computed goto to fail_address */
9872 amode = insn->variant.evcheck.fail_addr;
9873 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009874 d = amode->d;
florianbf516d12012-04-21 15:53:13 +00009875 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
florian8844a632012-04-13 04:04:06 +00009876 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
9877
9878 code_end = buf;
9879
9880 /* Make sure the size of the generated code is identical to the size
9881 returned by evCheckSzB_S390 */
sewardj9b769162014-07-24 12:42:03 +00009882 vassert(evCheckSzB_S390(endness_host) == code_end - code_begin);
florian8844a632012-04-13 04:04:06 +00009883
9884 return buf;
9885}
9886
9887
9888static UChar *
9889s390_insn_profinc_emit(UChar *buf,
9890 const s390_insn *insn __attribute__((unused)))
9891{
9892 /* Generate a code template to increment a memory location whose
9893 address will be known later as an immediate value. This code
9894 template will be patched once the memory location is known.
9895 For now we do this with address == 0. */
9896 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
florian0e047d62012-04-21 16:06:04 +00009897 if (s390_host_has_gie) {
9898 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9899 } else {
9900 buf = s390_emit_LGHI(buf, R0, 1);
9901 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9902 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9903 }
florian8844a632012-04-13 04:04:06 +00009904
9905 return buf;
9906}
9907
9908
sewardj2019a972011-03-07 16:04:07 +00009909Int
floriand8c64e02014-10-08 08:54:44 +00009910emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn,
sewardj9b769162014-07-24 12:42:03 +00009911 Bool mode64, VexEndness endness_host,
florian8462d112014-09-24 15:18:09 +00009912 const void *disp_cp_chain_me_to_slowEP,
9913 const void *disp_cp_chain_me_to_fastEP,
9914 const void *disp_cp_xindir,
9915 const void *disp_cp_xassisted)
sewardj2019a972011-03-07 16:04:07 +00009916{
9917 UChar *end;
9918
florianc4aa7ed2012-12-22 15:01:04 +00009919 /* Used to be 48 bytes. Make sure it stays low */
9920 vassert(sizeof(s390_insn) == 32);
9921
sewardj2019a972011-03-07 16:04:07 +00009922 switch (insn->tag) {
9923 case S390_INSN_LOAD:
9924 end = s390_insn_load_emit(buf, insn);
9925 break;
9926
9927 case S390_INSN_STORE:
9928 end = s390_insn_store_emit(buf, insn);
9929 break;
9930
9931 case S390_INSN_MOVE:
9932 end = s390_insn_move_emit(buf, insn);
9933 break;
9934
floriancec3a8a2013-02-02 00:16:58 +00009935 case S390_INSN_MEMCPY:
9936 end = s390_insn_memcpy_emit(buf, insn);
9937 break;
9938
sewardj2019a972011-03-07 16:04:07 +00009939 case S390_INSN_COND_MOVE:
9940 end = s390_insn_cond_move_emit(buf, insn);
9941 break;
9942
9943 case S390_INSN_LOAD_IMMEDIATE:
9944 end = s390_insn_load_immediate_emit(buf, insn);
9945 break;
9946
9947 case S390_INSN_ALU:
9948 end = s390_insn_alu_emit(buf, insn);
9949 break;
9950
florianc4aa7ed2012-12-22 15:01:04 +00009951 case S390_INSN_SMUL:
9952 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +00009953 end = s390_insn_mul_emit(buf, insn);
9954 break;
9955
florianc4aa7ed2012-12-22 15:01:04 +00009956 case S390_INSN_SDIV:
9957 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +00009958 end = s390_insn_div_emit(buf, insn);
9959 break;
9960
9961 case S390_INSN_DIVS:
9962 end = s390_insn_divs_emit(buf, insn);
9963 break;
9964
sewardj611b06e2011-03-24 08:57:29 +00009965 case S390_INSN_CLZ:
9966 end = s390_insn_clz_emit(buf, insn);
sewardj2019a972011-03-07 16:04:07 +00009967 break;
9968
9969 case S390_INSN_UNOP:
9970 end = s390_insn_unop_emit(buf, insn);
9971 break;
9972
9973 case S390_INSN_TEST:
9974 end = s390_insn_test_emit(buf, insn);
9975 break;
9976
9977 case S390_INSN_CC2BOOL:
9978 end = s390_insn_cc2bool_emit(buf, insn);
9979 break;
9980
9981 case S390_INSN_CAS:
9982 end = s390_insn_cas_emit(buf, insn);
9983 break;
9984
florian448cbba2012-06-06 02:26:01 +00009985 case S390_INSN_CDAS:
9986 end = s390_insn_cdas_emit(buf, insn);
9987 break;
9988
sewardj2019a972011-03-07 16:04:07 +00009989 case S390_INSN_COMPARE:
9990 end = s390_insn_compare_emit(buf, insn);
9991 break;
9992
sewardj2019a972011-03-07 16:04:07 +00009993 case S390_INSN_HELPER_CALL:
9994 end = s390_insn_helper_call_emit(buf, insn);
sewardjcfe046e2013-01-17 14:23:53 +00009995 if (end == buf) goto fail;
sewardj2019a972011-03-07 16:04:07 +00009996 break;
9997
9998 case S390_INSN_BFP_TRIOP:
9999 end = s390_insn_bfp_triop_emit(buf, insn);
10000 break;
10001
10002 case S390_INSN_BFP_BINOP:
10003 end = s390_insn_bfp_binop_emit(buf, insn);
10004 break;
10005
10006 case S390_INSN_BFP_UNOP:
10007 end = s390_insn_bfp_unop_emit(buf, insn);
10008 break;
10009
10010 case S390_INSN_BFP_COMPARE:
10011 end = s390_insn_bfp_compare_emit(buf, insn);
10012 break;
10013
florian9fcff4c2012-09-10 03:09:04 +000010014 case S390_INSN_BFP_CONVERT:
10015 end = s390_insn_bfp_convert_emit(buf, insn);
10016 break;
10017
florian12390202012-11-10 22:34:14 +000010018 case S390_INSN_DFP_BINOP:
10019 end = s390_insn_dfp_binop_emit(buf, insn);
10020 break;
10021
floriance9e3db2012-12-27 20:14:03 +000010022 case S390_INSN_DFP_UNOP:
10023 end = s390_insn_dfp_unop_emit(buf, insn);
10024 break;
10025
florian1b901d42013-01-01 22:19:24 +000010026 case S390_INSN_DFP_INTOP:
10027 end = s390_insn_dfp_intop_emit(buf, insn);
10028 break;
10029
floriane38f6412012-12-21 17:32:12 +000010030 case S390_INSN_DFP_COMPARE:
10031 end = s390_insn_dfp_compare_emit(buf, insn);
10032 break;
10033
10034 case S390_INSN_DFP_CONVERT:
10035 end = s390_insn_dfp_convert_emit(buf, insn);
10036 break;
10037
florian5c539732013-02-14 14:27:12 +000010038 case S390_INSN_DFP_REROUND:
10039 end = s390_insn_dfp_reround_emit(buf, insn);
10040 break;
10041
florian78d5ef72013-05-11 15:02:58 +000010042 case S390_INSN_FP_CONVERT:
10043 end = s390_insn_fp_convert_emit(buf, insn);
10044 break;
10045
sewardja52e37e2011-04-28 18:48:06 +000010046 case S390_INSN_MFENCE:
10047 end = s390_insn_mfence_emit(buf, insn);
10048 break;
10049
florianb93348d2012-12-27 00:59:43 +000010050 case S390_INSN_MIMM:
10051 end = s390_insn_mimm_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +000010052 break;
10053
florianf85fe3e2012-12-22 02:28:25 +000010054 case S390_INSN_MADD:
10055 end = s390_insn_madd_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +000010056 break;
10057
florian125e20d2012-10-07 15:42:37 +000010058 case S390_INSN_SET_FPC_BFPRM:
10059 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
florian2c74d242012-09-12 19:38:42 +000010060 break;
10061
florianc8e4f562012-10-27 16:19:31 +000010062 case S390_INSN_SET_FPC_DFPRM:
10063 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
10064 break;
10065
florian8844a632012-04-13 04:04:06 +000010066 case S390_INSN_PROFINC:
10067 end = s390_insn_profinc_emit(buf, insn);
10068 /* Tell the caller .. */
10069 vassert(*is_profinc == False);
10070 *is_profinc = True;
10071 break;
10072
10073 case S390_INSN_EVCHECK:
sewardj9b769162014-07-24 12:42:03 +000010074 end = s390_insn_evcheck_emit(buf, insn, endness_host);
florian8844a632012-04-13 04:04:06 +000010075 break;
10076
10077 case S390_INSN_XDIRECT:
10078 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
10079 disp_cp_chain_me_to_fastEP);
10080 break;
10081
10082 case S390_INSN_XINDIR:
10083 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
10084 break;
10085
10086 case S390_INSN_XASSISTED:
10087 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
10088 break;
10089
sewardjcfe046e2013-01-17 14:23:53 +000010090 fail:
sewardj2019a972011-03-07 16:04:07 +000010091 default:
florian616458b2012-03-25 16:17:18 +000010092 vpanic("emit_S390Instr");
sewardj2019a972011-03-07 16:04:07 +000010093 }
10094
10095 vassert(end - buf <= nbuf);
10096
10097 return end - buf;
10098}
10099
10100
florian8844a632012-04-13 04:04:06 +000010101/* Return the number of bytes emitted for an S390_INSN_EVCHECK.
10102 See s390_insn_evcheck_emit */
10103Int
sewardj9b769162014-07-24 12:42:03 +000010104evCheckSzB_S390(VexEndness endness_host)
florian8844a632012-04-13 04:04:06 +000010105{
florian0e047d62012-04-21 16:06:04 +000010106 return s390_host_has_gie ? 18 : 24;
florian8844a632012-04-13 04:04:06 +000010107}
10108
10109
10110/* Patch the counter address into CODE_TO_PATCH as previously
10111 generated by s390_insn_profinc_emit. */
10112VexInvalRange
sewardj9b769162014-07-24 12:42:03 +000010113patchProfInc_S390(VexEndness endness_host,
florian7d6f81d2014-09-22 21:43:37 +000010114 void *code_to_patch, const ULong *location_of_counter)
florian8844a632012-04-13 04:04:06 +000010115{
10116 vassert(sizeof(ULong *) == 8);
10117
10118 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
10119
florian5ea257b2012-09-29 17:05:46 +000010120 UChar *p = s390_tchain_patch_load64(code_to_patch,
10121 Ptr_to_ULong(location_of_counter));
florian8844a632012-04-13 04:04:06 +000010122
florian5ea257b2012-09-29 17:05:46 +000010123 UInt len = p - (UChar *)code_to_patch;
10124 VexInvalRange vir = { (HWord)code_to_patch, len };
florian8844a632012-04-13 04:04:06 +000010125 return vir;
10126}
10127
10128
10129/* NB: what goes on here has to be very closely coordinated with the
10130 s390_insn_xdirect_emit code above. */
10131VexInvalRange
sewardj9b769162014-07-24 12:42:03 +000010132chainXDirect_S390(VexEndness endness_host,
10133 void *place_to_chain,
florian7d6f81d2014-09-22 21:43:37 +000010134 const void *disp_cp_chain_me_EXPECTED,
10135 const void *place_to_jump_to)
florian8844a632012-04-13 04:04:06 +000010136{
sewardj9b769162014-07-24 12:42:03 +000010137 vassert(endness_host == VexEndnessBE);
10138
florianebaf8d92012-04-22 17:38:46 +000010139 /* What we're expecting to see @ PLACE_TO_CHAIN is:
florian8844a632012-04-13 04:04:06 +000010140
florianebaf8d92012-04-22 17:38:46 +000010141 load tchain_scratch, #disp_cp_chain_me_EXPECTED
10142 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010143 */
10144 const UChar *next;
10145 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
10146 Ptr_to_ULong(disp_cp_chain_me_EXPECTED));
florianebaf8d92012-04-22 17:38:46 +000010147 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +000010148
10149 /* And what we want to change it to is either:
10150 (general case):
10151
florianebaf8d92012-04-22 17:38:46 +000010152 load tchain_scratch, #place_to_jump_to
10153 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010154
10155 ---OR---
10156
10157 in the case where the displacement is small enough
10158
10159 BRCL delta where delta is in half-words
10160 invalid opcodes
10161
10162 In both cases the replacement has the same length as the original.
10163 To remain sane & verifiable,
10164 (1) limit the displacement for the short form to
10165 (say) +/- one billion, so as to avoid wraparound
10166 off-by-ones
10167 (2) even if the short form is applicable, once every (say)
10168 1024 times use the long form anyway, so as to maintain
10169 verifiability
10170 */
10171
10172 /* This is the delta we need to put into a BRCL insn. Note, that the
10173 offset in BRCL is in half-words. Hence division by 2. */
florian7d6f81d2014-09-22 21:43:37 +000010174 Long delta =
10175 (Long)((const UChar *)place_to_jump_to - (const UChar *)place_to_chain) / 2;
florian8844a632012-04-13 04:04:06 +000010176 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
10177
10178 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
10179 if (shortOK) {
10180 shortCTR++; // thread safety bleh
10181 if (0 == (shortCTR & 0x3FF)) {
10182 shortOK = False;
10183 if (0)
10184 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
10185 "using long jmp\n", shortCTR);
10186 }
10187 }
10188
10189 /* And make the modifications. */
10190 UChar *p = (UChar *)place_to_chain;
10191 if (shortOK) {
10192 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
10193
florian48cb9612012-04-20 02:50:28 +000010194 /* Make sure that BRCL fits into the patchable part of an xdirect
florian1c857042012-04-15 04:11:07 +000010195 code sequence */
florian48cb9612012-04-20 02:50:28 +000010196 vassert(6 <= s390_xdirect_patchable_len());
florian1c857042012-04-15 04:11:07 +000010197
florian8844a632012-04-13 04:04:06 +000010198 /* Fill remaining bytes with 0x00 (invalid opcode) */
10199 Int i;
10200 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
10201 p[i] = 0x00;
10202 } else {
florian1c857042012-04-15 04:11:07 +000010203 /*
florianebaf8d92012-04-22 17:38:46 +000010204 load tchain_scratch, #place_to_jump_to
10205 goto *tchain_scratch
florian1c857042012-04-15 04:11:07 +000010206 */
10207 ULong addr = Ptr_to_ULong(place_to_jump_to);
10208 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +000010209 /* There is not need to emit a BCR here, as it is already there. */
florian8844a632012-04-13 04:04:06 +000010210 }
10211
florian5ea257b2012-09-29 17:05:46 +000010212 UInt len = p - (UChar *)place_to_chain;
10213 VexInvalRange vir = { (HWord)place_to_chain, len };
florian8844a632012-04-13 04:04:06 +000010214 return vir;
10215}
10216
10217
10218/* NB: what goes on here has to be very closely coordinated with the
10219 s390_insn_xdirect_emit code above. */
10220VexInvalRange
sewardj9b769162014-07-24 12:42:03 +000010221unchainXDirect_S390(VexEndness endness_host,
10222 void *place_to_unchain,
florian7d6f81d2014-09-22 21:43:37 +000010223 const void *place_to_jump_to_EXPECTED,
10224 const void *disp_cp_chain_me)
florian8844a632012-04-13 04:04:06 +000010225{
sewardj9b769162014-07-24 12:42:03 +000010226 vassert(endness_host == VexEndnessBE);
10227
florian8844a632012-04-13 04:04:06 +000010228 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
10229
florianebaf8d92012-04-22 17:38:46 +000010230 load tchain_scratch, #place_to_jump_to_EXPECTED
10231 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010232
10233 ---OR---
10234 in the case where the displacement falls within 32 bits
10235
10236 BRCL delta
10237 invalid opcodes
10238 */
10239 UChar *p = place_to_unchain;
florian1c857042012-04-15 04:11:07 +000010240
florianebaf8d92012-04-22 17:38:46 +000010241 Bool uses_short_form = False;
10242
florian1c857042012-04-15 04:11:07 +000010243 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
florian8844a632012-04-13 04:04:06 +000010244 /* Looks like the short form */
10245 Int num_hw = *(Int *)&p[2];
10246 Int delta = 2 *num_hw;
10247
10248 vassert(p + delta == place_to_jump_to_EXPECTED);
10249
florian8844a632012-04-13 04:04:06 +000010250 Int i;
10251 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
florian1c857042012-04-15 04:11:07 +000010252 vassert(p[6+i] == 0x00);
florianebaf8d92012-04-22 17:38:46 +000010253 uses_short_form = True;
florian8844a632012-04-13 04:04:06 +000010254 } else {
10255 /* Should be the long form */
10256 const UChar *next;
10257
10258 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
10259 Ptr_to_ULong(place_to_jump_to_EXPECTED));
10260 /* Check for BR *tchain_scratch */
florian1c857042012-04-15 04:11:07 +000010261 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +000010262 }
10263
10264 /* And what we want to change it to is:
10265
10266 load tchain_scratch, #disp_cp_chain_me
florianebaf8d92012-04-22 17:38:46 +000010267 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010268 */
florianebaf8d92012-04-22 17:38:46 +000010269
10270 /* Get the address of the beginning of the load64 code sequence into %r1.
10271 Do not change the register! This is part of the protocol with the
10272 dispatcher.
10273 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
10274 load64 insn sequence. That sequence is prefixed with a BASR to get its
10275 address (see s390_insn_xdirect_emit). */
10276 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
10277
florian8844a632012-04-13 04:04:06 +000010278 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
10279 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +000010280
10281 /* Emit the BCR in case the short form was used. In case of the long
10282 form, the BCR is already there. */
10283 if (uses_short_form)
10284 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +000010285
florian5ea257b2012-09-29 17:05:46 +000010286 UInt len = p - (UChar *)place_to_unchain;
10287 VexInvalRange vir = { (HWord)place_to_unchain, len };
florian8844a632012-04-13 04:04:06 +000010288 return vir;
10289}
10290
sewardj2019a972011-03-07 16:04:07 +000010291/*---------------------------------------------------------------*/
10292/*--- end host_s390_defs.c ---*/
10293/*---------------------------------------------------------------*/