blob: 91f08e5e9f22b5677a370e653f5c6ef7265fe90c [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
Elliott Hughesed398002017-06-21 14:41:24 -070011 Copyright IBM Corp. 2010-2017
12 Copyright (C) 2012-2017 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
florianb4df7682011-07-05 02:09:01 +000047/*------------------------------------------------------------*/
48/*--- Forward declarations ---*/
49/*------------------------------------------------------------*/
50
51static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
52static void s390_insn_map_regs(HRegRemap *, s390_insn *);
53static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
florian1c857042012-04-15 04:11:07 +000054static UInt s390_tchain_load64_len(void);
florianb4df7682011-07-05 02:09:01 +000055
56
sewardj2019a972011-03-07 16:04:07 +000057/*------------------------------------------------------------*/
58/*--- Registers ---*/
59/*------------------------------------------------------------*/
60
sewardja5b50222015-03-26 07:18:32 +000061/* A mapping from register number to register index */
62static Int gpr_index[16]; // GPR regno -> register index
63static Int fpr_index[16]; // FPR regno -> register index
64
65HReg
66s390_hreg_gpr(UInt regno)
67{
68 Int ix = gpr_index[regno];
69 vassert(ix >= 0);
70 return mkHReg(/*virtual*/False, HRcInt64, regno, ix);
71}
72
73HReg
74s390_hreg_fpr(UInt regno)
75{
76 Int ix = fpr_index[regno];
77 vassert(ix >= 0);
78 return mkHReg(/*virtual*/False, HRcFlt64, regno, ix);
79}
80
81static __inline__ UInt
82hregNumber(HReg reg)
83{
84 return hregEncoding(reg);
85}
86
sewardj2019a972011-03-07 16:04:07 +000087/* Decompile the given register into a static buffer and return it */
88const HChar *
89s390_hreg_as_string(HReg reg)
90{
91 static HChar buf[10];
92
93 static const HChar ireg_names[16][5] = {
94 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
95 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
96 };
97
98 static const HChar freg_names[16][5] = {
99 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
100 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
101 };
102
103 UInt r; /* hregNumber() returns an UInt */
104
105 r = hregNumber(reg);
106
107 /* Be generic for all virtual regs. */
108 if (hregIsVirtual(reg)) {
109 buf[0] = '\0';
110 switch (hregClass(reg)) {
florianb1737742015-08-03 16:03:13 +0000111 case HRcInt64: vex_sprintf(buf, "%%vR%u", r); break;
112 case HRcFlt64: vex_sprintf(buf, "%%vF%u", r); break;
sewardj2019a972011-03-07 16:04:07 +0000113 default: goto fail;
114 }
115 return buf;
116 }
117
118 /* But specific for real regs. */
119 vassert(r < 16);
120
121 switch (hregClass(reg)) {
122 case HRcInt64: return ireg_names[r];
123 case HRcFlt64: return freg_names[r];
124 default: goto fail;
125 }
126
127 fail: vpanic("s390_hreg_as_string");
128}
129
130
sewardj2019a972011-03-07 16:04:07 +0000131/* Return the real register that holds the guest state pointer */
132HReg
133s390_hreg_guest_state_pointer(void)
134{
sewardja5b50222015-03-26 07:18:32 +0000135 return s390_hreg_gpr(S390_REGNO_GUEST_STATE_POINTER);
sewardj2019a972011-03-07 16:04:07 +0000136}
137
florian8844a632012-04-13 04:04:06 +0000138
sewardj2019a972011-03-07 16:04:07 +0000139/* Is VALUE within the domain of a 20-bit signed integer. */
140static __inline__ Bool
141fits_signed_20bit(Int value)
142{
florian8cf66372015-02-09 23:21:07 +0000143 UInt uval = value;
144 return ((Int)(uval << 12) >> 12) == value;
sewardj2019a972011-03-07 16:04:07 +0000145}
146
147
148/* Is VALUE within the domain of a 12-bit unsigned integer. */
149static __inline__ Bool
150fits_unsigned_12bit(Int value)
151{
152 return (value & 0xFFF) == value;
153}
154
155/*------------------------------------------------------------*/
156/*--- Addressing modes (amodes) ---*/
157/*------------------------------------------------------------*/
158
159/* Construct a b12 amode. */
160s390_amode *
161s390_amode_b12(Int d, HReg b)
162{
floriand8e3eca2015-03-13 12:46:49 +0000163 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
sewardj2019a972011-03-07 16:04:07 +0000164
165 vassert(fits_unsigned_12bit(d));
166
167 am->tag = S390_AMODE_B12;
168 am->d = d;
169 am->b = b;
sewardja5b50222015-03-26 07:18:32 +0000170 am->x = s390_hreg_gpr(0); /* hregNumber(am->x) == 0 */
sewardj2019a972011-03-07 16:04:07 +0000171
172 return am;
173}
174
175
176/* Construct a b20 amode. */
177s390_amode *
178s390_amode_b20(Int d, HReg b)
179{
floriand8e3eca2015-03-13 12:46:49 +0000180 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
sewardj2019a972011-03-07 16:04:07 +0000181
182 vassert(fits_signed_20bit(d));
183
184 am->tag = S390_AMODE_B20;
185 am->d = d;
186 am->b = b;
sewardja5b50222015-03-26 07:18:32 +0000187 am->x = s390_hreg_gpr(0); /* hregNumber(am->x) == 0 */
sewardj2019a972011-03-07 16:04:07 +0000188
189 return am;
190}
191
192
193/* Construct a bx12 amode. */
194s390_amode *
195s390_amode_bx12(Int d, HReg b, HReg x)
196{
floriand8e3eca2015-03-13 12:46:49 +0000197 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
sewardj2019a972011-03-07 16:04:07 +0000198
199 vassert(fits_unsigned_12bit(d));
florian3123f722013-01-24 15:55:52 +0000200 vassert(hregNumber(b) != 0);
201 vassert(hregNumber(x) != 0);
sewardj2019a972011-03-07 16:04:07 +0000202
203 am->tag = S390_AMODE_BX12;
204 am->d = d;
205 am->b = b;
206 am->x = x;
207
208 return am;
209}
210
211
212/* Construct a bx20 amode. */
213s390_amode *
214s390_amode_bx20(Int d, HReg b, HReg x)
215{
floriand8e3eca2015-03-13 12:46:49 +0000216 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
sewardj2019a972011-03-07 16:04:07 +0000217
218 vassert(fits_signed_20bit(d));
florian3123f722013-01-24 15:55:52 +0000219 vassert(hregNumber(b) != 0);
220 vassert(hregNumber(x) != 0);
sewardj2019a972011-03-07 16:04:07 +0000221
222 am->tag = S390_AMODE_BX20;
223 am->d = d;
224 am->b = b;
225 am->x = x;
226
227 return am;
228}
229
230
florian08d02cb2014-02-11 09:23:01 +0000231/* Construct an AMODE for accessing the guest state at OFFSET.
232 OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES
233 which may be too large for a B12 addressing mode.
234 Use a B20 amode as a fallback which will be safe for any offset.
235*/
sewardj2019a972011-03-07 16:04:07 +0000236s390_amode *
237s390_amode_for_guest_state(Int offset)
238{
239 if (fits_unsigned_12bit(offset))
240 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
sewardj2019a972011-03-07 16:04:07 +0000241
florian08d02cb2014-02-11 09:23:01 +0000242 if (fits_signed_20bit(offset))
243 return s390_amode_b20(offset, s390_hreg_guest_state_pointer());
244
sewardj2019a972011-03-07 16:04:07 +0000245 vpanic("invalid guest state offset");
246}
247
248
249/* Decompile the given amode into a static buffer and return it. */
250const HChar *
251s390_amode_as_string(const s390_amode *am)
252{
253 static HChar buf[30];
254 HChar *p;
255
256 buf[0] = '\0';
257 p = buf;
258
259 switch (am->tag) {
260 case S390_AMODE_B12:
261 case S390_AMODE_B20:
262 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
263 break;
264
265 case S390_AMODE_BX12:
266 case S390_AMODE_BX20:
267 /* s390_hreg_as_string returns pointer to local buffer. Need to
268 split this into two printfs */
269 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
270 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
271 break;
272
273 default:
274 vpanic("s390_amode_as_string");
275 }
276
277 return buf;
278}
279
280
281/* Helper function for s390_amode_is_sane */
282static __inline__ Bool
283is_virtual_gpr(HReg reg)
284{
285 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
286}
287
288
289/* Sanity check for an amode */
290Bool
291s390_amode_is_sane(const s390_amode *am)
292{
293 switch (am->tag) {
294 case S390_AMODE_B12:
295 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
296
297 case S390_AMODE_B20:
298 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
299
300 case S390_AMODE_BX12:
301 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
302 fits_unsigned_12bit(am->d);
303
304 case S390_AMODE_BX20:
305 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
306 fits_signed_20bit(am->d);
307
308 default:
309 vpanic("s390_amode_is_sane");
310 }
311}
312
313
314/* Record the register use of an amode */
florianb4df7682011-07-05 02:09:01 +0000315static void
sewardj2019a972011-03-07 16:04:07 +0000316s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
317{
318 switch (am->tag) {
319 case S390_AMODE_B12:
320 case S390_AMODE_B20:
321 addHRegUse(u, HRmRead, am->b);
322 return;
323
324 case S390_AMODE_BX12:
325 case S390_AMODE_BX20:
326 addHRegUse(u, HRmRead, am->b);
327 addHRegUse(u, HRmRead, am->x);
328 return;
329
330 default:
331 vpanic("s390_amode_get_reg_usage");
332 }
333}
334
335
florianb4df7682011-07-05 02:09:01 +0000336static void
sewardj2019a972011-03-07 16:04:07 +0000337s390_amode_map_regs(HRegRemap *m, s390_amode *am)
338{
339 switch (am->tag) {
340 case S390_AMODE_B12:
341 case S390_AMODE_B20:
342 am->b = lookupHRegRemap(m, am->b);
343 return;
344
345 case S390_AMODE_BX12:
346 case S390_AMODE_BX20:
347 am->b = lookupHRegRemap(m, am->b);
348 am->x = lookupHRegRemap(m, am->x);
349 return;
350
351 default:
352 vpanic("s390_amode_map_regs");
353 }
354}
355
356
sewardj2019a972011-03-07 16:04:07 +0000357void
floriancacba8e2014-12-15 18:58:07 +0000358ppS390AMode(const s390_amode *am)
sewardj2019a972011-03-07 16:04:07 +0000359{
360 vex_printf("%s", s390_amode_as_string(am));
361}
362
363void
floriand8c64e02014-10-08 08:54:44 +0000364ppS390Instr(const s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000365{
366 vex_printf("%s", s390_insn_as_string(insn));
367}
368
369void
370ppHRegS390(HReg reg)
371{
372 vex_printf("%s", s390_hreg_as_string(reg));
373}
374
375/*------------------------------------------------------------*/
376/*--- Helpers for register allocation ---*/
377/*------------------------------------------------------------*/
378
sewardja5b50222015-03-26 07:18:32 +0000379/* Initialise and return the "register universe", i.e. a list of
380 all hardware registers. Called once. */
381const RRegUniverse *
382getRRegUniverse_S390(void)
sewardj2019a972011-03-07 16:04:07 +0000383{
sewardja5b50222015-03-26 07:18:32 +0000384 static RRegUniverse all_regs;
385 static Bool initialised = False;
386 RRegUniverse *ru = &all_regs;
387
388 if (LIKELY(initialised))
389 return ru;
sewardj2019a972011-03-07 16:04:07 +0000390
sewardja5b50222015-03-26 07:18:32 +0000391 RRegUniverse__init(ru);
392
393 /* Assign invalid values to the gpr/fpr_index */
394 for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
395 gpr_index[i] = -1;
396 for (UInt i = 0; i < sizeof fpr_index / sizeof fpr_index[0]; ++i)
397 fpr_index[i] = -1;
398
399 /* Add the registers that are available to the register allocator.
400 GPRs: registers 1..11 are available
401 FPRs: registers 0..15 are available
402 FPR12 - FPR15 are also used as register pairs for 128-bit
403 floating point operations
404 */
405 UInt regno;
406 for (regno = 1; regno <= 11; ++regno) {
407 gpr_index[regno] = ru->size;
408 ru->regs[ru->size++] = s390_hreg_gpr(regno);
409 }
410 for (regno = 0; regno <= 15; ++regno) {
411 fpr_index[regno] = ru->size;
412 ru->regs[ru->size++] = s390_hreg_fpr(regno);
413 }
414 ru->allocable = ru->size;
415
416 /* Add the registers that are not available for allocation.
417 r0 -- cannot be used as a base or index register
418 r12 -- scratch register for translation chaining support
419 r13 -- guest state pointer
420 r14 -- link register
421 r15 -- stack pointer
422 */
423 UInt other[] = { 0, 12, 13, 14, 15 };
424 for (UInt i = 0; i < sizeof other / sizeof other[0]; ++i) {
425 gpr_index[other[i]] = ru->size;
426 ru->regs[ru->size++] = s390_hreg_gpr(other[i]);
427 }
428
429 /* Sanity checking */
430 for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
431 vassert(gpr_index[i] >= 0);
432 for (UInt i = 0; i < sizeof fpr_index / sizeof fpr_index[0]; ++i)
433 vassert(fpr_index[i] >= 0);
434
435 initialised = True;
436 return ru;
437}
sewardj2019a972011-03-07 16:04:07 +0000438
439/* Tell the register allocator how the given instruction uses the registers
440 it refers to. */
441void
floriand8c64e02014-10-08 08:54:44 +0000442getRegUsage_S390Instr(HRegUsage *u, const s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000443{
444 s390_insn_get_reg_usage(u, insn);
445}
446
447
448/* Map the registers of the given instruction */
449void
florianb4df7682011-07-05 02:09:01 +0000450mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000451{
452 s390_insn_map_regs(m, insn);
453}
454
455
456/* Figure out if the given insn represents a reg-reg move, and if so
457 assign the source and destination to *src and *dst. If in doubt say No.
458 Used by the register allocator to do move coalescing. */
459Bool
floriand8c64e02014-10-08 08:54:44 +0000460isMove_S390Instr(const s390_insn *insn, HReg *src, HReg *dst)
sewardj2019a972011-03-07 16:04:07 +0000461{
462 return s390_insn_is_reg_reg_move(insn, src, dst);
463}
464
465
466/* Generate s390 spill/reload instructions under the direction of the
467 register allocator. Note it's critical these don't write the
468 condition codes. This is like an Ist_Put */
469void
470genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
471{
472 s390_amode *am;
473
474 vassert(offsetB >= 0);
sewardj2019a972011-03-07 16:04:07 +0000475 vassert(!hregIsVirtual(rreg));
476
477 *i1 = *i2 = NULL;
478
479 am = s390_amode_for_guest_state(offsetB);
480
481 switch (hregClass(rreg)) {
482 case HRcInt64:
483 case HRcFlt64:
484 *i1 = s390_insn_store(8, am, rreg);
485 return;
486
487 default:
488 ppHRegClass(hregClass(rreg));
489 vpanic("genSpill_S390: unimplemented regclass");
490 }
491}
492
493
494/* This is like an Iex_Get */
495void
496genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
497{
498 s390_amode *am;
499
500 vassert(offsetB >= 0);
sewardj2019a972011-03-07 16:04:07 +0000501 vassert(!hregIsVirtual(rreg));
502
503 *i1 = *i2 = NULL;
504
505 am = s390_amode_for_guest_state(offsetB);
506
507 switch (hregClass(rreg)) {
508 case HRcInt64:
509 case HRcFlt64:
510 *i1 = s390_insn_load(8, rreg, am);
511 return;
512
513 default:
514 ppHRegClass(hregClass(rreg));
515 vpanic("genReload_S390: unimplemented regclass");
516 }
517}
518
519/* Helper function for s390_insn_get_reg_usage */
520static void
521s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
522{
523 switch (op.tag) {
524 case S390_OPND_REG:
525 addHRegUse(u, HRmRead, op.variant.reg);
526 break;
527
528 case S390_OPND_AMODE:
529 s390_amode_get_reg_usage(u, op.variant.am);
530 break;
531
532 case S390_OPND_IMMEDIATE:
533 break;
534
535 default:
536 vpanic("s390_opnd_RMI_get_reg_usage");
537 }
538}
539
540
541/* Tell the register allocator how the given insn uses the registers */
florianb4df7682011-07-05 02:09:01 +0000542static void
sewardj2019a972011-03-07 16:04:07 +0000543s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
544{
545 initHRegUsage(u);
546
547 switch (insn->tag) {
548 case S390_INSN_LOAD:
549 addHRegUse(u, HRmWrite, insn->variant.load.dst);
550 s390_amode_get_reg_usage(u, insn->variant.load.src);
551 break;
552
553 case S390_INSN_LOAD_IMMEDIATE:
554 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
555 break;
556
557 case S390_INSN_STORE:
558 addHRegUse(u, HRmRead, insn->variant.store.src);
559 s390_amode_get_reg_usage(u, insn->variant.store.dst);
560 break;
561
562 case S390_INSN_MOVE:
563 addHRegUse(u, HRmRead, insn->variant.move.src);
564 addHRegUse(u, HRmWrite, insn->variant.move.dst);
565 break;
566
floriancec3a8a2013-02-02 00:16:58 +0000567 case S390_INSN_MEMCPY:
568 s390_amode_get_reg_usage(u, insn->variant.memcpy.src);
569 s390_amode_get_reg_usage(u, insn->variant.memcpy.dst);
570 break;
571
sewardj2019a972011-03-07 16:04:07 +0000572 case S390_INSN_COND_MOVE:
573 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
574 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
575 break;
576
577 case S390_INSN_ALU:
578 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
579 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
580 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
581 break;
582
florianc4aa7ed2012-12-22 15:01:04 +0000583 case S390_INSN_SMUL:
584 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +0000585 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
586 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
587 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
588 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
589 break;
590
florianc4aa7ed2012-12-22 15:01:04 +0000591 case S390_INSN_SDIV:
592 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +0000593 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
594 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
595 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
596 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
597 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
598 break;
599
600 case S390_INSN_DIVS:
601 addHRegUse(u, HRmRead, insn->variant.divs.op1);
602 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
603 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
604 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
605 break;
606
sewardj611b06e2011-03-24 08:57:29 +0000607 case S390_INSN_CLZ:
608 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
609 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
610 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000611 break;
612
613 case S390_INSN_UNOP:
614 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
615 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
616 break;
617
618 case S390_INSN_TEST:
619 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
620 break;
621
622 case S390_INSN_CC2BOOL:
623 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
624 break;
625
626 case S390_INSN_CAS:
627 addHRegUse(u, HRmRead, insn->variant.cas.op1);
628 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
629 addHRegUse(u, HRmRead, insn->variant.cas.op3);
630 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
631 break;
632
florianc4aa7ed2012-12-22 15:01:04 +0000633 case S390_INSN_CDAS: {
634 s390_cdas *cdas = insn->variant.cdas.details;
635
636 addHRegUse(u, HRmRead, cdas->op1_high);
637 addHRegUse(u, HRmRead, cdas->op1_low);
638 s390_amode_get_reg_usage(u, cdas->op2);
639 addHRegUse(u, HRmRead, cdas->op3_high);
640 addHRegUse(u, HRmRead, cdas->op3_low);
641 addHRegUse(u, HRmWrite, cdas->old_mem_high);
642 addHRegUse(u, HRmWrite, cdas->old_mem_low);
643 addHRegUse(u, HRmWrite, cdas->scratch);
florian448cbba2012-06-06 02:26:01 +0000644 break;
florianc4aa7ed2012-12-22 15:01:04 +0000645 }
florian448cbba2012-06-06 02:26:01 +0000646
sewardj2019a972011-03-07 16:04:07 +0000647 case S390_INSN_COMPARE:
648 addHRegUse(u, HRmRead, insn->variant.compare.src1);
649 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
650 break;
651
sewardj2019a972011-03-07 16:04:07 +0000652 case S390_INSN_HELPER_CALL: {
653 UInt i;
654
655 /* Assume that all volatile registers are clobbered. ABI says,
656 volatile registers are: r0 - r5. Valgrind's register allocator
657 does not know about r0, so we can leave that out */
658 for (i = 1; i <= 5; ++i) {
sewardja5b50222015-03-26 07:18:32 +0000659 addHRegUse(u, HRmWrite, s390_hreg_gpr(i));
sewardj2019a972011-03-07 16:04:07 +0000660 }
661
662 /* Ditto for floating point registers. f0 - f7 are volatile */
663 for (i = 0; i <= 7; ++i) {
sewardja5b50222015-03-26 07:18:32 +0000664 addHRegUse(u, HRmWrite, s390_hreg_fpr(i));
sewardj2019a972011-03-07 16:04:07 +0000665 }
666
667 /* The registers that are used for passing arguments will be read.
668 Not all of them may, but in general we need to assume that. */
sewardj74142b82013-08-08 10:28:59 +0000669 for (i = 0; i < insn->variant.helper_call.details->num_args; ++i) {
sewardja5b50222015-03-26 07:18:32 +0000670 addHRegUse(u, HRmRead, s390_hreg_gpr(s390_gprno_from_arg_index(i)));
sewardj2019a972011-03-07 16:04:07 +0000671 }
672
673 /* s390_insn_helper_call_emit also reads / writes the link register
674 and stack pointer. But those registers are not visible to the
675 register allocator. So we don't need to do anything for them. */
676 break;
677 }
678
679 case S390_INSN_BFP_TRIOP:
680 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
681 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
682 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
683 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
684 break;
685
686 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000687 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_hi);
688 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_hi); /* left */
689 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_hi); /* right */
690 if (insn->size == 16) {
691 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_lo);
692 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_lo); /* left */
693 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_lo); /* right */
694 }
sewardj2019a972011-03-07 16:04:07 +0000695 break;
696
697 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +0000698 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi);
699 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_hi); /* operand */
700 if (insn->size == 16) {
701 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo);
702 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_lo); /* operand */
703 }
sewardj2019a972011-03-07 16:04:07 +0000704 break;
705
706 case S390_INSN_BFP_COMPARE:
707 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +0000708 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_hi); /* left */
709 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_hi); /* right */
710 if (insn->size == 16) {
711 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_lo); /* left */
712 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_lo); /* right */
713 }
sewardj2019a972011-03-07 16:04:07 +0000714 break;
715
florian9fcff4c2012-09-10 03:09:04 +0000716 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +0000717 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +0000718 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
floriancc491a62012-09-10 23:44:37 +0000719 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo);
720 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +0000721 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
floriancc491a62012-09-10 23:44:37 +0000722 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +0000723 break;
724
florianc4aa7ed2012-12-22 15:01:04 +0000725 case S390_INSN_DFP_BINOP: {
726 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
727
728 addHRegUse(u, HRmWrite, dfp_binop->dst_hi);
729 addHRegUse(u, HRmRead, dfp_binop->op2_hi); /* left */
730 addHRegUse(u, HRmRead, dfp_binop->op3_hi); /* right */
florian12390202012-11-10 22:34:14 +0000731 if (insn->size == 16) {
florianc4aa7ed2012-12-22 15:01:04 +0000732 addHRegUse(u, HRmWrite, dfp_binop->dst_lo);
733 addHRegUse(u, HRmRead, dfp_binop->op2_lo); /* left */
734 addHRegUse(u, HRmRead, dfp_binop->op3_lo); /* right */
florian12390202012-11-10 22:34:14 +0000735 }
736 break;
florianc4aa7ed2012-12-22 15:01:04 +0000737 }
florian12390202012-11-10 22:34:14 +0000738
floriance9e3db2012-12-27 20:14:03 +0000739 case S390_INSN_DFP_UNOP:
740 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_hi);
741 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_hi); /* operand */
742 if (insn->size == 16) {
743 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_lo);
744 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_lo); /* operand */
745 }
746 break;
747
florian1b901d42013-01-01 22:19:24 +0000748 case S390_INSN_DFP_INTOP:
749 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_hi);
750 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op2);
751 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_hi);
752 if (insn->size == 16) {
753 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_lo);
754 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_lo);
755 }
756 break;
757
floriane38f6412012-12-21 17:32:12 +0000758 case S390_INSN_DFP_COMPARE:
759 addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst);
760 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_hi); /* left */
761 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_hi); /* right */
762 if (insn->size == 16) {
763 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_lo); /* left */
764 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_lo); /* right */
765 }
766 break;
767
768 case S390_INSN_DFP_CONVERT:
769 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +0000770 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
floriane38f6412012-12-21 17:32:12 +0000771 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_lo);
772 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_hi); /* operand */
florian79efdc62013-02-11 00:47:35 +0000773 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
floriane38f6412012-12-21 17:32:12 +0000774 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_lo); /* operand */
775 break;
776
florian5c539732013-02-14 14:27:12 +0000777 case S390_INSN_DFP_REROUND:
778 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_hi);
779 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op2); /* left */
780 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_hi); /* right */
781 if (insn->size == 16) {
782 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_lo);
783 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_lo); /* right */
784 }
785 break;
786
florian78d5ef72013-05-11 15:02:58 +0000787 case S390_INSN_FP_CONVERT: {
788 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
789
790 addHRegUse(u, HRmWrite, fp_convert->dst_hi);
791 if (! hregIsInvalid(fp_convert->dst_lo))
792 addHRegUse(u, HRmWrite, fp_convert->dst_lo);
793 addHRegUse(u, HRmRead, fp_convert->op_hi);
794 if (! hregIsInvalid(fp_convert->op_lo))
795 addHRegUse(u, HRmRead, fp_convert->op_lo);
796 addHRegUse(u, HRmWrite, fp_convert->r1);
797 break;
798 }
799
florianb93348d2012-12-27 00:59:43 +0000800 case S390_INSN_MIMM:
801 s390_amode_get_reg_usage(u, insn->variant.mimm.dst);
florian09bbba82012-12-11 04:09:43 +0000802 break;
803
florianf85fe3e2012-12-22 02:28:25 +0000804 case S390_INSN_MADD:
805 s390_amode_get_reg_usage(u, insn->variant.madd.dst);
806 break;
807
sewardja52e37e2011-04-28 18:48:06 +0000808 case S390_INSN_MFENCE:
809 break;
810
florian125e20d2012-10-07 15:42:37 +0000811 case S390_INSN_SET_FPC_BFPRM:
812 addHRegUse(u, HRmRead, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +0000813 break;
814
florianc8e4f562012-10-27 16:19:31 +0000815 case S390_INSN_SET_FPC_DFPRM:
816 addHRegUse(u, HRmRead, insn->variant.set_fpc_dfprm.mode);
817 break;
818
florian8844a632012-04-13 04:04:06 +0000819 case S390_INSN_EVCHECK:
820 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
821 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
822 break;
823
824 case S390_INSN_PROFINC:
825 /* Does not use any register visible to the register allocator */
826 break;
827
828 case S390_INSN_XDIRECT:
829 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
830 break;
831
832 case S390_INSN_XINDIR:
833 addHRegUse(u, HRmRead, insn->variant.xindir.dst);
834 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
835 break;
836
837 case S390_INSN_XASSISTED:
838 addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
839 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
840 break;
841
sewardj2019a972011-03-07 16:04:07 +0000842 default:
843 vpanic("s390_insn_get_reg_usage");
844 }
845}
846
847
848/* Helper function for s390_insn_map_regs */
849static void
850s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
851{
852 switch (op->tag) {
853 case S390_OPND_REG:
854 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
855 break;
856
857 case S390_OPND_IMMEDIATE:
858 break;
859
860 case S390_OPND_AMODE:
861 s390_amode_map_regs(m, op->variant.am);
862 break;
863
864 default:
865 vpanic("s390_opnd_RMI_map_regs");
866 }
867}
868
869
florianb4df7682011-07-05 02:09:01 +0000870static void
sewardj2019a972011-03-07 16:04:07 +0000871s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
872{
873 switch (insn->tag) {
874 case S390_INSN_LOAD:
875 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
876 s390_amode_map_regs(m, insn->variant.load.src);
877 break;
878
879 case S390_INSN_STORE:
880 s390_amode_map_regs(m, insn->variant.store.dst);
881 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
882 break;
883
884 case S390_INSN_MOVE:
885 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
886 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
887 break;
888
floriancec3a8a2013-02-02 00:16:58 +0000889 case S390_INSN_MEMCPY:
890 s390_amode_map_regs(m, insn->variant.memcpy.dst);
891 s390_amode_map_regs(m, insn->variant.memcpy.src);
892 break;
893
sewardj2019a972011-03-07 16:04:07 +0000894 case S390_INSN_COND_MOVE:
895 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
896 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
897 break;
898
899 case S390_INSN_LOAD_IMMEDIATE:
900 insn->variant.load_immediate.dst =
901 lookupHRegRemap(m, insn->variant.load_immediate.dst);
902 break;
903
904 case S390_INSN_ALU:
905 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
906 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
907 break;
908
florianc4aa7ed2012-12-22 15:01:04 +0000909 case S390_INSN_SMUL:
910 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +0000911 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
912 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
913 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
914 break;
915
florianc4aa7ed2012-12-22 15:01:04 +0000916 case S390_INSN_SDIV:
917 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +0000918 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
919 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
920 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
921 break;
922
923 case S390_INSN_DIVS:
924 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
925 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
926 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
927 break;
928
sewardj611b06e2011-03-24 08:57:29 +0000929 case S390_INSN_CLZ:
930 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
931 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
932 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000933 break;
934
935 case S390_INSN_UNOP:
936 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
937 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
938 break;
939
940 case S390_INSN_TEST:
941 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
942 break;
943
944 case S390_INSN_CC2BOOL:
945 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
946 break;
947
948 case S390_INSN_CAS:
949 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
950 s390_amode_map_regs(m, insn->variant.cas.op2);
951 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
952 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
953 break;
954
florianc4aa7ed2012-12-22 15:01:04 +0000955 case S390_INSN_CDAS: {
956 s390_cdas *cdas = insn->variant.cdas.details;
957
958 cdas->op1_high = lookupHRegRemap(m, cdas->op1_high);
959 cdas->op1_low = lookupHRegRemap(m, cdas->op1_low);
960 s390_amode_map_regs(m, cdas->op2);
961 cdas->op3_high = lookupHRegRemap(m, cdas->op3_high);
962 cdas->op3_low = lookupHRegRemap(m, cdas->op3_low);
963 cdas->old_mem_high = lookupHRegRemap(m, cdas->old_mem_high);
964 cdas->old_mem_low = lookupHRegRemap(m, cdas->old_mem_low);
965 cdas->scratch = lookupHRegRemap(m, cdas->scratch);
florian448cbba2012-06-06 02:26:01 +0000966 break;
florianc4aa7ed2012-12-22 15:01:04 +0000967 }
florian448cbba2012-06-06 02:26:01 +0000968
sewardj2019a972011-03-07 16:04:07 +0000969 case S390_INSN_COMPARE:
970 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
971 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
972 break;
973
sewardj2019a972011-03-07 16:04:07 +0000974 case S390_INSN_HELPER_CALL:
975 /* s390_insn_helper_call_emit also reads / writes the link register
976 and stack pointer. But those registers are not visible to the
977 register allocator. So we don't need to do anything for them.
978 As for the arguments of the helper call -- they will be loaded into
979 non-virtual registers. Again, we don't need to do anything for those
980 here. */
981 break;
982
983 case S390_INSN_BFP_TRIOP:
floriancc491a62012-09-10 23:44:37 +0000984 insn->variant.bfp_triop.dst =
985 lookupHRegRemap(m, insn->variant.bfp_triop.dst);
986 insn->variant.bfp_triop.op2 =
987 lookupHRegRemap(m, insn->variant.bfp_triop.op2);
988 insn->variant.bfp_triop.op3 =
989 lookupHRegRemap(m, insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +0000990 break;
991
992 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000993 insn->variant.bfp_binop.dst_hi =
994 lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi);
995 insn->variant.bfp_binop.op2_hi =
996 lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi);
997 if (insn->size == 16) {
floriana1659202012-09-19 16:01:21 +0000998 insn->variant.bfp_binop.dst_lo =
floriancc491a62012-09-10 23:44:37 +0000999 lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo);
floriana1659202012-09-19 16:01:21 +00001000 insn->variant.bfp_binop.op2_lo =
floriancc491a62012-09-10 23:44:37 +00001001 lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo);
1002 }
sewardj2019a972011-03-07 16:04:07 +00001003 break;
1004
1005 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +00001006 insn->variant.bfp_unop.dst_hi =
1007 lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi);
1008 insn->variant.bfp_unop.op_hi =
1009 lookupHRegRemap(m, insn->variant.bfp_unop.op_hi);
1010 if (insn->size == 16) {
1011 insn->variant.bfp_unop.dst_lo =
1012 lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo);
1013 insn->variant.bfp_unop.op_lo =
1014 lookupHRegRemap(m, insn->variant.bfp_unop.op_lo);
1015 }
sewardj2019a972011-03-07 16:04:07 +00001016 break;
1017
1018 case S390_INSN_BFP_COMPARE:
floriancc491a62012-09-10 23:44:37 +00001019 insn->variant.bfp_compare.dst =
1020 lookupHRegRemap(m, insn->variant.bfp_compare.dst);
1021 insn->variant.bfp_compare.op1_hi =
1022 lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi);
1023 insn->variant.bfp_compare.op2_hi =
1024 lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi);
1025 if (insn->size == 16) {
1026 insn->variant.bfp_compare.op1_lo =
1027 lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo);
1028 insn->variant.bfp_compare.op2_lo =
1029 lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo);
1030 }
sewardj2019a972011-03-07 16:04:07 +00001031 break;
1032
florian9fcff4c2012-09-10 03:09:04 +00001033 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +00001034 insn->variant.bfp_convert.dst_hi =
1035 lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +00001036 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
floriancc491a62012-09-10 23:44:37 +00001037 insn->variant.bfp_convert.dst_lo =
1038 lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo);
1039 insn->variant.bfp_convert.op_hi =
1040 lookupHRegRemap(m, insn->variant.bfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +00001041 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
floriancc491a62012-09-10 23:44:37 +00001042 insn->variant.bfp_convert.op_lo =
1043 lookupHRegRemap(m, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +00001044 break;
1045
florianc4aa7ed2012-12-22 15:01:04 +00001046 case S390_INSN_DFP_BINOP: {
1047 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
1048
1049 dfp_binop->dst_hi = lookupHRegRemap(m, dfp_binop->dst_hi);
1050 dfp_binop->op2_hi = lookupHRegRemap(m, dfp_binop->op2_hi);
1051 dfp_binop->op3_hi = lookupHRegRemap(m, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +00001052 if (insn->size == 16) {
florianc4aa7ed2012-12-22 15:01:04 +00001053 dfp_binop->dst_lo = lookupHRegRemap(m, dfp_binop->dst_lo);
1054 dfp_binop->op2_lo = lookupHRegRemap(m, dfp_binop->op2_lo);
1055 dfp_binop->op3_lo = lookupHRegRemap(m, dfp_binop->op3_lo);
florian12390202012-11-10 22:34:14 +00001056 }
1057 break;
florianc4aa7ed2012-12-22 15:01:04 +00001058 }
florian12390202012-11-10 22:34:14 +00001059
floriance9e3db2012-12-27 20:14:03 +00001060 case S390_INSN_DFP_UNOP:
1061 insn->variant.dfp_unop.dst_hi =
1062 lookupHRegRemap(m, insn->variant.dfp_unop.dst_hi);
1063 insn->variant.dfp_unop.op_hi =
1064 lookupHRegRemap(m, insn->variant.dfp_unop.op_hi);
1065 if (insn->size == 16) {
1066 insn->variant.dfp_unop.dst_lo =
1067 lookupHRegRemap(m, insn->variant.dfp_unop.dst_lo);
1068 insn->variant.dfp_unop.op_lo =
1069 lookupHRegRemap(m, insn->variant.dfp_unop.op_lo);
1070 }
1071 break;
1072
florian1b901d42013-01-01 22:19:24 +00001073 case S390_INSN_DFP_INTOP:
1074 insn->variant.dfp_intop.dst_hi =
1075 lookupHRegRemap(m, insn->variant.dfp_intop.dst_hi);
1076 insn->variant.dfp_intop.op2 =
1077 lookupHRegRemap(m, insn->variant.dfp_intop.op2);
1078 insn->variant.dfp_intop.op3_hi =
1079 lookupHRegRemap(m, insn->variant.dfp_intop.op3_hi);
1080 if (insn->size == 16) {
1081 insn->variant.dfp_intop.dst_lo =
1082 lookupHRegRemap(m, insn->variant.dfp_intop.dst_lo);
1083 insn->variant.dfp_intop.op3_lo =
1084 lookupHRegRemap(m, insn->variant.dfp_intop.op3_lo);
1085 }
1086 break;
1087
floriane38f6412012-12-21 17:32:12 +00001088 case S390_INSN_DFP_COMPARE:
1089 insn->variant.dfp_compare.dst =
1090 lookupHRegRemap(m, insn->variant.dfp_compare.dst);
1091 insn->variant.dfp_compare.op1_hi =
1092 lookupHRegRemap(m, insn->variant.dfp_compare.op1_hi);
1093 insn->variant.dfp_compare.op2_hi =
1094 lookupHRegRemap(m, insn->variant.dfp_compare.op2_hi);
1095 if (insn->size == 16) {
1096 insn->variant.dfp_compare.op1_lo =
1097 lookupHRegRemap(m, insn->variant.dfp_compare.op1_lo);
1098 insn->variant.dfp_compare.op2_lo =
1099 lookupHRegRemap(m, insn->variant.dfp_compare.op2_lo);
1100 }
1101 break;
1102
1103 case S390_INSN_DFP_CONVERT:
1104 insn->variant.dfp_convert.dst_hi =
1105 lookupHRegRemap(m, insn->variant.dfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +00001106 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
floriane38f6412012-12-21 17:32:12 +00001107 insn->variant.dfp_convert.dst_lo =
1108 lookupHRegRemap(m, insn->variant.dfp_convert.dst_lo);
1109 insn->variant.dfp_convert.op_hi =
1110 lookupHRegRemap(m, insn->variant.dfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +00001111 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
floriane38f6412012-12-21 17:32:12 +00001112 insn->variant.dfp_convert.op_lo =
1113 lookupHRegRemap(m, insn->variant.dfp_convert.op_lo);
1114 break;
1115
florian5c539732013-02-14 14:27:12 +00001116 case S390_INSN_DFP_REROUND:
1117 insn->variant.dfp_reround.dst_hi =
1118 lookupHRegRemap(m, insn->variant.dfp_reround.dst_hi);
1119 insn->variant.dfp_reround.op2 =
1120 lookupHRegRemap(m, insn->variant.dfp_reround.op2);
1121 insn->variant.dfp_reround.op3_hi =
1122 lookupHRegRemap(m, insn->variant.dfp_reround.op3_hi);
1123 if (insn->size == 16) {
1124 insn->variant.dfp_reround.dst_lo =
1125 lookupHRegRemap(m, insn->variant.dfp_reround.dst_lo);
1126 insn->variant.dfp_reround.op3_lo =
1127 lookupHRegRemap(m, insn->variant.dfp_reround.op3_lo);
1128 }
1129 break;
1130
florian78d5ef72013-05-11 15:02:58 +00001131 case S390_INSN_FP_CONVERT: {
1132 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
1133
1134 fp_convert->dst_hi = lookupHRegRemap(m, fp_convert->dst_hi);
1135 if (! hregIsInvalid(fp_convert->dst_lo))
1136 fp_convert->dst_lo = lookupHRegRemap(m, fp_convert->dst_lo);
1137 fp_convert->op_hi = lookupHRegRemap(m, fp_convert->op_hi);
1138 if (! hregIsInvalid(fp_convert->op_lo))
1139 fp_convert->op_lo = lookupHRegRemap(m, fp_convert->op_lo);
1140 fp_convert->r1 = lookupHRegRemap(m, fp_convert->r1);
1141 break;
1142 }
1143
florianb93348d2012-12-27 00:59:43 +00001144 case S390_INSN_MIMM:
1145 s390_amode_map_regs(m, insn->variant.mimm.dst);
florian09bbba82012-12-11 04:09:43 +00001146 break;
1147
florianf85fe3e2012-12-22 02:28:25 +00001148 case S390_INSN_MADD:
1149 s390_amode_map_regs(m, insn->variant.madd.dst);
1150 break;
1151
sewardja52e37e2011-04-28 18:48:06 +00001152 case S390_INSN_MFENCE:
1153 break;
1154
florian125e20d2012-10-07 15:42:37 +00001155 case S390_INSN_SET_FPC_BFPRM:
1156 insn->variant.set_fpc_bfprm.mode =
1157 lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00001158 break;
1159
florianc8e4f562012-10-27 16:19:31 +00001160 case S390_INSN_SET_FPC_DFPRM:
1161 insn->variant.set_fpc_dfprm.mode =
1162 lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode);
1163 break;
1164
florian8844a632012-04-13 04:04:06 +00001165 case S390_INSN_EVCHECK:
1166 s390_amode_map_regs(m, insn->variant.evcheck.counter);
1167 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
1168 break;
1169
1170 case S390_INSN_PROFINC:
1171 /* Does not use any register visible to the register allocator */
1172 break;
1173
1174 case S390_INSN_XDIRECT:
1175 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
1176 break;
1177
1178 case S390_INSN_XINDIR:
1179 s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
1180 insn->variant.xindir.dst =
1181 lookupHRegRemap(m, insn->variant.xindir.dst);
1182 break;
1183
1184 case S390_INSN_XASSISTED:
1185 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
1186 insn->variant.xassisted.dst =
1187 lookupHRegRemap(m, insn->variant.xassisted.dst);
1188 break;
1189
sewardj2019a972011-03-07 16:04:07 +00001190 default:
1191 vpanic("s390_insn_map_regs");
1192 }
1193}
1194
1195
1196/* Return True, if INSN is a move between two registers of the same class.
1197 In that case assign the source and destination registers to SRC and DST,
1198 respectively. */
florianb4df7682011-07-05 02:09:01 +00001199static Bool
sewardj2019a972011-03-07 16:04:07 +00001200s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
1201{
1202 if (insn->tag == S390_INSN_MOVE &&
1203 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
1204 *src = insn->variant.move.src;
1205 *dst = insn->variant.move.dst;
1206 return True;
1207 }
1208
1209 return False;
1210}
1211
1212
sewardj2019a972011-03-07 16:04:07 +00001213/*------------------------------------------------------------*/
1214/*--- Functions to emit a sequence of bytes ---*/
1215/*------------------------------------------------------------*/
1216
sewardj2019a972011-03-07 16:04:07 +00001217static __inline__ UChar *
1218emit_2bytes(UChar *p, ULong val)
1219{
1220 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1221}
1222
1223
1224static __inline__ UChar *
1225emit_4bytes(UChar *p, ULong val)
1226{
1227 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1228}
1229
1230
1231static __inline__ UChar *
1232emit_6bytes(UChar *p, ULong val)
1233{
1234 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1235}
1236
1237
1238/*------------------------------------------------------------*/
1239/*--- Functions to emit various instruction formats ---*/
1240/*------------------------------------------------------------*/
1241
sewardj2019a972011-03-07 16:04:07 +00001242static UChar *
1243emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1244{
1245 ULong the_insn = op;
1246
1247 the_insn |= ((ULong)r1) << 20;
1248 the_insn |= ((ULong)i2) << 0;
1249
1250 return emit_4bytes(p, the_insn);
1251}
1252
1253
1254static UChar *
1255emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1256{
1257 ULong the_insn = op;
1258
1259 the_insn |= ((ULong)r1) << 36;
1260 the_insn |= ((ULong)i2) << 0;
1261
1262 return emit_6bytes(p, the_insn);
1263}
1264
1265
1266static UChar *
1267emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1268{
1269 ULong the_insn = op;
1270
1271 the_insn |= ((ULong)r1) << 4;
1272 the_insn |= ((ULong)r2) << 0;
1273
1274 return emit_2bytes(p, the_insn);
1275}
1276
1277
1278static UChar *
1279emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1280{
1281 ULong the_insn = op;
1282
1283 the_insn |= ((ULong)r1) << 4;
1284 the_insn |= ((ULong)r2) << 0;
1285
1286 return emit_4bytes(p, the_insn);
1287}
1288
1289
1290static UChar *
1291emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1292{
1293 ULong the_insn = op;
1294
1295 the_insn |= ((ULong)r1) << 12;
1296 the_insn |= ((ULong)r3) << 4;
1297 the_insn |= ((ULong)r2) << 0;
1298
1299 return emit_4bytes(p, the_insn);
1300}
1301
1302
1303static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00001304emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
1305{
1306 ULong the_insn = op;
1307
1308 the_insn |= ((ULong)m3) << 12;
1309 the_insn |= ((ULong)m4) << 8;
1310 the_insn |= ((ULong)r1) << 4;
1311 the_insn |= ((ULong)r2) << 0;
1312
1313 return emit_4bytes(p, the_insn);
1314}
1315
1316
1317static UChar *
sewardj2019a972011-03-07 16:04:07 +00001318emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1319{
1320 ULong the_insn = op;
1321
1322 the_insn |= ((ULong)r3) << 12;
1323 the_insn |= ((ULong)r1) << 4;
1324 the_insn |= ((ULong)r2) << 0;
1325
1326 return emit_4bytes(p, the_insn);
1327}
1328
1329
1330static UChar *
florian12390202012-11-10 22:34:14 +00001331emit_RRF4(UChar *p, UInt op, UChar r3, UChar m4, UChar r1, UChar r2)
1332{
1333 ULong the_insn = op;
1334
1335 the_insn |= ((ULong)r3) << 12;
1336 the_insn |= ((ULong)m4) << 8;
1337 the_insn |= ((ULong)r1) << 4;
1338 the_insn |= ((ULong)r2) << 0;
1339
1340 return emit_4bytes(p, the_insn);
1341}
1342
1343
1344static UChar *
floriane38f6412012-12-21 17:32:12 +00001345emit_RRF5(UChar *p, UInt op, UChar m4, UChar r1, UChar r2)
1346{
1347 ULong the_insn = op;
1348
1349 the_insn |= ((ULong)m4) << 8;
1350 the_insn |= ((ULong)r1) << 4;
1351 the_insn |= ((ULong)r2) << 0;
1352
1353 return emit_4bytes(p, the_insn);
1354}
1355
1356
1357static UChar *
sewardj2019a972011-03-07 16:04:07 +00001358emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1359{
1360 ULong the_insn = op;
1361
1362 the_insn |= ((ULong)r1) << 20;
1363 the_insn |= ((ULong)r3) << 16;
1364 the_insn |= ((ULong)b2) << 12;
1365 the_insn |= ((ULong)d2) << 0;
1366
1367 return emit_4bytes(p, the_insn);
1368}
1369
1370
1371static UChar *
1372emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1373{
1374 ULong the_insn = op;
1375
1376 the_insn |= ((ULong)r1) << 36;
1377 the_insn |= ((ULong)r3) << 32;
1378 the_insn |= ((ULong)b2) << 28;
1379 the_insn |= ((ULong)dl2) << 16;
1380 the_insn |= ((ULong)dh2) << 8;
1381
1382 return emit_6bytes(p, the_insn);
1383}
1384
1385
1386static UChar *
1387emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1388{
1389 ULong the_insn = op;
1390
1391 the_insn |= ((ULong)r1) << 20;
1392 the_insn |= ((ULong)x2) << 16;
1393 the_insn |= ((ULong)b2) << 12;
1394 the_insn |= ((ULong)d2) << 0;
1395
1396 return emit_4bytes(p, the_insn);
1397}
1398
1399
1400static UChar *
florian1b901d42013-01-01 22:19:24 +00001401emit_RXF(UChar *p, ULong op, UChar r3, UChar x2, UChar b2, UShort d2, UChar r1)
1402{
1403 ULong the_insn = op;
1404
1405 the_insn |= ((ULong)r3) << 36;
1406 the_insn |= ((ULong)x2) << 32;
1407 the_insn |= ((ULong)b2) << 28;
1408 the_insn |= ((ULong)d2) << 16;
1409 the_insn |= ((ULong)r1) << 12;
1410
1411 return emit_6bytes(p, the_insn);
1412}
1413
1414
1415static UChar *
sewardj2019a972011-03-07 16:04:07 +00001416emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1417{
1418 ULong the_insn = op;
1419
1420 the_insn |= ((ULong)r1) << 36;
1421 the_insn |= ((ULong)x2) << 32;
1422 the_insn |= ((ULong)b2) << 28;
1423 the_insn |= ((ULong)dl2) << 16;
1424 the_insn |= ((ULong)dh2) << 8;
1425
1426 return emit_6bytes(p, the_insn);
1427}
1428
1429
1430static UChar *
1431emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1432{
1433 ULong the_insn = op;
1434
1435 the_insn |= ((ULong)b2) << 12;
1436 the_insn |= ((ULong)d2) << 0;
1437
1438 return emit_4bytes(p, the_insn);
1439}
1440
1441
florianad43b3a2012-02-20 15:01:14 +00001442static UChar *
florianb93348d2012-12-27 00:59:43 +00001443emit_SI(UChar *p, UInt op, UChar i2, UChar b1, UShort d1)
1444{
1445 ULong the_insn = op;
1446
1447 the_insn |= ((ULong)i2) << 16;
1448 the_insn |= ((ULong)b1) << 12;
1449 the_insn |= ((ULong)d1) << 0;
1450
1451 return emit_4bytes(p, the_insn);
1452}
1453
1454
1455static UChar *
1456emit_SIL(UChar *p, ULong op, UChar b1, UShort d1, UShort i2)
1457{
1458 ULong the_insn = op;
1459
1460 the_insn |= ((ULong)b1) << 28;
1461 the_insn |= ((ULong)d1) << 16;
1462 the_insn |= ((ULong)i2) << 0;
1463
1464 return emit_6bytes(p, the_insn);
1465}
1466
1467
1468static UChar *
florianad43b3a2012-02-20 15:01:14 +00001469emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1470{
1471 ULong the_insn = op;
1472
1473 the_insn |= ((ULong)i2) << 32;
1474 the_insn |= ((ULong)b1) << 28;
1475 the_insn |= ((ULong)dl1) << 16;
1476 the_insn |= ((ULong)dh1) << 8;
1477
1478 return emit_6bytes(p, the_insn);
1479}
1480
1481
1482static UChar *
1483emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1484{
1485 ULong the_insn = op;
1486
1487 the_insn |= ((ULong)l) << 32;
1488 the_insn |= ((ULong)b1) << 28;
1489 the_insn |= ((ULong)d1) << 16;
1490 the_insn |= ((ULong)b2) << 12;
1491 the_insn |= ((ULong)d2) << 0;
1492
1493 return emit_6bytes(p, the_insn);
1494}
1495
1496
sewardj2019a972011-03-07 16:04:07 +00001497/*------------------------------------------------------------*/
1498/*--- Functions to emit particular instructions ---*/
1499/*------------------------------------------------------------*/
1500
sewardj9d31dfd2011-03-15 12:36:44 +00001501static UChar *
sewardj2019a972011-03-07 16:04:07 +00001502s390_emit_AR(UChar *p, UChar r1, UChar r2)
1503{
sewardj7ee97522011-05-09 21:45:04 +00001504 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001505 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1506
1507 return emit_RR(p, 0x1a00, r1, r2);
1508}
1509
1510
sewardj9d31dfd2011-03-15 12:36:44 +00001511static UChar *
sewardj2019a972011-03-07 16:04:07 +00001512s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1513{
sewardj7ee97522011-05-09 21:45:04 +00001514 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001515 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1516
1517 return emit_RRE(p, 0xb9080000, r1, r2);
1518}
1519
1520
sewardj9d31dfd2011-03-15 12:36:44 +00001521static UChar *
sewardj2019a972011-03-07 16:04:07 +00001522s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1523{
sewardj7ee97522011-05-09 21:45:04 +00001524 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001525 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1526
1527 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1528}
1529
1530
sewardj9d31dfd2011-03-15 12:36:44 +00001531static UChar *
sewardj2019a972011-03-07 16:04:07 +00001532s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1533{
sewardj7ee97522011-05-09 21:45:04 +00001534 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001535 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1536
1537 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1538}
1539
1540
sewardj9d31dfd2011-03-15 12:36:44 +00001541static UChar *
sewardj2019a972011-03-07 16:04:07 +00001542s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1543{
sewardj7ee97522011-05-09 21:45:04 +00001544 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001545 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1546
1547 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1548}
1549
1550
sewardj9d31dfd2011-03-15 12:36:44 +00001551static UChar *
sewardj2019a972011-03-07 16:04:07 +00001552s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1553{
sewardj652b56a2011-04-13 15:38:17 +00001554 vassert(s390_host_has_eimm);
1555
sewardj7ee97522011-05-09 21:45:04 +00001556 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001557 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1558
1559 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1560}
1561
1562
sewardj9d31dfd2011-03-15 12:36:44 +00001563static UChar *
sewardj2019a972011-03-07 16:04:07 +00001564s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1565{
sewardj652b56a2011-04-13 15:38:17 +00001566 vassert(s390_host_has_eimm);
1567
sewardj7ee97522011-05-09 21:45:04 +00001568 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001569 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1570
1571 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1572}
1573
1574
sewardj9d31dfd2011-03-15 12:36:44 +00001575static UChar *
sewardj2019a972011-03-07 16:04:07 +00001576s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1577{
sewardj7ee97522011-05-09 21:45:04 +00001578 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001579 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1580
1581 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1582}
1583
1584
sewardj9d31dfd2011-03-15 12:36:44 +00001585static UChar *
sewardj2019a972011-03-07 16:04:07 +00001586s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
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{
sewardj7ee97522011-05-09 21:45:04 +00001672 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001673 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1674
1675 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1676}
1677
1678
sewardj9d31dfd2011-03-15 12:36:44 +00001679static UChar *
sewardj2019a972011-03-07 16:04:07 +00001680s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1681{
sewardj7ee97522011-05-09 21:45:04 +00001682 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001683 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1684
1685 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1686}
1687
1688
sewardj9d31dfd2011-03-15 12:36:44 +00001689static UChar *
sewardj2019a972011-03-07 16:04:07 +00001690s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1691{
sewardj652b56a2011-04-13 15:38:17 +00001692 vassert(s390_host_has_eimm);
1693
sewardj7ee97522011-05-09 21:45:04 +00001694 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001695 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1696
1697 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1698}
1699
1700
sewardj9d31dfd2011-03-15 12:36:44 +00001701static UChar *
sewardj2019a972011-03-07 16:04:07 +00001702s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1703{
sewardj652b56a2011-04-13 15:38:17 +00001704 vassert(s390_host_has_eimm);
1705
sewardj7ee97522011-05-09 21:45:04 +00001706 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001707 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1708
1709 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1710}
1711
1712
sewardj9d31dfd2011-03-15 12:36:44 +00001713static UChar *
sewardj2019a972011-03-07 16:04:07 +00001714s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1715{
sewardj7ee97522011-05-09 21:45:04 +00001716 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001717 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1718
1719 return emit_RI(p, 0xa5070000, r1, i2);
1720}
1721
1722
sewardj9d31dfd2011-03-15 12:36:44 +00001723static UChar *
sewardj2019a972011-03-07 16:04:07 +00001724s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1725{
sewardj7ee97522011-05-09 21:45:04 +00001726 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001727 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1728
1729 return emit_RR(p, 0x0d00, r1, r2);
1730}
1731
1732
sewardj9d31dfd2011-03-15 12:36:44 +00001733static UChar *
sewardj2019a972011-03-07 16:04:07 +00001734s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1735{
sewardj7ee97522011-05-09 21:45:04 +00001736 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001737 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1738
1739 return emit_RR(p, 0x0700, r1, r2);
1740}
1741
1742
sewardj9d31dfd2011-03-15 12:36:44 +00001743static UChar *
sewardj2019a972011-03-07 16:04:07 +00001744s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1745{
sewardj7ee97522011-05-09 21:45:04 +00001746 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001747 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1748
1749 return emit_RI(p, 0xa7040000, r1, i2);
1750}
1751
1752
sewardj9d31dfd2011-03-15 12:36:44 +00001753static UChar *
florian8844a632012-04-13 04:04:06 +00001754s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
1755{
1756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1757 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
1758
1759 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
1760}
1761
1762
1763static UChar *
sewardj2019a972011-03-07 16:04:07 +00001764s390_emit_CR(UChar *p, UChar r1, UChar r2)
1765{
sewardj7ee97522011-05-09 21:45:04 +00001766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001767 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1768
1769 return emit_RR(p, 0x1900, r1, r2);
1770}
1771
1772
sewardj9d31dfd2011-03-15 12:36:44 +00001773static UChar *
sewardj2019a972011-03-07 16:04:07 +00001774s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1775{
sewardj7ee97522011-05-09 21:45:04 +00001776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001777 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1778
1779 return emit_RRE(p, 0xb9200000, r1, r2);
1780}
1781
1782
sewardj9d31dfd2011-03-15 12:36:44 +00001783static UChar *
sewardj2019a972011-03-07 16:04:07 +00001784s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1785{
sewardj7ee97522011-05-09 21:45:04 +00001786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001787 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1788
1789 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1790}
1791
1792
sewardj9d31dfd2011-03-15 12:36:44 +00001793static UChar *
sewardj2019a972011-03-07 16:04:07 +00001794s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1795{
sewardj7ee97522011-05-09 21:45:04 +00001796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001797 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1798
1799 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1800}
1801
1802
sewardj9d31dfd2011-03-15 12:36:44 +00001803static UChar *
sewardj2019a972011-03-07 16:04:07 +00001804s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1805{
sewardj7ee97522011-05-09 21:45:04 +00001806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001807 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1808
1809 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1810}
1811
1812
sewardj9d31dfd2011-03-15 12:36:44 +00001813static UChar *
sewardj2019a972011-03-07 16:04:07 +00001814s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1815{
sewardj652b56a2011-04-13 15:38:17 +00001816 vassert(s390_host_has_eimm);
1817
sewardj7ee97522011-05-09 21:45:04 +00001818 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001819 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1820
1821 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1822}
1823
1824
sewardj9d31dfd2011-03-15 12:36:44 +00001825static UChar *
florian07d34552012-05-26 01:59:21 +00001826s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
1827{
1828 vassert(s390_host_has_eimm);
1829
1830 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1831 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
1832
1833 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
1834}
1835
1836
1837static UChar *
sewardj2019a972011-03-07 16:04:07 +00001838s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1839{
sewardj7ee97522011-05-09 21:45:04 +00001840 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001841 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1842
1843 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1844}
1845
1846
sewardj9d31dfd2011-03-15 12:36:44 +00001847static UChar *
sewardj2019a972011-03-07 16:04:07 +00001848s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1849{
sewardj7ee97522011-05-09 21:45:04 +00001850 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001851 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1852
1853 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1854}
1855
1856
sewardj9d31dfd2011-03-15 12:36:44 +00001857static UChar *
sewardj2019a972011-03-07 16:04:07 +00001858s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
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), "csg", r1, r3, dh2, dl2, 0, b2);
1862
1863 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1864}
1865
1866
sewardj9d31dfd2011-03-15 12:36:44 +00001867static UChar *
florian448cbba2012-06-06 02:26:01 +00001868s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1869{
1870 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1871 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
1872
1873 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
1874}
1875
1876
1877static UChar *
1878s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1879{
florian448cbba2012-06-06 02:26:01 +00001880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1881 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
1882
1883 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
1884}
1885
1886
1887static UChar *
1888s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1889{
florian448cbba2012-06-06 02:26:01 +00001890 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1891 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
1892
1893 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
1894}
1895
1896
1897static UChar *
sewardj2019a972011-03-07 16:04:07 +00001898s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1899{
sewardj7ee97522011-05-09 21:45:04 +00001900 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001901 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1902
1903 return emit_RR(p, 0x1500, r1, r2);
1904}
1905
1906
sewardj9d31dfd2011-03-15 12:36:44 +00001907static UChar *
sewardj2019a972011-03-07 16:04:07 +00001908s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1909{
sewardj7ee97522011-05-09 21:45:04 +00001910 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001911 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1912
1913 return emit_RRE(p, 0xb9210000, r1, r2);
1914}
1915
1916
sewardj9d31dfd2011-03-15 12:36:44 +00001917static UChar *
sewardj2019a972011-03-07 16:04:07 +00001918s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1919{
sewardj7ee97522011-05-09 21:45:04 +00001920 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001921 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1922
1923 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1924}
1925
1926
sewardj9d31dfd2011-03-15 12:36:44 +00001927static UChar *
sewardj2019a972011-03-07 16:04:07 +00001928s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1929{
sewardj7ee97522011-05-09 21:45:04 +00001930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001931 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1932
1933 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1934}
1935
1936
sewardj9d31dfd2011-03-15 12:36:44 +00001937static UChar *
sewardj2019a972011-03-07 16:04:07 +00001938s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1939{
sewardj7ee97522011-05-09 21:45:04 +00001940 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001941 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1942
1943 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1944}
1945
1946
sewardj9d31dfd2011-03-15 12:36:44 +00001947static UChar *
sewardj2019a972011-03-07 16:04:07 +00001948s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1949{
sewardj652b56a2011-04-13 15:38:17 +00001950 vassert(s390_host_has_eimm);
1951
sewardj7ee97522011-05-09 21:45:04 +00001952 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001953 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1954
1955 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1956}
1957
1958
sewardj9d31dfd2011-03-15 12:36:44 +00001959static UChar *
florian07d34552012-05-26 01:59:21 +00001960s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
1961{
1962 vassert(s390_host_has_eimm);
1963
1964 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1965 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
1966
1967 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
1968}
1969
1970
1971static UChar *
sewardj2019a972011-03-07 16:04:07 +00001972s390_emit_DR(UChar *p, UChar r1, UChar r2)
1973{
sewardj7ee97522011-05-09 21:45:04 +00001974 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001975 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1976
1977 return emit_RR(p, 0x1d00, r1, r2);
1978}
1979
1980
sewardj9d31dfd2011-03-15 12:36:44 +00001981static UChar *
sewardj2019a972011-03-07 16:04:07 +00001982s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1983{
sewardj7ee97522011-05-09 21:45:04 +00001984 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001985 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1986
1987 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1988}
1989
1990
sewardj9d31dfd2011-03-15 12:36:44 +00001991static UChar *
sewardj2019a972011-03-07 16:04:07 +00001992s390_emit_DLR(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), "dlr", r1, r2);
1996
1997 return emit_RRE(p, 0xb9970000, r1, r2);
1998}
1999
2000
sewardj9d31dfd2011-03-15 12:36:44 +00002001static UChar *
sewardj2019a972011-03-07 16:04:07 +00002002s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
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, GPR), "dlgr", r1, r2);
2006
2007 return emit_RRE(p, 0xb9870000, r1, r2);
2008}
2009
2010
sewardj9d31dfd2011-03-15 12:36:44 +00002011static UChar *
sewardj2019a972011-03-07 16:04:07 +00002012s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
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, SDXB), "dl", r1, dh2, dl2, x2, b2);
2016
2017 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
2018}
2019
2020
sewardj9d31dfd2011-03-15 12:36:44 +00002021static UChar *
sewardj2019a972011-03-07 16:04:07 +00002022s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
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, SDXB), "dlg", r1, dh2, dl2, x2, b2);
2026
2027 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
2028}
2029
2030
sewardj9d31dfd2011-03-15 12:36:44 +00002031static UChar *
sewardj2019a972011-03-07 16:04:07 +00002032s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
2033{
sewardj7ee97522011-05-09 21:45:04 +00002034 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002035 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
2036
2037 return emit_RRE(p, 0xb90d0000, r1, r2);
2038}
2039
2040
sewardj9d31dfd2011-03-15 12:36:44 +00002041static UChar *
sewardj2019a972011-03-07 16:04:07 +00002042s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2043{
sewardj7ee97522011-05-09 21:45:04 +00002044 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002045 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
2046
2047 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
2048}
2049
2050
sewardj9d31dfd2011-03-15 12:36:44 +00002051static UChar *
sewardj2019a972011-03-07 16:04:07 +00002052s390_emit_XR(UChar *p, UChar r1, UChar r2)
2053{
sewardj7ee97522011-05-09 21:45:04 +00002054 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002055 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
2056
2057 return emit_RR(p, 0x1700, r1, r2);
2058}
2059
2060
sewardj9d31dfd2011-03-15 12:36:44 +00002061static UChar *
sewardj2019a972011-03-07 16:04:07 +00002062s390_emit_XGR(UChar *p, UChar r1, UChar r2)
2063{
sewardj7ee97522011-05-09 21:45:04 +00002064 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002065 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
2066
2067 return emit_RRE(p, 0xb9820000, r1, r2);
2068}
2069
2070
sewardj9d31dfd2011-03-15 12:36:44 +00002071static UChar *
sewardj2019a972011-03-07 16:04:07 +00002072s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2073{
sewardj7ee97522011-05-09 21:45:04 +00002074 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002075 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
2076
2077 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
2078}
2079
2080
sewardj9d31dfd2011-03-15 12:36:44 +00002081static UChar *
sewardj2019a972011-03-07 16:04:07 +00002082s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2083{
sewardj7ee97522011-05-09 21:45:04 +00002084 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002085 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
2086
2087 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
2088}
2089
2090
sewardj9d31dfd2011-03-15 12:36:44 +00002091static UChar *
sewardj2019a972011-03-07 16:04:07 +00002092s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2093{
sewardj7ee97522011-05-09 21:45:04 +00002094 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002095 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
2096
2097 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
2098}
2099
2100
sewardj9d31dfd2011-03-15 12:36:44 +00002101static UChar *
sewardj2019a972011-03-07 16:04:07 +00002102s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
2103{
sewardj652b56a2011-04-13 15:38:17 +00002104 vassert(s390_host_has_eimm);
2105
sewardj7ee97522011-05-09 21:45:04 +00002106 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002107 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
2108
2109 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
2110}
2111
2112
sewardj9d31dfd2011-03-15 12:36:44 +00002113static UChar *
sewardj2019a972011-03-07 16:04:07 +00002114s390_emit_XILF(UChar *p, UChar r1, UInt i2)
2115{
sewardj652b56a2011-04-13 15:38:17 +00002116 vassert(s390_host_has_eimm);
2117
sewardj7ee97522011-05-09 21:45:04 +00002118 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002119 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
2120
2121 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
2122}
2123
2124
sewardj9d31dfd2011-03-15 12:36:44 +00002125static UChar *
florianad43b3a2012-02-20 15:01:14 +00002126s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2127{
2128 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2129 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
2130
2131 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
2132}
2133
2134
2135static UChar *
sewardj2019a972011-03-07 16:04:07 +00002136s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
2137{
sewardj652b56a2011-04-13 15:38:17 +00002138 vassert(s390_host_has_eimm);
2139
sewardj7ee97522011-05-09 21:45:04 +00002140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002141 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
2142
2143 return emit_RRE(p, 0xb9830000, r1, r2);
2144}
2145
2146
sewardj9d31dfd2011-03-15 12:36:44 +00002147static UChar *
sewardj2019a972011-03-07 16:04:07 +00002148s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2149{
sewardj7ee97522011-05-09 21:45:04 +00002150 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002151 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
2152
2153 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
2154}
2155
2156
sewardj9d31dfd2011-03-15 12:36:44 +00002157static UChar *
sewardj2019a972011-03-07 16:04:07 +00002158s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2159{
sewardj7ee97522011-05-09 21:45:04 +00002160 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002161 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
2162
2163 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
2164}
2165
2166
sewardj9d31dfd2011-03-15 12:36:44 +00002167static UChar *
sewardj2019a972011-03-07 16:04:07 +00002168s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
2169{
sewardj652b56a2011-04-13 15:38:17 +00002170 vassert(s390_host_has_eimm);
2171
sewardj7ee97522011-05-09 21:45:04 +00002172 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002173 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
2174
2175 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
2176}
2177
2178
sewardj9d31dfd2011-03-15 12:36:44 +00002179static UChar *
sewardj2019a972011-03-07 16:04:07 +00002180s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
2181{
sewardj7ee97522011-05-09 21:45:04 +00002182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002183 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
2184
2185 return emit_RI(p, 0xa5000000, r1, i2);
2186}
2187
2188
sewardj9d31dfd2011-03-15 12:36:44 +00002189static UChar *
sewardj2019a972011-03-07 16:04:07 +00002190s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
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, UINT), "iihl", r1, i2);
2194
2195 return emit_RI(p, 0xa5010000, r1, i2);
2196}
2197
2198
sewardj9d31dfd2011-03-15 12:36:44 +00002199static UChar *
sewardj2019a972011-03-07 16:04:07 +00002200s390_emit_IILF(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), "iilf", r1, i2);
2206
2207 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
2208}
2209
2210
sewardj9d31dfd2011-03-15 12:36:44 +00002211static UChar *
sewardj2019a972011-03-07 16:04:07 +00002212s390_emit_IILH(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), "iilh", r1, i2);
2216
2217 return emit_RI(p, 0xa5020000, r1, i2);
2218}
2219
2220
sewardj9d31dfd2011-03-15 12:36:44 +00002221static UChar *
sewardj2019a972011-03-07 16:04:07 +00002222s390_emit_IILL(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), "iill", r1, i2);
2226
2227 return emit_RI(p, 0xa5030000, r1, i2);
2228}
2229
2230
sewardj9d31dfd2011-03-15 12:36:44 +00002231static UChar *
sewardj2019a972011-03-07 16:04:07 +00002232s390_emit_IPM(UChar *p, UChar r1, UChar r2)
2233{
sewardj7ee97522011-05-09 21:45:04 +00002234 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002235 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
2236
2237 return emit_RRE(p, 0xb2220000, r1, r2);
2238}
2239
2240
sewardj9d31dfd2011-03-15 12:36:44 +00002241static UChar *
sewardj2019a972011-03-07 16:04:07 +00002242s390_emit_LR(UChar *p, UChar r1, UChar r2)
2243{
sewardj7ee97522011-05-09 21:45:04 +00002244 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002245 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
2246
2247 return emit_RR(p, 0x1800, r1, r2);
2248}
2249
2250
sewardj9d31dfd2011-03-15 12:36:44 +00002251static UChar *
sewardj2019a972011-03-07 16:04:07 +00002252s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2253{
sewardj7ee97522011-05-09 21:45:04 +00002254 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002255 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2256
2257 return emit_RRE(p, 0xb9040000, r1, r2);
2258}
2259
2260
sewardj9d31dfd2011-03-15 12:36:44 +00002261static UChar *
sewardj2019a972011-03-07 16:04:07 +00002262s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2263{
sewardj7ee97522011-05-09 21:45:04 +00002264 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002265 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2266
2267 return emit_RRE(p, 0xb9140000, r1, r2);
2268}
2269
2270
sewardj9d31dfd2011-03-15 12:36:44 +00002271static UChar *
sewardj2019a972011-03-07 16:04:07 +00002272s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2273{
sewardj7ee97522011-05-09 21:45:04 +00002274 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002275 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2276
2277 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2278}
2279
2280
sewardj9d31dfd2011-03-15 12:36:44 +00002281static UChar *
sewardj2019a972011-03-07 16:04:07 +00002282s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2283{
sewardj7ee97522011-05-09 21:45:04 +00002284 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002285 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2286
2287 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2288}
2289
2290
sewardj9d31dfd2011-03-15 12:36:44 +00002291static UChar *
sewardj2019a972011-03-07 16:04:07 +00002292s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2293{
sewardj7ee97522011-05-09 21:45:04 +00002294 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002295 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2296
2297 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2298}
2299
2300
sewardj9d31dfd2011-03-15 12:36:44 +00002301static UChar *
sewardj2019a972011-03-07 16:04:07 +00002302s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2303{
sewardj7ee97522011-05-09 21:45:04 +00002304 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002305 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2306
2307 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2308}
2309
2310
sewardj9d31dfd2011-03-15 12:36:44 +00002311static UChar *
sewardj2019a972011-03-07 16:04:07 +00002312s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2313{
sewardj652b56a2011-04-13 15:38:17 +00002314 vassert(s390_host_has_eimm);
2315
sewardj7ee97522011-05-09 21:45:04 +00002316 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002317 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2318
2319 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2320}
2321
2322
sewardj9d31dfd2011-03-15 12:36:44 +00002323static UChar *
sewardj2019a972011-03-07 16:04:07 +00002324s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2325{
sewardj7ee97522011-05-09 21:45:04 +00002326 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002327 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2328
2329 return emit_RR(p, 0x1200, r1, r2);
2330}
2331
2332
sewardj9d31dfd2011-03-15 12:36:44 +00002333static UChar *
sewardj2019a972011-03-07 16:04:07 +00002334s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2335{
sewardj7ee97522011-05-09 21:45:04 +00002336 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002337 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2338
2339 return emit_RRE(p, 0xb9020000, r1, r2);
2340}
2341
2342
sewardj9d31dfd2011-03-15 12:36:44 +00002343static UChar *
sewardj2019a972011-03-07 16:04:07 +00002344s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2345{
sewardj652b56a2011-04-13 15:38:17 +00002346 vassert(s390_host_has_eimm);
2347
sewardj7ee97522011-05-09 21:45:04 +00002348 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002349 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2350
2351 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2352}
2353
2354
sewardj9d31dfd2011-03-15 12:36:44 +00002355static UChar *
sewardj2019a972011-03-07 16:04:07 +00002356s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2357{
sewardj652b56a2011-04-13 15:38:17 +00002358 vassert(s390_host_has_eimm);
2359
sewardj7ee97522011-05-09 21:45:04 +00002360 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002361 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2362
2363 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2364}
2365
2366
sewardj9d31dfd2011-03-15 12:36:44 +00002367static UChar *
sewardj2019a972011-03-07 16:04:07 +00002368s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2369{
sewardj652b56a2011-04-13 15:38:17 +00002370 vassert(s390_host_has_eimm);
2371
sewardj7ee97522011-05-09 21:45:04 +00002372 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002373 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2374
2375 return emit_RRE(p, 0xb9260000, r1, r2);
2376}
2377
2378
sewardj9d31dfd2011-03-15 12:36:44 +00002379static UChar *
sewardj2019a972011-03-07 16:04:07 +00002380s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2381{
sewardj652b56a2011-04-13 15:38:17 +00002382 vassert(s390_host_has_eimm);
2383
sewardj7ee97522011-05-09 21:45:04 +00002384 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002385 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2386
2387 return emit_RRE(p, 0xb9060000, r1, r2);
2388}
2389
2390
sewardj9d31dfd2011-03-15 12:36:44 +00002391static UChar *
sewardj2019a972011-03-07 16:04:07 +00002392s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2393{
sewardj7ee97522011-05-09 21:45:04 +00002394 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002395 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2396
2397 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2398}
2399
2400
sewardj9d31dfd2011-03-15 12:36:44 +00002401static UChar *
sewardj2019a972011-03-07 16:04:07 +00002402s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2403{
sewardj7ee97522011-05-09 21:45:04 +00002404 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002405 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2406
2407 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2408}
2409
2410
sewardj9d31dfd2011-03-15 12:36:44 +00002411static UChar *
sewardj2019a972011-03-07 16:04:07 +00002412s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2413{
sewardj7ee97522011-05-09 21:45:04 +00002414 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002415 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2416
2417 return emit_RR(p, 0x1300, r1, r2);
2418}
2419
2420
sewardj9d31dfd2011-03-15 12:36:44 +00002421static UChar *
sewardj2019a972011-03-07 16:04:07 +00002422s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2423{
sewardj7ee97522011-05-09 21:45:04 +00002424 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002425 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2426
2427 return emit_RRE(p, 0xb9030000, r1, r2);
2428}
2429
2430
sewardj9d31dfd2011-03-15 12:36:44 +00002431static UChar *
sewardj2019a972011-03-07 16:04:07 +00002432s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2433{
sewardj652b56a2011-04-13 15:38:17 +00002434 vassert(s390_host_has_eimm);
2435
sewardj7ee97522011-05-09 21:45:04 +00002436 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002437 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2438
2439 return emit_RRE(p, 0xb9270000, r1, r2);
2440}
2441
2442
sewardj9d31dfd2011-03-15 12:36:44 +00002443static UChar *
sewardj2019a972011-03-07 16:04:07 +00002444s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2445{
sewardj652b56a2011-04-13 15:38:17 +00002446 vassert(s390_host_has_eimm);
2447
sewardj7ee97522011-05-09 21:45:04 +00002448 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002449 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2450
2451 return emit_RRE(p, 0xb9070000, r1, r2);
2452}
2453
2454
sewardj9d31dfd2011-03-15 12:36:44 +00002455static UChar *
sewardj2019a972011-03-07 16:04:07 +00002456s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2457{
sewardj7ee97522011-05-09 21:45:04 +00002458 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002459 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2460
2461 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2462}
2463
2464
sewardj9d31dfd2011-03-15 12:36:44 +00002465static UChar *
sewardj2019a972011-03-07 16:04:07 +00002466s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2467{
sewardj7ee97522011-05-09 21:45:04 +00002468 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002469 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2470
2471 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2472}
2473
2474
sewardj9d31dfd2011-03-15 12:36:44 +00002475static UChar *
sewardj2019a972011-03-07 16:04:07 +00002476s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
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, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2480
2481 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2482}
2483
2484
sewardj9d31dfd2011-03-15 12:36:44 +00002485static UChar *
sewardj2019a972011-03-07 16:04:07 +00002486s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2487{
sewardj7ee97522011-05-09 21:45:04 +00002488 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002489 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2490
2491 return emit_RI(p, 0xa7080000, r1, i2);
2492}
2493
2494
sewardj9d31dfd2011-03-15 12:36:44 +00002495static UChar *
sewardj2019a972011-03-07 16:04:07 +00002496s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2497{
sewardj7ee97522011-05-09 21:45:04 +00002498 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002499 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2500
2501 return emit_RI(p, 0xa7090000, r1, i2);
2502}
2503
2504
sewardj9d31dfd2011-03-15 12:36:44 +00002505static UChar *
sewardj2019a972011-03-07 16:04:07 +00002506s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2507{
sewardj7ee97522011-05-09 21:45:04 +00002508 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002509 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2510
2511 return emit_RRE(p, 0xb9160000, r1, r2);
2512}
2513
2514
sewardj9d31dfd2011-03-15 12:36:44 +00002515static UChar *
sewardj2019a972011-03-07 16:04:07 +00002516s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2517{
sewardj7ee97522011-05-09 21:45:04 +00002518 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002519 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2520
2521 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2522}
2523
2524
sewardj9d31dfd2011-03-15 12:36:44 +00002525static UChar *
sewardj2019a972011-03-07 16:04:07 +00002526s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2527{
sewardj652b56a2011-04-13 15:38:17 +00002528 vassert(s390_host_has_eimm);
2529
sewardj7ee97522011-05-09 21:45:04 +00002530 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002531 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2532
2533 return emit_RRE(p, 0xb9940000, r1, r2);
2534}
2535
2536
sewardj9d31dfd2011-03-15 12:36:44 +00002537static UChar *
sewardj2019a972011-03-07 16:04:07 +00002538s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2539{
sewardj652b56a2011-04-13 15:38:17 +00002540 vassert(s390_host_has_eimm);
2541
sewardj7ee97522011-05-09 21:45:04 +00002542 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002543 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2544
2545 return emit_RRE(p, 0xb9840000, r1, r2);
2546}
2547
2548
sewardj9d31dfd2011-03-15 12:36:44 +00002549static UChar *
sewardj2019a972011-03-07 16:04:07 +00002550s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2551{
sewardj652b56a2011-04-13 15:38:17 +00002552 vassert(s390_host_has_eimm);
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, SDXB), "llc", r1, dh2, dl2, x2, b2);
2556
2557 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2558}
2559
2560
sewardj9d31dfd2011-03-15 12:36:44 +00002561static UChar *
sewardj2019a972011-03-07 16:04:07 +00002562s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2563{
sewardj7ee97522011-05-09 21:45:04 +00002564 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002565 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2566
2567 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2568}
2569
2570
sewardj9d31dfd2011-03-15 12:36:44 +00002571static UChar *
sewardj2019a972011-03-07 16:04:07 +00002572s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2573{
sewardj652b56a2011-04-13 15:38:17 +00002574 vassert(s390_host_has_eimm);
2575
sewardj7ee97522011-05-09 21:45:04 +00002576 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002577 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2578
2579 return emit_RRE(p, 0xb9950000, r1, r2);
2580}
2581
2582
sewardj9d31dfd2011-03-15 12:36:44 +00002583static UChar *
sewardj2019a972011-03-07 16:04:07 +00002584s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2585{
sewardj652b56a2011-04-13 15:38:17 +00002586 vassert(s390_host_has_eimm);
2587
sewardj7ee97522011-05-09 21:45:04 +00002588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002589 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2590
2591 return emit_RRE(p, 0xb9850000, r1, r2);
2592}
2593
2594
sewardj9d31dfd2011-03-15 12:36:44 +00002595static UChar *
sewardj2019a972011-03-07 16:04:07 +00002596s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2597{
sewardj652b56a2011-04-13 15:38:17 +00002598 vassert(s390_host_has_eimm);
2599
sewardj7ee97522011-05-09 21:45:04 +00002600 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002601 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2602
2603 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2604}
2605
2606
sewardj9d31dfd2011-03-15 12:36:44 +00002607static UChar *
sewardj2019a972011-03-07 16:04:07 +00002608s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2609{
sewardj7ee97522011-05-09 21:45:04 +00002610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002611 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2612
2613 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2614}
2615
2616
sewardj9d31dfd2011-03-15 12:36:44 +00002617static UChar *
sewardj2019a972011-03-07 16:04:07 +00002618s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2619{
sewardj652b56a2011-04-13 15:38:17 +00002620 vassert(s390_host_has_eimm);
2621
sewardj7ee97522011-05-09 21:45:04 +00002622 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002623 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2624
2625 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2626}
2627
2628
sewardj9d31dfd2011-03-15 12:36:44 +00002629static UChar *
sewardj2019a972011-03-07 16:04:07 +00002630s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2631{
sewardj7ee97522011-05-09 21:45:04 +00002632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002633 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2634
2635 return emit_RI(p, 0xa50e0000, r1, i2);
2636}
2637
2638
sewardj9d31dfd2011-03-15 12:36:44 +00002639static UChar *
sewardj2019a972011-03-07 16:04:07 +00002640s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2641{
sewardj7ee97522011-05-09 21:45:04 +00002642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002643 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2644
2645 return emit_RI(p, 0xa50f0000, r1, i2);
2646}
2647
2648
sewardj9d31dfd2011-03-15 12:36:44 +00002649static UChar *
sewardj2019a972011-03-07 16:04:07 +00002650s390_emit_MR(UChar *p, UChar r1, UChar r2)
2651{
sewardj7ee97522011-05-09 21:45:04 +00002652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002653 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2654
2655 return emit_RR(p, 0x1c00, r1, r2);
2656}
2657
2658
sewardj9d31dfd2011-03-15 12:36:44 +00002659static UChar *
sewardj2019a972011-03-07 16:04:07 +00002660s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2661{
sewardj7ee97522011-05-09 21:45:04 +00002662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002663 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2664
2665 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2666}
2667
2668
sewardj9d31dfd2011-03-15 12:36:44 +00002669static UChar *
sewardj2019a972011-03-07 16:04:07 +00002670s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2671{
sewardj652b56a2011-04-13 15:38:17 +00002672 vassert(s390_host_has_gie);
2673
sewardj7ee97522011-05-09 21:45:04 +00002674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002675 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2676
2677 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2678}
2679
2680
sewardj9d31dfd2011-03-15 12:36:44 +00002681static UChar *
sewardj2019a972011-03-07 16:04:07 +00002682s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
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, UDXB), "mh", r1, d2, x2, b2);
2686
2687 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2688}
2689
2690
sewardj9d31dfd2011-03-15 12:36:44 +00002691static UChar *
sewardj2019a972011-03-07 16:04:07 +00002692s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2693{
sewardj652b56a2011-04-13 15:38:17 +00002694 vassert(s390_host_has_gie);
2695
sewardj7ee97522011-05-09 21:45:04 +00002696 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002697 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2698
2699 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2700}
2701
2702
sewardj9d31dfd2011-03-15 12:36:44 +00002703static UChar *
sewardj2019a972011-03-07 16:04:07 +00002704s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2705{
sewardj7ee97522011-05-09 21:45:04 +00002706 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002707 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2708
2709 return emit_RI(p, 0xa70c0000, r1, i2);
2710}
2711
2712
sewardj9d31dfd2011-03-15 12:36:44 +00002713static UChar *
sewardj2019a972011-03-07 16:04:07 +00002714s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2715{
sewardj7ee97522011-05-09 21:45:04 +00002716 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002717 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2718
2719 return emit_RRE(p, 0xb9960000, r1, r2);
2720}
2721
2722
sewardj9d31dfd2011-03-15 12:36:44 +00002723static UChar *
sewardj2019a972011-03-07 16:04:07 +00002724s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
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, GPR), "mlgr", r1, r2);
2728
2729 return emit_RRE(p, 0xb9860000, r1, r2);
2730}
2731
2732
sewardj9d31dfd2011-03-15 12:36:44 +00002733static UChar *
sewardj2019a972011-03-07 16:04:07 +00002734s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
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, SDXB), "ml", r1, dh2, dl2, x2, b2);
2738
2739 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2740}
2741
2742
sewardj9d31dfd2011-03-15 12:36:44 +00002743static UChar *
sewardj2019a972011-03-07 16:04:07 +00002744s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2745{
sewardj7ee97522011-05-09 21:45:04 +00002746 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002747 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2748
2749 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2750}
2751
2752
sewardj9d31dfd2011-03-15 12:36:44 +00002753static UChar *
sewardj2019a972011-03-07 16:04:07 +00002754s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2755{
sewardj7ee97522011-05-09 21:45:04 +00002756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002757 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2758
2759 return emit_RRE(p, 0xb2520000, r1, r2);
2760}
2761
2762
sewardj9d31dfd2011-03-15 12:36:44 +00002763static UChar *
sewardj2019a972011-03-07 16:04:07 +00002764s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2765{
sewardj7ee97522011-05-09 21:45:04 +00002766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002767 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2768
2769 return emit_RRE(p, 0xb90c0000, r1, r2);
2770}
2771
2772
sewardj9d31dfd2011-03-15 12:36:44 +00002773static UChar *
sewardj2019a972011-03-07 16:04:07 +00002774s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2775{
sewardj7ee97522011-05-09 21:45:04 +00002776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002777 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2778
2779 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2780}
2781
2782
sewardj9d31dfd2011-03-15 12:36:44 +00002783static UChar *
sewardj2019a972011-03-07 16:04:07 +00002784s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2785{
sewardj7ee97522011-05-09 21:45:04 +00002786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002787 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2788
2789 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2790}
2791
2792
sewardj9d31dfd2011-03-15 12:36:44 +00002793static UChar *
sewardj2019a972011-03-07 16:04:07 +00002794s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2795{
sewardj7ee97522011-05-09 21:45:04 +00002796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002797 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2798
2799 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2800}
2801
2802
sewardj9d31dfd2011-03-15 12:36:44 +00002803static UChar *
sewardj2019a972011-03-07 16:04:07 +00002804s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2805{
sewardj652b56a2011-04-13 15:38:17 +00002806 vassert(s390_host_has_gie);
2807
sewardj7ee97522011-05-09 21:45:04 +00002808 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002809 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2810
2811 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2812}
2813
2814
sewardj9d31dfd2011-03-15 12:36:44 +00002815static UChar *
sewardj2019a972011-03-07 16:04:07 +00002816s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2817{
sewardj652b56a2011-04-13 15:38:17 +00002818 vassert(s390_host_has_gie);
2819
sewardj7ee97522011-05-09 21:45:04 +00002820 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002821 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2822
2823 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2824}
2825
2826
sewardj9d31dfd2011-03-15 12:36:44 +00002827static UChar *
floriancec3a8a2013-02-02 00:16:58 +00002828s390_emit_MVC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2829{
2830 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2831 s390_disasm(ENC3(MNM, UDLB, UDXB), "mvc", d1, l, b1, d2, 0, b2);
2832
2833 return emit_SSa(p, 0xd20000000000ULL, l, b1, d1, b2, d2);
2834}
2835
2836
2837static UChar *
florianb93348d2012-12-27 00:59:43 +00002838s390_emit_MVI(UChar *p, UChar i2, UChar b1, UShort d1)
2839{
2840 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002841 s390_disasm(ENC3(MNM, UDXB, INT), "mvi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002842
2843 return emit_SI(p, 0x92000000, i2, b1, d1);
2844}
2845
2846
2847static UChar *
2848s390_emit_MVHHI(UChar *p, UChar b1, UShort d1, UShort i2)
2849{
florian49adf862014-12-06 20:24:08 +00002850 vassert(s390_host_has_gie);
2851
florianb93348d2012-12-27 00:59:43 +00002852 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002853 s390_disasm(ENC3(MNM, UDXB, INT), "mvhhi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002854
2855 return emit_SIL(p, 0xe54400000000ULL, b1, d1, i2);
2856}
2857
2858
2859static UChar *
2860s390_emit_MVHI(UChar *p, UChar b1, UShort d1, UShort i2)
2861{
florian49adf862014-12-06 20:24:08 +00002862 vassert(s390_host_has_gie);
2863
florianb93348d2012-12-27 00:59:43 +00002864 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002865 s390_disasm(ENC3(MNM, UDXB, INT), "mvhi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002866
2867 return emit_SIL(p, 0xe54c00000000ULL, b1, d1, i2);
2868}
2869
2870
2871static UChar *
2872s390_emit_MVGHI(UChar *p, UChar b1, UShort d1, UShort i2)
2873{
florian49adf862014-12-06 20:24:08 +00002874 vassert(s390_host_has_gie);
2875
florianb93348d2012-12-27 00:59:43 +00002876 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002877 s390_disasm(ENC3(MNM, UDXB, INT), "mvghi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002878
2879 return emit_SIL(p, 0xe54800000000ULL, b1, d1, i2);
2880}
2881
2882
2883static UChar *
sewardj2019a972011-03-07 16:04:07 +00002884s390_emit_OR(UChar *p, UChar r1, UChar r2)
2885{
sewardj7ee97522011-05-09 21:45:04 +00002886 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002887 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2888
2889 return emit_RR(p, 0x1600, r1, r2);
2890}
2891
2892
sewardj9d31dfd2011-03-15 12:36:44 +00002893static UChar *
sewardj2019a972011-03-07 16:04:07 +00002894s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2895{
sewardj7ee97522011-05-09 21:45:04 +00002896 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002897 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2898
2899 return emit_RRE(p, 0xb9810000, r1, r2);
2900}
2901
2902
sewardj9d31dfd2011-03-15 12:36:44 +00002903static UChar *
sewardj2019a972011-03-07 16:04:07 +00002904s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2905{
sewardj7ee97522011-05-09 21:45:04 +00002906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002907 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2908
2909 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2910}
2911
2912
sewardj9d31dfd2011-03-15 12:36:44 +00002913static UChar *
sewardj2019a972011-03-07 16:04:07 +00002914s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2915{
sewardj7ee97522011-05-09 21:45:04 +00002916 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002917 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2918
2919 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2920}
2921
2922
sewardj9d31dfd2011-03-15 12:36:44 +00002923static UChar *
sewardj2019a972011-03-07 16:04:07 +00002924s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2925{
sewardj7ee97522011-05-09 21:45:04 +00002926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002927 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2928
2929 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2930}
2931
2932
sewardj9d31dfd2011-03-15 12:36:44 +00002933static UChar *
sewardj2019a972011-03-07 16:04:07 +00002934s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2935{
sewardj652b56a2011-04-13 15:38:17 +00002936 vassert(s390_host_has_eimm);
2937
sewardj7ee97522011-05-09 21:45:04 +00002938 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002939 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2940
2941 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2942}
2943
2944
sewardj9d31dfd2011-03-15 12:36:44 +00002945static UChar *
sewardj2019a972011-03-07 16:04:07 +00002946s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2947{
sewardj652b56a2011-04-13 15:38:17 +00002948 vassert(s390_host_has_eimm);
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, UINT), "oilf", r1, i2);
2952
2953 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2954}
2955
2956
sewardj9d31dfd2011-03-15 12:36:44 +00002957static UChar *
sewardj2019a972011-03-07 16:04:07 +00002958s390_emit_OILL(UChar *p, UChar r1, UShort i2)
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, UINT), "oill", r1, i2);
2962
2963 return emit_RI(p, 0xa50b0000, r1, i2);
2964}
2965
2966
sewardj9d31dfd2011-03-15 12:36:44 +00002967static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002968s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002969{
sewardj7ee97522011-05-09 21:45:04 +00002970 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002971 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2972
sewardj3c49aaa2011-04-05 14:00:37 +00002973 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002974}
2975
2976
sewardj9d31dfd2011-03-15 12:36:44 +00002977static UChar *
sewardj2019a972011-03-07 16:04:07 +00002978s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2979{
sewardj7ee97522011-05-09 21:45:04 +00002980 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002981 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2982
2983 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2984}
2985
2986
sewardj9d31dfd2011-03-15 12:36:44 +00002987static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002988s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002989{
sewardj7ee97522011-05-09 21:45:04 +00002990 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002991 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
2992
sewardj3c49aaa2011-04-05 14:00:37 +00002993 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002994}
2995
2996
sewardj9d31dfd2011-03-15 12:36:44 +00002997static UChar *
sewardj2019a972011-03-07 16:04:07 +00002998s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2999{
sewardj7ee97522011-05-09 21:45:04 +00003000 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003001 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
3002
3003 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
3004}
3005
3006
sewardj9d31dfd2011-03-15 12:36:44 +00003007static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00003008s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00003009{
sewardj7ee97522011-05-09 21:45:04 +00003010 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003011 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
3012
sewardj3c49aaa2011-04-05 14:00:37 +00003013 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00003014}
3015
3016
sewardj9d31dfd2011-03-15 12:36:44 +00003017static UChar *
sewardj2019a972011-03-07 16:04:07 +00003018s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3019{
sewardj7ee97522011-05-09 21:45:04 +00003020 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003021 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
3022
3023 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
3024}
3025
3026
sewardj9d31dfd2011-03-15 12:36:44 +00003027static UChar *
sewardj2019a972011-03-07 16:04:07 +00003028s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3029{
sewardj7ee97522011-05-09 21:45:04 +00003030 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003031 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
3032
3033 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
3034}
3035
3036
sewardj9d31dfd2011-03-15 12:36:44 +00003037static UChar *
sewardj2019a972011-03-07 16:04:07 +00003038s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3039{
sewardj7ee97522011-05-09 21:45:04 +00003040 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003041 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
3042
3043 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
3044}
3045
3046
sewardj9d31dfd2011-03-15 12:36:44 +00003047static UChar *
sewardj2019a972011-03-07 16:04:07 +00003048s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3049{
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, SDXB), "stg", r1, dh2, dl2, x2, b2);
3052
3053 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
3054}
3055
3056
sewardj9d31dfd2011-03-15 12:36:44 +00003057static UChar *
sewardj2019a972011-03-07 16:04:07 +00003058s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3059{
sewardj7ee97522011-05-09 21:45:04 +00003060 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003061 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
3062
3063 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
3064}
3065
3066
sewardj9d31dfd2011-03-15 12:36:44 +00003067static UChar *
sewardj2019a972011-03-07 16:04:07 +00003068s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3069{
sewardj7ee97522011-05-09 21:45:04 +00003070 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003071 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
3072
3073 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
3074}
3075
3076
sewardj9d31dfd2011-03-15 12:36:44 +00003077static UChar *
sewardj2019a972011-03-07 16:04:07 +00003078s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3079{
sewardj7ee97522011-05-09 21:45:04 +00003080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003081 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
3082
3083 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
3084}
3085
3086
sewardj9d31dfd2011-03-15 12:36:44 +00003087static UChar *
sewardj2019a972011-03-07 16:04:07 +00003088s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3089{
sewardj7ee97522011-05-09 21:45:04 +00003090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003091 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
3092
3093 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
3094}
3095
3096
sewardj9d31dfd2011-03-15 12:36:44 +00003097static UChar *
sewardj2019a972011-03-07 16:04:07 +00003098s390_emit_SR(UChar *p, UChar r1, UChar r2)
3099{
sewardj7ee97522011-05-09 21:45:04 +00003100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003101 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
3102
3103 return emit_RR(p, 0x1b00, r1, r2);
3104}
3105
3106
sewardj9d31dfd2011-03-15 12:36:44 +00003107static UChar *
sewardj2019a972011-03-07 16:04:07 +00003108s390_emit_SGR(UChar *p, UChar r1, UChar r2)
3109{
sewardj7ee97522011-05-09 21:45:04 +00003110 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003111 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
3112
3113 return emit_RRE(p, 0xb9090000, r1, r2);
3114}
3115
3116
sewardj9d31dfd2011-03-15 12:36:44 +00003117static UChar *
sewardj2019a972011-03-07 16:04:07 +00003118s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3119{
sewardj7ee97522011-05-09 21:45:04 +00003120 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003121 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
3122
3123 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
3124}
3125
3126
sewardj9d31dfd2011-03-15 12:36:44 +00003127static UChar *
sewardj2019a972011-03-07 16:04:07 +00003128s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3129{
sewardj7ee97522011-05-09 21:45:04 +00003130 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003131 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
3132
3133 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
3134}
3135
3136
sewardj9d31dfd2011-03-15 12:36:44 +00003137static UChar *
sewardj2019a972011-03-07 16:04:07 +00003138s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
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), "sg", r1, dh2, dl2, x2, b2);
3142
3143 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
3144}
3145
3146
sewardj9d31dfd2011-03-15 12:36:44 +00003147static UChar *
sewardj2019a972011-03-07 16:04:07 +00003148s390_emit_SH(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), "sh", r1, d2, x2, b2);
3152
3153 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
3154}
3155
3156
sewardj9d31dfd2011-03-15 12:36:44 +00003157static UChar *
sewardj2019a972011-03-07 16:04:07 +00003158s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3159{
sewardj7ee97522011-05-09 21:45:04 +00003160 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003161 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
3162
3163 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
3164}
3165
3166
sewardj9d31dfd2011-03-15 12:36:44 +00003167static UChar *
sewardj2019a972011-03-07 16:04:07 +00003168s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
3169{
sewardj652b56a2011-04-13 15:38:17 +00003170 vassert(s390_host_has_eimm);
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, UINT), "slfi", r1, i2);
3174
3175 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
3176}
3177
3178
sewardj9d31dfd2011-03-15 12:36:44 +00003179static UChar *
sewardjb13a92a2011-04-13 14:44:29 +00003180s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
3181{
sewardj7ee97522011-05-09 21:45:04 +00003182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardjb13a92a2011-04-13 14:44:29 +00003183 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
3184
3185 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
3186}
3187
3188
3189static UChar *
sewardj2019a972011-03-07 16:04:07 +00003190s390_emit_LDR(UChar *p, UChar r1, UChar r2)
3191{
sewardj7ee97522011-05-09 21:45:04 +00003192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003193 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
3194
3195 return emit_RR(p, 0x2800, r1, r2);
3196}
3197
3198
sewardj9d31dfd2011-03-15 12:36:44 +00003199static UChar *
sewardj2019a972011-03-07 16:04:07 +00003200s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3201{
sewardj7ee97522011-05-09 21:45:04 +00003202 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003203 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
3204
3205 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
3206}
3207
3208
sewardj9d31dfd2011-03-15 12:36:44 +00003209static UChar *
sewardj2019a972011-03-07 16:04:07 +00003210s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3211{
sewardj7ee97522011-05-09 21:45:04 +00003212 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003213 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
3214
3215 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
3216}
3217
3218
sewardj9d31dfd2011-03-15 12:36:44 +00003219static UChar *
sewardj2019a972011-03-07 16:04:07 +00003220s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3221{
sewardj7ee97522011-05-09 21:45:04 +00003222 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003223 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
3224
3225 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
3226}
3227
3228
sewardj9d31dfd2011-03-15 12:36:44 +00003229static UChar *
sewardj2019a972011-03-07 16:04:07 +00003230s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3231{
sewardj7ee97522011-05-09 21:45:04 +00003232 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003233 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
3234
3235 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
3236}
3237
3238
sewardj9d31dfd2011-03-15 12:36:44 +00003239static UChar *
sewardj2019a972011-03-07 16:04:07 +00003240s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
3241{
sewardj7ee97522011-05-09 21:45:04 +00003242 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003243 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
3244
3245 return emit_S(p, 0xb29d0000, b2, d2);
3246}
3247
3248
sewardj9d31dfd2011-03-15 12:36:44 +00003249static UChar *
sewardj2019a972011-03-07 16:04:07 +00003250s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3251{
sewardjd07b8562011-04-27 11:58:22 +00003252 vassert(s390_host_has_fgx);
3253
sewardj7ee97522011-05-09 21:45:04 +00003254 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003255 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
3256
3257 return emit_RRE(p, 0xb3c10000, r1, r2);
3258}
3259
3260
sewardj9d31dfd2011-03-15 12:36:44 +00003261static UChar *
sewardj2019a972011-03-07 16:04:07 +00003262s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3263{
sewardjd07b8562011-04-27 11:58:22 +00003264 vassert(s390_host_has_fgx);
3265
sewardj7ee97522011-05-09 21:45:04 +00003266 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003267 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3268
3269 return emit_RRE(p, 0xb3cd0000, r1, r2);
3270}
3271
3272
sewardj9d31dfd2011-03-15 12:36:44 +00003273static UChar *
sewardj2019a972011-03-07 16:04:07 +00003274s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3275{
sewardj7ee97522011-05-09 21:45:04 +00003276 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003277 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3278
3279 return emit_RRE(p, 0xb3740000, r1, r2);
3280}
3281
3282
sewardj9d31dfd2011-03-15 12:36:44 +00003283static UChar *
sewardj2019a972011-03-07 16:04:07 +00003284s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3285{
sewardj7ee97522011-05-09 21:45:04 +00003286 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003287 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3288
3289 return emit_RRE(p, 0xb3750000, r1, r2);
3290}
3291
3292
sewardj9d31dfd2011-03-15 12:36:44 +00003293static UChar *
florian6d8e26e2012-09-12 19:52:16 +00003294s390_emit_SFPC(UChar *p, UChar r1)
sewardj2019a972011-03-07 16:04:07 +00003295{
sewardj7ee97522011-05-09 21:45:04 +00003296 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003297 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3298
florian6d8e26e2012-09-12 19:52:16 +00003299 return emit_RRE(p, 0xb3840000, r1, 0);
sewardj2019a972011-03-07 16:04:07 +00003300}
3301
3302
sewardj9d31dfd2011-03-15 12:36:44 +00003303static UChar *
sewardj2019a972011-03-07 16:04:07 +00003304s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3305{
sewardj7ee97522011-05-09 21:45:04 +00003306 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003307 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3308
3309 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3310}
3311
3312
sewardj9d31dfd2011-03-15 12:36:44 +00003313static UChar *
sewardj2019a972011-03-07 16:04:07 +00003314s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3315{
sewardj7ee97522011-05-09 21:45:04 +00003316 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003317 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3318
3319 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3320}
3321
3322
sewardj9d31dfd2011-03-15 12:36:44 +00003323static UChar *
sewardj2019a972011-03-07 16:04:07 +00003324s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3325{
sewardj7ee97522011-05-09 21:45:04 +00003326 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003327 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3328
3329 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3330}
3331
3332
sewardj9d31dfd2011-03-15 12:36:44 +00003333static UChar *
sewardj2019a972011-03-07 16:04:07 +00003334s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
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, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3338
3339 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3340}
3341
3342
sewardj9d31dfd2011-03-15 12:36:44 +00003343static UChar *
sewardj2019a972011-03-07 16:04:07 +00003344s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3345{
sewardj7ee97522011-05-09 21:45:04 +00003346 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003347 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3348
3349 return emit_S(p, 0xb29c0000, b2, d2);
3350}
3351
3352
sewardj9d31dfd2011-03-15 12:36:44 +00003353static UChar *
sewardj2019a972011-03-07 16:04:07 +00003354s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3355{
sewardj7ee97522011-05-09 21:45:04 +00003356 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003357 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3358
3359 return emit_RRE(p, 0xb30a0000, r1, r2);
3360}
3361
3362
sewardj9d31dfd2011-03-15 12:36:44 +00003363static UChar *
sewardj2019a972011-03-07 16:04:07 +00003364s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3365{
sewardj7ee97522011-05-09 21:45:04 +00003366 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003367 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3368
3369 return emit_RRE(p, 0xb31a0000, r1, r2);
3370}
3371
3372
sewardj9d31dfd2011-03-15 12:36:44 +00003373static UChar *
sewardj2019a972011-03-07 16:04:07 +00003374s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3375{
sewardj7ee97522011-05-09 21:45:04 +00003376 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003377 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3378
3379 return emit_RRE(p, 0xb34a0000, r1, r2);
3380}
3381
3382
sewardj9d31dfd2011-03-15 12:36:44 +00003383static UChar *
sewardj2019a972011-03-07 16:04:07 +00003384s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3385{
sewardj7ee97522011-05-09 21:45:04 +00003386 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003387 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3388
3389 return emit_RRE(p, 0xb3090000, r1, r2);
3390}
3391
3392
sewardj9d31dfd2011-03-15 12:36:44 +00003393static UChar *
sewardj2019a972011-03-07 16:04:07 +00003394s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3395{
sewardj7ee97522011-05-09 21:45:04 +00003396 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003397 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3398
3399 return emit_RRE(p, 0xb3190000, r1, r2);
3400}
3401
3402
sewardj9d31dfd2011-03-15 12:36:44 +00003403static UChar *
sewardj2019a972011-03-07 16:04:07 +00003404s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3405{
sewardj7ee97522011-05-09 21:45:04 +00003406 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003407 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3408
3409 return emit_RRE(p, 0xb3490000, r1, r2);
3410}
3411
3412
sewardj9d31dfd2011-03-15 12:36:44 +00003413static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003414s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003415{
florian8c3ccaf2012-09-09 18:18:25 +00003416 vassert(m4 == 0);
3417 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003418
florian8c3ccaf2012-09-09 18:18:25 +00003419 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3420 if (m3 == 0)
3421 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3422 else
3423 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3424 "cefbra", r1, m3, r2, m4);
3425 }
3426
3427 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003428}
3429
3430
sewardj9d31dfd2011-03-15 12:36:44 +00003431static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003432s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003433{
florian8c3ccaf2012-09-09 18:18:25 +00003434 vassert(m4 == 0);
3435 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003436
florian8c3ccaf2012-09-09 18:18:25 +00003437 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3438 if (m3 == 0)
3439 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3440 else
3441 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3442 "cdfbra", r1, m3, r2, m4);
3443 }
3444
3445 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003446}
3447
3448
sewardj9d31dfd2011-03-15 12:36:44 +00003449static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003450s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003451{
florian8c3ccaf2012-09-09 18:18:25 +00003452 vassert(m4 == 0);
3453 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003454
florian8c3ccaf2012-09-09 18:18:25 +00003455 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3456 if (m3 == 0)
3457 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3458 else
3459 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3460 "cxfbra", r1, m3, r2, m4);
3461 }
3462
3463 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003464}
3465
3466
sewardj9d31dfd2011-03-15 12:36:44 +00003467static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003468s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003469{
florian8c3ccaf2012-09-09 18:18:25 +00003470 vassert(m4 == 0);
3471 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003472
florian8c3ccaf2012-09-09 18:18:25 +00003473 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3474 if (m3 == 0)
3475 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3476 else
3477 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3478 "cegbra", r1, m3, r2, m4);
3479 }
3480
3481 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003482}
3483
3484
sewardj9d31dfd2011-03-15 12:36:44 +00003485static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003486s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003487{
florian8c3ccaf2012-09-09 18:18:25 +00003488 vassert(m4 == 0);
3489 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003490
florian8c3ccaf2012-09-09 18:18:25 +00003491 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3492 if (m3 == 0)
3493 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3494 else
3495 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3496 "cdgbra", r1, m3, r2, m4);
3497 }
3498
3499 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003500}
3501
3502
sewardj9d31dfd2011-03-15 12:36:44 +00003503static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003504s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003505{
florian8c3ccaf2012-09-09 18:18:25 +00003506 vassert(m4 == 0);
3507 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003508
florian8c3ccaf2012-09-09 18:18:25 +00003509 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3510 if (m3 == 0)
3511 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3512 else
3513 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3514 "cxgbra", r1, m3, r2, m4);
3515 }
3516
3517 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003518}
3519
3520
sewardj9d31dfd2011-03-15 12:36:44 +00003521static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00003522s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3523{
florian606dbeb2012-09-09 18:12:28 +00003524 vassert(m4 == 0);
3525 vassert(s390_host_has_fpext);
3526
florian1c8f7ff2012-09-01 00:12:11 +00003527 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3528 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
3529
3530 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
3531}
3532
3533
3534static UChar *
3535s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3536{
florian606dbeb2012-09-09 18:12:28 +00003537 vassert(m4 == 0);
3538 vassert(s390_host_has_fpext);
3539
florian1c8f7ff2012-09-01 00:12:11 +00003540 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3541 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
3542
3543 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
3544}
3545
3546
3547static UChar *
3548s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3549{
florian606dbeb2012-09-09 18:12:28 +00003550 vassert(m4 == 0);
3551 vassert(s390_host_has_fpext);
3552
florian1c8f7ff2012-09-01 00:12:11 +00003553 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3554 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
3555
3556 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
3557}
3558
3559
3560static UChar *
3561s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3562{
florian606dbeb2012-09-09 18:12:28 +00003563 vassert(m4 == 0);
3564 vassert(s390_host_has_fpext);
3565
florian1c8f7ff2012-09-01 00:12:11 +00003566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3567 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
3568
3569 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
3570}
3571
3572
3573static UChar *
3574s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3575{
florian606dbeb2012-09-09 18:12:28 +00003576 vassert(m4 == 0);
3577 vassert(s390_host_has_fpext);
3578
florian1c8f7ff2012-09-01 00:12:11 +00003579 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3580 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
3581
3582 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
3583}
3584
3585
3586static UChar *
3587s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3588{
florian606dbeb2012-09-09 18:12:28 +00003589 vassert(m4 == 0);
3590 vassert(s390_host_has_fpext);
3591
florian1c8f7ff2012-09-01 00:12:11 +00003592 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3593 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
3594
3595 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
3596}
3597
3598
3599static UChar *
3600s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3601{
florian606dbeb2012-09-09 18:12:28 +00003602 vassert(m4 == 0);
3603 vassert(s390_host_has_fpext);
3604
florian1c8f7ff2012-09-01 00:12:11 +00003605 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3606 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
3607
3608 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
3609}
3610
3611
3612static UChar *
3613s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3614{
florian606dbeb2012-09-09 18:12:28 +00003615 vassert(m4 == 0);
3616 vassert(s390_host_has_fpext);
3617
florian1c8f7ff2012-09-01 00:12:11 +00003618 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3619 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
3620
3621 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
3622}
3623
3624
3625static UChar *
3626s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3627{
florian606dbeb2012-09-09 18:12:28 +00003628 vassert(m4 == 0);
3629 vassert(s390_host_has_fpext);
3630
florian1c8f7ff2012-09-01 00:12:11 +00003631 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3632 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
3633
3634 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
3635}
3636
3637
3638static UChar *
3639s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3640{
florian606dbeb2012-09-09 18:12:28 +00003641 vassert(m4 == 0);
3642 vassert(s390_host_has_fpext);
3643
florian1c8f7ff2012-09-01 00:12:11 +00003644 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3645 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
3646
3647 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
3648}
3649
3650
3651static UChar *
3652s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3653{
florian606dbeb2012-09-09 18:12:28 +00003654 vassert(m4 == 0);
3655 vassert(s390_host_has_fpext);
3656
florian1c8f7ff2012-09-01 00:12:11 +00003657 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3658 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
3659
3660 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
3661}
3662
3663
3664static UChar *
3665s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3666{
florian606dbeb2012-09-09 18:12:28 +00003667 vassert(m4 == 0);
3668 vassert(s390_host_has_fpext);
3669
florian1c8f7ff2012-09-01 00:12:11 +00003670 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3671 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
3672
3673 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
3674}
3675
3676
3677static UChar *
sewardj2019a972011-03-07 16:04:07 +00003678s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3679{
sewardj7ee97522011-05-09 21:45:04 +00003680 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003681 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3682
3683 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3684}
3685
3686
sewardj9d31dfd2011-03-15 12:36:44 +00003687static UChar *
sewardj2019a972011-03-07 16:04:07 +00003688s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3689{
sewardj7ee97522011-05-09 21:45:04 +00003690 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003691 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3692
3693 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3694}
3695
3696
sewardj9d31dfd2011-03-15 12:36:44 +00003697static UChar *
sewardj2019a972011-03-07 16:04:07 +00003698s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3699{
sewardj7ee97522011-05-09 21:45:04 +00003700 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003701 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3702
3703 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3704}
3705
3706
sewardj9d31dfd2011-03-15 12:36:44 +00003707static UChar *
sewardj2019a972011-03-07 16:04:07 +00003708s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3709{
sewardj7ee97522011-05-09 21:45:04 +00003710 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003711 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3712
3713 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3714}
3715
3716
sewardj9d31dfd2011-03-15 12:36:44 +00003717static UChar *
sewardj2019a972011-03-07 16:04:07 +00003718s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3719{
sewardj7ee97522011-05-09 21:45:04 +00003720 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003721 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3722
3723 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3724}
3725
3726
sewardj9d31dfd2011-03-15 12:36:44 +00003727static UChar *
sewardj2019a972011-03-07 16:04:07 +00003728s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3729{
sewardj7ee97522011-05-09 21:45:04 +00003730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003731 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3732
3733 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3734}
3735
3736
sewardj9d31dfd2011-03-15 12:36:44 +00003737static UChar *
sewardj2019a972011-03-07 16:04:07 +00003738s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3739{
sewardj7ee97522011-05-09 21:45:04 +00003740 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003741 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3742
3743 return emit_RRE(p, 0xb30d0000, r1, r2);
3744}
3745
3746
sewardj9d31dfd2011-03-15 12:36:44 +00003747static UChar *
sewardj2019a972011-03-07 16:04:07 +00003748s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3749{
sewardj7ee97522011-05-09 21:45:04 +00003750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003751 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3752
3753 return emit_RRE(p, 0xb31d0000, r1, r2);
3754}
3755
3756
sewardj9d31dfd2011-03-15 12:36:44 +00003757static UChar *
sewardj2019a972011-03-07 16:04:07 +00003758s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3759{
sewardj7ee97522011-05-09 21:45:04 +00003760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003761 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3762
3763 return emit_RRE(p, 0xb34d0000, r1, r2);
3764}
3765
3766
sewardj9d31dfd2011-03-15 12:36:44 +00003767static UChar *
sewardj2019a972011-03-07 16:04:07 +00003768s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3769{
sewardj7ee97522011-05-09 21:45:04 +00003770 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003771 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3772
3773 return emit_RRE(p, 0xb3030000, r1, r2);
3774}
3775
3776
sewardj9d31dfd2011-03-15 12:36:44 +00003777static UChar *
sewardj2019a972011-03-07 16:04:07 +00003778s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3779{
sewardj7ee97522011-05-09 21:45:04 +00003780 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003781 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3782
3783 return emit_RRE(p, 0xb3130000, r1, r2);
3784}
3785
3786
sewardj9d31dfd2011-03-15 12:36:44 +00003787static UChar *
sewardj2019a972011-03-07 16:04:07 +00003788s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3789{
sewardj7ee97522011-05-09 21:45:04 +00003790 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003791 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3792
3793 return emit_RRE(p, 0xb3430000, r1, r2);
3794}
3795
3796
sewardj9d31dfd2011-03-15 12:36:44 +00003797static UChar *
sewardj2019a972011-03-07 16:04:07 +00003798s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3799{
sewardj7ee97522011-05-09 21:45:04 +00003800 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003801 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3802
3803 return emit_RRE(p, 0xb3040000, r1, r2);
3804}
3805
3806
sewardj9d31dfd2011-03-15 12:36:44 +00003807static UChar *
sewardj2019a972011-03-07 16:04:07 +00003808s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3809{
sewardj7ee97522011-05-09 21:45:04 +00003810 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003811 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3812
3813 return emit_RRE(p, 0xb3050000, r1, r2);
3814}
3815
3816
sewardj9d31dfd2011-03-15 12:36:44 +00003817static UChar *
sewardj2019a972011-03-07 16:04:07 +00003818s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3819{
sewardj7ee97522011-05-09 21:45:04 +00003820 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003821 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3822
3823 return emit_RRE(p, 0xb3060000, r1, r2);
3824}
3825
3826
sewardj9d31dfd2011-03-15 12:36:44 +00003827static UChar *
sewardj2019a972011-03-07 16:04:07 +00003828s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3829{
sewardj7ee97522011-05-09 21:45:04 +00003830 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003831 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3832
3833 return emit_RRE(p, 0xb3010000, r1, r2);
3834}
3835
3836
sewardj9d31dfd2011-03-15 12:36:44 +00003837static UChar *
sewardj2019a972011-03-07 16:04:07 +00003838s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3839{
sewardj7ee97522011-05-09 21:45:04 +00003840 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003841 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3842
3843 return emit_RRE(p, 0xb3110000, r1, r2);
3844}
3845
3846
sewardj9d31dfd2011-03-15 12:36:44 +00003847static UChar *
sewardj2019a972011-03-07 16:04:07 +00003848s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3849{
sewardj7ee97522011-05-09 21:45:04 +00003850 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003851 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3852
3853 return emit_RRE(p, 0xb3410000, r1, r2);
3854}
3855
3856
sewardj9d31dfd2011-03-15 12:36:44 +00003857static UChar *
sewardj2019a972011-03-07 16:04:07 +00003858s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3859{
sewardj7ee97522011-05-09 21:45:04 +00003860 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003861 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3862
3863 return emit_RRE(p, 0xb3000000, r1, r2);
3864}
3865
3866
sewardj9d31dfd2011-03-15 12:36:44 +00003867static UChar *
sewardj2019a972011-03-07 16:04:07 +00003868s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3869{
sewardj7ee97522011-05-09 21:45:04 +00003870 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003871 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3872
3873 return emit_RRE(p, 0xb3100000, r1, r2);
3874}
3875
3876
sewardj9d31dfd2011-03-15 12:36:44 +00003877static UChar *
sewardj2019a972011-03-07 16:04:07 +00003878s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3879{
sewardj7ee97522011-05-09 21:45:04 +00003880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003881 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3882
3883 return emit_RRE(p, 0xb3400000, r1, r2);
3884}
3885
3886
sewardj9d31dfd2011-03-15 12:36:44 +00003887static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003888s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003889{
florian8c3ccaf2012-09-09 18:18:25 +00003890 vassert(m4 == 0);
3891 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003892
florian8c3ccaf2012-09-09 18:18:25 +00003893 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3894 if (m3 == 0)
3895 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3896 else
3897 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3898 "ledbra", r1, m3, r2, m4);
3899 }
3900
3901 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003902}
3903
3904
sewardj9d31dfd2011-03-15 12:36:44 +00003905static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003906s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003907{
florian8c3ccaf2012-09-09 18:18:25 +00003908 vassert(m4 == 0);
3909 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003910
florian8c3ccaf2012-09-09 18:18:25 +00003911 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3912 if (m3 == 0)
3913 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3914 else
3915 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3916 "ldxbra", r1, m3, r2, m4);
3917 }
3918
3919 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003920}
3921
3922
sewardj9d31dfd2011-03-15 12:36:44 +00003923static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003924s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003925{
florian8c3ccaf2012-09-09 18:18:25 +00003926 vassert(m4 == 0);
3927 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003928
florian8c3ccaf2012-09-09 18:18:25 +00003929 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3930 if (m3 == 0)
3931 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3932 else
3933 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3934 "lexbra", r1, m3, r2, m4);
3935 }
3936
3937 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003938}
3939
3940
sewardj9d31dfd2011-03-15 12:36:44 +00003941static UChar *
florian6d0b0152015-07-09 20:59:24 +00003942s390_emit_FIEBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3943{
3944 vassert(m3 == 0 || s390_host_has_fpext);
3945
3946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3947 if (m4 == 0)
3948 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fiebr", r1, m3, r2);
3949 else
3950 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3951 "fiebra", r1, m3, r2, m4);
3952 }
3953
3954 return emit_RRF2(p, 0xb3570000, m3, m4, r1, r2);
3955}
3956
3957
3958static UChar *
3959s390_emit_FIDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3960{
3961 vassert(m3 == 0 || s390_host_has_fpext);
3962
3963 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3964 if (m4 == 0)
3965 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fidbr", r1, m3, r2);
3966 else
3967 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3968 "fidbra", r1, m3, r2, m4);
3969 }
3970
3971 return emit_RRF2(p, 0xb35f0000, m3, m4, r1, r2);
3972}
3973
3974
3975static UChar *
florianb53f9482015-09-05 20:35:52 +00003976s390_emit_FIXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3977{
3978 vassert(m3 == 0 || s390_host_has_fpext);
3979
3980 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3981 if (m4 == 0)
3982 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fixbr", r1, m3, r2);
3983 else
3984 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3985 "fixbra", r1, m3, r2, m4);
3986 }
3987
3988 return emit_RRF2(p, 0xb3470000, m3, m4, r1, r2);
3989}
3990
3991
3992static UChar *
sewardj2019a972011-03-07 16:04:07 +00003993s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3994{
sewardj7ee97522011-05-09 21:45:04 +00003995 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003996 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3997
3998 return emit_RRE(p, 0xb3170000, r1, r2);
3999}
4000
4001
sewardj9d31dfd2011-03-15 12:36:44 +00004002static UChar *
sewardj2019a972011-03-07 16:04:07 +00004003s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
4004{
sewardj7ee97522011-05-09 21:45:04 +00004005 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004006 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
4007
4008 return emit_RRE(p, 0xb31c0000, r1, r2);
4009}
4010
4011
sewardj9d31dfd2011-03-15 12:36:44 +00004012static UChar *
sewardj2019a972011-03-07 16:04:07 +00004013s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
4014{
sewardj7ee97522011-05-09 21:45:04 +00004015 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004016 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
4017
4018 return emit_RRE(p, 0xb34c0000, r1, r2);
4019}
4020
4021
sewardj9d31dfd2011-03-15 12:36:44 +00004022static UChar *
sewardj2019a972011-03-07 16:04:07 +00004023s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4024{
sewardj7ee97522011-05-09 21:45:04 +00004025 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004026 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
4027
4028 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
4029}
4030
4031
sewardj9d31dfd2011-03-15 12:36:44 +00004032static UChar *
sewardj2019a972011-03-07 16:04:07 +00004033s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
4034{
sewardj7ee97522011-05-09 21:45:04 +00004035 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004036 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
4037
4038 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
4039}
4040
4041
sewardj9d31dfd2011-03-15 12:36:44 +00004042static UChar *
sewardj2019a972011-03-07 16:04:07 +00004043s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4044{
sewardj7ee97522011-05-09 21:45:04 +00004045 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004046 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
4047
4048 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
4049}
4050
4051
sewardj9d31dfd2011-03-15 12:36:44 +00004052static UChar *
sewardj2019a972011-03-07 16:04:07 +00004053s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
4054{
sewardj7ee97522011-05-09 21:45:04 +00004055 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004056 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
4057
4058 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
4059}
4060
4061
sewardj9d31dfd2011-03-15 12:36:44 +00004062static UChar *
sewardj2019a972011-03-07 16:04:07 +00004063s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
4064{
sewardj7ee97522011-05-09 21:45:04 +00004065 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004066 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
4067
4068 return emit_RRE(p, 0xb3140000, r1, r2);
4069}
4070
4071
sewardj9d31dfd2011-03-15 12:36:44 +00004072static UChar *
sewardj2019a972011-03-07 16:04:07 +00004073s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
4074{
sewardj7ee97522011-05-09 21:45:04 +00004075 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004076 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
4077
4078 return emit_RRE(p, 0xb3150000, r1, r2);
4079}
4080
4081
sewardj9d31dfd2011-03-15 12:36:44 +00004082static UChar *
sewardj2019a972011-03-07 16:04:07 +00004083s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
4084{
sewardj7ee97522011-05-09 21:45:04 +00004085 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004086 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
4087
4088 return emit_RRE(p, 0xb3160000, r1, r2);
4089}
4090
4091
sewardj9d31dfd2011-03-15 12:36:44 +00004092static UChar *
sewardj2019a972011-03-07 16:04:07 +00004093s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
4094{
sewardj7ee97522011-05-09 21:45:04 +00004095 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004096 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
4097
4098 return emit_RRE(p, 0xb30b0000, r1, r2);
4099}
4100
4101
sewardj9d31dfd2011-03-15 12:36:44 +00004102static UChar *
sewardj2019a972011-03-07 16:04:07 +00004103s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
4104{
sewardj7ee97522011-05-09 21:45:04 +00004105 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004106 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
4107
4108 return emit_RRE(p, 0xb31b0000, r1, r2);
4109}
4110
4111
sewardj9d31dfd2011-03-15 12:36:44 +00004112static UChar *
sewardj2019a972011-03-07 16:04:07 +00004113s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
4114{
sewardj7ee97522011-05-09 21:45:04 +00004115 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004116 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
4117
4118 return emit_RRE(p, 0xb34b0000, r1, r2);
4119}
4120
sewardj2019a972011-03-07 16:04:07 +00004121
florian12390202012-11-10 22:34:14 +00004122static UChar *
4123s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4124{
4125 vassert(s390_host_has_dfp);
4126 vassert(m4 == 0 || s390_host_has_fpext);
4127 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4128 if (m4 == 0)
4129 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
4130 else
florianb3764a92012-12-20 14:44:42 +00004131 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004132 }
4133
4134 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
4135}
4136
4137
4138static UChar *
floriane38f6412012-12-21 17:32:12 +00004139s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4140{
4141 vassert(s390_host_has_dfp);
4142 vassert(m4 == 0 || s390_host_has_fpext);
4143 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4144 if (m4 == 0)
4145 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
4146 else
4147 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
4148 }
4149
4150 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
4151}
4152
4153
4154static UChar *
4155s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
4156{
4157 vassert(s390_host_has_dfp);
4158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4159 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
4160
4161 return emit_RRE(p, 0xb3e40000, r1, r2);
4162}
4163
4164
4165static UChar *
4166s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
4167{
4168 vassert(s390_host_has_dfp);
4169 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4170 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
4171
4172 return emit_RRE(p, 0xb3ec0000, r1, r2);
4173}
4174
4175
4176static UChar *
floriana887acd2013-02-08 23:32:54 +00004177s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4178{
4179 vassert(s390_host_has_dfp);
4180 vassert(m4 == 0);
4181 vassert(m3 == 0 || s390_host_has_fpext);
4182
4183 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4184 if (m3 == 0)
4185 s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2);
4186 else
4187 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4);
4188 }
4189
4190 return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2);
4191}
4192
4193
4194static UChar *
4195s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4196{
4197 vassert(s390_host_has_dfp);
4198 vassert(m4 == 0);
4199 /* rounding mode m3 is not considered, as the corresponding
4200 IRop (Iop_I64StoD128) does not take rounding mode. */
4201 vassert(m3 == 0);
4202
florian08f65d92013-02-22 03:40:22 +00004203 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004204 s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2);
floriana887acd2013-02-08 23:32:54 +00004205
4206 return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2);
4207}
4208
4209
4210static UChar *
florian5f034622013-01-13 02:29:05 +00004211s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4212{
4213 vassert(m4 == 0);
4214 vassert(s390_host_has_dfp);
4215 vassert(s390_host_has_fpext);
4216
florian08f65d92013-02-22 03:40:22 +00004217 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004218 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004219
4220 return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2);
4221}
4222
4223
4224static UChar *
4225s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4226{
4227 vassert(m4 == 0);
4228 vassert(s390_host_has_dfp);
4229 vassert(s390_host_has_fpext);
4230
florian08f65d92013-02-22 03:40:22 +00004231 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004232 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004233
4234 return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2);
4235}
4236
4237
4238static UChar *
4239s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4240{
4241 vassert(m4 == 0);
4242 vassert(s390_host_has_dfp);
4243 vassert(s390_host_has_fpext);
4244
4245 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4246 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4);
4247
4248 return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2);
4249}
4250
4251
4252static UChar *
4253s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4254{
4255 vassert(m4 == 0);
4256 vassert(s390_host_has_dfp);
4257 vassert(s390_host_has_fpext);
4258
4259 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4260 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4);
4261
4262 return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2);
4263}
4264
4265
4266static UChar *
4267s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4268{
4269 vassert(m4 == 0);
4270 vassert(s390_host_has_dfp);
4271 vassert(s390_host_has_fpext);
4272
4273 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4274 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4);
4275
4276 return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2);
4277}
4278
4279
4280static UChar *
4281s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4282{
4283 vassert(m4 == 0);
4284 vassert(s390_host_has_dfp);
4285 vassert(s390_host_has_fpext);
4286
4287 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4288 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4);
4289
4290 return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2);
4291}
4292
4293
4294static UChar *
florian20c6bca2012-12-26 17:47:19 +00004295s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
4296{
4297 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4298 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
4299
4300 return emit_RRE(p, 0xb3f40000, r1, r2);
4301}
4302
4303
4304static UChar *
4305s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
4306{
4307 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4308 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
4309
4310 return emit_RRE(p, 0xb3fc0000, r1, r2);
4311}
4312
4313
4314static UChar *
florian5f034622013-01-13 02:29:05 +00004315s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4316{
4317 vassert(m4 == 0);
4318 vassert(s390_host_has_dfp);
4319 vassert(s390_host_has_fpext);
4320
florian08f65d92013-02-22 03:40:22 +00004321 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004322 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004323
4324 return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2);
4325}
4326
4327
4328static UChar *
4329s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4330{
4331 vassert(m4 == 0);
4332 vassert(s390_host_has_dfp);
4333 vassert(s390_host_has_fpext);
4334
florian08f65d92013-02-22 03:40:22 +00004335 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004336 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004337
4338 return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2);
4339}
4340
4341
4342static UChar *
floriana887acd2013-02-08 23:32:54 +00004343s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4344{
4345 vassert(s390_host_has_dfp);
4346 vassert(m4 == 0);
4347 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4348
florian08f65d92013-02-22 03:40:22 +00004349 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004350 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2);
floriana887acd2013-02-08 23:32:54 +00004351
4352 return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2);
4353}
4354
4355
4356static UChar *
4357s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4358{
4359 vassert(s390_host_has_dfp);
4360 vassert(m4 == 0);
4361 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4362
florian08f65d92013-02-22 03:40:22 +00004363 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004364 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2);
floriana887acd2013-02-08 23:32:54 +00004365
4366 return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2);
4367}
4368
4369
4370static UChar *
florian5f034622013-01-13 02:29:05 +00004371s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4372{
4373 vassert(m4 == 0);
4374 vassert(s390_host_has_dfp);
4375 vassert(s390_host_has_fpext);
4376
4377 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4378 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4);
4379
4380 return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2);
4381}
4382
4383
4384static UChar *
4385s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4386{
4387 vassert(m4 == 0);
4388 vassert(s390_host_has_dfp);
4389 vassert(s390_host_has_fpext);
4390
4391 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4392 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4);
4393
4394 return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2);
4395}
4396
4397
4398static UChar *
4399s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4400{
4401 vassert(m4 == 0);
4402 vassert(s390_host_has_dfp);
4403 vassert(s390_host_has_fpext);
4404
4405 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4406 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4);
4407
4408 return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2);
4409}
4410
4411
4412static UChar *
4413s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4414{
4415 vassert(m4 == 0);
4416 vassert(s390_host_has_dfp);
4417 vassert(s390_host_has_fpext);
4418
4419 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4420 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4);
4421
4422 return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2);
4423}
4424
4425
4426static UChar *
florian12390202012-11-10 22:34:14 +00004427s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4428{
4429 vassert(s390_host_has_dfp);
4430 vassert(m4 == 0 || s390_host_has_fpext);
4431 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4432 if (m4 == 0)
4433 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
4434 else
florianb3764a92012-12-20 14:44:42 +00004435 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004436 }
4437
4438 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
4439}
4440
4441
4442static UChar *
floriane38f6412012-12-21 17:32:12 +00004443s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4444{
4445 vassert(s390_host_has_dfp);
4446 vassert(m4 == 0 || s390_host_has_fpext);
4447 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4448 if (m4 == 0)
4449 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
4450 else
4451 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
4452 }
4453
4454 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
4455}
4456
4457
4458static UChar *
florian5c539732013-02-14 14:27:12 +00004459s390_emit_EEDTR(UChar *p, UChar r1, UChar r2)
4460{
4461 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4462 s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2);
4463
4464 return emit_RRE(p, 0xb3e50000, r1, r2);
4465}
4466
4467
4468static UChar *
4469s390_emit_EEXTR(UChar *p, UChar r1, UChar r2)
4470{
4471 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4472 s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2);
4473
4474 return emit_RRE(p, 0xb3ed0000, r1, r2);
4475}
4476
4477
4478static UChar *
floriance9e3db2012-12-27 20:14:03 +00004479s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
4480{
4481 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4482 s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
4483
4484 return emit_RRE(p, 0xb3e70000, r1, r2);
4485}
4486
4487
4488static UChar *
4489s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
4490{
4491 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4492 s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
4493
4494 return emit_RRE(p, 0xb3ef0000, r1, r2);
4495}
4496
4497
4498static UChar *
florian5c539732013-02-14 14:27:12 +00004499s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2)
4500{
4501 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4502 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2);
4503
4504 return emit_RRF(p, 0xb3f60000, r3, r1, r2);
4505}
4506
4507
4508static UChar *
4509s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2)
4510{
4511 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4512 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2);
4513
4514 return emit_RRF(p, 0xb3fe0000, r3, r1, r2);
4515}
4516
4517
4518static UChar *
floriane38f6412012-12-21 17:32:12 +00004519s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
4520{
4521 vassert(s390_host_has_dfp);
4522 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4523 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
4524
4525 return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
4526}
4527
4528
4529static UChar *
4530s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
4531{
4532 vassert(s390_host_has_dfp);
4533 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4534 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
4535
4536 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
4537}
4538
4539
4540static UChar *
4541s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4542{
4543 vassert(s390_host_has_dfp);
4544 vassert(m4 == 0);
florian1bb7f6f2013-02-11 00:03:27 +00004545 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
floriane38f6412012-12-21 17:32:12 +00004546
florian08f65d92013-02-22 03:40:22 +00004547 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4548 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4);
floriane38f6412012-12-21 17:32:12 +00004549
4550 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
4551}
4552
4553
4554static UChar *
4555s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4556{
4557 vassert(s390_host_has_dfp);
4558 vassert(m4 == 0);
florian1bb7f6f2013-02-11 00:03:27 +00004559 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
floriane38f6412012-12-21 17:32:12 +00004560
florian08f65d92013-02-22 03:40:22 +00004561 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4562 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4);
floriane38f6412012-12-21 17:32:12 +00004563
4564 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
4565}
4566
4567
4568static UChar *
florian12390202012-11-10 22:34:14 +00004569s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4570{
4571 vassert(s390_host_has_dfp);
4572 vassert(m4 == 0 || s390_host_has_fpext);
4573 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4574 if (m4 == 0)
4575 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
4576 else
florianb3764a92012-12-20 14:44:42 +00004577 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004578 }
4579
4580 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
4581}
4582
4583
4584static UChar *
floriane38f6412012-12-21 17:32:12 +00004585s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4586{
4587 vassert(s390_host_has_dfp);
4588 vassert(m4 == 0 || s390_host_has_fpext);
4589 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4590 if (m4 == 0)
4591 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
4592 else
4593 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
4594 }
4595
4596 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
4597}
4598
4599
4600static UChar *
florian78d5ef72013-05-11 15:02:58 +00004601emit_E(UChar *p, UInt op)
4602{
4603 ULong the_insn = op;
4604
4605 return emit_2bytes(p, the_insn);
4606}
4607
4608
4609static UChar *
4610s390_emit_PFPO(UChar *p)
4611{
4612 vassert(s390_host_has_pfpo);
4613 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4614 s390_disasm(ENC1(MNM), "pfpo");
4615 }
4616
4617 return emit_E(p, 0x010a);
4618}
4619
4620
4621static UChar *
florian5c539732013-02-14 14:27:12 +00004622s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4623{
4624 vassert(s390_host_has_dfp);
4625 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4626 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4);
4627
4628 return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2);
4629}
4630
4631
4632static UChar *
4633s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4634{
4635 vassert(s390_host_has_dfp);
4636 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4637 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4);
4638
4639 return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2);
4640}
4641
4642
4643static UChar *
4644s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4645{
4646 vassert(s390_host_has_dfp);
4647 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4648 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4);
4649
4650 return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2);
4651}
4652
4653
4654static UChar *
4655s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4656{
4657 vassert(s390_host_has_dfp);
4658 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4659 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4);
4660
4661 return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2);
4662}
4663
4664
4665static UChar *
florian12390202012-11-10 22:34:14 +00004666s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4667{
4668 vassert(s390_host_has_dfp);
4669 vassert(m4 == 0 || s390_host_has_fpext);
4670 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4671 if (m4 == 0)
4672 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
4673 else
florianb3764a92012-12-20 14:44:42 +00004674 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004675 }
4676
4677 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
4678}
4679
florian3a3d7f12012-12-03 13:32:05 +00004680
4681static UChar *
floriane38f6412012-12-21 17:32:12 +00004682s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4683{
4684 vassert(s390_host_has_dfp);
4685 vassert(m4 == 0 || s390_host_has_fpext);
4686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4687 if (m4 == 0)
4688 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
4689 else
4690 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
4691 }
4692
4693 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
4694}
4695
4696
4697static UChar *
florian1b901d42013-01-01 22:19:24 +00004698s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2)
4699{
4700 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004701 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004702 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004703
sewardj6938b9d2013-02-11 16:06:03 +00004704 return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004705}
4706
4707
4708static UChar *
4709s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2)
4710{
4711 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004712 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004713 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004714
sewardj6938b9d2013-02-11 16:06:03 +00004715 return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004716}
4717
4718
4719static UChar *
4720s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2)
4721{
4722 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004723 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004724 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004725
sewardj6938b9d2013-02-11 16:06:03 +00004726 return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004727}
4728
4729
4730static UChar *
4731s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2)
4732{
4733 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004734 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004735 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004736
sewardj6938b9d2013-02-11 16:06:03 +00004737 return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004738}
4739
4740
4741static UChar *
florian3a3d7f12012-12-03 13:32:05 +00004742s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
4743{
florianaec8e052012-12-09 17:26:32 +00004744 vassert(s390_host_has_lsc);
florian08f65d92013-02-22 03:40:22 +00004745 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian3a3d7f12012-12-03 13:32:05 +00004746 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
florian3a3d7f12012-12-03 13:32:05 +00004747
4748 return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
4749}
4750
4751
4752static UChar *
4753s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4754{
florian3a3d7f12012-12-03 13:32:05 +00004755 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4756 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
4757
4758 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
4759}
4760
4761
4762static UChar *
4763s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4764{
florian3a3d7f12012-12-03 13:32:05 +00004765 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4766 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
4767
4768 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
4769}
4770
4771
sewardj2019a972011-03-07 16:04:07 +00004772/* Provide a symbolic name for register "R0" */
4773#define R0 0
4774
4775/* Split up a 20-bit displacement into its high and low piece
4776 suitable for passing as function arguments */
sewardjcd2b0252011-05-09 20:35:41 +00004777#define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
sewardj2019a972011-03-07 16:04:07 +00004778
4779/*---------------------------------------------------------------*/
4780/*--- Helper functions ---*/
4781/*---------------------------------------------------------------*/
4782
4783static __inline__ Bool
4784uint_fits_signed_16bit(UInt val)
4785{
florian8cf66372015-02-09 23:21:07 +00004786 UInt v = val & 0xFFFFu;
sewardj2019a972011-03-07 16:04:07 +00004787
4788 /* sign extend */
florian8cf66372015-02-09 23:21:07 +00004789 v = (Int)(v << 16) >> 16;
sewardj2019a972011-03-07 16:04:07 +00004790
florian8cf66372015-02-09 23:21:07 +00004791 return val == v;
sewardj2019a972011-03-07 16:04:07 +00004792}
4793
4794
4795static __inline__ Bool
4796ulong_fits_signed_16bit(ULong val)
4797{
florian8cf66372015-02-09 23:21:07 +00004798 ULong v = val & 0xFFFFu;
sewardj2019a972011-03-07 16:04:07 +00004799
4800 /* sign extend */
florian8cf66372015-02-09 23:21:07 +00004801 v = (Long)(v << 48) >> 48;
sewardj2019a972011-03-07 16:04:07 +00004802
florian8cf66372015-02-09 23:21:07 +00004803 return val == v;
sewardj2019a972011-03-07 16:04:07 +00004804}
4805
4806
4807static __inline__ Bool
4808ulong_fits_signed_32bit(ULong val)
4809{
florian8cf66372015-02-09 23:21:07 +00004810 ULong v = val & 0xFFFFFFFFu;
sewardj2019a972011-03-07 16:04:07 +00004811
4812 /* sign extend */
florian8cf66372015-02-09 23:21:07 +00004813 v = (Long)(v << 32) >> 32;
sewardj2019a972011-03-07 16:04:07 +00004814
florian8cf66372015-02-09 23:21:07 +00004815 return val == v;
sewardj2019a972011-03-07 16:04:07 +00004816}
4817
4818
4819static __inline__ Bool
4820ulong_fits_unsigned_32bit(ULong val)
4821{
4822 return (val & 0xFFFFFFFFu) == val;
4823}
4824
4825
4826/* Load a 64-bit immediate VAL into register REG. */
4827static UChar *
4828s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
4829{
4830 if (ulong_fits_signed_16bit(val)) {
4831 return s390_emit_LGHI(p, reg, val);
4832 }
4833
4834 if (s390_host_has_eimm) {
4835 if (ulong_fits_unsigned_32bit(val)) {
4836 return s390_emit_LLILF(p, reg, val);
4837 }
4838 if (ulong_fits_signed_32bit(val)) {
4839 /* LGFI's sign extension will recreate the correct 64-bit value */
4840 return s390_emit_LGFI(p, reg, val);
4841 }
4842 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
4843 p = s390_emit_IIHF(p, reg, val >> 32);
4844 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
4845 }
4846
4847 /* Fall back */
4848 if (ulong_fits_unsigned_32bit(val)) {
4849 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
4850 val[0:31] = 0 */
4851 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
4852 return p;
4853 }
4854
4855 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
4856 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
4857 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4858 p = s390_emit_IILL(p, reg, val & 0xFFFF);
4859
4860 return p;
4861}
4862
4863/* Load a 32-bit immediate VAL into register REG. */
4864static UChar *
4865s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
4866{
4867 if (uint_fits_signed_16bit(val)) {
4868 /* LHI's sign extension will recreate the correct 32-bit value */
4869 return s390_emit_LHI(p, reg, val);
4870 }
4871 if (s390_host_has_eimm) {
4872 return s390_emit_IILF(p, reg, val);
4873 }
4874 /* val[0:15] --> (val >> 16) & 0xFFFF
4875 val[16:31] --> val & 0xFFFF */
4876 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4877 return s390_emit_IILL(p, reg, val & 0xFFFF);
4878}
4879
4880/*------------------------------------------------------------*/
4881/*--- Wrapper functions ---*/
4882/*------------------------------------------------------------*/
4883
sewardjeae8db52011-03-24 09:01:50 +00004884/* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
sewardj2019a972011-03-07 16:04:07 +00004885static UChar *
4886s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4887{
4888 if (s390_host_has_gie) {
4889 return s390_emit_MFY(p, r1, x, b, dl, dh);
4890 }
4891
4892 /* Load from memory into R0, then MULTIPLY with R1 */
4893 p = s390_emit_LY(p, R0, x, b, dl, dh);
4894 return s390_emit_MR(p, r1, R0);
4895}
4896
sewardjeae8db52011-03-24 09:01:50 +00004897/* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
4898static UChar *
4899s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4900{
4901 if (s390_host_has_gie) {
4902 return s390_emit_MHY(p, r1, x, b, dl, dh);
4903 }
4904
4905 /* Load from memory into R0, then MULTIPLY with R1 */
4906 p = s390_emit_LHY(p, R0, x, b, dl, dh);
4907 return s390_emit_MSR(p, r1, R0);
4908}
4909
sewardj2019a972011-03-07 16:04:07 +00004910/* r1[32:63] = r1[32:63] * i2 */
4911static UChar *
4912s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
4913{
4914 if (s390_host_has_gie) {
4915 return s390_emit_MSFI(p, r1, i2);
4916 }
4917
4918 /* Load I2 into R0; then MULTIPLY R0 with R1 */
4919 p = s390_emit_load_32imm(p, R0, i2);
4920 return s390_emit_MSR(p, r1, R0);
4921}
4922
4923
4924/* r1[32:63] = r1[32:63] & i2 */
4925static UChar *
4926s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
4927{
4928 if (s390_host_has_eimm) {
4929 return s390_emit_NILF(p, r1, i2);
4930 }
4931
4932 /* Load I2 into R0; then AND R0 with R1 */
4933 p = s390_emit_load_32imm(p, R0, i2);
4934 return s390_emit_NR(p, r1, R0);
4935}
4936
4937
4938/* r1[32:63] = r1[32:63] | i2 */
4939static UChar *
4940s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
4941{
4942 if (s390_host_has_eimm) {
4943 return s390_emit_OILF(p, r1, i2);
4944 }
4945
4946 /* Load I2 into R0; then AND R0 with R1 */
4947 p = s390_emit_load_32imm(p, R0, i2);
4948 return s390_emit_OR(p, r1, R0);
4949}
4950
4951
4952/* r1[32:63] = r1[32:63] ^ i2 */
4953static UChar *
4954s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
4955{
4956 if (s390_host_has_eimm) {
4957 return s390_emit_XILF(p, r1, i2);
4958 }
4959
4960 /* Load I2 into R0; then AND R0 with R1 */
4961 p = s390_emit_load_32imm(p, R0, i2);
4962 return s390_emit_XR(p, r1, R0);
4963}
4964
4965
4966/* r1[32:63] = sign_extend(r2[56:63]) */
4967static UChar *
4968s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
4969{
4970 if (s390_host_has_eimm) {
4971 return s390_emit_LBR(p, r1, r2);
4972 }
4973
4974 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004975 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4976 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
sewardj2019a972011-03-07 16:04:07 +00004977}
4978
4979
4980/* r1[0:63] = sign_extend(r2[56:63]) */
4981static UChar *
4982s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
4983{
4984 if (s390_host_has_eimm) {
4985 return s390_emit_LGBR(p, r1, r2);
4986 }
4987
4988 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4989 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4990 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4991}
4992
4993
4994/* r1[32:63] = sign_extend(r2[48:63]) */
4995static UChar *
4996s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
4997{
4998 if (s390_host_has_eimm) {
4999 return s390_emit_LHR(p, r1, r2);
5000 }
5001
5002 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00005003 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
5004 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
sewardj2019a972011-03-07 16:04:07 +00005005}
5006
5007
5008/* r1[0:63] = sign_extend(r2[48:63]) */
5009static UChar *
5010s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
5011{
5012 if (s390_host_has_eimm) {
5013 return s390_emit_LGHR(p, r1, r2);
5014 }
5015
5016 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5017 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
5018 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
5019}
5020
5021
5022/* r1[0:63] = sign_extend(i2) */
5023static UChar *
5024s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
5025{
5026 if (s390_host_has_eimm) {
5027 return s390_emit_LGFI(p, r1, i2);
5028 }
5029
5030 p = s390_emit_load_32imm(p, R0, i2);
5031 return s390_emit_LGFR(p, r1, R0);
5032}
5033
5034
5035/* r1[32:63] = zero_extend($r2[56:63]) */
5036static UChar *
5037s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
5038{
5039 if (s390_host_has_eimm) {
5040 return s390_emit_LLCR(p, r1, r2);
5041 }
5042
5043 p = s390_emit_LR(p, r1, r2);
5044 p = s390_emit_LHI(p, R0, 0xFF);
5045 return s390_emit_NR(p, r1, R0);
5046}
5047
5048
5049/* r1[0:63] = zero_extend($r2[56:63]) */
5050static UChar *
5051s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
5052{
5053 if (s390_host_has_eimm) {
5054 return s390_emit_LLGCR(p, r1, r2);
5055 }
5056
5057 p = s390_emit_LR(p, r1, r2);
5058 p = s390_emit_LLILL(p, R0, 0xFF);
5059 return s390_emit_NGR(p, r1, R0);
5060}
5061
5062
5063/* r1[32:63] = zero_extend(r2[48:63]) */
5064static UChar *
5065s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
5066{
5067 if (s390_host_has_eimm) {
5068 return s390_emit_LLHR(p, r1, r2);
5069 }
5070
5071 p = s390_emit_LR(p, r1, r2);
5072 p = s390_emit_LLILL(p, R0, 0xFFFF);
5073 return s390_emit_NR(p, r1, R0);
5074}
5075
5076
5077/* r1[0:63] = zero_extend(r2[48:63]) */
5078static UChar *
5079s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
5080{
5081 if (s390_host_has_eimm) {
5082 return s390_emit_LLGHR(p, r1, r2);
5083 }
5084
5085 p = s390_emit_LR(p, r1, r2);
5086 p = s390_emit_LLILL(p, R0, 0xFFFF);
5087 return s390_emit_NGR(p, r1, R0);
5088}
5089
5090
5091/* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
5092static UChar *
5093s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5094{
5095 if (s390_host_has_eimm) {
5096 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
5097 }
5098
5099 if (dh == 0) {
5100 p = s390_emit_IC(p, r1, x2, b2, dl);
5101 } else {
5102 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
5103 }
5104 p = s390_emit_LLILL(p, R0, 0xFF);
5105 return s390_emit_NR(p, r1, R0);
5106}
5107
5108
5109/* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
5110static UChar *
5111s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5112{
5113 if (s390_host_has_eimm) {
5114 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
5115 }
5116
5117 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
5118 p = s390_emit_LLILL(p, R0, 0xFFFF);
5119 return s390_emit_NR(p, r1, R0);
5120}
5121
5122
5123/* r1[0:63] = zero_extend(i2) */
5124static UChar *
5125s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
5126{
5127 if (s390_host_has_eimm) {
5128 return s390_emit_LLILF(p, r1, i2);
5129 }
5130
5131 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
5132 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
5133}
5134
5135
5136/* r1[32:63] = r1[32:63] + i2 */
5137static UChar *
5138s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
5139{
5140 if (s390_host_has_eimm) {
5141 return s390_emit_AFI(p, r1, i2);
5142 }
5143 /* Load 32 bit immediate to R0 then add */
5144 p = s390_emit_load_32imm(p, R0, i2);
5145 return s390_emit_AR(p, r1, R0);
5146}
5147
5148
5149/* r1[32:63] = r1[32:63] - i2 */
5150static UChar *
5151s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
5152{
5153 if (s390_host_has_eimm) {
5154 return s390_emit_SLFI(p, r1, i2);
5155 }
5156
5157 /* Load 32 bit immediate to R0 then subtract */
5158 p = s390_emit_load_32imm(p, R0, i2);
5159 return s390_emit_SR(p, r1, R0);
5160}
5161
5162
sewardjb13a92a2011-04-13 14:44:29 +00005163/* r1[0:63] = r1[0:63] - zero_extend(i2) */
5164static UChar *
5165s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
5166{
5167 if (s390_host_has_eimm) {
5168 return s390_emit_SLGFI(p, r1, i2);
5169 }
5170
5171 /* Load zero-extended 32 bit immediate to R0 then subtract */
5172 p = s390_emit_load_64imm(p, R0, i2);
5173 return s390_emit_SGR(p, r1, R0);
5174}
5175
5176
sewardj2019a972011-03-07 16:04:07 +00005177static UChar *
5178s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5179{
5180 if (s390_host_has_eimm) {
5181 return s390_emit_LT(p, r1, x2, b2, dl, dh);
5182 }
5183 /* Load 32 bit from memory to R0 then compare */
5184 if (dh == 0) {
5185 p = s390_emit_L(p, R0, x2, b2, dl);
5186 } else {
5187 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
5188 }
5189 return s390_emit_LTR(p, r1, R0);
5190}
5191
5192
5193static UChar *
5194s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5195{
5196 if (s390_host_has_eimm) {
5197 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
5198 }
5199 /* Load 64 bit from memory to R0 then compare */
5200 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
5201 return s390_emit_LTGR(p, r1, R0);
5202}
5203
5204
5205static UChar *
5206s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
5207{
5208 if (s390_host_has_eimm) {
5209 return s390_emit_CFI(p, r1, i2);
5210 }
5211 /* Load 32 bit immediate to R0 then compare */
5212 p = s390_emit_load_32imm(p, R0, i2);
5213 return s390_emit_CR(p, r1, R0);
5214}
5215
5216
5217static UChar *
5218s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
5219{
5220 if (s390_host_has_eimm) {
5221 return s390_emit_CLFI(p, r1, i2);
5222 }
5223 /* Load 32 bit immediate to R0 then compare */
5224 p = s390_emit_load_32imm(p, R0, i2);
5225 return s390_emit_CLR(p, r1, R0);
5226}
5227
sewardjd07b8562011-04-27 11:58:22 +00005228
5229static UChar *
5230s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
5231{
5232 if (s390_host_has_fgx) {
5233 return s390_emit_LGDR(p, r1, r2);
5234 }
5235
5236 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
5237 smaller addresses and is 8-byte aligned. Then load the GPR from that
5238 memory location/ */
floriandc6e7472014-12-08 14:01:33 +00005239 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5240 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
sewardjd07b8562011-04-27 11:58:22 +00005241}
5242
5243
5244static UChar *
5245s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
5246{
5247 if (s390_host_has_fgx) {
5248 return s390_emit_LDGR(p, r1, r2);
5249 }
5250
5251 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
5252 smaller addresses and is 8-byte aligned. Then load the FPR from that
5253 memory location/ */
floriandc6e7472014-12-08 14:01:33 +00005254 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5255 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
sewardjd07b8562011-04-27 11:58:22 +00005256}
5257
5258
sewardj2019a972011-03-07 16:04:07 +00005259/*---------------------------------------------------------------*/
5260/*--- Constructors for the various s390_insn kinds ---*/
5261/*---------------------------------------------------------------*/
5262
5263s390_insn *
5264s390_insn_load(UChar size, HReg dst, s390_amode *src)
5265{
floriand8e3eca2015-03-13 12:46:49 +00005266 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005267
5268 insn->tag = S390_INSN_LOAD;
5269 insn->size = size;
5270 insn->variant.load.src = src;
5271 insn->variant.load.dst = dst;
5272
5273 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5274
5275 return insn;
5276}
5277
5278
5279s390_insn *
5280s390_insn_store(UChar size, s390_amode *dst, HReg src)
5281{
floriand8e3eca2015-03-13 12:46:49 +00005282 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005283
5284 insn->tag = S390_INSN_STORE;
5285 insn->size = size;
5286 insn->variant.store.src = src;
5287 insn->variant.store.dst = dst;
5288
5289 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5290
5291 return insn;
5292}
5293
5294
5295s390_insn *
5296s390_insn_move(UChar size, HReg dst, HReg src)
5297{
floriand8e3eca2015-03-13 12:46:49 +00005298 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005299
5300 insn->tag = S390_INSN_MOVE;
5301 insn->size = size;
5302 insn->variant.move.src = src;
5303 insn->variant.move.dst = dst;
5304
5305 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5306
5307 return insn;
5308}
5309
5310
5311s390_insn *
floriancec3a8a2013-02-02 00:16:58 +00005312s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src)
5313{
floriand8e3eca2015-03-13 12:46:49 +00005314 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
floriancec3a8a2013-02-02 00:16:58 +00005315
5316 /* This insn will be mapped to MVC which requires base register
5317 plus 12-bit displacement */
5318 vassert(src->tag == S390_AMODE_B12);
5319 vassert(dst->tag == S390_AMODE_B12);
5320
5321 insn->tag = S390_INSN_MEMCPY;
5322 insn->size = size;
5323 insn->variant.memcpy.src = src;
5324 insn->variant.memcpy.dst = dst;
5325
5326 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5327
5328 return insn;
5329}
5330
5331
5332s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005333s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
5334{
floriand8e3eca2015-03-13 12:46:49 +00005335 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005336
5337 insn->tag = S390_INSN_COND_MOVE;
5338 insn->size = size;
5339 insn->variant.cond_move.cond = cond;
5340 insn->variant.cond_move.src = src;
5341 insn->variant.cond_move.dst = dst;
5342
5343 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5344
5345 return insn;
5346}
5347
5348
5349s390_insn *
5350s390_insn_load_immediate(UChar size, HReg dst, ULong value)
5351{
floriand8e3eca2015-03-13 12:46:49 +00005352 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005353
5354 insn->tag = S390_INSN_LOAD_IMMEDIATE;
5355 insn->size = size;
5356 insn->variant.load_immediate.dst = dst;
5357 insn->variant.load_immediate.value = value;
5358
5359 return insn;
5360}
5361
5362
5363s390_insn *
5364s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
5365{
floriand8e3eca2015-03-13 12:46:49 +00005366 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005367
5368 insn->tag = S390_INSN_ALU;
5369 insn->size = size;
5370 insn->variant.alu.tag = tag;
5371 insn->variant.alu.dst = dst;
5372 insn->variant.alu.op2 = op2;
5373
5374 return insn;
5375}
5376
5377
5378s390_insn *
5379s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
5380 Bool signed_multiply)
5381{
floriand8e3eca2015-03-13 12:46:49 +00005382 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005383
5384 vassert(! hregIsVirtual(dst_hi));
5385 vassert(! hregIsVirtual(dst_lo));
5386
florianc4aa7ed2012-12-22 15:01:04 +00005387 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
sewardj2019a972011-03-07 16:04:07 +00005388 insn->size = size;
5389 insn->variant.mul.dst_hi = dst_hi;
5390 insn->variant.mul.dst_lo = dst_lo;
5391 insn->variant.mul.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00005392
5393 return insn;
5394}
5395
5396
5397s390_insn *
5398s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
5399 Bool signed_divide)
5400{
floriand8e3eca2015-03-13 12:46:49 +00005401 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005402
5403 vassert(size == 4 || size == 8);
5404 vassert(! hregIsVirtual(op1_hi));
5405 vassert(! hregIsVirtual(op1_lo));
5406
florianc4aa7ed2012-12-22 15:01:04 +00005407 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
sewardj2019a972011-03-07 16:04:07 +00005408 insn->size = size;
5409 insn->variant.div.op1_hi = op1_hi;
5410 insn->variant.div.op1_lo = op1_lo;
5411 insn->variant.div.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00005412
5413 return insn;
5414}
5415
5416
5417s390_insn *
5418s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
5419{
floriand8e3eca2015-03-13 12:46:49 +00005420 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005421
5422 vassert(size == 8);
5423 vassert(! hregIsVirtual(op1));
5424 vassert(! hregIsVirtual(rem));
5425
5426 insn->tag = S390_INSN_DIVS;
5427 insn->size = size;
5428 insn->variant.divs.rem = rem; /* remainder */
5429 insn->variant.divs.op1 = op1; /* also quotient */
5430 insn->variant.divs.op2 = op2;
5431
5432 return insn;
5433}
5434
5435
5436s390_insn *
sewardj611b06e2011-03-24 08:57:29 +00005437s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
sewardj2019a972011-03-07 16:04:07 +00005438{
floriand8e3eca2015-03-13 12:46:49 +00005439 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005440
5441 vassert(size == 8);
sewardj611b06e2011-03-24 08:57:29 +00005442 vassert(! hregIsVirtual(num_bits));
5443 vassert(! hregIsVirtual(clobber));
sewardj2019a972011-03-07 16:04:07 +00005444
sewardj611b06e2011-03-24 08:57:29 +00005445 insn->tag = S390_INSN_CLZ;
sewardj2019a972011-03-07 16:04:07 +00005446 insn->size = size;
sewardj611b06e2011-03-24 08:57:29 +00005447 insn->variant.clz.num_bits = num_bits;
5448 insn->variant.clz.clobber = clobber;
5449 insn->variant.clz.src = src;
sewardj2019a972011-03-07 16:04:07 +00005450
5451 return insn;
5452}
5453
5454
5455s390_insn *
5456s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
5457{
floriand8e3eca2015-03-13 12:46:49 +00005458 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005459
5460 insn->tag = S390_INSN_UNOP;
5461 insn->size = size;
5462 insn->variant.unop.tag = tag;
5463 insn->variant.unop.dst = dst;
5464 insn->variant.unop.src = opnd;
5465
5466 return insn;
5467}
5468
5469
5470s390_insn *
5471s390_insn_test(UChar size, s390_opnd_RMI src)
5472{
floriand8e3eca2015-03-13 12:46:49 +00005473 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005474
5475 vassert(size == 4 || size == 8);
5476
5477 insn->tag = S390_INSN_TEST;
5478 insn->size = size;
5479 insn->variant.test.src = src;
5480
5481 return insn;
5482}
5483
5484
5485s390_insn *
5486s390_insn_cc2bool(HReg dst, s390_cc_t cond)
5487{
floriand8e3eca2015-03-13 12:46:49 +00005488 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005489
5490 insn->tag = S390_INSN_CC2BOOL;
5491 insn->size = 0; /* does not matter */
5492 insn->variant.cc2bool.cond = cond;
5493 insn->variant.cc2bool.dst = dst;
5494
5495 return insn;
5496}
5497
5498
5499s390_insn *
5500s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
5501{
floriand8e3eca2015-03-13 12:46:49 +00005502 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005503
5504 vassert(size == 4 || size == 8);
florian3123f722013-01-24 15:55:52 +00005505 vassert(hregNumber(op2->x) == 0);
florian406ac942014-11-22 20:10:21 +00005506 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
sewardj2019a972011-03-07 16:04:07 +00005507
5508 insn->tag = S390_INSN_CAS;
5509 insn->size = size;
5510 insn->variant.cas.op1 = op1;
5511 insn->variant.cas.op2 = op2;
5512 insn->variant.cas.op3 = op3;
5513 insn->variant.cas.old_mem = old_mem;
5514
5515 return insn;
5516}
5517
5518
5519s390_insn *
florian448cbba2012-06-06 02:26:01 +00005520s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
5521 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
5522 HReg scratch)
5523{
floriand8e3eca2015-03-13 12:46:49 +00005524 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5525 s390_cdas *cdas = LibVEX_Alloc_inline(sizeof(s390_cdas));
florian448cbba2012-06-06 02:26:01 +00005526
5527 vassert(size == 4 || size == 8);
florian3123f722013-01-24 15:55:52 +00005528 vassert(hregNumber(op2->x) == 0);
florian448cbba2012-06-06 02:26:01 +00005529 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
florian406ac942014-11-22 20:10:21 +00005530 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
florian448cbba2012-06-06 02:26:01 +00005531
5532 insn->tag = S390_INSN_CDAS;
5533 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005534 insn->variant.cdas.details = cdas;
5535
5536 cdas->op1_high = op1_high;
5537 cdas->op1_low = op1_low;
5538 cdas->op2 = op2;
5539 cdas->op3_high = op3_high;
5540 cdas->op3_low = op3_low;
5541 cdas->old_mem_high = old_mem_high;
5542 cdas->old_mem_low = old_mem_low;
5543 cdas->scratch = scratch;
florian448cbba2012-06-06 02:26:01 +00005544
5545 return insn;
5546}
5547
5548
5549s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005550s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
5551 Bool signed_comparison)
5552{
floriand8e3eca2015-03-13 12:46:49 +00005553 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005554
5555 vassert(size == 4 || size == 8);
5556
5557 insn->tag = S390_INSN_COMPARE;
5558 insn->size = size;
5559 insn->variant.compare.src1 = src1;
5560 insn->variant.compare.src2 = src2;
5561 insn->variant.compare.signed_comparison = signed_comparison;
5562
5563 return insn;
5564}
5565
5566
5567s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005568s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
sewardj74142b82013-08-08 10:28:59 +00005569 const HChar *name, RetLoc rloc)
sewardj2019a972011-03-07 16:04:07 +00005570{
floriand8e3eca2015-03-13 12:46:49 +00005571 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5572 s390_helper_call *helper_call = LibVEX_Alloc_inline(sizeof(s390_helper_call));
sewardj2019a972011-03-07 16:04:07 +00005573
5574 insn->tag = S390_INSN_HELPER_CALL;
5575 insn->size = 0; /* does not matter */
sewardj74142b82013-08-08 10:28:59 +00005576 insn->variant.helper_call.details = helper_call;
5577
5578 helper_call->cond = cond;
5579 helper_call->target = target;
5580 helper_call->num_args = num_args;
5581 helper_call->name = name;
5582 helper_call->rloc = rloc;
5583
5584 vassert(is_sane_RetLoc(rloc));
sewardj2019a972011-03-07 16:04:07 +00005585
5586 return insn;
5587}
5588
5589
5590s390_insn *
5591s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
florian2c74d242012-09-12 19:38:42 +00005592 HReg op3)
sewardj2019a972011-03-07 16:04:07 +00005593{
floriand8e3eca2015-03-13 12:46:49 +00005594 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005595
floriancc491a62012-09-10 23:44:37 +00005596 vassert(size == 4 || size == 8);
5597
sewardj2019a972011-03-07 16:04:07 +00005598 insn->tag = S390_INSN_BFP_TRIOP;
5599 insn->size = size;
5600 insn->variant.bfp_triop.tag = tag;
5601 insn->variant.bfp_triop.dst = dst;
5602 insn->variant.bfp_triop.op2 = op2;
5603 insn->variant.bfp_triop.op3 = op3;
sewardj2019a972011-03-07 16:04:07 +00005604
5605 return insn;
5606}
5607
5608
5609s390_insn *
florian2c74d242012-09-12 19:38:42 +00005610s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
sewardj2019a972011-03-07 16:04:07 +00005611{
floriand8e3eca2015-03-13 12:46:49 +00005612 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005613
floriancc491a62012-09-10 23:44:37 +00005614 vassert(size == 4 || size == 8);
5615
sewardj2019a972011-03-07 16:04:07 +00005616 insn->tag = S390_INSN_BFP_BINOP;
5617 insn->size = size;
5618 insn->variant.bfp_binop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005619 insn->variant.bfp_binop.dst_hi = dst;
5620 insn->variant.bfp_binop.op2_hi = op2;
5621 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
5622 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005623
5624 return insn;
5625}
5626
5627
5628s390_insn *
florian2c74d242012-09-12 19:38:42 +00005629s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
sewardj2019a972011-03-07 16:04:07 +00005630{
floriand8e3eca2015-03-13 12:46:49 +00005631 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005632
floriancc491a62012-09-10 23:44:37 +00005633 vassert(size == 4 || size == 8);
5634
sewardj2019a972011-03-07 16:04:07 +00005635 insn->tag = S390_INSN_BFP_UNOP;
5636 insn->size = size;
5637 insn->variant.bfp_unop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005638 insn->variant.bfp_unop.dst_hi = dst;
5639 insn->variant.bfp_unop.op_hi = op;
5640 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
5641 insn->variant.bfp_unop.op_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005642
5643 return insn;
5644}
5645
5646
5647s390_insn *
5648s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
5649{
floriand8e3eca2015-03-13 12:46:49 +00005650 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005651
5652 vassert(size == 4 || size == 8);
5653
5654 insn->tag = S390_INSN_BFP_COMPARE;
5655 insn->size = size;
5656 insn->variant.bfp_compare.dst = dst;
floriancc491a62012-09-10 23:44:37 +00005657 insn->variant.bfp_compare.op1_hi = op1;
5658 insn->variant.bfp_compare.op2_hi = op2;
5659 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
5660 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005661
5662 return insn;
5663}
5664
5665
5666s390_insn *
florian6dc90242012-12-21 21:43:00 +00005667s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
florian125e20d2012-10-07 15:42:37 +00005668 s390_bfp_round_t rounding_mode)
florian9fcff4c2012-09-10 03:09:04 +00005669{
floriand8e3eca2015-03-13 12:46:49 +00005670 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian9fcff4c2012-09-10 03:09:04 +00005671
floriancc491a62012-09-10 23:44:37 +00005672 vassert(size == 4 || size == 8);
5673
florian9fcff4c2012-09-10 03:09:04 +00005674 insn->tag = S390_INSN_BFP_CONVERT;
5675 insn->size = size;
5676 insn->variant.bfp_convert.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005677 insn->variant.bfp_convert.dst_hi = dst;
5678 insn->variant.bfp_convert.op_hi = op;
5679 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
5680 insn->variant.bfp_convert.op_lo = INVALID_HREG;
florian9fcff4c2012-09-10 03:09:04 +00005681 insn->variant.bfp_convert.rounding_mode = rounding_mode;
5682
5683 return insn;
5684}
5685
5686
floriane38f6412012-12-21 17:32:12 +00005687/* Check validity of a register pair for 128-bit FP. Valid register
floriancc491a62012-09-10 23:44:37 +00005688 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
5689 and (13, 15). */
5690static Bool
floriane38f6412012-12-21 17:32:12 +00005691is_valid_fp128_regpair(HReg hi, HReg lo)
floriancc491a62012-09-10 23:44:37 +00005692{
5693 UInt hi_regno = hregNumber(hi);
5694 UInt lo_regno = hregNumber(lo);
5695
5696 if (lo_regno != hi_regno + 2) return False;
5697 if ((hi_regno & 0x2) != 0) return False;
5698
5699 return True;
5700}
5701
florian9fcff4c2012-09-10 03:09:04 +00005702s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005703s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005704 HReg dst_lo, HReg op2_hi, HReg op2_lo)
sewardj2019a972011-03-07 16:04:07 +00005705{
floriand8e3eca2015-03-13 12:46:49 +00005706 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005707
floriancc491a62012-09-10 23:44:37 +00005708 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005709 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5710 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005711
5712 insn->tag = S390_INSN_BFP_BINOP;
sewardj2019a972011-03-07 16:04:07 +00005713 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005714 insn->variant.bfp_binop.tag = tag;
5715 insn->variant.bfp_binop.dst_hi = dst_hi;
5716 insn->variant.bfp_binop.dst_lo = dst_lo;
5717 insn->variant.bfp_binop.op2_hi = op2_hi;
5718 insn->variant.bfp_binop.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005719
5720 return insn;
5721}
5722
5723
5724s390_insn *
sewardja970c402011-04-28 18:38:42 +00005725s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005726 HReg dst_lo, HReg op_hi, HReg op_lo)
sewardj2019a972011-03-07 16:04:07 +00005727{
floriand8e3eca2015-03-13 12:46:49 +00005728 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005729
floriancc491a62012-09-10 23:44:37 +00005730 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005731 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5732 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005733
5734 insn->tag = S390_INSN_BFP_UNOP;
sewardj2019a972011-03-07 16:04:07 +00005735 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005736 insn->variant.bfp_unop.tag = tag;
5737 insn->variant.bfp_unop.dst_hi = dst_hi;
5738 insn->variant.bfp_unop.dst_lo = dst_lo;
5739 insn->variant.bfp_unop.op_hi = op_hi;
5740 insn->variant.bfp_unop.op_lo = op_lo;
sewardj2019a972011-03-07 16:04:07 +00005741
5742 return insn;
5743}
5744
5745
5746s390_insn *
5747s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
5748 HReg op2_hi, HReg op2_lo)
5749{
floriand8e3eca2015-03-13 12:46:49 +00005750 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005751
floriancc491a62012-09-10 23:44:37 +00005752 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005753 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
5754 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005755
5756 insn->tag = S390_INSN_BFP_COMPARE;
sewardj2019a972011-03-07 16:04:07 +00005757 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005758 insn->variant.bfp_compare.dst = dst;
5759 insn->variant.bfp_compare.op1_hi = op1_hi;
5760 insn->variant.bfp_compare.op1_lo = op1_lo;
5761 insn->variant.bfp_compare.op2_hi = op2_hi;
5762 insn->variant.bfp_compare.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005763
5764 return insn;
5765}
5766
5767
florianb53f9482015-09-05 20:35:52 +00005768s390_insn *
florian6dc90242012-12-21 21:43:00 +00005769s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005770 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005771 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005772{
floriand8e3eca2015-03-13 12:46:49 +00005773 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardj2019a972011-03-07 16:04:07 +00005774
floriancc491a62012-09-10 23:44:37 +00005775 if (size == 16) {
florianb53f9482015-09-05 20:35:52 +00005776 /* From smaller or equal size to 16 bytes */
floriane38f6412012-12-21 17:32:12 +00005777 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
florianb53f9482015-09-05 20:35:52 +00005778 vassert(hregIsInvalid(op_lo)
5779 || is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005780 } else {
5781 /* From 16 bytes to smaller size */
floriane38f6412012-12-21 17:32:12 +00005782 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005783 }
5784
5785 insn->tag = S390_INSN_BFP_CONVERT;
sewardj2019a972011-03-07 16:04:07 +00005786 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005787 insn->variant.bfp_convert.tag = tag;
5788 insn->variant.bfp_convert.dst_hi = dst_hi;
5789 insn->variant.bfp_convert.dst_lo = dst_lo;
5790 insn->variant.bfp_convert.op_hi = op_hi;
5791 insn->variant.bfp_convert.op_lo = op_lo;
5792 insn->variant.bfp_convert.rounding_mode = rounding_mode;
sewardj2019a972011-03-07 16:04:07 +00005793
5794 return insn;
5795}
5796
5797
5798s390_insn *
florian6dc90242012-12-21 21:43:00 +00005799s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005800 HReg dst_lo, HReg op)
5801{
5802 /* Conversion to bfp128 never requires a rounding mode. Provide default
5803 rounding mode. It will not be used when emitting insns. */
florian125e20d2012-10-07 15:42:37 +00005804 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
florian9fcff4c2012-09-10 03:09:04 +00005805
5806 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
5807 INVALID_HREG, rounding_mode);
5808}
5809
5810
5811s390_insn *
floriana2039c52013-12-10 16:51:15 +00005812s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
5813 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005814 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005815{
floriana2039c52013-12-10 16:51:15 +00005816 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
florian9fcff4c2012-09-10 03:09:04 +00005817 rounding_mode);
sewardj2019a972011-03-07 16:04:07 +00005818}
5819
5820
sewardja52e37e2011-04-28 18:48:06 +00005821s390_insn *
florian12390202012-11-10 22:34:14 +00005822s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
5823 HReg op3, s390_dfp_round_t rounding_mode)
5824{
floriand8e3eca2015-03-13 12:46:49 +00005825 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5826 s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
florian12390202012-11-10 22:34:14 +00005827
5828 vassert(size == 8);
5829
5830 insn->tag = S390_INSN_DFP_BINOP;
5831 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005832 insn->variant.dfp_binop.details = dfp_binop;
5833
5834 dfp_binop->tag = tag;
5835 dfp_binop->dst_hi = dst;
5836 dfp_binop->op2_hi = op2;
5837 dfp_binop->op3_hi = op3;
5838 dfp_binop->dst_lo = INVALID_HREG;
5839 dfp_binop->op2_lo = INVALID_HREG;
5840 dfp_binop->op3_lo = INVALID_HREG;
5841 dfp_binop->rounding_mode = rounding_mode;
florian12390202012-11-10 22:34:14 +00005842
5843 return insn;
5844}
5845
5846
5847s390_insn *
floriance9e3db2012-12-27 20:14:03 +00005848s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
5849{
floriand8e3eca2015-03-13 12:46:49 +00005850 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
floriance9e3db2012-12-27 20:14:03 +00005851
5852 vassert(size == 8);
5853
5854 insn->tag = S390_INSN_DFP_UNOP;
5855 insn->size = size;
5856 insn->variant.dfp_unop.tag = tag;
5857 insn->variant.dfp_unop.dst_hi = dst;
5858 insn->variant.dfp_unop.op_hi = op;
5859 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
5860 insn->variant.dfp_unop.op_lo = INVALID_HREG;
5861
5862 return insn;
5863}
5864
5865
5866s390_insn *
florian1b901d42013-01-01 22:19:24 +00005867s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2,
5868 HReg op3)
5869{
floriand8e3eca2015-03-13 12:46:49 +00005870 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian1b901d42013-01-01 22:19:24 +00005871
5872 vassert(size == 8);
5873
5874 insn->tag = S390_INSN_DFP_INTOP;
5875 insn->size = size;
5876 insn->variant.dfp_intop.tag = tag;
5877 insn->variant.dfp_intop.dst_hi = dst;
5878 insn->variant.dfp_intop.op2 = op2;
5879 insn->variant.dfp_intop.op3_hi = op3;
5880 insn->variant.dfp_intop.dst_lo = INVALID_HREG;
5881 insn->variant.dfp_intop.op3_lo = INVALID_HREG;
5882
5883 return insn;
5884}
5885
5886
5887s390_insn *
florian20c6bca2012-12-26 17:47:19 +00005888s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
5889 HReg op1, HReg op2)
floriane38f6412012-12-21 17:32:12 +00005890{
floriand8e3eca2015-03-13 12:46:49 +00005891 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
floriane38f6412012-12-21 17:32:12 +00005892
5893 vassert(size == 8);
5894
5895 insn->tag = S390_INSN_DFP_COMPARE;
5896 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00005897 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00005898 insn->variant.dfp_compare.dst = dst;
5899 insn->variant.dfp_compare.op1_hi = op1;
5900 insn->variant.dfp_compare.op2_hi = op2;
5901 insn->variant.dfp_compare.op1_lo = INVALID_HREG;
5902 insn->variant.dfp_compare.op2_lo = INVALID_HREG;
5903
5904 return insn;
5905}
5906
5907
5908s390_insn *
5909s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
5910 s390_dfp_round_t rounding_mode)
5911{
floriand8e3eca2015-03-13 12:46:49 +00005912 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
floriane38f6412012-12-21 17:32:12 +00005913
florian06dfe212012-12-22 02:09:40 +00005914 vassert(size == 4 || size == 8);
floriane38f6412012-12-21 17:32:12 +00005915
5916 insn->tag = S390_INSN_DFP_CONVERT;
5917 insn->size = size;
5918 insn->variant.dfp_convert.tag = tag;
5919 insn->variant.dfp_convert.dst_hi = dst;
5920 insn->variant.dfp_convert.op_hi = op;
5921 insn->variant.dfp_convert.dst_lo = INVALID_HREG;
5922 insn->variant.dfp_convert.op_lo = INVALID_HREG;
5923 insn->variant.dfp_convert.rounding_mode = rounding_mode;
5924
5925 return insn;
5926}
5927
5928
5929s390_insn *
florian5c539732013-02-14 14:27:12 +00005930s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3,
5931 s390_dfp_round_t rounding_mode)
5932{
floriand8e3eca2015-03-13 12:46:49 +00005933 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian5c539732013-02-14 14:27:12 +00005934
5935 vassert(size == 8);
5936
5937 insn->tag = S390_INSN_DFP_REROUND;
5938 insn->size = size;
5939 insn->variant.dfp_reround.dst_hi = dst;
5940 insn->variant.dfp_reround.op2 = op2;
5941 insn->variant.dfp_reround.op3_hi = op3;
5942 insn->variant.dfp_reround.dst_lo = INVALID_HREG;
5943 insn->variant.dfp_reround.op3_lo = INVALID_HREG;
5944 insn->variant.dfp_reround.rounding_mode = rounding_mode;
5945
5946 return insn;
5947}
5948
5949
5950s390_insn *
florian78d5ef72013-05-11 15:02:58 +00005951s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op,
5952 HReg r1, s390_dfp_round_t rounding_mode)
5953{
floriand8e3eca2015-03-13 12:46:49 +00005954 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5955 s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
florian78d5ef72013-05-11 15:02:58 +00005956
5957 vassert(size == 4 || size == 8);
5958
5959 insn->tag = S390_INSN_FP_CONVERT;
5960 insn->size = size;
5961 insn->variant.fp_convert.details = fp_convert;
5962
5963 fp_convert->tag = tag;
5964 fp_convert->dst_hi = dst;
5965 fp_convert->op_hi = op;
5966 fp_convert->r1 = r1;
5967 fp_convert->dst_lo = INVALID_HREG;
5968 fp_convert->op_lo = INVALID_HREG;
5969 fp_convert->rounding_mode = rounding_mode;
5970
5971 return insn;
5972}
5973
5974
5975s390_insn *
5976s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi,
5977 HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1,
5978 s390_dfp_round_t rounding_mode)
5979{
floriand8e3eca2015-03-13 12:46:49 +00005980 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5981 s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
florian78d5ef72013-05-11 15:02:58 +00005982
5983 vassert(size == 16);
5984
5985 insn->tag = S390_INSN_FP_CONVERT;
5986 insn->size = size;
5987 insn->variant.fp_convert.details = fp_convert;
5988
5989 fp_convert->tag = tag;
5990 fp_convert->dst_hi = dst_hi;
5991 fp_convert->dst_lo = dst_lo;
5992 fp_convert->op_hi = op_hi;
5993 fp_convert->r1 = r1;
5994 fp_convert->op_lo = op_lo;
5995 fp_convert->rounding_mode = rounding_mode;
5996
5997 return insn;
5998}
5999
6000
6001s390_insn *
floriane38f6412012-12-21 17:32:12 +00006002s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
6003 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
6004 HReg op3_lo, s390_dfp_round_t rounding_mode)
6005{
floriand8e3eca2015-03-13 12:46:49 +00006006 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6007 s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
floriane38f6412012-12-21 17:32:12 +00006008
6009 vassert(size == 16);
6010 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6011 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6012 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6013
floriane38f6412012-12-21 17:32:12 +00006014 insn->tag = S390_INSN_DFP_BINOP;
6015 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00006016 insn->variant.dfp_binop.details = dfp_binop;
6017
6018 dfp_binop->tag = tag;
6019 dfp_binop->dst_hi = dst_hi;
6020 dfp_binop->dst_lo = dst_lo;
6021 dfp_binop->op2_hi = op2_hi;
6022 dfp_binop->op2_lo = op2_lo;
6023 dfp_binop->op3_hi = op3_hi;
6024 dfp_binop->op3_lo = op3_lo;
6025 dfp_binop->rounding_mode = rounding_mode;
floriane38f6412012-12-21 17:32:12 +00006026
6027 return insn;
6028}
6029
6030
6031s390_insn *
floriance9e3db2012-12-27 20:14:03 +00006032s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
6033 HReg op_hi, HReg op_lo)
6034{
floriand8e3eca2015-03-13 12:46:49 +00006035 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
floriance9e3db2012-12-27 20:14:03 +00006036
6037 /* destination is an 8 byte integer value */
6038 vassert(size == 8);
6039 vassert(is_valid_fp128_regpair(op_hi, op_lo));
6040
6041 insn->tag = S390_INSN_DFP_UNOP;
6042 insn->size = size;
6043 insn->variant.dfp_unop.tag = tag;
6044 insn->variant.dfp_unop.dst_hi = dst;
6045 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
6046 insn->variant.dfp_unop.op_hi = op_hi;
6047 insn->variant.dfp_unop.op_lo = op_lo;
6048
6049 return insn;
6050}
6051
6052
6053s390_insn *
florian1b901d42013-01-01 22:19:24 +00006054s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi,
6055 HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo)
6056{
floriand8e3eca2015-03-13 12:46:49 +00006057 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian1b901d42013-01-01 22:19:24 +00006058
6059 vassert(size == 16);
6060 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6061 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6062
6063 insn->tag = S390_INSN_DFP_INTOP;
6064 insn->size = size;
6065 insn->variant.dfp_intop.tag = tag;
6066 insn->variant.dfp_intop.dst_hi = dst_hi;
6067 insn->variant.dfp_intop.dst_lo = dst_lo;
6068 insn->variant.dfp_intop.op2 = op2;
6069 insn->variant.dfp_intop.op3_hi = op3_hi;
6070 insn->variant.dfp_intop.op3_lo = op3_lo;
6071
6072 return insn;
6073}
6074
6075
6076s390_insn *
florian20c6bca2012-12-26 17:47:19 +00006077s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
6078 HReg op1_lo, HReg op2_hi, HReg op2_lo)
floriane38f6412012-12-21 17:32:12 +00006079{
floriand8e3eca2015-03-13 12:46:49 +00006080 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
floriane38f6412012-12-21 17:32:12 +00006081
6082 vassert(size == 16);
6083 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
6084 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6085
6086 insn->tag = S390_INSN_DFP_COMPARE;
6087 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00006088 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00006089 insn->variant.dfp_compare.dst = dst;
6090 insn->variant.dfp_compare.op1_hi = op1_hi;
6091 insn->variant.dfp_compare.op1_lo = op1_lo;
6092 insn->variant.dfp_compare.op2_hi = op2_hi;
6093 insn->variant.dfp_compare.op2_lo = op2_lo;
6094
6095 return insn;
6096}
6097
6098
6099static s390_insn *
6100s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6101 HReg dst_lo, HReg op_hi, HReg op_lo,
6102 s390_dfp_round_t rounding_mode)
6103{
floriand8e3eca2015-03-13 12:46:49 +00006104 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
floriane38f6412012-12-21 17:32:12 +00006105
6106 if (size == 16) {
6107 /* From smaller size to 16 bytes */
6108 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
florian79efdc62013-02-11 00:47:35 +00006109 vassert(hregIsInvalid(op_lo));
floriane38f6412012-12-21 17:32:12 +00006110 } else {
6111 /* From 16 bytes to smaller size */
6112 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriane38f6412012-12-21 17:32:12 +00006113 }
6114
6115 insn->tag = S390_INSN_DFP_CONVERT;
6116 insn->size = size;
6117 insn->variant.dfp_convert.tag = tag;
6118 insn->variant.dfp_convert.dst_hi = dst_hi;
6119 insn->variant.dfp_convert.dst_lo = dst_lo;
6120 insn->variant.dfp_convert.op_hi = op_hi;
6121 insn->variant.dfp_convert.op_lo = op_lo;
6122 insn->variant.dfp_convert.rounding_mode = rounding_mode;
6123
6124 return insn;
6125}
6126
6127
6128s390_insn *
6129s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6130 HReg dst_lo, HReg op)
6131{
6132 /* Conversion to dfp128 never requires a rounding mode. Provide default
6133 rounding mode. It will not be used when emitting insns. */
6134 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
6135
6136 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
6137 INVALID_HREG, rounding_mode);
6138}
6139
6140
6141s390_insn *
floriana2039c52013-12-10 16:51:15 +00006142s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6143 HReg dst_lo, HReg op_hi, HReg op_lo,
floriane38f6412012-12-21 17:32:12 +00006144 s390_dfp_round_t rounding_mode)
6145{
floriana2039c52013-12-10 16:51:15 +00006146 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
floriane38f6412012-12-21 17:32:12 +00006147 rounding_mode);
6148}
6149
6150
6151s390_insn *
florian5c539732013-02-14 14:27:12 +00006152s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2,
6153 HReg op3_hi, HReg op3_lo,
6154 s390_dfp_round_t rounding_mode)
6155{
floriand8e3eca2015-03-13 12:46:49 +00006156 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian5c539732013-02-14 14:27:12 +00006157
6158 vassert(size == 16);
6159 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6160 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6161
6162 insn->tag = S390_INSN_DFP_REROUND;
6163 insn->size = size;
6164 insn->variant.dfp_reround.dst_hi = dst_hi;
6165 insn->variant.dfp_reround.dst_lo = dst_lo;
6166 insn->variant.dfp_reround.op2 = op2;
6167 insn->variant.dfp_reround.op3_hi = op3_hi;
6168 insn->variant.dfp_reround.op3_lo = op3_lo;
6169 insn->variant.dfp_reround.rounding_mode = rounding_mode;
6170
6171 return insn;
6172}
6173
6174
6175s390_insn *
sewardja52e37e2011-04-28 18:48:06 +00006176s390_insn_mfence(void)
6177{
floriand8e3eca2015-03-13 12:46:49 +00006178 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
sewardja52e37e2011-04-28 18:48:06 +00006179
6180 insn->tag = S390_INSN_MFENCE;
6181 insn->size = 0; /* not needed */
6182
6183 return insn;
6184}
6185
6186
florianad43b3a2012-02-20 15:01:14 +00006187s390_insn *
florianb93348d2012-12-27 00:59:43 +00006188s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
florianad43b3a2012-02-20 15:01:14 +00006189{
floriand8e3eca2015-03-13 12:46:49 +00006190 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florianad43b3a2012-02-20 15:01:14 +00006191
florianb93348d2012-12-27 00:59:43 +00006192 /* This insn will be mapped to insns that require base register
florian09bbba82012-12-11 04:09:43 +00006193 plus 12-bit displacement */
6194 vassert(dst->tag == S390_AMODE_B12);
6195
florianb93348d2012-12-27 00:59:43 +00006196 insn->tag = S390_INSN_MIMM;
florianad43b3a2012-02-20 15:01:14 +00006197 insn->size = size;
florianb93348d2012-12-27 00:59:43 +00006198 insn->variant.mimm.dst = dst;
6199 insn->variant.mimm.value = value;
florianad43b3a2012-02-20 15:01:14 +00006200
6201 return insn;
6202}
6203
6204
6205s390_insn *
florianf85fe3e2012-12-22 02:28:25 +00006206s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
florianad43b3a2012-02-20 15:01:14 +00006207{
floriand8e3eca2015-03-13 12:46:49 +00006208 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florianad43b3a2012-02-20 15:01:14 +00006209
florianf85fe3e2012-12-22 02:28:25 +00006210 vassert(size == 4 || size == 8);
6211
6212 /* This insn will be mapped to an ASI or AGSI so we can only allow base
6213 register plus 12-bit / 20-bit displacement. */
6214 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
florian49adf862014-12-06 20:24:08 +00006215 /* ASI and AGSI require the GIE facility */
6216 vassert(s390_host_has_gie);
florianf85fe3e2012-12-22 02:28:25 +00006217
6218 insn->tag = S390_INSN_MADD;
florianad43b3a2012-02-20 15:01:14 +00006219 insn->size = size;
florianf85fe3e2012-12-22 02:28:25 +00006220 insn->variant.madd.dst = dst;
6221 insn->variant.madd.delta = delta;
6222 insn->variant.madd.value = value;
florianad43b3a2012-02-20 15:01:14 +00006223
6224 return insn;
6225}
6226
6227
florian8844a632012-04-13 04:04:06 +00006228s390_insn *
florian125e20d2012-10-07 15:42:37 +00006229s390_insn_set_fpc_bfprm(UChar size, HReg mode)
florian2c74d242012-09-12 19:38:42 +00006230{
6231 vassert(size == 4);
6232
floriand8e3eca2015-03-13 12:46:49 +00006233 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian2c74d242012-09-12 19:38:42 +00006234
florian125e20d2012-10-07 15:42:37 +00006235 insn->tag = S390_INSN_SET_FPC_BFPRM;
florian2c74d242012-09-12 19:38:42 +00006236 insn->size = size;
florian125e20d2012-10-07 15:42:37 +00006237 insn->variant.set_fpc_bfprm.mode = mode;
florian2c74d242012-09-12 19:38:42 +00006238
6239 return insn;
6240}
6241
6242
6243s390_insn *
florianc8e4f562012-10-27 16:19:31 +00006244s390_insn_set_fpc_dfprm(UChar size, HReg mode)
6245{
6246 vassert(size == 4);
6247
floriand8e3eca2015-03-13 12:46:49 +00006248 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florianc8e4f562012-10-27 16:19:31 +00006249
6250 insn->tag = S390_INSN_SET_FPC_DFPRM;
6251 insn->size = size;
6252 insn->variant.set_fpc_dfprm.mode = mode;
6253
6254 return insn;
6255}
6256
6257
6258s390_insn *
florian8844a632012-04-13 04:04:06 +00006259s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
6260 Bool to_fast_entry)
6261{
floriand8e3eca2015-03-13 12:46:49 +00006262 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian8844a632012-04-13 04:04:06 +00006263
florian406ac942014-11-22 20:10:21 +00006264 vassert(guest_IA->tag == S390_AMODE_B12);
6265
florian8844a632012-04-13 04:04:06 +00006266 insn->tag = S390_INSN_XDIRECT;
6267 insn->size = 0; /* does not matter */
6268
6269 insn->variant.xdirect.cond = cond;
6270 insn->variant.xdirect.dst = dst;
6271 insn->variant.xdirect.guest_IA = guest_IA;
6272 insn->variant.xdirect.to_fast_entry = to_fast_entry;
6273
6274 return insn;
6275}
6276
6277
6278s390_insn *
6279s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
6280{
floriand8e3eca2015-03-13 12:46:49 +00006281 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian8844a632012-04-13 04:04:06 +00006282
florian406ac942014-11-22 20:10:21 +00006283 vassert(guest_IA->tag == S390_AMODE_B12);
6284
florian7346c7a2012-04-13 21:14:24 +00006285 insn->tag = S390_INSN_XINDIR;
florian8844a632012-04-13 04:04:06 +00006286 insn->size = 0; /* does not matter */
6287
florian7346c7a2012-04-13 21:14:24 +00006288 insn->variant.xindir.cond = cond;
6289 insn->variant.xindir.dst = dst;
6290 insn->variant.xindir.guest_IA = guest_IA;
florian8844a632012-04-13 04:04:06 +00006291
6292 return insn;
6293}
6294
6295
6296s390_insn *
6297s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
6298 IRJumpKind kind)
6299{
floriand8e3eca2015-03-13 12:46:49 +00006300 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian8844a632012-04-13 04:04:06 +00006301
florian406ac942014-11-22 20:10:21 +00006302 vassert(guest_IA->tag == S390_AMODE_B12);
6303
florian8844a632012-04-13 04:04:06 +00006304 insn->tag = S390_INSN_XASSISTED;
6305 insn->size = 0; /* does not matter */
6306
6307 insn->variant.xassisted.cond = cond;
6308 insn->variant.xassisted.dst = dst;
6309 insn->variant.xassisted.guest_IA = guest_IA;
6310 insn->variant.xassisted.kind = kind;
6311
6312 return insn;
6313}
6314
6315
6316s390_insn *
6317s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
6318{
floriand8e3eca2015-03-13 12:46:49 +00006319 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian8844a632012-04-13 04:04:06 +00006320
florianbf516d12012-04-21 15:53:13 +00006321 vassert(counter->tag == S390_AMODE_B12);
6322 vassert(fail_addr->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00006323
6324 insn->tag = S390_INSN_EVCHECK;
6325 insn->size = 0; /* does not matter */
6326
6327 insn->variant.evcheck.counter = counter;
6328 insn->variant.evcheck.fail_addr = fail_addr;
6329
6330 return insn;
6331}
6332
6333
6334s390_insn *
6335s390_insn_profinc(void)
6336{
floriand8e3eca2015-03-13 12:46:49 +00006337 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
florian8844a632012-04-13 04:04:06 +00006338
6339 insn->tag = S390_INSN_PROFINC;
6340 insn->size = 0; /* does not matter */
6341
6342 return insn;
6343}
6344
6345
sewardj2019a972011-03-07 16:04:07 +00006346/*---------------------------------------------------------------*/
6347/*--- Debug print ---*/
6348/*---------------------------------------------------------------*/
6349
6350static const HChar *
6351s390_cc_as_string(s390_cc_t cc)
6352{
6353 switch (cc) {
6354 case S390_CC_NEVER: return "never";
6355 case S390_CC_OVFL: return "overflow";
6356 case S390_CC_H: return "greater than"; /* A > B ; high */
6357 case S390_CC_NLE: return "not low or equal";
6358 case S390_CC_L: return "less than"; /* A < B ; low */
6359 case S390_CC_NHE: return "not high or equal";
6360 case S390_CC_LH: return "low or high";
6361 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
6362 case S390_CC_E: return "equal"; /* A == B ; zero */
6363 case S390_CC_NLH: return "not low or high";
6364 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
6365 case S390_CC_NL: return "not low"; /* not low */
6366 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
6367 case S390_CC_NH: return "not high";
6368 case S390_CC_NO: return "not overflow";
6369 case S390_CC_ALWAYS: return "always";
6370 default:
6371 vpanic("s390_cc_as_string");
6372 }
6373}
6374
6375
florian8844a632012-04-13 04:04:06 +00006376static const HChar *
6377s390_jump_kind_as_string(IRJumpKind kind)
6378{
6379 switch (kind) {
6380 case Ijk_Boring: return "Boring";
6381 case Ijk_Call: return "Call";
6382 case Ijk_Ret: return "Return";
6383 case Ijk_ClientReq: return "ClientReq";
6384 case Ijk_Yield: return "Yield";
6385 case Ijk_EmWarn: return "EmWarn";
6386 case Ijk_EmFail: return "EmFail";
6387 case Ijk_NoDecode: return "NoDecode";
6388 case Ijk_MapFail: return "MapFail";
sewardj05f5e012014-05-04 10:52:11 +00006389 case Ijk_InvalICache: return "Invalidate";
florian8844a632012-04-13 04:04:06 +00006390 case Ijk_NoRedir: return "NoRedir";
6391 case Ijk_SigTRAP: return "SigTRAP";
6392 case Ijk_SigSEGV: return "SigSEGV";
6393 case Ijk_SigBUS: return "SigBUS";
6394 case Ijk_Sys_syscall: return "Sys_syscall";
6395 default:
6396 vpanic("s390_jump_kind_as_string");
6397 }
6398}
6399
6400
sewardj2019a972011-03-07 16:04:07 +00006401/* Helper function for writing out a V insn */
6402static void
florian55085f82012-11-21 00:36:55 +00006403s390_sprintf(HChar *buf, const HChar *fmt, ...)
sewardj2019a972011-03-07 16:04:07 +00006404{
6405 HChar *p;
6406 ULong value;
6407 va_list args;
6408 va_start(args, fmt);
6409
6410 p = buf;
6411 for ( ; *fmt; ++fmt) {
6412 Int c = *fmt;
6413
6414 if (c != '%') {
6415 *p++ = c;
6416 continue;
6417 }
6418
6419 c = *++fmt; /* next char */
6420 switch (c) {
6421 case '%':
6422 *p++ = c; /* %% */
6423 continue;
6424
6425 case 's': /* %s */
6426 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
6427 continue;
6428
6429 case 'M': /* %M = mnemonic */
6430 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
6431 continue;
6432
6433 case 'R': /* %R = register */
6434 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
6435 continue;
6436
6437 case 'A': /* %A = amode */
6438 p += vex_sprintf(p, "%s",
6439 s390_amode_as_string(va_arg(args, s390_amode *)));
6440 continue;
6441
florianad43b3a2012-02-20 15:01:14 +00006442 case 'G': /* %G = guest state @ offset */
florianb1737742015-08-03 16:03:13 +00006443 p += vex_sprintf(p, "guest[%u]", va_arg(args, UInt));
florianad43b3a2012-02-20 15:01:14 +00006444 continue;
6445
sewardj2019a972011-03-07 16:04:07 +00006446 case 'C': /* %C = condition code */
6447 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
6448 continue;
6449
florian8844a632012-04-13 04:04:06 +00006450 case 'J': /* &J = jump kind */
6451 p += vex_sprintf(p, "%s",
6452 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
6453 continue;
6454
sewardj2019a972011-03-07 16:04:07 +00006455 case 'L': { /* %L = argument list in helper call*/
6456 UInt i, num_args;
6457
6458 num_args = va_arg(args, UInt);
6459
6460 for (i = 0; i < num_args; ++i) {
6461 if (i != 0) p += vex_sprintf(p, ", ");
florianb1737742015-08-03 16:03:13 +00006462 p += vex_sprintf(p, "r%u", s390_gprno_from_arg_index(i));
sewardj2019a972011-03-07 16:04:07 +00006463 }
6464 continue;
6465 }
6466
6467 case 'O': { /* %O = RMI operand */
6468 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
6469
6470 switch (op->tag) {
6471 case S390_OPND_REG:
6472 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
6473 continue;
6474
6475 case S390_OPND_AMODE:
6476 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
6477 continue;
6478
6479 case S390_OPND_IMMEDIATE:
6480 value = op->variant.imm;
6481 goto print_value;
6482
6483 default:
6484 goto fail;
6485 }
6486 }
6487
6488 case 'I': /* %I = immediate value */
6489 value = va_arg(args, ULong);
6490 goto print_value;
6491
6492 print_value:
6493 if ((Long)value < 0)
6494 p += vex_sprintf(p, "%lld", (Long)value);
6495 else if (value < 100)
6496 p += vex_sprintf(p, "%llu", value);
6497 else
6498 p += vex_sprintf(p, "0x%llx", value);
6499 continue;
6500
6501 default:
6502 goto fail;
6503 }
6504 }
6505 *p = '\0';
6506 va_end(args);
6507
6508 return;
6509
6510 fail: vpanic("s390_printf");
6511}
6512
6513
6514/* Decompile the given insn into a static buffer and return it */
6515const HChar *
6516s390_insn_as_string(const s390_insn *insn)
6517{
florian8a45a4e2014-12-23 11:05:03 +00006518 static HChar buf[300]; // large enough
sewardj2019a972011-03-07 16:04:07 +00006519 const HChar *op;
6520 HChar *p;
6521
6522 buf[0] = '\0';
6523
6524 switch (insn->tag) {
6525 case S390_INSN_LOAD:
6526 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
6527 insn->variant.load.src);
6528 break;
6529
6530 case S390_INSN_STORE:
6531 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
6532 insn->variant.store.dst);
6533 break;
6534
6535 case S390_INSN_MOVE:
6536 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
6537 insn->variant.move.src);
6538 break;
6539
floriancec3a8a2013-02-02 00:16:58 +00006540 case S390_INSN_MEMCPY:
6541 s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst,
6542 insn->variant.memcpy.src);
6543 break;
6544
sewardj2019a972011-03-07 16:04:07 +00006545 case S390_INSN_COND_MOVE:
6546 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
6547 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
6548 &insn->variant.cond_move.src);
6549 break;
6550
6551 case S390_INSN_LOAD_IMMEDIATE:
6552 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
6553 insn->variant.load_immediate.value);
6554 break;
6555
6556 case S390_INSN_ALU:
6557 switch (insn->variant.alu.tag) {
6558 case S390_ALU_ADD: op = "v-add"; break;
6559 case S390_ALU_SUB: op = "v-sub"; break;
6560 case S390_ALU_MUL: op = "v-mul"; break;
6561 case S390_ALU_AND: op = "v-and"; break;
6562 case S390_ALU_OR: op = "v-or"; break;
6563 case S390_ALU_XOR: op = "v-xor"; break;
6564 case S390_ALU_LSH: op = "v-lsh"; break;
6565 case S390_ALU_RSH: op = "v-rsh"; break;
6566 case S390_ALU_RSHA: op = "v-rsha"; break;
6567 default: goto fail;
6568 }
florian043af212012-06-06 02:44:53 +00006569 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
sewardj2019a972011-03-07 16:04:07 +00006570 &insn->variant.alu.op2);
6571 break;
6572
florianc4aa7ed2012-12-22 15:01:04 +00006573 case S390_INSN_SMUL:
6574 case S390_INSN_UMUL:
6575 if (insn->tag == S390_INSN_SMUL) {
sewardj2019a972011-03-07 16:04:07 +00006576 op = "v-muls";
6577 } else {
6578 op = "v-mulu";
6579 }
6580 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
6581 &insn->variant.mul.op2);
6582 break;
6583
florianc4aa7ed2012-12-22 15:01:04 +00006584 case S390_INSN_SDIV:
6585 case S390_INSN_UDIV:
6586 if (insn->tag == S390_INSN_SDIV) {
sewardj2019a972011-03-07 16:04:07 +00006587 op = "v-divs";
6588 } else {
6589 op = "v-divu";
6590 }
6591 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
6592 &insn->variant.div.op2);
6593 break;
6594
6595 case S390_INSN_DIVS:
6596 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
6597 &insn->variant.divs.op2);
6598 break;
6599
sewardj611b06e2011-03-24 08:57:29 +00006600 case S390_INSN_CLZ:
6601 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
6602 &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +00006603 break;
6604
6605 case S390_INSN_UNOP:
6606 switch (insn->variant.unop.tag) {
6607 case S390_ZERO_EXTEND_8:
6608 case S390_ZERO_EXTEND_16:
6609 case S390_ZERO_EXTEND_32:
6610 op = "v-zerox";
6611 break;
6612
6613 case S390_SIGN_EXTEND_8:
6614 case S390_SIGN_EXTEND_16:
6615 case S390_SIGN_EXTEND_32:
6616 op = "v-signx";
6617 break;
6618
6619 case S390_NEGATE:
6620 op = "v-neg";
6621 break;
6622
6623 default:
6624 goto fail;
6625 }
6626 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
6627 &insn->variant.unop.src);
6628 break;
6629
6630 case S390_INSN_TEST:
6631 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
6632 break;
6633
6634 case S390_INSN_CC2BOOL:
6635 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
6636 insn->variant.cc2bool.cond);
6637 break;
6638
6639 case S390_INSN_CAS:
6640 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
6641 insn->variant.cas.op2, insn->variant.cas.op3,
6642 insn->variant.cas.old_mem);
6643 break;
6644
florianc4aa7ed2012-12-22 15:01:04 +00006645 case S390_INSN_CDAS: {
6646 s390_cdas *cdas = insn->variant.cdas.details;
6647
florian448cbba2012-06-06 02:26:01 +00006648 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
florianc4aa7ed2012-12-22 15:01:04 +00006649 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
6650 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
florian448cbba2012-06-06 02:26:01 +00006651 break;
florianc4aa7ed2012-12-22 15:01:04 +00006652 }
florian448cbba2012-06-06 02:26:01 +00006653
sewardj2019a972011-03-07 16:04:07 +00006654 case S390_INSN_COMPARE:
6655 if (insn->variant.compare.signed_comparison) {
6656 op = "v-cmps";
6657 } else {
6658 op = "v-cmpu";
6659 }
6660 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
6661 &insn->variant.compare.src2);
6662 break;
6663
sewardj2019a972011-03-07 16:04:07 +00006664 case S390_INSN_HELPER_CALL: {
sewardj74142b82013-08-08 10:28:59 +00006665 s390_helper_call *helper_call = insn->variant.helper_call.details;
6666 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
6667 helper_call->cond,
6668 helper_call->name,
6669 helper_call->target,
6670 helper_call->num_args);
florian8844a632012-04-13 04:04:06 +00006671 return buf; /* avoid printing "size = ..." which is meaningless */
sewardj2019a972011-03-07 16:04:07 +00006672 }
6673
6674 case S390_INSN_BFP_TRIOP:
6675 switch (insn->variant.bfp_triop.tag) {
6676 case S390_BFP_MADD: op = "v-fmadd"; break;
6677 case S390_BFP_MSUB: op = "v-fmsub"; break;
6678 default: goto fail;
6679 }
florian043af212012-06-06 02:44:53 +00006680 s390_sprintf(buf, "%M %R,%R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00006681 insn->variant.bfp_triop.dst /* op1 same as dst */,
6682 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
6683 break;
6684
6685 case S390_INSN_BFP_BINOP:
6686 switch (insn->variant.bfp_binop.tag) {
6687 case S390_BFP_ADD: op = "v-fadd"; break;
6688 case S390_BFP_SUB: op = "v-fsub"; break;
6689 case S390_BFP_MUL: op = "v-fmul"; break;
6690 case S390_BFP_DIV: op = "v-fdiv"; break;
6691 default: goto fail;
6692 }
florian043af212012-06-06 02:44:53 +00006693 s390_sprintf(buf, "%M %R,%R", op,
floriancc491a62012-09-10 23:44:37 +00006694 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
6695 insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00006696 break;
6697
6698 case S390_INSN_BFP_COMPARE:
6699 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
floriancc491a62012-09-10 23:44:37 +00006700 insn->variant.bfp_compare.op1_hi,
6701 insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00006702 break;
6703
6704 case S390_INSN_BFP_UNOP:
6705 switch (insn->variant.bfp_unop.tag) {
6706 case S390_BFP_ABS: op = "v-fabs"; break;
6707 case S390_BFP_NABS: op = "v-fnabs"; break;
6708 case S390_BFP_NEG: op = "v-fneg"; break;
6709 case S390_BFP_SQRT: op = "v-fsqrt"; break;
florian9fcff4c2012-09-10 03:09:04 +00006710 default: goto fail;
6711 }
floriancc491a62012-09-10 23:44:37 +00006712 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
6713 insn->variant.bfp_unop.op_hi);
florian9fcff4c2012-09-10 03:09:04 +00006714 break;
6715
6716 case S390_INSN_BFP_CONVERT:
6717 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00006718 case S390_BFP_I32_TO_F32:
6719 case S390_BFP_I32_TO_F64:
6720 case S390_BFP_I32_TO_F128:
6721 case S390_BFP_I64_TO_F32:
6722 case S390_BFP_I64_TO_F64:
6723 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006724 case S390_BFP_U32_TO_F32:
6725 case S390_BFP_U32_TO_F64:
6726 case S390_BFP_U32_TO_F128:
6727 case S390_BFP_U64_TO_F32:
6728 case S390_BFP_U64_TO_F64:
6729 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
sewardj2019a972011-03-07 16:04:07 +00006730 case S390_BFP_F32_TO_I32:
6731 case S390_BFP_F32_TO_I64:
6732 case S390_BFP_F64_TO_I32:
6733 case S390_BFP_F64_TO_I64:
6734 case S390_BFP_F128_TO_I32:
6735 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006736 case S390_BFP_F32_TO_U32:
6737 case S390_BFP_F32_TO_U64:
6738 case S390_BFP_F64_TO_U32:
6739 case S390_BFP_F64_TO_U64:
6740 case S390_BFP_F128_TO_U32:
6741 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
sewardj2019a972011-03-07 16:04:07 +00006742 case S390_BFP_F32_TO_F64:
6743 case S390_BFP_F32_TO_F128:
6744 case S390_BFP_F64_TO_F32:
6745 case S390_BFP_F64_TO_F128:
6746 case S390_BFP_F128_TO_F32:
6747 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
florian6d0b0152015-07-09 20:59:24 +00006748 case S390_BFP_F32_TO_F32I:
florianb53f9482015-09-05 20:35:52 +00006749 case S390_BFP_F64_TO_F64I:
6750 case S390_BFP_F128_TO_F128I: op = "v-f2fi"; break;
sewardj2019a972011-03-07 16:04:07 +00006751 default: goto fail;
6752 }
floriancc491a62012-09-10 23:44:37 +00006753 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
6754 insn->variant.bfp_convert.op_hi);
sewardj2019a972011-03-07 16:04:07 +00006755 break;
6756
florianc4aa7ed2012-12-22 15:01:04 +00006757 case S390_INSN_DFP_BINOP: {
6758 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
6759
6760 switch (dfp_binop->tag) {
florian12390202012-11-10 22:34:14 +00006761 case S390_DFP_ADD: op = "v-dadd"; break;
6762 case S390_DFP_SUB: op = "v-dsub"; break;
6763 case S390_DFP_MUL: op = "v-dmul"; break;
6764 case S390_DFP_DIV: op = "v-ddiv"; break;
florian5c539732013-02-14 14:27:12 +00006765 case S390_DFP_QUANTIZE: op = "v-dqua"; break;
florian12390202012-11-10 22:34:14 +00006766 default: goto fail;
6767 }
florianc4aa7ed2012-12-22 15:01:04 +00006768 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
6769 dfp_binop->op2_hi, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +00006770 break;
florianc4aa7ed2012-12-22 15:01:04 +00006771 }
florian12390202012-11-10 22:34:14 +00006772
floriance9e3db2012-12-27 20:14:03 +00006773 case S390_INSN_DFP_UNOP:
6774 switch (insn->variant.dfp_unop.tag) {
florian5c539732013-02-14 14:27:12 +00006775 case S390_DFP_EXTRACT_EXP_D64:
6776 case S390_DFP_EXTRACT_EXP_D128: op = "v-d2exp"; break;
floriance9e3db2012-12-27 20:14:03 +00006777 case S390_DFP_EXTRACT_SIG_D64:
6778 case S390_DFP_EXTRACT_SIG_D128: op = "v-d2sig"; break;
6779 default: goto fail;
6780 }
6781 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
6782 insn->variant.dfp_unop.op_hi);
6783 break;
6784
florian1b901d42013-01-01 22:19:24 +00006785 case S390_INSN_DFP_INTOP:
6786 switch (insn->variant.dfp_intop.tag) {
6787 case S390_DFP_SHIFT_LEFT: op = "v-dshl"; break;
6788 case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break;
florian5c539732013-02-14 14:27:12 +00006789 case S390_DFP_INSERT_EXP: op = "v-diexp"; break;
florian1b901d42013-01-01 22:19:24 +00006790 default: goto fail;
6791 }
6792 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi,
6793 insn->variant.dfp_intop.op2,
6794 insn->variant.dfp_intop.op3_hi);
6795 break;
6796
floriane38f6412012-12-21 17:32:12 +00006797 case S390_INSN_DFP_COMPARE:
florian20c6bca2012-12-26 17:47:19 +00006798 switch (insn->variant.dfp_compare.tag) {
6799 case S390_DFP_COMPARE: op = "v-dcmp"; break;
6800 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
6801 default: goto fail;
6802 }
6803 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
floriane38f6412012-12-21 17:32:12 +00006804 insn->variant.dfp_compare.op1_hi,
6805 insn->variant.dfp_compare.op2_hi);
6806 break;
6807
6808 case S390_INSN_DFP_CONVERT:
6809 switch (insn->variant.dfp_convert.tag) {
6810 case S390_DFP_D32_TO_D64:
6811 case S390_DFP_D64_TO_D32:
6812 case S390_DFP_D64_TO_D128:
6813 case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
florian5f034622013-01-13 02:29:05 +00006814 case S390_DFP_I32_TO_D64:
floriana887acd2013-02-08 23:32:54 +00006815 case S390_DFP_I32_TO_D128:
6816 case S390_DFP_I64_TO_D64:
6817 case S390_DFP_I64_TO_D128: op = "v-i2d"; break;
florian5f034622013-01-13 02:29:05 +00006818 case S390_DFP_U32_TO_D64:
6819 case S390_DFP_U32_TO_D128:
6820 case S390_DFP_U64_TO_D64:
6821 case S390_DFP_U64_TO_D128: op = "v-u2d"; break;
6822 case S390_DFP_D64_TO_I32:
floriana887acd2013-02-08 23:32:54 +00006823 case S390_DFP_D128_TO_I32:
6824 case S390_DFP_D64_TO_I64:
6825 case S390_DFP_D128_TO_I64: op = "v-d2i"; break;
florian5f034622013-01-13 02:29:05 +00006826 case S390_DFP_D64_TO_U32:
6827 case S390_DFP_D64_TO_U64:
6828 case S390_DFP_D128_TO_U32:
6829 case S390_DFP_D128_TO_U64: op = "v-d2u"; break;
floriane38f6412012-12-21 17:32:12 +00006830 default: goto fail;
6831 }
6832 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
6833 insn->variant.dfp_convert.op_hi);
6834 break;
6835
florian5c539732013-02-14 14:27:12 +00006836 case S390_INSN_DFP_REROUND:
6837 s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd",
6838 insn->variant.dfp_reround.dst_hi,
6839 insn->variant.dfp_reround.op2,
6840 insn->variant.dfp_reround.op3_hi);
6841 break;
6842
florian78d5ef72013-05-11 15:02:58 +00006843 case S390_INSN_FP_CONVERT: {
6844 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
6845
6846 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00006847 case S390_FP_F32_TO_D32:
6848 case S390_FP_F32_TO_D64:
6849 case S390_FP_F32_TO_D128:
6850 case S390_FP_F64_TO_D32:
6851 case S390_FP_F64_TO_D64:
6852 case S390_FP_F64_TO_D128:
6853 case S390_FP_F128_TO_D32:
6854 case S390_FP_F128_TO_D64:
florian78d5ef72013-05-11 15:02:58 +00006855 case S390_FP_F128_TO_D128: op = "v-f2d"; break;
florian7ab421d2013-06-17 21:03:56 +00006856 case S390_FP_D32_TO_F32:
6857 case S390_FP_D32_TO_F64:
6858 case S390_FP_D32_TO_F128:
6859 case S390_FP_D64_TO_F32:
6860 case S390_FP_D64_TO_F64:
6861 case S390_FP_D64_TO_F128:
6862 case S390_FP_D128_TO_F32:
6863 case S390_FP_D128_TO_F64:
florian78d5ef72013-05-11 15:02:58 +00006864 case S390_FP_D128_TO_F128: op = "v-d2f"; break;
6865 default: goto fail;
6866 }
6867 s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi,
6868 fp_convert->op_hi);
6869 break;
6870 }
6871
sewardja52e37e2011-04-28 18:48:06 +00006872 case S390_INSN_MFENCE:
6873 s390_sprintf(buf, "%M", "v-mfence");
6874 return buf; /* avoid printing "size = ..." which is meaningless */
6875
florianb93348d2012-12-27 00:59:43 +00006876 case S390_INSN_MIMM:
6877 s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
6878 insn->variant.mimm.value);
florianad43b3a2012-02-20 15:01:14 +00006879 break;
6880
florianf85fe3e2012-12-22 02:28:25 +00006881 case S390_INSN_MADD:
6882 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd",
6883 insn->variant.madd.dst,
6884 (Long)(Char)insn->variant.madd.delta,
6885 insn->variant.madd.value);
florianad43b3a2012-02-20 15:01:14 +00006886 break;
6887
florian125e20d2012-10-07 15:42:37 +00006888 case S390_INSN_SET_FPC_BFPRM:
6889 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
6890 insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00006891 break;
6892
florianc8e4f562012-10-27 16:19:31 +00006893 case S390_INSN_SET_FPC_DFPRM:
6894 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
6895 insn->variant.set_fpc_dfprm.mode);
6896 break;
6897
florian8844a632012-04-13 04:04:06 +00006898 case S390_INSN_EVCHECK:
6899 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
6900 insn->variant.evcheck.counter,
6901 insn->variant.evcheck.fail_addr);
6902 return buf; /* avoid printing "size = ..." which is meaningless */
6903
6904 case S390_INSN_PROFINC:
6905 s390_sprintf(buf, "%M", "v-profinc");
6906 return buf; /* avoid printing "size = ..." which is meaningless */
6907
6908 case S390_INSN_XDIRECT:
6909 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
6910 insn->variant.xdirect.cond,
6911 insn->variant.xdirect.guest_IA,
6912 insn->variant.xdirect.dst,
6913 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
6914 return buf; /* avoid printing "size = ..." which is meaningless */
6915
6916 case S390_INSN_XINDIR:
6917 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
6918 insn->variant.xindir.cond,
6919 insn->variant.xindir.guest_IA,
6920 insn->variant.xindir.dst);
6921 return buf; /* avoid printing "size = ..." which is meaningless */
6922
6923 case S390_INSN_XASSISTED:
6924 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
6925 insn->variant.xassisted.cond,
6926 insn->variant.xassisted.kind,
6927 insn->variant.xassisted.guest_IA,
6928 insn->variant.xassisted.dst);
6929 return buf; /* avoid printing "size = ..." which is meaningless */
6930
sewardj2019a972011-03-07 16:04:07 +00006931 default: goto fail;
6932 }
6933
6934 /* Write out how many bytes are involved in the operation */
6935
6936 {
6937 UInt len, i;
6938
6939 for (p = buf; *p; ++p)
6940 continue;
6941
6942 len = p - buf;
6943
6944 if (len < 32) {
6945 for (i = len; i < 32; ++i)
6946 p += vex_sprintf(p, " ");
6947 } else {
6948 p += vex_sprintf(p, "\t");
6949 }
6950 }
6951
6952 /* Special cases first */
6953 switch (insn->tag) {
6954 case S390_INSN_UNOP:
6955 switch (insn->variant.unop.tag) {
6956 case S390_SIGN_EXTEND_8:
6957 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
6958 case S390_SIGN_EXTEND_16:
6959 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
6960 case S390_SIGN_EXTEND_32:
6961 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
6962 default:
6963 goto common;
6964 }
6965
floriancc491a62012-09-10 23:44:37 +00006966 case S390_INSN_BFP_CONVERT:
6967 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00006968 case S390_BFP_I32_TO_F32:
6969 case S390_BFP_I32_TO_F64:
6970 case S390_BFP_I32_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00006971 case S390_BFP_U32_TO_F32:
6972 case S390_BFP_U32_TO_F64:
6973 case S390_BFP_U32_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00006974 case S390_BFP_F32_TO_I32:
6975 case S390_BFP_F32_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006976 case S390_BFP_F32_TO_U32:
6977 case S390_BFP_F32_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006978 case S390_BFP_F32_TO_F64:
6979 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
6980 case S390_BFP_I64_TO_F32:
6981 case S390_BFP_I64_TO_F64:
6982 case S390_BFP_I64_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00006983 case S390_BFP_U64_TO_F32:
6984 case S390_BFP_U64_TO_F64:
6985 case S390_BFP_U64_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00006986 case S390_BFP_F64_TO_I32:
6987 case S390_BFP_F64_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006988 case S390_BFP_F64_TO_U32:
6989 case S390_BFP_F64_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006990 case S390_BFP_F64_TO_F32:
6991 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
6992 case S390_BFP_F128_TO_I32:
6993 case S390_BFP_F128_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006994 case S390_BFP_F128_TO_U32:
6995 case S390_BFP_F128_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006996 case S390_BFP_F128_TO_F32:
6997 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
6998 default:
6999 goto common;
7000 }
7001
floriane38f6412012-12-21 17:32:12 +00007002 case S390_INSN_DFP_CONVERT:
7003 switch (insn->variant.dfp_convert.tag) {
florian5f034622013-01-13 02:29:05 +00007004 case S390_DFP_D32_TO_D64:
7005 case S390_DFP_I32_TO_D64:
7006 case S390_DFP_I32_TO_D128:
7007 case S390_DFP_U32_TO_D64:
7008 case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common;
floriane38f6412012-12-21 17:32:12 +00007009 case S390_DFP_D64_TO_D32:
florian5f034622013-01-13 02:29:05 +00007010 case S390_DFP_D64_TO_D128:
floriana887acd2013-02-08 23:32:54 +00007011 case S390_DFP_I64_TO_D64:
7012 case S390_DFP_I64_TO_D128:
florian5f034622013-01-13 02:29:05 +00007013 case S390_DFP_U64_TO_D64:
7014 case S390_DFP_U64_TO_D128:
7015 case S390_DFP_D64_TO_I32:
floriana887acd2013-02-08 23:32:54 +00007016 case S390_DFP_D64_TO_I64:
florian5f034622013-01-13 02:29:05 +00007017 case S390_DFP_D64_TO_U32:
7018 case S390_DFP_D64_TO_U64: p += vex_sprintf(p, "8 -> "); goto common;
7019 case S390_DFP_D128_TO_D64:
7020 case S390_DFP_D128_TO_I32:
floriana887acd2013-02-08 23:32:54 +00007021 case S390_DFP_D128_TO_I64:
florian5f034622013-01-13 02:29:05 +00007022 case S390_DFP_D128_TO_U32:
7023 case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common;
floriane38f6412012-12-21 17:32:12 +00007024 default:
7025 goto common;
7026 }
7027
florian78d5ef72013-05-11 15:02:58 +00007028 case S390_INSN_FP_CONVERT: {
7029 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
7030
7031 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00007032 case S390_FP_F32_TO_D32:
7033 case S390_FP_F32_TO_D64:
7034 case S390_FP_F32_TO_D128:
7035 case S390_FP_D32_TO_F32:
7036 case S390_FP_D32_TO_F64:
7037 case S390_FP_D32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
7038 case S390_FP_F64_TO_D32:
florian78d5ef72013-05-11 15:02:58 +00007039 case S390_FP_F64_TO_D64:
florian7ab421d2013-06-17 21:03:56 +00007040 case S390_FP_F64_TO_D128:
7041 case S390_FP_D64_TO_F32:
florian78d5ef72013-05-11 15:02:58 +00007042 case S390_FP_D64_TO_F64:
florian7ab421d2013-06-17 21:03:56 +00007043 case S390_FP_D64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
7044 case S390_FP_F128_TO_D32:
7045 case S390_FP_F128_TO_D64:
florian78d5ef72013-05-11 15:02:58 +00007046 case S390_FP_F128_TO_D128:
florian7ab421d2013-06-17 21:03:56 +00007047 case S390_FP_D128_TO_F32:
7048 case S390_FP_D128_TO_F64:
florian78d5ef72013-05-11 15:02:58 +00007049 case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
7050 default:
7051 goto common;
7052 }
7053 }
7054
sewardj2019a972011-03-07 16:04:07 +00007055 default:
7056 goto common;
7057 }
7058
7059 /* Common case */
7060 common:
7061 vex_sprintf(p, "%u bytes", (UInt)insn->size);
7062
7063 return buf;
7064
7065 fail: vpanic("s390_insn_as_string");
7066}
7067
7068
7069
7070/* Load NUM bytes from memory into register REG using addressing mode AM. */
7071static UChar *
7072s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
7073{
7074 UInt b = hregNumber(am->b);
7075 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
7076 UInt d = am->d;
7077
7078 switch (am->tag) {
7079 case S390_AMODE_B12:
7080 case S390_AMODE_BX12:
7081 switch (num) {
7082 case 1: return s390_emit_IC(p, reg, x, b, d);
7083 case 2: return s390_emit_LH(p, reg, x, b, d);
7084 case 4: return s390_emit_L(p, reg, x, b, d);
7085 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
7086 default: goto fail;
7087 }
7088 break;
7089
7090 case S390_AMODE_B20:
7091 case S390_AMODE_BX20:
7092 switch (num) {
7093 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
7094 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
7095 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
7096 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
7097 default: goto fail;
7098 }
7099 break;
7100
7101 default: goto fail;
7102 }
7103
7104 fail:
7105 vpanic("s390_emit_load_mem");
7106}
7107
7108
7109/* Load condition code into register REG */
7110static UChar *
7111s390_emit_load_cc(UChar *p, UChar reg)
7112{
7113 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
7114 p = s390_emit_IPM(p, reg, reg);
7115 /* Shift 28 bits to the right --> [0,1,2,3] */
sewardjf74c86f2011-04-05 14:04:53 +00007116 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
sewardj2019a972011-03-07 16:04:07 +00007117}
7118
7119
7120/*---------------------------------------------------------------*/
7121/*--- Code generation ---*/
7122/*---------------------------------------------------------------*/
7123
7124/* Do not load more bytes than requested. */
7125static UChar *
7126s390_insn_load_emit(UChar *buf, const s390_insn *insn)
7127{
7128 UInt r, x, b, d;
7129 const s390_amode *src;
7130
7131 src = insn->variant.load.src;
7132
7133 r = hregNumber(insn->variant.load.dst);
7134
7135 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
7136 b = hregNumber(src->b);
7137 x = hregNumber(src->x); /* 0 for B12 and B20 */
7138 d = src->d;
7139
7140 switch (insn->size) {
7141
7142 case 4:
7143 switch (src->tag) {
7144 case S390_AMODE_B12:
7145 case S390_AMODE_BX12:
7146 return s390_emit_LE(buf, r, x, b, d);
7147
7148 case S390_AMODE_B20:
7149 case S390_AMODE_BX20:
7150 return s390_emit_LEY(buf, r, x, b, DISP20(d));
7151 }
7152 break;
7153
7154 case 8:
7155 switch (src->tag) {
7156 case S390_AMODE_B12:
7157 case S390_AMODE_BX12:
7158 return s390_emit_LD(buf, r, x, b, d);
7159
7160 case S390_AMODE_B20:
7161 case S390_AMODE_BX20:
7162 return s390_emit_LDY(buf, r, x, b, DISP20(d));
7163 }
7164 break;
7165 }
7166 vpanic("s390_insn_load_emit");
7167 }
7168
7169 /* Integer stuff */
7170 return s390_emit_load_mem(buf, insn->size, r, src);
7171}
7172
7173
7174static UChar *
7175s390_insn_store_emit(UChar *buf, const s390_insn *insn)
7176{
7177 UInt r, x, b, d;
7178 const s390_amode *dst;
7179
7180 dst = insn->variant.store.dst;
7181
7182 r = hregNumber(insn->variant.store.src);
7183 b = hregNumber(dst->b);
7184 x = hregNumber(dst->x); /* 0 for B12 and B20 */
7185 d = dst->d;
7186
7187 if (hregClass(insn->variant.store.src) == HRcFlt64) {
7188 switch (insn->size) {
7189
7190 case 4:
7191 switch (dst->tag) {
7192 case S390_AMODE_B12:
7193 case S390_AMODE_BX12:
7194 return s390_emit_STE(buf, r, x, b, d);
7195
7196 case S390_AMODE_B20:
7197 case S390_AMODE_BX20:
7198 return s390_emit_STEY(buf, r, x, b, DISP20(d));
7199 }
7200 break;
7201
7202 case 8:
7203 switch (dst->tag) {
7204 case S390_AMODE_B12:
7205 case S390_AMODE_BX12:
7206 return s390_emit_STD(buf, r, x, b, d);
7207
7208 case S390_AMODE_B20:
7209 case S390_AMODE_BX20:
7210 return s390_emit_STDY(buf, r, x, b, DISP20(d));
7211 }
7212 break;
7213 }
7214 vpanic("s390_insn_store_emit");
7215 }
7216
7217 /* Integer stuff */
7218 switch (insn->size) {
7219 case 1:
7220 switch (dst->tag) {
7221 case S390_AMODE_B12:
7222 case S390_AMODE_BX12:
7223 return s390_emit_STC(buf, r, x, b, d);
7224
7225 case S390_AMODE_B20:
7226 case S390_AMODE_BX20:
7227 return s390_emit_STCY(buf, r, x, b, DISP20(d));
7228 }
7229 break;
7230
7231 case 2:
7232 switch (dst->tag) {
7233 case S390_AMODE_B12:
7234 case S390_AMODE_BX12:
7235 return s390_emit_STH(buf, r, x, b, d);
7236
7237 case S390_AMODE_B20:
7238 case S390_AMODE_BX20:
7239 return s390_emit_STHY(buf, r, x, b, DISP20(d));
7240 }
7241 break;
7242
7243 case 4:
7244 switch (dst->tag) {
7245 case S390_AMODE_B12:
7246 case S390_AMODE_BX12:
7247 return s390_emit_ST(buf, r, x, b, d);
7248
7249 case S390_AMODE_B20:
7250 case S390_AMODE_BX20:
7251 return s390_emit_STY(buf, r, x, b, DISP20(d));
7252 }
7253 break;
7254
7255 case 8:
7256 return s390_emit_STG(buf, r, x, b, DISP20(d));
7257
7258 default:
7259 break;
7260 }
7261
7262 vpanic("s390_insn_store_emit");
7263}
7264
7265
7266static UChar *
7267s390_insn_move_emit(UChar *buf, const s390_insn *insn)
7268{
7269 UInt dst, src;
7270 HRegClass dst_class, src_class;
7271
7272 dst = hregNumber(insn->variant.move.dst);
7273 src = hregNumber(insn->variant.move.src);
7274
7275 dst_class = hregClass(insn->variant.move.dst);
7276 src_class = hregClass(insn->variant.move.src);
7277
7278 if (dst_class == src_class) {
7279 if (dst_class == HRcInt64)
7280 return s390_emit_LGR(buf, dst, src);
7281 if (dst_class == HRcFlt64)
7282 return s390_emit_LDR(buf, dst, src);
7283 } else {
floriana782a172011-12-18 15:51:54 +00007284 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
7285 if (insn->size == 4) {
7286 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
7287 return s390_emit_LDGRw(buf, dst, R0);
7288 } else {
7289 return s390_emit_LDGRw(buf, dst, src);
7290 }
7291 }
7292 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
7293 if (insn->size == 4) {
7294 buf = s390_emit_LGDRw(buf, dst, src);
7295 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
7296 } else {
7297 return s390_emit_LGDRw(buf, dst, src);
7298 }
7299 }
sewardj2019a972011-03-07 16:04:07 +00007300 /* A move between floating point registers and general purpose
7301 registers of different size should never occur and indicates
7302 an error elsewhere. */
7303 }
7304
7305 vpanic("s390_insn_move_emit");
7306}
7307
7308
7309static UChar *
floriancec3a8a2013-02-02 00:16:58 +00007310s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn)
7311{
7312 s390_amode *dst = insn->variant.memcpy.dst;
7313 s390_amode *src = insn->variant.memcpy.src;
7314
7315 return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d,
7316 hregNumber(src->b), src->d);
7317}
7318
7319
7320static UChar *
sewardj2019a972011-03-07 16:04:07 +00007321s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
7322{
7323 UInt r;
7324 ULong value = insn->variant.load_immediate.value;
7325
7326 r = hregNumber(insn->variant.load_immediate.dst);
7327
7328 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
7329 vassert(value == 0);
7330 switch (insn->size) {
7331 case 4: return s390_emit_LZER(buf, r, value);
7332 case 8: return s390_emit_LZDR(buf, r, value);
7333 }
7334 vpanic("s390_insn_load_immediate_emit");
7335 }
7336
7337 switch (insn->size) {
7338 case 1:
7339 case 2:
7340 /* Load the immediate values as a 4 byte value. That does not hurt as
7341 those extra bytes will not be looked at. Fall through .... */
7342 case 4:
7343 return s390_emit_load_32imm(buf, r, value);
7344
7345 case 8:
7346 return s390_emit_load_64imm(buf, r, value);
7347 }
7348
7349 vpanic("s390_insn_load_immediate_emit");
7350}
7351
7352
7353/* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
7354 So we simply perform a 4-byte operation. Doing so uses possibly undefined
7355 bits and produces an undefined result in those extra bit positions. But
7356 upstream does not look at those positions, so this is OK. */
7357static UChar *
7358s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
7359{
7360 s390_opnd_RMI op2;
7361 UInt dst;
7362
7363 dst = hregNumber(insn->variant.alu.dst);
7364 op2 = insn->variant.alu.op2;
7365
7366 /* Second operand is in a register */
7367 if (op2.tag == S390_OPND_REG) {
7368 UInt r2 = hregNumber(op2.variant.reg);
7369
7370 switch (insn->size) {
7371 case 1:
7372 case 2:
7373 case 4:
7374 switch (insn->variant.alu.tag) {
7375 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
7376 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
7377 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
7378 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
7379 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
7380 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
sewardj3c49aaa2011-04-05 14:00:37 +00007381 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
7382 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
7383 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
sewardj2019a972011-03-07 16:04:07 +00007384 }
7385 goto fail;
7386
7387 case 8:
7388 switch (insn->variant.alu.tag) {
7389 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
7390 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
7391 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
7392 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
7393 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
7394 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
7395 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
7396 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
7397 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
7398 }
7399 goto fail;
7400 }
7401 goto fail;
7402 }
7403
7404 /* 2nd operand is in memory */
7405 if (op2.tag == S390_OPND_AMODE) {
7406 UInt b, x, d;
7407 const s390_amode *src = op2.variant.am;
7408
7409 b = hregNumber(src->b);
7410 x = hregNumber(src->x); /* 0 for B12 and B20 */
7411 d = src->d;
7412
7413 /* Shift operands are special here as there are no opcodes that
sewardje0dd77e2011-04-27 12:07:01 +00007414 allow a memory operand. So we first load the 2nd operand into
7415 some register. R0 is used to save restore the contents of the
7416 chosen register.. */
sewardj652b56a2011-04-13 15:38:17 +00007417
sewardj2019a972011-03-07 16:04:07 +00007418 if (insn->variant.alu.tag == S390_ALU_LSH ||
7419 insn->variant.alu.tag == S390_ALU_RSH ||
7420 insn->variant.alu.tag == S390_ALU_RSHA) {
sewardje0dd77e2011-04-27 12:07:01 +00007421 UInt b2;
sewardj2019a972011-03-07 16:04:07 +00007422
sewardje0dd77e2011-04-27 12:07:01 +00007423 /* Choose a register (other than DST or R0) into which to stick the
7424 shift amount. The following works because r15 is reserved and
7425 thusly dst != 15. */
7426 vassert(dst != 15); /* extra paranoia */
7427 b2 = (dst + 1) % 16;
7428
7429 buf = s390_emit_LGR(buf, R0, b2); /* save */
7430
7431 /* Loading SRC to B2 does not modify R0. */
7432 buf = s390_emit_load_mem(buf, insn->size, b2, src);
sewardj2019a972011-03-07 16:04:07 +00007433
7434 if (insn->size == 8) {
sewardje0dd77e2011-04-27 12:07:01 +00007435 switch (insn->variant.alu.tag) {
7436 case S390_ALU_LSH:
7437 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
7438 break;
7439 case S390_ALU_RSH:
7440 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
7441 break;
7442 case S390_ALU_RSHA:
7443 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
7444 break;
7445 default: /* unreachable */
7446 goto fail;
7447 }
sewardj2019a972011-03-07 16:04:07 +00007448 } else {
sewardje0dd77e2011-04-27 12:07:01 +00007449 switch (insn->variant.alu.tag) {
7450 case S390_ALU_LSH:
7451 buf = s390_emit_SLL(buf, dst, b2, 0);
7452 break;
7453 case S390_ALU_RSH:
7454 buf = s390_emit_SRL(buf, dst, b2, 0);
7455 break;
7456 case S390_ALU_RSHA:
7457 buf = s390_emit_SRA(buf, dst, b2, 0);
7458 break;
7459 default: /* unreachable */
7460 goto fail;
7461 }
sewardj2019a972011-03-07 16:04:07 +00007462 }
sewardje0dd77e2011-04-27 12:07:01 +00007463 return s390_emit_LGR(buf, b2, R0); /* restore */
sewardj2019a972011-03-07 16:04:07 +00007464 }
7465
7466 switch (insn->size) {
7467 case 1:
7468 /* Move the byte from memory into scratch register r0 */
7469 buf = s390_emit_load_mem(buf, 1, R0, src);
7470
7471 switch (insn->variant.alu.tag) {
7472 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
7473 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
7474 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
7475 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
7476 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
7477 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
7478 case S390_ALU_LSH:
7479 case S390_ALU_RSH:
7480 case S390_ALU_RSHA: ; /* avoid GCC warning */
7481 }
7482 goto fail;
7483
7484 case 2:
7485 switch (src->tag) {
7486 case S390_AMODE_B12:
7487 case S390_AMODE_BX12:
7488 switch (insn->variant.alu.tag) {
7489 case S390_ALU_ADD:
7490 return s390_emit_AH(buf, dst, x, b, d);
7491
7492 case S390_ALU_SUB:
7493 return s390_emit_SH(buf, dst, x, b, d);
7494
7495 case S390_ALU_MUL:
7496 return s390_emit_MH(buf, dst, x, b, d);
7497
7498 /* For bitwise operations: Move two bytes from memory into scratch
7499 register r0; then perform operation */
7500 case S390_ALU_AND:
7501 buf = s390_emit_LH(buf, R0, x, b, d);
7502 return s390_emit_NR(buf, dst, R0);
7503
7504 case S390_ALU_OR:
7505 buf = s390_emit_LH(buf, R0, x, b, d);
7506 return s390_emit_OR(buf, dst, R0);
7507
7508 case S390_ALU_XOR:
7509 buf = s390_emit_LH(buf, R0, x, b, d);
7510 return s390_emit_XR(buf, dst, R0);
7511
7512 case S390_ALU_LSH:
7513 case S390_ALU_RSH:
7514 case S390_ALU_RSHA: ; /* avoid GCC warning */
7515 }
7516 goto fail;
7517
7518 case S390_AMODE_B20:
7519 case S390_AMODE_BX20:
7520 switch (insn->variant.alu.tag) {
7521 case S390_ALU_ADD:
7522 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
7523
7524 case S390_ALU_SUB:
7525 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
7526
7527 case S390_ALU_MUL:
sewardjeae8db52011-03-24 09:01:50 +00007528 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007529
7530 /* For bitwise operations: Move two bytes from memory into scratch
7531 register r0; then perform operation */
7532 case S390_ALU_AND:
7533 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7534 return s390_emit_NR(buf, dst, R0);
7535
7536 case S390_ALU_OR:
7537 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7538 return s390_emit_OR(buf, dst, R0);
7539
7540 case S390_ALU_XOR:
7541 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7542 return s390_emit_XR(buf, dst, R0);
7543
7544 case S390_ALU_LSH:
7545 case S390_ALU_RSH:
7546 case S390_ALU_RSHA: ; /* avoid GCC warning */
7547 }
7548 goto fail;
7549 }
7550 goto fail;
7551
7552 case 4:
7553 switch (src->tag) {
7554 case S390_AMODE_B12:
7555 case S390_AMODE_BX12:
7556 switch (insn->variant.alu.tag) {
7557 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
7558 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
7559 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
7560 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
7561 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
7562 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
7563 case S390_ALU_LSH:
7564 case S390_ALU_RSH:
7565 case S390_ALU_RSHA: ; /* avoid GCC warning */
7566 }
7567 goto fail;
7568
7569 case S390_AMODE_B20:
7570 case S390_AMODE_BX20:
7571 switch (insn->variant.alu.tag) {
7572 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
7573 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
7574 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
7575 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
7576 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
7577 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
7578 case S390_ALU_LSH:
7579 case S390_ALU_RSH:
7580 case S390_ALU_RSHA: ; /* avoid GCC warning */
7581 }
7582 goto fail;
7583 }
7584 goto fail;
7585
7586 case 8:
7587 switch (insn->variant.alu.tag) {
7588 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
7589 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
7590 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
7591 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
7592 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
7593 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
7594 case S390_ALU_LSH:
7595 case S390_ALU_RSH:
7596 case S390_ALU_RSHA: ; /* avoid GCC warning */
7597 }
7598 goto fail;
7599 }
7600 goto fail;
7601 }
7602
7603 /* 2nd operand is an immediate value */
7604 if (op2.tag == S390_OPND_IMMEDIATE) {
7605 ULong value;
7606
7607 /* No masking of the value is required as it is not sign extended */
7608 value = op2.variant.imm;
7609
7610 switch (insn->size) {
7611 case 1:
7612 case 2:
7613 /* There is no 1-byte opcode. Do the computation in
7614 2 bytes. The extra byte will be ignored. */
7615 switch (insn->variant.alu.tag) {
7616 case S390_ALU_ADD:
7617 return s390_emit_AHI(buf, dst, value);
7618
7619 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00007620 return s390_emit_SLFIw(buf, dst, value);
sewardj2019a972011-03-07 16:04:07 +00007621
7622 case S390_ALU_MUL:
7623 return s390_emit_MHI(buf, dst, value);
7624
7625 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
7626 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
7627 case S390_ALU_XOR:
7628 /* There is no XILL instruction. Load the immediate value into
7629 R0 and combine with the destination register. */
7630 buf = s390_emit_LHI(buf, R0, value);
7631 return s390_emit_XR(buf, dst, R0);
7632
7633 case S390_ALU_LSH:
sewardj3c49aaa2011-04-05 14:00:37 +00007634 return s390_emit_SLL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007635
7636 case S390_ALU_RSH:
sewardj3c49aaa2011-04-05 14:00:37 +00007637 return s390_emit_SRL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007638
7639 case S390_ALU_RSHA:
sewardj3c49aaa2011-04-05 14:00:37 +00007640 return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007641 }
7642 goto fail;
7643
7644 case 4:
7645 switch (insn->variant.alu.tag) {
7646 case S390_ALU_ADD:
7647 if (uint_fits_signed_16bit(value)) {
7648 return s390_emit_AHI(buf, dst, value);
7649 }
7650 return s390_emit_AFIw(buf, dst, value);
7651
7652 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
7653 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
7654 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
7655 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
7656 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
sewardj3c49aaa2011-04-05 14:00:37 +00007657 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
7658 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
7659 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007660 }
7661 goto fail;
7662
7663 case 8:
7664 switch (insn->variant.alu.tag) {
7665 case S390_ALU_ADD:
7666 if (ulong_fits_signed_16bit(value)) {
7667 return s390_emit_AGHI(buf, dst, value);
7668 }
7669 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
7670 return s390_emit_AGFI(buf, dst, value);
7671 }
7672 /* Load constant into R0 then add */
7673 buf = s390_emit_load_64imm(buf, R0, value);
7674 return s390_emit_AGR(buf, dst, R0);
7675
7676 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00007677 if (ulong_fits_unsigned_32bit(value)) {
7678 return s390_emit_SLGFIw(buf, dst, value);
7679 }
sewardj2019a972011-03-07 16:04:07 +00007680 /* Load value into R0; then subtract from destination reg */
7681 buf = s390_emit_load_64imm(buf, R0, value);
7682 return s390_emit_SGR(buf, dst, R0);
7683
7684 case S390_ALU_MUL:
7685 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
7686 return s390_emit_MSGFI(buf, dst, value);
7687 }
7688 /* Load constant into R0 then add */
7689 buf = s390_emit_load_64imm(buf, R0, value);
7690 return s390_emit_MSGR(buf, dst, R0);
7691
7692 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
7693 case S390_ALU_AND:
7694 if (s390_host_has_eimm) {
7695 buf = s390_emit_NIHF(buf, dst, value >> 32);
7696 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
7697 }
7698 /* Load value into R0; then combine with destination reg */
7699 buf = s390_emit_load_64imm(buf, R0, value);
7700 return s390_emit_NGR(buf, dst, R0);
7701
7702 case S390_ALU_OR:
7703 if (s390_host_has_eimm) {
7704 buf = s390_emit_OIHF(buf, dst, value >> 32);
7705 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
7706 }
7707 /* Load value into R0; then combine with destination reg */
7708 buf = s390_emit_load_64imm(buf, R0, value);
7709 return s390_emit_OGR(buf, dst, R0);
7710
7711 case S390_ALU_XOR:
7712 if (s390_host_has_eimm) {
7713 buf = s390_emit_XIHF(buf, dst, value >> 32);
7714 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
7715 }
7716 /* Load value into R0; then combine with destination reg */
7717 buf = s390_emit_load_64imm(buf, R0, value);
7718 return s390_emit_XGR(buf, dst, R0);
7719
sewardj652b56a2011-04-13 15:38:17 +00007720 /* No special considerations for long displacement here. Only the six
7721 least significant bits of VALUE will be taken; all other bits are
7722 ignored. So the DH2 bits are irrelevant and do not influence the
7723 shift operation, independent of whether long-displacement is available
7724 or not. */
sewardj2019a972011-03-07 16:04:07 +00007725 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
7726 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
7727 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
7728 }
7729 goto fail;
7730 }
7731 goto fail;
7732 }
7733
7734 fail:
7735 vpanic("s390_insn_alu_emit");
7736}
7737
7738
7739static UChar *
7740s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
7741 Bool sign_extend)
7742{
sewardj06122e72011-03-28 12:14:48 +00007743 s390_opnd_RMI opnd = insn->variant.unop.src;
sewardj2019a972011-03-07 16:04:07 +00007744
7745 switch (opnd.tag) {
7746 case S390_OPND_REG: {
7747 UChar r1 = hregNumber(insn->variant.unop.dst);
7748 UChar r2 = hregNumber(opnd.variant.reg);
7749
7750 switch (from_size) {
7751 case 1:
7752 /* Widening to a half-word is implemented like widening to a word
7753 because the upper half-word will not be looked at. */
7754 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7755 if (sign_extend)
7756 return s390_emit_LBRw(buf, r1, r2);
7757 else
7758 return s390_emit_LLCRw(buf, r1, r2);
7759 }
7760 if (insn->size == 8) { /* 8 --> 64 */
7761 if (sign_extend)
7762 return s390_emit_LGBRw(buf, r1, r2);
7763 else
7764 return s390_emit_LLGCRw(buf, r1, r2);
7765 }
7766 goto fail;
7767
7768 case 2:
7769 if (insn->size == 4) { /* 16 --> 32 */
7770 if (sign_extend)
7771 return s390_emit_LHRw(buf, r1, r2);
7772 else
7773 return s390_emit_LLHRw(buf, r1, r2);
7774 }
7775 if (insn->size == 8) { /* 16 --> 64 */
7776 if (sign_extend)
7777 return s390_emit_LGHRw(buf, r1, r2);
7778 else
7779 return s390_emit_LLGHRw(buf, r1, r2);
7780 }
7781 goto fail;
7782
7783 case 4:
7784 if (insn->size == 8) { /* 32 --> 64 */
7785 if (sign_extend)
7786 return s390_emit_LGFR(buf, r1, r2);
7787 else
7788 return s390_emit_LLGFR(buf, r1, r2);
7789 }
7790 goto fail;
7791
7792 default: /* unexpected "from" size */
7793 goto fail;
7794 }
7795 }
7796
7797 case S390_OPND_AMODE: {
7798 UChar r1 = hregNumber(insn->variant.unop.dst);
7799 const s390_amode *src = opnd.variant.am;
7800 UChar b = hregNumber(src->b);
7801 UChar x = hregNumber(src->x);
7802 Int d = src->d;
7803
7804 switch (from_size) {
7805 case 1:
7806 if (insn->size == 4 || insn->size == 2) {
7807 if (sign_extend)
floriandc6e7472014-12-08 14:01:33 +00007808 return s390_emit_LB(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007809 else
7810 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
7811 }
7812 if (insn->size == 8) {
7813 if (sign_extend)
floriandc6e7472014-12-08 14:01:33 +00007814 return s390_emit_LGB(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007815 else
sewardj2019a972011-03-07 16:04:07 +00007816 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
7817 }
7818 goto fail;
7819
7820 case 2:
7821 if (insn->size == 4) { /* 16 --> 32 */
7822 if (sign_extend == 0)
7823 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
7824
7825 switch (src->tag) {
7826 case S390_AMODE_B12:
7827 case S390_AMODE_BX12:
7828 return s390_emit_LH(buf, r1, x, b, d);
7829
7830 case S390_AMODE_B20:
7831 case S390_AMODE_BX20:
7832 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
7833 }
7834 goto fail;
7835 }
7836 if (insn->size == 8) { /* 16 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00007837 if (sign_extend)
7838 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
7839 else
7840 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
7841 }
7842 goto fail;
7843
7844 case 4:
7845 if (insn->size == 8) { /* 32 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00007846 if (sign_extend)
7847 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
7848 else
7849 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
7850 }
7851 goto fail;
7852
7853 default: /* unexpected "from" size */
7854 goto fail;
7855 }
7856 }
7857
7858 case S390_OPND_IMMEDIATE: {
7859 UChar r1 = hregNumber(insn->variant.unop.dst);
7860 ULong value = opnd.variant.imm;
7861
7862 switch (from_size) {
7863 case 1:
7864 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7865 if (sign_extend) {
7866 /* host can do the sign extension to 16-bit; LHI does the rest */
7867 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
7868 } else {
7869 return s390_emit_LHI(buf, r1, value);
7870 }
7871 }
7872 if (insn->size == 8) { /* 8 --> 64 */
7873 if (sign_extend) {
7874 /* host can do the sign extension to 16-bit; LGHI does the rest */
7875 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
7876 } else {
7877 return s390_emit_LGHI(buf, r1, value);
7878 }
7879 }
7880 goto fail;
7881
7882 case 2:
7883 if (insn->size == 4) { /* 16 --> 32 */
7884 return s390_emit_LHI(buf, r1, value);
7885 }
7886 if (insn->size == 8) { /* 16 --> 64 */
7887 if (sign_extend)
7888 return s390_emit_LGHI(buf, r1, value);
7889 else
7890 return s390_emit_LLILL(buf, r1, value);
7891 }
7892 goto fail;
7893
7894 case 4:
7895 if (insn->size == 8) { /* 32 --> 64 */
7896 if (sign_extend)
7897 return s390_emit_LGFIw(buf, r1, value);
7898 else
7899 return s390_emit_LLILFw(buf, r1, value);
7900 }
7901 goto fail;
7902
7903 default: /* unexpected "from" size */
7904 goto fail;
7905 }
7906 }
7907 }
7908
7909 fail:
7910 vpanic("s390_widen_emit");
7911}
7912
7913
7914static UChar *
7915s390_negate_emit(UChar *buf, const s390_insn *insn)
7916{
7917 s390_opnd_RMI opnd;
7918
7919 opnd = insn->variant.unop.src;
7920
7921 switch (opnd.tag) {
7922 case S390_OPND_REG: {
7923 UChar r1 = hregNumber(insn->variant.unop.dst);
7924 UChar r2 = hregNumber(opnd.variant.reg);
7925
7926 switch (insn->size) {
7927 case 1:
7928 case 2:
7929 case 4:
7930 return s390_emit_LCR(buf, r1, r2);
7931
7932 case 8:
7933 return s390_emit_LCGR(buf, r1, r2);
7934
7935 default:
7936 goto fail;
7937 }
7938 }
7939
7940 case S390_OPND_AMODE: {
7941 UChar r1 = hregNumber(insn->variant.unop.dst);
7942
7943 /* Load bytes into scratch register R0, then negate */
7944 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
7945
7946 switch (insn->size) {
7947 case 1:
7948 case 2:
7949 case 4:
7950 return s390_emit_LCR(buf, r1, R0);
7951
7952 case 8:
7953 return s390_emit_LCGR(buf, r1, R0);
7954
7955 default:
7956 goto fail;
7957 }
7958 }
7959
7960 case S390_OPND_IMMEDIATE: {
7961 UChar r1 = hregNumber(insn->variant.unop.dst);
7962 ULong value = opnd.variant.imm;
7963
7964 value = ~value + 1; /* two's complement */
7965
7966 switch (insn->size) {
7967 case 1:
7968 case 2:
7969 /* Load the immediate values as a 4 byte value. That does not hurt as
7970 those extra bytes will not be looked at. Fall through .... */
7971 case 4:
7972 return s390_emit_load_32imm(buf, r1, value);
7973
7974 case 8:
7975 return s390_emit_load_64imm(buf, r1, value);
7976
7977 default:
7978 goto fail;
7979 }
7980 }
7981 }
7982
7983 fail:
7984 vpanic("s390_negate_emit");
7985}
7986
7987
7988static UChar *
7989s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
7990{
7991 switch (insn->variant.unop.tag) {
7992 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
7993 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
7994 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
7995
7996 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
7997 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
7998 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
7999
8000 case S390_NEGATE: return s390_negate_emit(buf, insn);
8001 }
8002
8003 vpanic("s390_insn_unop_emit");
8004}
8005
8006
8007/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
8008 comparisons will have been converted to 4-byte comparisons in
8009 s390_isel_cc and should not occur here. */
8010static UChar *
8011s390_insn_test_emit(UChar *buf, const s390_insn *insn)
8012{
8013 s390_opnd_RMI opnd;
8014
8015 opnd = insn->variant.test.src;
8016
8017 switch (opnd.tag) {
8018 case S390_OPND_REG: {
8019 UInt reg = hregNumber(opnd.variant.reg);
8020
8021 switch (insn->size) {
8022 case 4:
8023 return s390_emit_LTR(buf, reg, reg);
8024
8025 case 8:
8026 return s390_emit_LTGR(buf, reg, reg);
8027
8028 default:
8029 goto fail;
8030 }
8031 }
8032
8033 case S390_OPND_AMODE: {
8034 const s390_amode *am = opnd.variant.am;
8035 UChar b = hregNumber(am->b);
8036 UChar x = hregNumber(am->x);
8037 Int d = am->d;
8038
8039 switch (insn->size) {
8040 case 4:
8041 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
8042
8043 case 8:
8044 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
8045
8046 default:
8047 goto fail;
8048 }
8049 }
8050
8051 case S390_OPND_IMMEDIATE: {
8052 ULong value = opnd.variant.imm;
8053
8054 switch (insn->size) {
8055 case 4:
8056 buf = s390_emit_load_32imm(buf, R0, value);
8057 return s390_emit_LTR(buf, R0, R0);
8058
8059 case 8:
8060 buf = s390_emit_load_64imm(buf, R0, value);
8061 return s390_emit_LTGR(buf, R0, R0);
8062
8063 default:
8064 goto fail;
8065 }
8066 }
8067
8068 default:
8069 goto fail;
8070 }
8071
8072 fail:
8073 vpanic("s390_insn_test_emit");
8074}
8075
8076
8077static UChar *
8078s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
8079{
8080 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
8081 s390_cc_t cond = insn->variant.cc2bool.cond;
8082
8083 /* Make the destination register be 1 or 0, depending on whether
8084 the relevant condition holds. A 64-bit value is computed. */
8085 if (cond == S390_CC_ALWAYS)
8086 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
8087
8088 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
8089 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
8090 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
8091 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
8092 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
8093
8094 return buf;
8095}
8096
8097
8098/* Only 4-byte and 8-byte operands are handled. */
8099static UChar *
8100s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
8101{
8102 UChar r1, r3, b, old;
8103 Int d;
8104 s390_amode *am;
8105
8106 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
8107 r3 = hregNumber(insn->variant.cas.op3);
8108 old= hregNumber(insn->variant.cas.old_mem);
8109 am = insn->variant.cas.op2;
8110 b = hregNumber(am->b);
8111 d = am->d;
8112
florian406ac942014-11-22 20:10:21 +00008113 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8114
sewardj2019a972011-03-07 16:04:07 +00008115 switch (insn->size) {
8116 case 4:
florian406ac942014-11-22 20:10:21 +00008117 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
sewardj2019a972011-03-07 16:04:07 +00008118 buf = s390_emit_LR(buf, R0, r1);
8119 if (am->tag == S390_AMODE_B12)
8120 buf = s390_emit_CS(buf, R0, r3, b, d);
8121 else
8122 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
8123 /* Now copy R0 which has the old memory value to OLD */
8124 return s390_emit_LR(buf, old, R0);
8125
8126 case 8:
florian406ac942014-11-22 20:10:21 +00008127 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
sewardj2019a972011-03-07 16:04:07 +00008128 buf = s390_emit_LGR(buf, R0, r1);
8129 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
8130 /* Now copy R0 which has the old memory value to OLD */
8131 return s390_emit_LGR(buf, old, R0);
8132
8133 default:
8134 goto fail;
8135 }
8136
8137 fail:
8138 vpanic("s390_insn_cas_emit");
8139}
8140
8141
florian448cbba2012-06-06 02:26:01 +00008142/* Only 4-byte and 8-byte operands are handled. */
8143static UChar *
8144s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
8145{
sewardja90622a2012-06-19 13:29:00 +00008146 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
florian448cbba2012-06-06 02:26:01 +00008147 Int d;
8148 s390_amode *am;
florianc4aa7ed2012-12-22 15:01:04 +00008149 s390_cdas *cdas = insn->variant.cdas.details;
florian448cbba2012-06-06 02:26:01 +00008150
florianc4aa7ed2012-12-22 15:01:04 +00008151 r1 = hregNumber(cdas->op1_high); /* expected value */
8152 r1p1 = hregNumber(cdas->op1_low); /* expected value */
8153 r3 = hregNumber(cdas->op3_high);
8154 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
8155 old_high = hregNumber(cdas->old_mem_high);
8156 old_low = hregNumber(cdas->old_mem_low);
8157 scratch = hregNumber(cdas->scratch);
8158 am = cdas->op2;
florian448cbba2012-06-06 02:26:01 +00008159 b = hregNumber(am->b);
8160 d = am->d;
8161
8162 vassert(scratch == 1);
florian406ac942014-11-22 20:10:21 +00008163 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
florian448cbba2012-06-06 02:26:01 +00008164
8165 switch (insn->size) {
8166 case 4:
8167 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
8168 and let CDS/CDSY clobber it */
8169 buf = s390_emit_LR(buf, R0, r1);
8170 buf = s390_emit_LR(buf, scratch, r1p1);
8171
8172 if (am->tag == S390_AMODE_B12)
8173 buf = s390_emit_CDS(buf, R0, r3, b, d);
8174 else
8175 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
8176
8177 /* Now copy R0,scratch which has the old memory value to OLD */
8178 buf = s390_emit_LR(buf, old_high, R0);
8179 buf = s390_emit_LR(buf, old_low, scratch);
8180 return buf;
8181
8182 case 8:
8183 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
8184 and let CDSG clobber it */
8185 buf = s390_emit_LGR(buf, R0, r1);
8186 buf = s390_emit_LGR(buf, scratch, r1p1);
8187
8188 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
8189
8190 /* Now copy R0,scratch which has the old memory value to OLD */
8191 buf = s390_emit_LGR(buf, old_high, R0);
8192 buf = s390_emit_LGR(buf, old_low, scratch);
8193 return buf;
8194
8195 default:
8196 goto fail;
8197 }
8198
8199 fail:
florianbb5aa782012-12-01 21:29:07 +00008200 vpanic("s390_insn_cdas_emit");
florian448cbba2012-06-06 02:26:01 +00008201}
8202
8203
sewardj2019a972011-03-07 16:04:07 +00008204/* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
8205 comparisons will have been converted to 4-byte comparisons in
8206 s390_isel_cc and should not occur here. */
8207static UChar *
8208s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
8209{
8210 s390_opnd_RMI op2;
8211 HReg op1;
8212 Bool signed_comparison;
8213
8214 op1 = insn->variant.compare.src1;
8215 op2 = insn->variant.compare.src2;
8216 signed_comparison = insn->variant.compare.signed_comparison;
8217
8218 switch (op2.tag) {
8219 case S390_OPND_REG: {
8220 UInt r1 = hregNumber(op1);
8221 UInt r2 = hregNumber(op2.variant.reg);
8222
8223 switch (insn->size) {
8224 case 4:
8225 if (signed_comparison)
8226 return s390_emit_CR(buf, r1, r2);
8227 else
8228 return s390_emit_CLR(buf, r1, r2);
8229
8230 case 8:
8231 if (signed_comparison)
8232 return s390_emit_CGR(buf, r1, r2);
8233 else
8234 return s390_emit_CLGR(buf, r1, r2);
8235
8236 default:
8237 goto fail;
8238 }
8239 }
8240
8241 case S390_OPND_AMODE: {
8242 UChar r1 = hregNumber(op1);
8243 const s390_amode *am = op2.variant.am;
8244 UChar b = hregNumber(am->b);
8245 UChar x = hregNumber(am->x);
8246 Int d = am->d;
8247
8248 switch (insn->size) {
8249 case 4:
8250 switch (am->tag) {
8251 case S390_AMODE_B12:
8252 case S390_AMODE_BX12:
8253 if (signed_comparison)
8254 return s390_emit_C(buf, r1, x, b, d);
8255 else
8256 return s390_emit_CL(buf, r1, x, b, d);
8257
8258 case S390_AMODE_B20:
8259 case S390_AMODE_BX20:
8260 if (signed_comparison)
8261 return s390_emit_CY(buf, r1, x, b, DISP20(d));
8262 else
8263 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
8264 }
8265 goto fail;
8266
8267 case 8:
8268 if (signed_comparison)
8269 return s390_emit_CG(buf, r1, x, b, DISP20(d));
8270 else
8271 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
8272
8273 default:
8274 goto fail;
8275 }
8276 }
8277
8278 case S390_OPND_IMMEDIATE: {
8279 UChar r1 = hregNumber(op1);
8280 ULong value = op2.variant.imm;
8281
8282 switch (insn->size) {
8283 case 4:
8284 if (signed_comparison)
8285 return s390_emit_CFIw(buf, r1, value);
8286 else
8287 return s390_emit_CLFIw(buf, r1, value);
8288
8289 case 8:
florian07d34552012-05-26 01:59:21 +00008290 if (s390_host_has_eimm) {
8291 if (signed_comparison) {
8292 if (ulong_fits_signed_32bit(value))
8293 return s390_emit_CGFI(buf, r1, value);
8294 } else {
8295 if (ulong_fits_unsigned_32bit(value))
8296 return s390_emit_CLGFI(buf, r1, value);
8297 }
8298 }
sewardj2019a972011-03-07 16:04:07 +00008299 buf = s390_emit_load_64imm(buf, R0, value);
8300 if (signed_comparison)
8301 return s390_emit_CGR(buf, r1, R0);
8302 else
8303 return s390_emit_CLGR(buf, r1, R0);
8304
8305 default:
8306 goto fail;
8307 }
8308 }
8309
8310 default:
8311 goto fail;
8312 }
8313
8314 fail:
8315 vpanic("s390_insn_compare_emit");
8316}
8317
8318
8319static UChar *
8320s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
8321{
8322 s390_opnd_RMI op2;
8323 UChar r1;
8324 Bool signed_multiply;
8325
8326 /* The register number identifying the register pair */
8327 r1 = hregNumber(insn->variant.mul.dst_hi);
8328
8329 op2 = insn->variant.mul.op2;
florianc4aa7ed2012-12-22 15:01:04 +00008330 signed_multiply = insn->tag == S390_INSN_SMUL;
sewardj2019a972011-03-07 16:04:07 +00008331
8332 switch (op2.tag) {
8333 case S390_OPND_REG: {
8334 UInt r2 = hregNumber(op2.variant.reg);
8335
8336 switch (insn->size) {
8337 case 1:
8338 case 2:
8339 case 4:
8340 if (signed_multiply)
8341 return s390_emit_MR(buf, r1, r2);
8342 else
8343 return s390_emit_MLR(buf, r1, r2);
8344
8345 case 8:
8346 if (signed_multiply)
8347 vpanic("s390_insn_mul_emit");
8348 else
8349 return s390_emit_MLGR(buf, r1, r2);
8350
8351 default:
8352 goto fail;
8353 }
8354 }
8355
8356 case S390_OPND_AMODE: {
8357 const s390_amode *am = op2.variant.am;
8358 UChar b = hregNumber(am->b);
8359 UChar x = hregNumber(am->x);
8360 Int d = am->d;
8361
8362 switch (insn->size) {
8363 case 1:
8364 case 2:
8365 /* Load bytes into scratch register R0, then multiply */
8366 buf = s390_emit_load_mem(buf, insn->size, R0, am);
8367 if (signed_multiply)
8368 return s390_emit_MR(buf, r1, R0);
8369 else
8370 return s390_emit_MLR(buf, r1, R0);
8371
8372 case 4:
8373 switch (am->tag) {
8374 case S390_AMODE_B12:
8375 case S390_AMODE_BX12:
8376 if (signed_multiply)
8377 return s390_emit_M(buf, r1, x, b, d);
8378 else
8379 return s390_emit_ML(buf, r1, x, b, DISP20(d));
8380
8381 case S390_AMODE_B20:
8382 case S390_AMODE_BX20:
8383 if (signed_multiply)
8384 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
8385 else
sewardjb13a92a2011-04-13 14:44:29 +00008386 return s390_emit_ML(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008387 }
8388 goto fail;
8389
8390 case 8:
8391 if (signed_multiply)
8392 vpanic("s390_insn_mul_emit");
8393 else
8394 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
8395
8396 default:
8397 goto fail;
8398 }
8399 }
8400
8401 case S390_OPND_IMMEDIATE: {
8402 ULong value = op2.variant.imm;
8403
8404 switch (insn->size) {
8405 case 1:
8406 case 2:
8407 case 4:
8408 buf = s390_emit_load_32imm(buf, R0, value);
8409 if (signed_multiply)
8410 return s390_emit_MR(buf, r1, R0);
8411 else
8412 return s390_emit_MLR(buf, r1, R0);
8413
8414 case 8:
8415 buf = s390_emit_load_64imm(buf, R0, value);
8416 if (signed_multiply)
8417 vpanic("s390_insn_mul_emit");
8418 else
8419 return s390_emit_MLGR(buf, r1, R0);
8420
8421 default:
8422 goto fail;
8423 }
8424 }
8425
8426 default:
8427 goto fail;
8428 }
8429
8430 fail:
8431 vpanic("s390_insn_mul_emit");
8432}
8433
8434
8435static UChar *
8436s390_insn_div_emit(UChar *buf, const s390_insn *insn)
8437{
8438 s390_opnd_RMI op2;
8439 UChar r1;
8440 Bool signed_divide;
8441
8442 r1 = hregNumber(insn->variant.div.op1_hi);
8443 op2 = insn->variant.div.op2;
florianc4aa7ed2012-12-22 15:01:04 +00008444 signed_divide = insn->tag == S390_INSN_SDIV;
sewardj2019a972011-03-07 16:04:07 +00008445
8446 switch (op2.tag) {
8447 case S390_OPND_REG: {
8448 UInt r2 = hregNumber(op2.variant.reg);
8449
8450 switch (insn->size) {
8451 case 4:
8452 if (signed_divide)
8453 return s390_emit_DR(buf, r1, r2);
8454 else
8455 return s390_emit_DLR(buf, r1, r2);
8456
8457 case 8:
8458 if (signed_divide)
8459 vpanic("s390_insn_div_emit");
8460 else
8461 return s390_emit_DLGR(buf, r1, r2);
8462
8463 default:
8464 goto fail;
8465 }
8466 }
8467
8468 case S390_OPND_AMODE: {
8469 const s390_amode *am = op2.variant.am;
8470 UChar b = hregNumber(am->b);
8471 UChar x = hregNumber(am->x);
8472 Int d = am->d;
8473
8474 switch (insn->size) {
8475 case 4:
8476 switch (am->tag) {
8477 case S390_AMODE_B12:
8478 case S390_AMODE_BX12:
8479 if (signed_divide)
8480 return s390_emit_D(buf, r1, x, b, d);
8481 else
8482 return s390_emit_DL(buf, r1, x, b, DISP20(d));
8483
8484 case S390_AMODE_B20:
8485 case S390_AMODE_BX20:
sewardjb13a92a2011-04-13 14:44:29 +00008486 if (signed_divide) {
8487 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008488 return s390_emit_DR(buf, r1, R0);
sewardjb13a92a2011-04-13 14:44:29 +00008489 } else
8490 return s390_emit_DL(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008491 }
8492 goto fail;
8493
8494 case 8:
8495 if (signed_divide)
8496 vpanic("s390_insn_div_emit");
8497 else
8498 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
8499
8500 default:
8501 goto fail;
8502 }
8503 }
8504
8505 case S390_OPND_IMMEDIATE: {
8506 ULong value = op2.variant.imm;
8507
8508 switch (insn->size) {
8509 case 4:
8510 buf = s390_emit_load_32imm(buf, R0, value);
8511 if (signed_divide)
8512 return s390_emit_DR(buf, r1, R0);
8513 else
8514 return s390_emit_DLR(buf, r1, R0);
8515
8516 case 8:
8517 buf = s390_emit_load_64imm(buf, R0, value);
8518 if (signed_divide)
8519 vpanic("s390_insn_div_emit");
8520 else
8521 return s390_emit_DLGR(buf, r1, R0);
8522
8523 default:
8524 goto fail;
8525 }
8526 }
8527
8528 default:
8529 goto fail;
8530 }
8531
8532 fail:
8533 vpanic("s390_insn_div_emit");
8534}
8535
8536
8537static UChar *
8538s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
8539{
8540 s390_opnd_RMI op2;
8541 UChar r1;
8542
8543 r1 = hregNumber(insn->variant.divs.rem);
8544 op2 = insn->variant.divs.op2;
8545
8546 switch (op2.tag) {
8547 case S390_OPND_REG: {
8548 UInt r2 = hregNumber(op2.variant.reg);
8549
8550 return s390_emit_DSGR(buf, r1, r2);
8551 }
8552
8553 case S390_OPND_AMODE: {
8554 const s390_amode *am = op2.variant.am;
8555 UChar b = hregNumber(am->b);
8556 UChar x = hregNumber(am->x);
8557 Int d = am->d;
8558
8559 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
8560 }
8561
8562 case S390_OPND_IMMEDIATE: {
8563 ULong value = op2.variant.imm;
8564
8565 buf = s390_emit_load_64imm(buf, R0, value);
8566 return s390_emit_DSGR(buf, r1, R0);
8567 }
8568
8569 default:
8570 goto fail;
8571 }
8572
8573 fail:
8574 vpanic("s390_insn_divs_emit");
8575}
8576
8577
8578static UChar *
sewardj611b06e2011-03-24 08:57:29 +00008579s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
sewardj2019a972011-03-07 16:04:07 +00008580{
8581 s390_opnd_RMI src;
sewardj611b06e2011-03-24 08:57:29 +00008582 UChar r1, r1p1, r2, *p;
sewardj2019a972011-03-07 16:04:07 +00008583
sewardj611b06e2011-03-24 08:57:29 +00008584 r1 = hregNumber(insn->variant.clz.num_bits);
8585 r1p1 = hregNumber(insn->variant.clz.clobber);
sewardj2019a972011-03-07 16:04:07 +00008586
8587 vassert((r1 & 0x1) == 0);
8588 vassert(r1p1 == r1 + 1);
8589
sewardj611b06e2011-03-24 08:57:29 +00008590 p = buf;
8591 src = insn->variant.clz.src;
sewardj2019a972011-03-07 16:04:07 +00008592
sewardj611b06e2011-03-24 08:57:29 +00008593 /* Get operand and move it to r2 */
sewardj2019a972011-03-07 16:04:07 +00008594 switch (src.tag) {
sewardj611b06e2011-03-24 08:57:29 +00008595 case S390_OPND_REG:
8596 r2 = hregNumber(src.variant.reg);
8597 break;
sewardj2019a972011-03-07 16:04:07 +00008598
8599 case S390_OPND_AMODE: {
8600 const s390_amode *am = src.variant.am;
8601 UChar b = hregNumber(am->b);
8602 UChar x = hregNumber(am->x);
8603 Int d = am->d;
8604
sewardj611b06e2011-03-24 08:57:29 +00008605 p = s390_emit_LG(p, R0, x, b, DISP20(d));
8606 r2 = R0;
8607 break;
sewardj2019a972011-03-07 16:04:07 +00008608 }
8609
8610 case S390_OPND_IMMEDIATE: {
8611 ULong value = src.variant.imm;
8612
sewardj611b06e2011-03-24 08:57:29 +00008613 p = s390_emit_load_64imm(p, R0, value);
8614 r2 = R0;
8615 break;
sewardj2019a972011-03-07 16:04:07 +00008616 }
8617
8618 default:
8619 goto fail;
8620 }
8621
sewardj611b06e2011-03-24 08:57:29 +00008622 /* Use FLOGR if you can */
8623 if (s390_host_has_eimm) {
8624 return s390_emit_FLOGR(p, r1, r2);
8625 }
8626
8627 /*
8628 r0 = r2;
8629 r1 = 64;
8630 while (r0 != 0) {
8631 r1 -= 1;
8632 r0 >>= 1;
8633 }
8634 */
8635 p = s390_emit_LTGR(p, R0, r2);
8636 p = s390_emit_LLILL(p, r1, 64);
8637
8638 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
8639 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
8640 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
8641 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
8642 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
8643 (UShort)(-(4 + 6 + 4) / 2));
8644 return p;
8645
sewardj2019a972011-03-07 16:04:07 +00008646 fail:
sewardj611b06e2011-03-24 08:57:29 +00008647 vpanic("s390_insn_clz_emit");
sewardj2019a972011-03-07 16:04:07 +00008648}
8649
8650
sewardjcfe046e2013-01-17 14:23:53 +00008651/* Returns a value == BUF to denote failure, != BUF to denote success. */
sewardj2019a972011-03-07 16:04:07 +00008652static UChar *
sewardj2019a972011-03-07 16:04:07 +00008653s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
8654{
8655 s390_cc_t cond;
8656 ULong target;
8657 UChar *ptmp = buf;
sewardj74142b82013-08-08 10:28:59 +00008658 s390_helper_call *helper_call = insn->variant.helper_call.details;
sewardj2019a972011-03-07 16:04:07 +00008659
sewardj74142b82013-08-08 10:28:59 +00008660 cond = helper_call->cond;
8661 target = helper_call->target;
sewardj2019a972011-03-07 16:04:07 +00008662
sewardjcfe046e2013-01-17 14:23:53 +00008663 if (cond != S390_CC_ALWAYS
sewardj74142b82013-08-08 10:28:59 +00008664 && helper_call->rloc.pri != RLPri_None) {
sewardjcfe046e2013-01-17 14:23:53 +00008665 /* The call might not happen (it isn't unconditional) and it
8666 returns a result. In this case we will need to generate a
8667 control flow diamond to put 0x555..555 in the return
8668 register(s) in the case where the call doesn't happen. If
8669 this ever becomes necessary, maybe copy code from the ARM
8670 equivalent. Until that day, just give up. */
floriandff20412014-09-25 20:33:50 +00008671 return buf; /* To denote failure. */
sewardjcfe046e2013-01-17 14:23:53 +00008672 }
8673
sewardj2019a972011-03-07 16:04:07 +00008674 if (cond != S390_CC_ALWAYS) {
8675 /* So we have something like this
8676 if (cond) call X;
8677 Y: ...
8678 We convert this into
8679 if (! cond) goto Y; // BRC opcode; 4 bytes
8680 call X;
8681 Y:
8682 */
8683 /* 4 bytes (a BRC insn) to be filled in here */
8684 buf += 4;
8685 }
8686
8687 /* Load the target address into a register, that
8688 (a) is not used for passing parameters to the helper and
8689 (b) can be clobbered by the callee
florianc9e90e52012-05-27 17:20:47 +00008690 (c) is not special to the BASR insn
8691 r1 is the only choice.
sewardj2019a972011-03-07 16:04:07 +00008692 Also, need to arrange for the return address be put into the
8693 link-register */
8694 buf = s390_emit_load_64imm(buf, 1, target);
8695
8696 /* Stash away the client's FPC register because the helper might change it. */
8697 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
8698
sewardj2019a972011-03-07 16:04:07 +00008699 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
florian01ed6e72012-05-27 16:52:43 +00008700
sewardj2019a972011-03-07 16:04:07 +00008701 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
8702 S390_OFFSET_SAVED_FPC_C);
8703
8704 if (cond != S390_CC_ALWAYS) {
8705 Int delta = buf - ptmp;
8706
8707 delta >>= 1; /* immediate constant is #half-words */
8708 vassert(delta > 0 && delta < (1 << 16));
8709 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8710 }
8711
8712 return buf;
8713}
8714
8715
8716static UChar *
8717s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
8718{
8719 HReg dst;
8720 s390_opnd_RMI src;
8721 s390_cc_t cond;
8722 UChar *p, *ptmp = 0; /* avoid compiler warnings */
8723
8724 cond = insn->variant.cond_move.cond;
8725 dst = insn->variant.cond_move.dst;
8726 src = insn->variant.cond_move.src;
8727
florian3a3d7f12012-12-03 13:32:05 +00008728 if (cond == S390_CC_NEVER) return buf;
8729
sewardj2019a972011-03-07 16:04:07 +00008730 p = buf;
8731
florianaec8e052012-12-09 17:26:32 +00008732 if (s390_host_has_lsc) {
florian3a3d7f12012-12-03 13:32:05 +00008733 /* LOCx is not the preferred way to implement an unconditional load. */
8734 if (cond != S390_CC_ALWAYS) goto use_branch_insn;
8735
8736 switch (src.tag) {
8737 case S390_OPND_REG:
8738 return s390_emit_LOCGR(p, cond, hregNumber(dst),
8739 hregNumber(src.variant.reg));
8740
8741 case S390_OPND_AMODE: {
8742 const s390_amode *am = src.variant.am;
8743
8744 /* We cannot use LOCx for loads less than 4 bytes. In that case
8745 load into R0 and then use LOCGR. Do the same if the amode uses
8746 an index register. */
8747 if (insn->size < 4 ||
8748 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
8749 p = s390_emit_load_mem(p, insn->size, R0, am);
8750 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8751 return p;
8752 }
8753
8754 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8755 vassert(insn->size == 4 || insn->size == 8);
8756
8757 UInt b = hregNumber(am->b);
8758 UInt d = am->d;
8759
8760 if (insn->size == 4) {
8761 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
8762 }
8763 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
8764 }
8765
8766 case S390_OPND_IMMEDIATE: {
8767 ULong value = src.variant.imm;
8768
8769 /* Load value into R0, then use LOCGR */
8770 if (insn->size <= 4) {
8771 p = s390_emit_load_32imm(p, R0, value);
8772 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8773 }
8774
8775 vassert(insn->size == 8);
8776 p = s390_emit_load_64imm(p, R0, value);
8777 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8778 }
8779 }
8780 }
8781
8782use_branch_insn:
sewardj2019a972011-03-07 16:04:07 +00008783 /* Branch (if cond fails) over move instrs */
8784 if (cond != S390_CC_ALWAYS) {
8785 /* Don't know how many bytes to jump over yet.
8786 Make space for a BRC instruction (4 bytes) and fill in later. */
8787 ptmp = p; /* to be filled in here */
8788 p += 4;
8789 }
8790
8791 // cond true: move src => dst
8792
8793 switch (src.tag) {
8794 case S390_OPND_REG:
8795 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
8796 break;
8797
8798 case S390_OPND_AMODE:
8799 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
8800 break;
8801
8802 case S390_OPND_IMMEDIATE: {
8803 ULong value = src.variant.imm;
8804 UInt r = hregNumber(dst);
8805
8806 switch (insn->size) {
8807 case 1:
8808 case 2:
8809 /* Load the immediate values as a 4 byte value. That does not hurt as
8810 those extra bytes will not be looked at. Fall through .... */
8811 case 4:
8812 p = s390_emit_load_32imm(p, r, value);
8813 break;
8814
8815 case 8:
8816 p = s390_emit_load_64imm(p, r, value);
8817 break;
8818 }
8819 break;
8820 }
8821
8822 default:
8823 goto fail;
8824 }
8825
8826 if (cond != S390_CC_ALWAYS) {
8827 Int delta = p - ptmp;
8828
8829 delta >>= 1; /* immediate constant is #half-words */
8830 vassert(delta > 0 && delta < (1 << 16));
8831 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8832 }
8833
8834 return p;
8835
8836 fail:
8837 vpanic("s390_insn_cond_move_emit");
8838}
8839
8840
sewardj2019a972011-03-07 16:04:07 +00008841static UChar *
8842s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
8843{
8844 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
8845 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
8846 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +00008847
8848 switch (insn->size) {
8849 case 4:
8850 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008851 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
8852 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008853 default: goto fail;
8854 }
8855 break;
8856
8857 case 8:
8858 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008859 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
8860 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008861 default: goto fail;
8862 }
8863 break;
8864
8865 default: goto fail;
8866 }
8867
sewardj2019a972011-03-07 16:04:07 +00008868 fail:
8869 vpanic("s390_insn_bfp_triop_emit");
8870}
8871
8872
8873static UChar *
8874s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
8875{
floriancc491a62012-09-10 23:44:37 +00008876 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
8877 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00008878
8879 switch (insn->size) {
8880 case 4:
8881 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008882 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
8883 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
8884 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
8885 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008886 default: goto fail;
8887 }
8888 break;
8889
8890 case 8:
8891 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008892 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
8893 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
8894 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
8895 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008896 default: goto fail;
8897 }
8898 break;
8899
floriancc491a62012-09-10 23:44:37 +00008900 case 16:
8901 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008902 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
8903 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
8904 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
8905 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008906 default: goto fail;
8907 }
8908 break;
8909
sewardj2019a972011-03-07 16:04:07 +00008910 default: goto fail;
8911 }
8912
sewardj2019a972011-03-07 16:04:07 +00008913 fail:
8914 vpanic("s390_insn_bfp_binop_emit");
8915}
8916
8917
8918static UChar *
8919s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
8920{
floriancc491a62012-09-10 23:44:37 +00008921 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
8922 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
sewardj2019a972011-03-07 16:04:07 +00008923
8924 switch (insn->variant.bfp_unop.tag) {
8925 case S390_BFP_ABS:
8926 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008927 case 4: return s390_emit_LPEBR(buf, r1, r2);
8928 case 8: return s390_emit_LPDBR(buf, r1, r2);
8929 case 16: return s390_emit_LPXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008930 default: goto fail;
8931 }
8932 break;
8933
8934 case S390_BFP_NABS:
8935 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008936 case 4: return s390_emit_LNEBR(buf, r1, r2);
8937 case 8: return s390_emit_LNDBR(buf, r1, r2);
8938 case 16: return s390_emit_LNXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008939 default: goto fail;
8940 }
8941 break;
8942
8943 case S390_BFP_NEG:
8944 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008945 case 4: return s390_emit_LCEBR(buf, r1, r2);
8946 case 8: return s390_emit_LCDBR(buf, r1, r2);
8947 case 16: return s390_emit_LCXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008948 default: goto fail;
8949 }
8950 break;
8951
8952 case S390_BFP_SQRT:
8953 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008954 case 4: return s390_emit_SQEBR(buf, r1, r2);
8955 case 8: return s390_emit_SQDBR(buf, r1, r2);
8956 case 16: return s390_emit_SQXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008957 default: goto fail;
8958 }
8959 break;
8960
florian9fcff4c2012-09-10 03:09:04 +00008961 default: goto fail;
8962 }
8963
florian9fcff4c2012-09-10 03:09:04 +00008964 fail:
8965 vpanic("s390_insn_bfp_unop_emit");
8966}
8967
8968
8969static UChar *
8970s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
8971{
floriancc491a62012-09-10 23:44:37 +00008972 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
8973 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
florian125e20d2012-10-07 15:42:37 +00008974 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
florian2c74d242012-09-12 19:38:42 +00008975 /* The IEEE-inexact-exception control is not modelled. So the
8976 m4 field is 0 (which is what GCC does, too) */
8977 const UInt m4 = 0;
florian9fcff4c2012-09-10 03:09:04 +00008978
florian9fcff4c2012-09-10 03:09:04 +00008979 switch (insn->variant.bfp_convert.tag) {
floriancc491a62012-09-10 23:44:37 +00008980 /* Convert to fixed */
florian9fcff4c2012-09-10 03:09:04 +00008981 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
8982 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008983 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008984 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
8985 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008986 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008987
floriancc491a62012-09-10 23:44:37 +00008988 /* Convert to logical */
florian2c74d242012-09-12 19:38:42 +00008989 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
8990 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
8991 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
8992 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
8993 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
8994 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008995
florian2c74d242012-09-12 19:38:42 +00008996 /* Convert from fixed */
8997 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
8998 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
8999 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
9000 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
9001 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
9002 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
9003
9004 /* Convert from logical */
9005 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
9006 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
9007 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
9008 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
9009 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
9010 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
9011
9012 /* Load lengthened */
9013 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00009014 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
9015 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00009016
florian2c74d242012-09-12 19:38:42 +00009017 /* Load rounded */
9018 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
9019 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
9020 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
floriancc491a62012-09-10 23:44:37 +00009021
florian6d0b0152015-07-09 20:59:24 +00009022 /* Load FP integer */
9023 case S390_BFP_F32_TO_F32I: return s390_emit_FIEBRA(buf, m3, m4, r1, r2);
9024 case S390_BFP_F64_TO_F64I: return s390_emit_FIDBRA(buf, m3, m4, r1, r2);
florianb53f9482015-09-05 20:35:52 +00009025 case S390_BFP_F128_TO_F128I: return s390_emit_FIXBRA(buf, m3, m4, r1, r2);
florian6d0b0152015-07-09 20:59:24 +00009026
sewardj2019a972011-03-07 16:04:07 +00009027 default: goto fail;
9028 }
9029
sewardj2019a972011-03-07 16:04:07 +00009030 fail:
florian9fcff4c2012-09-10 03:09:04 +00009031 vpanic("s390_insn_bfp_convert_emit");
sewardj2019a972011-03-07 16:04:07 +00009032}
9033
9034
9035static UChar *
9036s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
9037{
9038 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +00009039 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
9040 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00009041
9042 switch (insn->size) {
floriancc491a62012-09-10 23:44:37 +00009043 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
9044 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
9045 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
sewardj2019a972011-03-07 16:04:07 +00009046 default: goto fail;
9047 }
9048
9049 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
9050
9051 fail:
9052 vpanic("s390_insn_bfp_compare_emit");
9053}
9054
9055
9056static UChar *
florian12390202012-11-10 22:34:14 +00009057s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
9058{
florianc4aa7ed2012-12-22 15:01:04 +00009059 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
9060
9061 UInt r1 = hregNumber(dfp_binop->dst_hi);
9062 UInt r2 = hregNumber(dfp_binop->op2_hi);
9063 UInt r3 = hregNumber(dfp_binop->op3_hi);
florian89bb1a92013-01-10 15:41:46 +00009064 s390_dfp_round_t m4 = dfp_binop->rounding_mode;
florian12390202012-11-10 22:34:14 +00009065
9066 switch (insn->size) {
9067 case 8:
florianc4aa7ed2012-12-22 15:01:04 +00009068 switch (dfp_binop->tag) {
florian362e2712013-01-22 14:02:05 +00009069 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2);
9070 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2);
9071 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2);
9072 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2);
florian5c539732013-02-14 14:27:12 +00009073 case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2);
florian12390202012-11-10 22:34:14 +00009074 default: goto fail;
9075 }
9076 break;
floriane38f6412012-12-21 17:32:12 +00009077
9078 case 16:
florianc4aa7ed2012-12-22 15:01:04 +00009079 switch (dfp_binop->tag) {
floriane38f6412012-12-21 17:32:12 +00009080 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2);
9081 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2);
9082 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2);
9083 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2);
florian5c539732013-02-14 14:27:12 +00009084 case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2);
floriane38f6412012-12-21 17:32:12 +00009085 default: goto fail;
9086 }
9087 break;
9088
florian12390202012-11-10 22:34:14 +00009089 default: goto fail;
9090 }
9091
9092 fail:
9093 vpanic("s390_insn_dfp_binop_emit");
9094}
9095
9096
9097static UChar *
florian5c539732013-02-14 14:27:12 +00009098s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn)
9099{
9100 UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi);
9101 UInt r2 = hregNumber(insn->variant.dfp_reround.op2);
9102 UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi);
9103 s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode;
9104
9105 switch (insn->size) {
9106 case 8:
9107 return s390_emit_RRDTR(buf, r3, m4, r1, r2);
9108
9109 case 16:
9110 return s390_emit_RRXTR(buf, r3, m4, r1, r2);
9111
9112 default: goto fail;
9113 }
9114 fail:
9115 vpanic("s390_insn_dfp_reround_emit");
9116}
9117
9118
9119static UChar *
floriance9e3db2012-12-27 20:14:03 +00009120s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
9121{
9122 UInt r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
9123 UInt r2 = hregNumber(insn->variant.dfp_unop.op_hi);
9124
9125 switch (insn->variant.dfp_unop.tag) {
florian5c539732013-02-14 14:27:12 +00009126 case S390_DFP_EXTRACT_EXP_D64: return s390_emit_EEDTR(buf, r1, r2); break;
9127 case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break;
floriance9e3db2012-12-27 20:14:03 +00009128 case S390_DFP_EXTRACT_SIG_D64: return s390_emit_ESDTR(buf, r1, r2); break;
9129 case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
9130 default: goto fail;
9131 }
9132 fail:
9133 vpanic("s390_insn_dfp_unop_emit");
9134}
9135
9136
9137static UChar *
florian1b901d42013-01-01 22:19:24 +00009138s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn)
9139{
9140 UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi);
9141 UInt r2 = hregNumber(insn->variant.dfp_intop.op2);
9142 UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi);
9143
9144 switch (insn->size) {
9145 case 8:
9146 switch (insn->variant.dfp_intop.tag) {
9147 case S390_DFP_SHIFT_LEFT: return s390_emit_SLDT(buf, r3, r1, r2);
9148 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2);
florian5c539732013-02-14 14:27:12 +00009149 case S390_DFP_INSERT_EXP: return s390_emit_IEDTR(buf, r3, r1, r2);
florian1b901d42013-01-01 22:19:24 +00009150 default: goto fail;
9151 }
9152 break;
9153
9154 case 16:
9155 switch (insn->variant.dfp_intop.tag) {
9156 case S390_DFP_SHIFT_LEFT: return s390_emit_SLXT(buf, r3, r1, r2);
9157 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2);
florian5c539732013-02-14 14:27:12 +00009158 case S390_DFP_INSERT_EXP: return s390_emit_IEXTR(buf, r3, r1, r2);
florian1b901d42013-01-01 22:19:24 +00009159 default: goto fail;
9160 }
9161 break;
9162
9163 default: goto fail;
9164 }
9165
9166 fail:
9167 vpanic("s390_insn_dfp_intop_emit");
9168}
9169
9170
9171static UChar *
floriane38f6412012-12-21 17:32:12 +00009172s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
9173{
9174 UInt dst = hregNumber(insn->variant.dfp_compare.dst);
9175 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi);
9176 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi);
9177
9178 switch (insn->size) {
florian20c6bca2012-12-26 17:47:19 +00009179 case 8:
9180 switch(insn->variant.dfp_compare.tag) {
9181 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break;
9182 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
9183 default: goto fail;
9184 }
9185 break;
9186
9187 case 16:
9188 switch(insn->variant.dfp_compare.tag) {
9189 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break;
9190 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
9191 default: goto fail;
9192 }
9193 break;
9194
floriane38f6412012-12-21 17:32:12 +00009195 default: goto fail;
9196 }
9197
9198 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
9199
9200 fail:
9201 vpanic("s390_insn_dfp_compare_emit");
9202}
9203
9204
9205static UChar *
9206s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
9207{
9208 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
9209 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi);
9210 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
9211 /* The IEEE-inexact-exception control is not modelled. So the
9212 m4 field is 0 (which is what GCC does, too) */
9213 const UInt m4 = 0;
9214
9215 switch (insn->variant.dfp_convert.tag) {
9216
florian5f034622013-01-13 02:29:05 +00009217 /* Convert to fixed */
9218 case S390_DFP_D64_TO_I32: return s390_emit_CFDTR(buf, m3, m4, r1, r2);
9219 case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2);
floriana887acd2013-02-08 23:32:54 +00009220 case S390_DFP_D64_TO_I64: return s390_emit_CGDTR(buf, m3, m4, r1, r2);
9221 case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2);
florian5f034622013-01-13 02:29:05 +00009222
9223 /* Convert to logical */
9224 case S390_DFP_D64_TO_U32: return s390_emit_CLFDTR(buf, m3, m4, r1, r2);
9225 case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2);
9226 case S390_DFP_D64_TO_U64: return s390_emit_CLGDTR(buf, m3, m4, r1, r2);
9227 case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2);
9228
9229 /* Convert from fixed */
9230 case S390_DFP_I32_TO_D64: return s390_emit_CDFTR(buf, 0, m4, r1, r2);
9231 case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2);
floriana887acd2013-02-08 23:32:54 +00009232 case S390_DFP_I64_TO_D64: return s390_emit_CDGTRA(buf, m3, m4, r1, r2);
9233 case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2);
florian5f034622013-01-13 02:29:05 +00009234
9235 /* Convert from logical */
9236 case S390_DFP_U32_TO_D64: return s390_emit_CDLFTR(buf, m3, m4, r1, r2);
9237 case S390_DFP_U64_TO_D64: return s390_emit_CDLGTR(buf, m3, m4, r1, r2);
9238 case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2);
9239 case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2);
9240
floriane38f6412012-12-21 17:32:12 +00009241 /* Load lengthened */
9242 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2);
9243 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2);
9244
9245 /* Load rounded */
9246 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2);
9247 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2);
9248
9249 default: goto fail;
9250 }
9251
9252 fail:
9253 vpanic("s390_insn_dfp_convert_emit");
9254}
9255
9256
9257static UChar *
florian78d5ef72013-05-11 15:02:58 +00009258s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
9259{
9260 UInt pfpo;
9261 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
9262 s390_dfp_round_t rm = fp_convert->rounding_mode;
9263
9264 vassert(rm < 2 || rm > 7);
9265
9266 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00009267 case S390_FP_F32_TO_D32: pfpo = S390_PFPO_F32_TO_D32 << 8; break;
9268 case S390_FP_F32_TO_D64: pfpo = S390_PFPO_F32_TO_D64 << 8; break;
9269 case S390_FP_F32_TO_D128: pfpo = S390_PFPO_F32_TO_D128 << 8; break;
9270 case S390_FP_F64_TO_D32: pfpo = S390_PFPO_F64_TO_D32 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009271 case S390_FP_F64_TO_D64: pfpo = S390_PFPO_F64_TO_D64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009272 case S390_FP_F64_TO_D128: pfpo = S390_PFPO_F64_TO_D128 << 8; break;
florian7ab421d2013-06-17 21:03:56 +00009273 case S390_FP_F128_TO_D32: pfpo = S390_PFPO_F128_TO_D32 << 8; break;
9274 case S390_FP_F128_TO_D64: pfpo = S390_PFPO_F128_TO_D64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009275 case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
florian7ab421d2013-06-17 21:03:56 +00009276 case S390_FP_D32_TO_F32: pfpo = S390_PFPO_D32_TO_F32 << 8; break;
9277 case S390_FP_D32_TO_F64: pfpo = S390_PFPO_D32_TO_F64 << 8; break;
9278 case S390_FP_D32_TO_F128: pfpo = S390_PFPO_D32_TO_F128 << 8; break;
9279 case S390_FP_D64_TO_F32: pfpo = S390_PFPO_D64_TO_F32 << 8; break;
9280 case S390_FP_D64_TO_F64: pfpo = S390_PFPO_D64_TO_F64 << 8; break;
9281 case S390_FP_D64_TO_F128: pfpo = S390_PFPO_D64_TO_F128 << 8; break;
9282 case S390_FP_D128_TO_F32: pfpo = S390_PFPO_D128_TO_F32 << 8; break;
9283 case S390_FP_D128_TO_F64: pfpo = S390_PFPO_D128_TO_F64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009284 case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
9285 default: goto fail;
9286 }
9287
9288 pfpo = pfpo | rm;
9289 buf = s390_emit_load_32imm(buf, R0, pfpo);
9290 buf = s390_emit_PFPO(buf);
9291 return buf;
9292
9293 fail:
9294 vpanic("s390_insn_fp_convert_emit");
9295}
9296
9297
9298static UChar *
sewardja52e37e2011-04-28 18:48:06 +00009299s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
9300{
9301 return s390_emit_BCR(buf, 0xF, 0x0);
9302}
9303
9304
florianad43b3a2012-02-20 15:01:14 +00009305static UChar *
florianb93348d2012-12-27 00:59:43 +00009306s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00009307{
florianb93348d2012-12-27 00:59:43 +00009308 s390_amode *am = insn->variant.mimm.dst;
florian3123f722013-01-24 15:55:52 +00009309 UChar b = hregNumber(am->b);
florian3123f722013-01-24 15:55:52 +00009310 Int d = am->d;
florianb93348d2012-12-27 00:59:43 +00009311 ULong value = insn->variant.mimm.value;
florian09bbba82012-12-11 04:09:43 +00009312
florianb93348d2012-12-27 00:59:43 +00009313 if (value == 0) {
florian3123f722013-01-24 15:55:52 +00009314 return s390_emit_XC(buf, insn->size - 1, b, d, b, d);
florianb93348d2012-12-27 00:59:43 +00009315 }
9316
9317 if (insn->size == 1) {
florian3123f722013-01-24 15:55:52 +00009318 return s390_emit_MVI(buf, value & 0xFF, b, d);
florianb93348d2012-12-27 00:59:43 +00009319 }
9320
9321 if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
9322 value &= 0xFFFF;
9323 switch (insn->size) {
florian3123f722013-01-24 15:55:52 +00009324 case 2: return s390_emit_MVHHI(buf, b, d, value);
9325 case 4: return s390_emit_MVHI(buf, b, d, value);
9326 case 8: return s390_emit_MVGHI(buf, b, d, value);
florianb93348d2012-12-27 00:59:43 +00009327 }
9328 } else {
9329 // Load value to R0, then store.
9330 switch (insn->size) {
9331 case 2:
9332 buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
florian3123f722013-01-24 15:55:52 +00009333 return s390_emit_STH(buf, R0, 0, b, d);
florianb93348d2012-12-27 00:59:43 +00009334 case 4:
9335 buf = s390_emit_load_32imm(buf, R0, value);
florian3123f722013-01-24 15:55:52 +00009336 return s390_emit_ST(buf, R0, 0, b, d);
florianb93348d2012-12-27 00:59:43 +00009337 case 8:
9338 buf = s390_emit_load_64imm(buf, R0, value);
florian3123f722013-01-24 15:55:52 +00009339 return s390_emit_STG(buf, R0, 0, b, DISP20(d));
florianb93348d2012-12-27 00:59:43 +00009340 }
9341 }
9342
9343 vpanic("s390_insn_mimm_emit");
florianad43b3a2012-02-20 15:01:14 +00009344}
9345
9346
9347static UChar *
florianf85fe3e2012-12-22 02:28:25 +00009348s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00009349{
florianf85fe3e2012-12-22 02:28:25 +00009350 s390_amode *am = insn->variant.madd.dst;
florian3123f722013-01-24 15:55:52 +00009351 UChar b = hregNumber(am->b);
florian3123f722013-01-24 15:55:52 +00009352 Int d = am->d;
florianf85fe3e2012-12-22 02:28:25 +00009353
9354 if (insn->size == 4) {
florian3123f722013-01-24 15:55:52 +00009355 return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d));
florianf85fe3e2012-12-22 02:28:25 +00009356 }
9357
florian3123f722013-01-24 15:55:52 +00009358 return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d));
florianad43b3a2012-02-20 15:01:14 +00009359}
9360
9361
florian2c74d242012-09-12 19:38:42 +00009362static UChar *
florian125e20d2012-10-07 15:42:37 +00009363s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
florian2c74d242012-09-12 19:38:42 +00009364{
florian125e20d2012-10-07 15:42:37 +00009365 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00009366
9367 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
9368 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
9369 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
9370
9371 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
9372 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
florian6d8e26e2012-09-12 19:52:16 +00009373 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
florian2c74d242012-09-12 19:38:42 +00009374
9375 return buf;
9376}
9377
9378
florianc8e4f562012-10-27 16:19:31 +00009379static UChar *
9380s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
9381{
9382 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
9383
9384 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
9385 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
9386 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
9387
9388 /* DFP rounding mode is set at bit position 25:27 in FPC register */
9389 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
9390 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
9391 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
9392 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
9393
9394 return buf;
9395}
9396
9397
florian8844a632012-04-13 04:04:06 +00009398/* Define convenience functions needed for translation chaining.
9399 Any changes need to be applied to the functions in concert. */
9400
florian1c857042012-04-15 04:11:07 +00009401static __inline__ Bool
9402s390_insn_is_BRCL(const UChar *p, UChar condition)
9403{
9404 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
9405}
9406
9407static __inline__ Bool
9408s390_insn_is_BR(const UChar *p, UChar reg)
9409{
9410 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
9411}
9412
florianebaf8d92012-04-22 17:38:46 +00009413
9414/* The length of the BASR insn */
9415#define S390_BASR_LEN 2
9416
florian1c857042012-04-15 04:11:07 +00009417
florian8844a632012-04-13 04:04:06 +00009418/* Load the 64-bit VALUE into REG. Note that this function must NOT
9419 optimise the generated code by looking at the value. I.e. using
floriane09e8bb2012-05-07 03:28:18 +00009420 LGHI if value == 0 would be very wrong. */
florian8844a632012-04-13 04:04:06 +00009421static UChar *
9422s390_tchain_load64(UChar *buf, UChar regno, ULong value)
9423{
florian1c857042012-04-15 04:11:07 +00009424 UChar *begin = buf;
9425
florian1c2b4db2012-04-22 17:46:31 +00009426 if (s390_host_has_eimm) {
9427 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
9428 buf = s390_emit_IIHF(buf, regno, value >> 32);
9429 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
9430 } else {
9431 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
9432 value >>= 16;
9433 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
9434 value >>= 16;
9435 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
9436 value >>= 16;
9437 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
9438 }
florian8844a632012-04-13 04:04:06 +00009439
florian1c857042012-04-15 04:11:07 +00009440 vassert(buf - begin == s390_tchain_load64_len());
9441
florian8844a632012-04-13 04:04:06 +00009442 return buf;
9443}
9444
9445/* Return number of bytes generated by s390_tchain_load64 */
9446static UInt
9447s390_tchain_load64_len(void)
9448{
florian1c2b4db2012-04-22 17:46:31 +00009449 if (s390_host_has_eimm) {
9450 return 6 + 6; /* IIHF + IILF */
9451 }
florianebaf8d92012-04-22 17:38:46 +00009452 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
florian8844a632012-04-13 04:04:06 +00009453}
9454
9455/* Verify that CODE is the code sequence generated by s390_tchain_load64
9456 to load VALUE into REGNO. Return pointer to the byte following the
9457 insn sequence. */
9458static const UChar *
9459s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
9460{
9461 UInt regmask = regno << 4;
9462 UInt hw;
9463
florian1c2b4db2012-04-22 17:46:31 +00009464 if (s390_host_has_eimm) {
9465 /* Check for IIHF */
9466 vassert(code[0] == 0xC0);
9467 vassert(code[1] == (0x08 | regmask));
9468 vassert(*(const UInt *)&code[2] == (value >> 32));
9469 /* Check for IILF */
9470 vassert(code[6] == 0xC0);
9471 vassert(code[7] == (0x09 | regmask));
9472 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
9473 } else {
9474 /* Check for IILL */
9475 hw = value & 0xFFFF;
9476 vassert(code[0] == 0xA5);
9477 vassert(code[1] == (0x03 | regmask));
9478 vassert(code[2] == (hw >> 8));
9479 vassert(code[3] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009480
florian1c2b4db2012-04-22 17:46:31 +00009481 /* Check for IILH */
9482 hw = (value >> 16) & 0xFFFF;
9483 vassert(code[4] == 0xA5);
9484 vassert(code[5] == (0x02 | regmask));
9485 vassert(code[6] == (hw >> 8));
9486 vassert(code[7] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009487
florian1c2b4db2012-04-22 17:46:31 +00009488 /* Check for IIHL */
9489 hw = (value >> 32) & 0xFFFF;
9490 vassert(code[8] == 0xA5);
9491 vassert(code[9] == (0x01 | regmask));
9492 vassert(code[10] == (hw >> 8));
9493 vassert(code[11] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009494
florian1c2b4db2012-04-22 17:46:31 +00009495 /* Check for IIHH */
9496 hw = (value >> 48) & 0xFFFF;
9497 vassert(code[12] == 0xA5);
9498 vassert(code[13] == (0x00 | regmask));
9499 vassert(code[14] == (hw >> 8));
9500 vassert(code[15] == (hw & 0xFF));
9501 }
florian8844a632012-04-13 04:04:06 +00009502
florian1c857042012-04-15 04:11:07 +00009503 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00009504}
9505
9506/* CODE points to the code sequence as generated by s390_tchain_load64.
florian5ea257b2012-09-29 17:05:46 +00009507 Change the loaded value to IMM64. Return pointer to the byte following
florian8844a632012-04-13 04:04:06 +00009508 the patched code sequence. */
9509static UChar *
9510s390_tchain_patch_load64(UChar *code, ULong imm64)
9511{
florian1c2b4db2012-04-22 17:46:31 +00009512 if (s390_host_has_eimm) {
9513 /* Patch IIHF */
9514 *(UInt *)&code[2] = imm64 >> 32;
9515 /* Patch IILF */
9516 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
9517 } else {
9518 code[3] = imm64 & 0xFF; imm64 >>= 8;
9519 code[2] = imm64 & 0xFF; imm64 >>= 8;
9520 code[7] = imm64 & 0xFF; imm64 >>= 8;
9521 code[6] = imm64 & 0xFF; imm64 >>= 8;
9522 code[11] = imm64 & 0xFF; imm64 >>= 8;
9523 code[10] = imm64 & 0xFF; imm64 >>= 8;
9524 code[15] = imm64 & 0xFF; imm64 >>= 8;
9525 code[14] = imm64 & 0xFF; imm64 >>= 8;
9526 }
florian8844a632012-04-13 04:04:06 +00009527
florian1c857042012-04-15 04:11:07 +00009528 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00009529}
9530
9531
9532/* NB: what goes on here has to be very closely coordinated with the
9533 chainXDirect_S390 and unchainXDirect_S390 below. */
9534static UChar *
9535s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
florian8462d112014-09-24 15:18:09 +00009536 const void *disp_cp_chain_me_to_slowEP,
9537 const void *disp_cp_chain_me_to_fastEP)
florian8844a632012-04-13 04:04:06 +00009538{
9539 /* We're generating chain-me requests here, so we need to be
9540 sure this is actually allowed -- no-redir translations can't
9541 use chain-me's. Hence: */
9542 vassert(disp_cp_chain_me_to_slowEP != NULL);
9543 vassert(disp_cp_chain_me_to_fastEP != NULL);
9544
9545 /* Use ptmp for backpatching conditional jumps. */
9546 UChar *ptmp = buf;
9547
9548 /* First off, if this is conditional, create a conditional
9549 jump over the rest of it. */
9550 s390_cc_t cond = insn->variant.xdirect.cond;
9551
9552 if (cond != S390_CC_ALWAYS) {
9553 /* So we have something like this
9554 if (cond) do_xdirect;
9555 Y: ...
9556 We convert this into
9557 if (! cond) goto Y; // BRC opcode; 4 bytes
9558 do_xdirect;
9559 Y:
9560 */
9561 /* 4 bytes (a BRC insn) to be filled in here */
9562 buf += 4;
9563 }
9564
9565 /* Update the guest IA. */
9566 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
9567
9568 const s390_amode *amode = insn->variant.xdirect.guest_IA;
florianbf516d12012-04-21 15:53:13 +00009569 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009570 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009571 UInt d = amode->d;
9572
florianbf516d12012-04-21 15:53:13 +00009573 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009574
florian8844a632012-04-13 04:04:06 +00009575 /* Load the chosen entry point into the scratch reg */
florian8462d112014-09-24 15:18:09 +00009576 const void *disp_cp_chain_me;
florian8844a632012-04-13 04:04:06 +00009577
9578 disp_cp_chain_me =
9579 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
9580 : disp_cp_chain_me_to_slowEP;
florianebaf8d92012-04-22 17:38:46 +00009581 /* Get the address of the beginning of the load64 code sequence into %r1.
9582 Do not change the register! This is part of the protocol with the
9583 dispatcher. */
9584 buf = s390_emit_BASR(buf, 1, R0);
florian8844a632012-04-13 04:04:06 +00009585
florianebaf8d92012-04-22 17:38:46 +00009586 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
florian93a09742015-01-07 20:14:48 +00009587 Addr64 addr = (Addr)disp_cp_chain_me;
florian8844a632012-04-13 04:04:06 +00009588 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
9589
florianebaf8d92012-04-22 17:38:46 +00009590 /* goto *tchain_scratch */
9591 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00009592
9593 /* --- END of PATCHABLE BYTES --- */
9594
9595 /* Fix up the conditional jump, if there was one. */
9596 if (cond != S390_CC_ALWAYS) {
9597 Int delta = buf - ptmp;
9598
9599 delta >>= 1; /* immediate constant is #half-words */
9600 vassert(delta > 0 && delta < (1 << 16));
9601 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9602 }
9603
9604 return buf;
9605}
9606
9607/* Return the number of patchable bytes from an xdirect insn. */
9608static UInt
9609s390_xdirect_patchable_len(void)
9610{
florianebaf8d92012-04-22 17:38:46 +00009611 return s390_tchain_load64_len() + S390_BASR_LEN;
florian8844a632012-04-13 04:04:06 +00009612}
9613
9614
9615static UChar *
florian8462d112014-09-24 15:18:09 +00009616s390_insn_xindir_emit(UChar *buf, const s390_insn *insn,
9617 const void *disp_cp_xindir)
florian8844a632012-04-13 04:04:06 +00009618{
9619 /* We're generating transfers that could lead indirectly to a
9620 chain-me, so we need to be sure this is actually allowed --
9621 no-redir translations are not allowed to reach normal
9622 translations without going through the scheduler. That means
9623 no XDirects or XIndirs out from no-redir translations.
9624 Hence: */
9625 vassert(disp_cp_xindir != NULL);
9626
9627 /* Use ptmp for backpatching conditional jumps. */
9628 UChar *ptmp = buf;
9629
9630 /* First off, if this is conditional, create a conditional
9631 jump over the rest of it. */
9632 s390_cc_t cond = insn->variant.xdirect.cond;
9633
9634 if (cond != S390_CC_ALWAYS) {
9635 /* So we have something like this
9636 if (cond) do_xdirect;
9637 Y: ...
9638 We convert this into
9639 if (! cond) goto Y; // BRC opcode; 4 bytes
9640 do_xdirect;
9641 Y:
9642 */
9643 /* 4 bytes (a BRC insn) to be filled in here */
9644 buf += 4;
9645 }
9646
9647 /* Update the guest IA with the address in xdirect.dst. */
florian7346c7a2012-04-13 21:14:24 +00009648 const s390_amode *amode = insn->variant.xindir.guest_IA;
florian8844a632012-04-13 04:04:06 +00009649
florianbf516d12012-04-21 15:53:13 +00009650 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009651 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009652 UInt d = amode->d;
florian7346c7a2012-04-13 21:14:24 +00009653 UInt regno = hregNumber(insn->variant.xindir.dst);
florian8844a632012-04-13 04:04:06 +00009654
florianbf516d12012-04-21 15:53:13 +00009655 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009656
9657 /* load tchain_scratch, #disp_indir */
9658 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
florian93a09742015-01-07 20:14:48 +00009659 (Addr)disp_cp_xindir);
florianebaf8d92012-04-22 17:38:46 +00009660 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00009661 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9662
9663 /* Fix up the conditional jump, if there was one. */
9664 if (cond != S390_CC_ALWAYS) {
9665 Int delta = buf - ptmp;
9666
9667 delta >>= 1; /* immediate constant is #half-words */
9668 vassert(delta > 0 && delta < (1 << 16));
9669 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9670 }
9671
9672 return buf;
9673}
9674
9675static UChar *
9676s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
florian8462d112014-09-24 15:18:09 +00009677 const void *disp_cp_xassisted)
florian8844a632012-04-13 04:04:06 +00009678{
9679 /* Use ptmp for backpatching conditional jumps. */
9680 UChar *ptmp = buf;
9681
9682 /* First off, if this is conditional, create a conditional
9683 jump over the rest of it. */
9684 s390_cc_t cond = insn->variant.xdirect.cond;
9685
9686 if (cond != S390_CC_ALWAYS) {
9687 /* So we have something like this
9688 if (cond) do_xdirect;
9689 Y: ...
9690 We convert this into
9691 if (! cond) goto Y; // BRC opcode; 4 bytes
9692 do_xdirect;
9693 Y:
9694 */
9695 /* 4 bytes (a BRC insn) to be filled in here */
9696 buf += 4;
9697 }
9698
9699 /* Update the guest IA with the address in xassisted.dst. */
9700 const s390_amode *amode = insn->variant.xassisted.guest_IA;
9701
florianbf516d12012-04-21 15:53:13 +00009702 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009703 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009704 UInt d = amode->d;
9705 UInt regno = hregNumber(insn->variant.xassisted.dst);
9706
florianbf516d12012-04-21 15:53:13 +00009707 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009708
9709 UInt trcval = 0;
9710
9711 switch (insn->variant.xassisted.kind) {
9712 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
9713 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
florian8844a632012-04-13 04:04:06 +00009714 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
9715 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
florian4e0083e2012-08-26 03:41:56 +00009716 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
florian8844a632012-04-13 04:04:06 +00009717 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
9718 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
sewardj05f5e012014-05-04 10:52:11 +00009719 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
florian8844a632012-04-13 04:04:06 +00009720 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
9721 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
9722 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
9723 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
9724 /* We don't expect to see the following being assisted. */
9725 case Ijk_Ret:
9726 case Ijk_Call:
9727 /* fallthrough */
9728 default:
9729 ppIRJumpKind(insn->variant.xassisted.kind);
9730 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
9731 }
9732
9733 vassert(trcval != 0);
9734
9735 /* guest_state_pointer = trcval */
9736 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
9737
9738 /* load tchain_scratch, #disp_assisted */
9739 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
florian93a09742015-01-07 20:14:48 +00009740 (Addr)disp_cp_xassisted);
florian8844a632012-04-13 04:04:06 +00009741
florianebaf8d92012-04-22 17:38:46 +00009742 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00009743 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9744
9745 /* Fix up the conditional jump, if there was one. */
9746 if (cond != S390_CC_ALWAYS) {
9747 Int delta = buf - ptmp;
9748
9749 delta >>= 1; /* immediate constant is #half-words */
9750 vassert(delta > 0 && delta < (1 << 16));
9751 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9752 }
9753
9754 return buf;
9755}
9756
9757
9758/* Pseudo code:
9759
9760 guest_state[host_EvC_COUNTER] -= 1;
9761 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
9762 goto guest_state[host_EvC_FAILADDR];
9763 nofail: ;
9764
9765 The dispatch counter is a 32-bit value. */
9766static UChar *
sewardj9b769162014-07-24 12:42:03 +00009767s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn,
9768 VexEndness endness_host)
florian8844a632012-04-13 04:04:06 +00009769{
9770 s390_amode *amode;
florianbf516d12012-04-21 15:53:13 +00009771 UInt b, d;
florian8844a632012-04-13 04:04:06 +00009772 UChar *code_begin, *code_end;
9773
9774 code_begin = buf;
9775
9776 amode = insn->variant.evcheck.counter;
florianbf516d12012-04-21 15:53:13 +00009777 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009778 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009779 d = amode->d;
9780
9781 /* Decrement the dispatch counter in the guest state */
florian0e047d62012-04-21 16:06:04 +00009782 if (s390_host_has_gie) {
9783 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
9784 } else {
9785 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
9786 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
9787 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
9788 }
florian8844a632012-04-13 04:04:06 +00009789
9790 /* Jump over the next insn if >= 0 */
9791 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
9792
9793 /* Computed goto to fail_address */
9794 amode = insn->variant.evcheck.fail_addr;
9795 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009796 d = amode->d;
florianbf516d12012-04-21 15:53:13 +00009797 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
florian8844a632012-04-13 04:04:06 +00009798 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
9799
9800 code_end = buf;
9801
9802 /* Make sure the size of the generated code is identical to the size
9803 returned by evCheckSzB_S390 */
florian7ce2cc82015-01-10 16:10:58 +00009804 vassert(evCheckSzB_S390() == code_end - code_begin);
florian8844a632012-04-13 04:04:06 +00009805
9806 return buf;
9807}
9808
9809
9810static UChar *
9811s390_insn_profinc_emit(UChar *buf,
9812 const s390_insn *insn __attribute__((unused)))
9813{
9814 /* Generate a code template to increment a memory location whose
9815 address will be known later as an immediate value. This code
9816 template will be patched once the memory location is known.
9817 For now we do this with address == 0. */
9818 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
florian0e047d62012-04-21 16:06:04 +00009819 if (s390_host_has_gie) {
9820 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9821 } else {
9822 buf = s390_emit_LGHI(buf, R0, 1);
9823 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9824 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9825 }
florian8844a632012-04-13 04:04:06 +00009826
9827 return buf;
9828}
9829
9830
sewardj2019a972011-03-07 16:04:07 +00009831Int
floriand8c64e02014-10-08 08:54:44 +00009832emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn,
sewardj9b769162014-07-24 12:42:03 +00009833 Bool mode64, VexEndness endness_host,
florian8462d112014-09-24 15:18:09 +00009834 const void *disp_cp_chain_me_to_slowEP,
9835 const void *disp_cp_chain_me_to_fastEP,
9836 const void *disp_cp_xindir,
9837 const void *disp_cp_xassisted)
sewardj2019a972011-03-07 16:04:07 +00009838{
9839 UChar *end;
9840
florianc4aa7ed2012-12-22 15:01:04 +00009841 /* Used to be 48 bytes. Make sure it stays low */
9842 vassert(sizeof(s390_insn) == 32);
9843
sewardj2019a972011-03-07 16:04:07 +00009844 switch (insn->tag) {
9845 case S390_INSN_LOAD:
9846 end = s390_insn_load_emit(buf, insn);
9847 break;
9848
9849 case S390_INSN_STORE:
9850 end = s390_insn_store_emit(buf, insn);
9851 break;
9852
9853 case S390_INSN_MOVE:
9854 end = s390_insn_move_emit(buf, insn);
9855 break;
9856
floriancec3a8a2013-02-02 00:16:58 +00009857 case S390_INSN_MEMCPY:
9858 end = s390_insn_memcpy_emit(buf, insn);
9859 break;
9860
sewardj2019a972011-03-07 16:04:07 +00009861 case S390_INSN_COND_MOVE:
9862 end = s390_insn_cond_move_emit(buf, insn);
9863 break;
9864
9865 case S390_INSN_LOAD_IMMEDIATE:
9866 end = s390_insn_load_immediate_emit(buf, insn);
9867 break;
9868
9869 case S390_INSN_ALU:
9870 end = s390_insn_alu_emit(buf, insn);
9871 break;
9872
florianc4aa7ed2012-12-22 15:01:04 +00009873 case S390_INSN_SMUL:
9874 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +00009875 end = s390_insn_mul_emit(buf, insn);
9876 break;
9877
florianc4aa7ed2012-12-22 15:01:04 +00009878 case S390_INSN_SDIV:
9879 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +00009880 end = s390_insn_div_emit(buf, insn);
9881 break;
9882
9883 case S390_INSN_DIVS:
9884 end = s390_insn_divs_emit(buf, insn);
9885 break;
9886
sewardj611b06e2011-03-24 08:57:29 +00009887 case S390_INSN_CLZ:
9888 end = s390_insn_clz_emit(buf, insn);
sewardj2019a972011-03-07 16:04:07 +00009889 break;
9890
9891 case S390_INSN_UNOP:
9892 end = s390_insn_unop_emit(buf, insn);
9893 break;
9894
9895 case S390_INSN_TEST:
9896 end = s390_insn_test_emit(buf, insn);
9897 break;
9898
9899 case S390_INSN_CC2BOOL:
9900 end = s390_insn_cc2bool_emit(buf, insn);
9901 break;
9902
9903 case S390_INSN_CAS:
9904 end = s390_insn_cas_emit(buf, insn);
9905 break;
9906
florian448cbba2012-06-06 02:26:01 +00009907 case S390_INSN_CDAS:
9908 end = s390_insn_cdas_emit(buf, insn);
9909 break;
9910
sewardj2019a972011-03-07 16:04:07 +00009911 case S390_INSN_COMPARE:
9912 end = s390_insn_compare_emit(buf, insn);
9913 break;
9914
sewardj2019a972011-03-07 16:04:07 +00009915 case S390_INSN_HELPER_CALL:
9916 end = s390_insn_helper_call_emit(buf, insn);
sewardjcfe046e2013-01-17 14:23:53 +00009917 if (end == buf) goto fail;
sewardj2019a972011-03-07 16:04:07 +00009918 break;
9919
9920 case S390_INSN_BFP_TRIOP:
9921 end = s390_insn_bfp_triop_emit(buf, insn);
9922 break;
9923
9924 case S390_INSN_BFP_BINOP:
9925 end = s390_insn_bfp_binop_emit(buf, insn);
9926 break;
9927
9928 case S390_INSN_BFP_UNOP:
9929 end = s390_insn_bfp_unop_emit(buf, insn);
9930 break;
9931
9932 case S390_INSN_BFP_COMPARE:
9933 end = s390_insn_bfp_compare_emit(buf, insn);
9934 break;
9935
florian9fcff4c2012-09-10 03:09:04 +00009936 case S390_INSN_BFP_CONVERT:
9937 end = s390_insn_bfp_convert_emit(buf, insn);
9938 break;
9939
florian12390202012-11-10 22:34:14 +00009940 case S390_INSN_DFP_BINOP:
9941 end = s390_insn_dfp_binop_emit(buf, insn);
9942 break;
9943
floriance9e3db2012-12-27 20:14:03 +00009944 case S390_INSN_DFP_UNOP:
9945 end = s390_insn_dfp_unop_emit(buf, insn);
9946 break;
9947
florian1b901d42013-01-01 22:19:24 +00009948 case S390_INSN_DFP_INTOP:
9949 end = s390_insn_dfp_intop_emit(buf, insn);
9950 break;
9951
floriane38f6412012-12-21 17:32:12 +00009952 case S390_INSN_DFP_COMPARE:
9953 end = s390_insn_dfp_compare_emit(buf, insn);
9954 break;
9955
9956 case S390_INSN_DFP_CONVERT:
9957 end = s390_insn_dfp_convert_emit(buf, insn);
9958 break;
9959
florian5c539732013-02-14 14:27:12 +00009960 case S390_INSN_DFP_REROUND:
9961 end = s390_insn_dfp_reround_emit(buf, insn);
9962 break;
9963
florian78d5ef72013-05-11 15:02:58 +00009964 case S390_INSN_FP_CONVERT:
9965 end = s390_insn_fp_convert_emit(buf, insn);
9966 break;
9967
sewardja52e37e2011-04-28 18:48:06 +00009968 case S390_INSN_MFENCE:
9969 end = s390_insn_mfence_emit(buf, insn);
9970 break;
9971
florianb93348d2012-12-27 00:59:43 +00009972 case S390_INSN_MIMM:
9973 end = s390_insn_mimm_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +00009974 break;
9975
florianf85fe3e2012-12-22 02:28:25 +00009976 case S390_INSN_MADD:
9977 end = s390_insn_madd_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +00009978 break;
9979
florian125e20d2012-10-07 15:42:37 +00009980 case S390_INSN_SET_FPC_BFPRM:
9981 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
florian2c74d242012-09-12 19:38:42 +00009982 break;
9983
florianc8e4f562012-10-27 16:19:31 +00009984 case S390_INSN_SET_FPC_DFPRM:
9985 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
9986 break;
9987
florian8844a632012-04-13 04:04:06 +00009988 case S390_INSN_PROFINC:
9989 end = s390_insn_profinc_emit(buf, insn);
9990 /* Tell the caller .. */
9991 vassert(*is_profinc == False);
9992 *is_profinc = True;
9993 break;
9994
9995 case S390_INSN_EVCHECK:
sewardj9b769162014-07-24 12:42:03 +00009996 end = s390_insn_evcheck_emit(buf, insn, endness_host);
florian8844a632012-04-13 04:04:06 +00009997 break;
9998
9999 case S390_INSN_XDIRECT:
10000 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
10001 disp_cp_chain_me_to_fastEP);
10002 break;
10003
10004 case S390_INSN_XINDIR:
10005 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
10006 break;
10007
10008 case S390_INSN_XASSISTED:
10009 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
10010 break;
10011
sewardjcfe046e2013-01-17 14:23:53 +000010012 fail:
sewardj2019a972011-03-07 16:04:07 +000010013 default:
florian616458b2012-03-25 16:17:18 +000010014 vpanic("emit_S390Instr");
sewardj2019a972011-03-07 16:04:07 +000010015 }
10016
10017 vassert(end - buf <= nbuf);
10018
10019 return end - buf;
10020}
10021
10022
florian8844a632012-04-13 04:04:06 +000010023/* Return the number of bytes emitted for an S390_INSN_EVCHECK.
10024 See s390_insn_evcheck_emit */
10025Int
florian7ce2cc82015-01-10 16:10:58 +000010026evCheckSzB_S390(void)
florian8844a632012-04-13 04:04:06 +000010027{
florian0e047d62012-04-21 16:06:04 +000010028 return s390_host_has_gie ? 18 : 24;
florian8844a632012-04-13 04:04:06 +000010029}
10030
10031
10032/* Patch the counter address into CODE_TO_PATCH as previously
10033 generated by s390_insn_profinc_emit. */
10034VexInvalRange
sewardj9b769162014-07-24 12:42:03 +000010035patchProfInc_S390(VexEndness endness_host,
florian7d6f81d2014-09-22 21:43:37 +000010036 void *code_to_patch, const ULong *location_of_counter)
florian8844a632012-04-13 04:04:06 +000010037{
10038 vassert(sizeof(ULong *) == 8);
10039
10040 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
10041
florian5ea257b2012-09-29 17:05:46 +000010042 UChar *p = s390_tchain_patch_load64(code_to_patch,
florian93a09742015-01-07 20:14:48 +000010043 (Addr)location_of_counter);
florian8844a632012-04-13 04:04:06 +000010044
florian5ea257b2012-09-29 17:05:46 +000010045 UInt len = p - (UChar *)code_to_patch;
10046 VexInvalRange vir = { (HWord)code_to_patch, len };
florian8844a632012-04-13 04:04:06 +000010047 return vir;
10048}
10049
10050
10051/* NB: what goes on here has to be very closely coordinated with the
10052 s390_insn_xdirect_emit code above. */
10053VexInvalRange
sewardj9b769162014-07-24 12:42:03 +000010054chainXDirect_S390(VexEndness endness_host,
10055 void *place_to_chain,
florian7d6f81d2014-09-22 21:43:37 +000010056 const void *disp_cp_chain_me_EXPECTED,
10057 const void *place_to_jump_to)
florian8844a632012-04-13 04:04:06 +000010058{
sewardj9b769162014-07-24 12:42:03 +000010059 vassert(endness_host == VexEndnessBE);
10060
florianebaf8d92012-04-22 17:38:46 +000010061 /* What we're expecting to see @ PLACE_TO_CHAIN is:
florian8844a632012-04-13 04:04:06 +000010062
florianebaf8d92012-04-22 17:38:46 +000010063 load tchain_scratch, #disp_cp_chain_me_EXPECTED
10064 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010065 */
10066 const UChar *next;
10067 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
florian93a09742015-01-07 20:14:48 +000010068 (Addr)disp_cp_chain_me_EXPECTED);
florianebaf8d92012-04-22 17:38:46 +000010069 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +000010070
10071 /* And what we want to change it to is either:
10072 (general case):
10073
florianebaf8d92012-04-22 17:38:46 +000010074 load tchain_scratch, #place_to_jump_to
10075 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010076
10077 ---OR---
10078
10079 in the case where the displacement is small enough
10080
10081 BRCL delta where delta is in half-words
10082 invalid opcodes
10083
10084 In both cases the replacement has the same length as the original.
10085 To remain sane & verifiable,
10086 (1) limit the displacement for the short form to
10087 (say) +/- one billion, so as to avoid wraparound
10088 off-by-ones
10089 (2) even if the short form is applicable, once every (say)
10090 1024 times use the long form anyway, so as to maintain
10091 verifiability
10092 */
10093
10094 /* This is the delta we need to put into a BRCL insn. Note, that the
10095 offset in BRCL is in half-words. Hence division by 2. */
florian7d6f81d2014-09-22 21:43:37 +000010096 Long delta =
10097 (Long)((const UChar *)place_to_jump_to - (const UChar *)place_to_chain) / 2;
florian8844a632012-04-13 04:04:06 +000010098 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
10099
10100 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
10101 if (shortOK) {
10102 shortCTR++; // thread safety bleh
10103 if (0 == (shortCTR & 0x3FF)) {
10104 shortOK = False;
10105 if (0)
10106 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
10107 "using long jmp\n", shortCTR);
10108 }
10109 }
10110
10111 /* And make the modifications. */
10112 UChar *p = (UChar *)place_to_chain;
10113 if (shortOK) {
10114 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
10115
florian48cb9612012-04-20 02:50:28 +000010116 /* Make sure that BRCL fits into the patchable part of an xdirect
florian1c857042012-04-15 04:11:07 +000010117 code sequence */
florian48cb9612012-04-20 02:50:28 +000010118 vassert(6 <= s390_xdirect_patchable_len());
florian1c857042012-04-15 04:11:07 +000010119
florian8844a632012-04-13 04:04:06 +000010120 /* Fill remaining bytes with 0x00 (invalid opcode) */
10121 Int i;
10122 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
10123 p[i] = 0x00;
10124 } else {
florian1c857042012-04-15 04:11:07 +000010125 /*
florianebaf8d92012-04-22 17:38:46 +000010126 load tchain_scratch, #place_to_jump_to
10127 goto *tchain_scratch
florian1c857042012-04-15 04:11:07 +000010128 */
florian93a09742015-01-07 20:14:48 +000010129 Addr64 addr = (Addr)place_to_jump_to;
florian1c857042012-04-15 04:11:07 +000010130 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +000010131 /* There is not need to emit a BCR here, as it is already there. */
florian8844a632012-04-13 04:04:06 +000010132 }
10133
florian5ea257b2012-09-29 17:05:46 +000010134 UInt len = p - (UChar *)place_to_chain;
10135 VexInvalRange vir = { (HWord)place_to_chain, len };
florian8844a632012-04-13 04:04:06 +000010136 return vir;
10137}
10138
10139
10140/* NB: what goes on here has to be very closely coordinated with the
10141 s390_insn_xdirect_emit code above. */
10142VexInvalRange
sewardj9b769162014-07-24 12:42:03 +000010143unchainXDirect_S390(VexEndness endness_host,
10144 void *place_to_unchain,
florian7d6f81d2014-09-22 21:43:37 +000010145 const void *place_to_jump_to_EXPECTED,
10146 const void *disp_cp_chain_me)
florian8844a632012-04-13 04:04:06 +000010147{
sewardj9b769162014-07-24 12:42:03 +000010148 vassert(endness_host == VexEndnessBE);
10149
florian8844a632012-04-13 04:04:06 +000010150 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
10151
florianebaf8d92012-04-22 17:38:46 +000010152 load tchain_scratch, #place_to_jump_to_EXPECTED
10153 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010154
10155 ---OR---
10156 in the case where the displacement falls within 32 bits
10157
10158 BRCL delta
10159 invalid opcodes
10160 */
10161 UChar *p = place_to_unchain;
florian1c857042012-04-15 04:11:07 +000010162
florianebaf8d92012-04-22 17:38:46 +000010163 Bool uses_short_form = False;
10164
florian1c857042012-04-15 04:11:07 +000010165 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
florian8844a632012-04-13 04:04:06 +000010166 /* Looks like the short form */
10167 Int num_hw = *(Int *)&p[2];
10168 Int delta = 2 *num_hw;
10169
10170 vassert(p + delta == place_to_jump_to_EXPECTED);
10171
florian8844a632012-04-13 04:04:06 +000010172 Int i;
10173 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
florian1c857042012-04-15 04:11:07 +000010174 vassert(p[6+i] == 0x00);
florianebaf8d92012-04-22 17:38:46 +000010175 uses_short_form = True;
florian8844a632012-04-13 04:04:06 +000010176 } else {
10177 /* Should be the long form */
10178 const UChar *next;
10179
10180 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
florian93a09742015-01-07 20:14:48 +000010181 (Addr)place_to_jump_to_EXPECTED);
florian8844a632012-04-13 04:04:06 +000010182 /* Check for BR *tchain_scratch */
florian1c857042012-04-15 04:11:07 +000010183 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +000010184 }
10185
10186 /* And what we want to change it to is:
10187
10188 load tchain_scratch, #disp_cp_chain_me
florianebaf8d92012-04-22 17:38:46 +000010189 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010190 */
florianebaf8d92012-04-22 17:38:46 +000010191
10192 /* Get the address of the beginning of the load64 code sequence into %r1.
10193 Do not change the register! This is part of the protocol with the
10194 dispatcher.
10195 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
10196 load64 insn sequence. That sequence is prefixed with a BASR to get its
10197 address (see s390_insn_xdirect_emit). */
10198 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
10199
florian93a09742015-01-07 20:14:48 +000010200 Addr64 addr = (Addr)disp_cp_chain_me;
florian8844a632012-04-13 04:04:06 +000010201 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +000010202
10203 /* Emit the BCR in case the short form was used. In case of the long
10204 form, the BCR is already there. */
10205 if (uses_short_form)
10206 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +000010207
florian5ea257b2012-09-29 17:05:46 +000010208 UInt len = p - (UChar *)place_to_unchain;
10209 VexInvalRange vir = { (HWord)place_to_unchain, len };
florian8844a632012-04-13 04:04:06 +000010210 return vir;
10211}
10212
sewardj2019a972011-03-07 16:04:07 +000010213/*---------------------------------------------------------------*/
10214/*--- end host_s390_defs.c ---*/
10215/*---------------------------------------------------------------*/