blob: adea62e7402a5208c8cf20b365c735163840f8b1 [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
florian61f23c12012-08-06 18:33:21 +000011 Copyright IBM Corp. 2010-2012
florian2c74d242012-09-12 19:38:42 +000012 Copyright (C) 2012-2012 Florian Krohm (britzel@acm.org)
sewardj2019a972011-03-07 16:04:07 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 02110-1301, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32/* Contributed by Florian Krohm */
33
34#include "libvex_basictypes.h"
35#include "libvex.h"
36#include "libvex_trc_values.h"
sewardj2019a972011-03-07 16:04:07 +000037#include "libvex_s390x_common.h"
38
39#include "main_util.h"
40#include "main_globals.h"
41#include "host_generic_regs.h"
42#include "host_s390_defs.h"
florian79af5752012-09-20 01:22:10 +000043#include "s390_disasm.h"
florian428dfdd2012-03-27 03:09:49 +000044#include "guest_s390_defs.h" /* S390X_GUEST_OFFSET */
sewardj2019a972011-03-07 16:04:07 +000045#include <stdarg.h>
46
47/* KLUDGE: We need to know the hwcaps of the host when generating
48 code. But that info is not passed to emit_S390Instr. Only mode64 is
49 being passed. So, ideally, we want this passed as an argument, too.
50 Until then, we use a global variable. This variable is set as a side
51 effect of iselSB_S390. This is safe because instructions are selected
52 before they are emitted. */
florianf26994a2012-04-21 03:34:54 +000053UInt s390_host_hwcaps;
sewardj2019a972011-03-07 16:04:07 +000054
florianb4df7682011-07-05 02:09:01 +000055
56/*------------------------------------------------------------*/
57/*--- Forward declarations ---*/
58/*------------------------------------------------------------*/
59
60static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
61static void s390_insn_map_regs(HRegRemap *, s390_insn *);
62static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
florian1c857042012-04-15 04:11:07 +000063static UInt s390_tchain_load64_len(void);
florianb4df7682011-07-05 02:09:01 +000064
65
sewardj2019a972011-03-07 16:04:07 +000066/*------------------------------------------------------------*/
67/*--- Registers ---*/
68/*------------------------------------------------------------*/
69
70/* Decompile the given register into a static buffer and return it */
71const HChar *
72s390_hreg_as_string(HReg reg)
73{
74 static HChar buf[10];
75
76 static const HChar ireg_names[16][5] = {
77 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
78 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
79 };
80
81 static const HChar freg_names[16][5] = {
82 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
83 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
84 };
85
86 UInt r; /* hregNumber() returns an UInt */
87
88 r = hregNumber(reg);
89
90 /* Be generic for all virtual regs. */
91 if (hregIsVirtual(reg)) {
92 buf[0] = '\0';
93 switch (hregClass(reg)) {
94 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
95 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
96 default: goto fail;
97 }
98 return buf;
99 }
100
101 /* But specific for real regs. */
102 vassert(r < 16);
103
104 switch (hregClass(reg)) {
105 case HRcInt64: return ireg_names[r];
106 case HRcFlt64: return freg_names[r];
107 default: goto fail;
108 }
109
110 fail: vpanic("s390_hreg_as_string");
111}
112
113
114/* Tell the register allocator which registers can be allocated. */
florianb4df7682011-07-05 02:09:01 +0000115static void
sewardj2019a972011-03-07 16:04:07 +0000116s390_hreg_get_allocable(Int *nregs, HReg **arr)
117{
118 UInt i;
119
120 /* Total number of allocable registers (all classes) */
121 *nregs = 16 /* GPRs */
122 - 1 /* r0 */
florian8844a632012-04-13 04:04:06 +0000123 - 1 /* r12 scratch register for translation chaining support */
sewardj2019a972011-03-07 16:04:07 +0000124 - 1 /* r13 guest state pointer */
125 - 1 /* r14 link register */
126 - 1 /* r15 stack pointer */
127 + 16 /* FPRs */
128 ;
129
130 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
131
132 i = 0;
133
134 /* GPR0 is not available because it is interpreted as 0, when used
135 as a base or index register. */
136 (*arr)[i++] = mkHReg(1, HRcInt64, False);
137 (*arr)[i++] = mkHReg(2, HRcInt64, False);
138 (*arr)[i++] = mkHReg(3, HRcInt64, False);
139 (*arr)[i++] = mkHReg(4, HRcInt64, False);
140 (*arr)[i++] = mkHReg(5, HRcInt64, False);
141 (*arr)[i++] = mkHReg(6, HRcInt64, False);
142 (*arr)[i++] = mkHReg(7, HRcInt64, False);
143 (*arr)[i++] = mkHReg(8, HRcInt64, False);
144 (*arr)[i++] = mkHReg(9, HRcInt64, False);
145 /* GPR10 and GPR11 are used for instructions that use register pairs.
146 Otherwise, they are available to the allocator */
147 (*arr)[i++] = mkHReg(10, HRcInt64, False);
148 (*arr)[i++] = mkHReg(11, HRcInt64, False);
florian8844a632012-04-13 04:04:06 +0000149 /* GPR12 is not available because it us used as a scratch register
150 in translation chaining. */
sewardj2019a972011-03-07 16:04:07 +0000151 /* GPR13 is not available because it is used as guest state pointer */
152 /* GPR14 is not available because it is used as link register */
153 /* GPR15 is not available because it is used as stack pointer */
154
155 /* Add the available real (non-virtual) FPRs */
156 (*arr)[i++] = mkHReg(0, HRcFlt64, False);
157 (*arr)[i++] = mkHReg(1, HRcFlt64, False);
158 (*arr)[i++] = mkHReg(2, HRcFlt64, False);
159 (*arr)[i++] = mkHReg(3, HRcFlt64, False);
160 (*arr)[i++] = mkHReg(4, HRcFlt64, False);
161 (*arr)[i++] = mkHReg(5, HRcFlt64, False);
162 (*arr)[i++] = mkHReg(6, HRcFlt64, False);
163 (*arr)[i++] = mkHReg(7, HRcFlt64, False);
164 (*arr)[i++] = mkHReg(8, HRcFlt64, False);
165 (*arr)[i++] = mkHReg(9, HRcFlt64, False);
166 (*arr)[i++] = mkHReg(10, HRcFlt64, False);
167 (*arr)[i++] = mkHReg(11, HRcFlt64, False);
168 (*arr)[i++] = mkHReg(12, HRcFlt64, False);
169 (*arr)[i++] = mkHReg(13, HRcFlt64, False);
170 (*arr)[i++] = mkHReg(14, HRcFlt64, False);
171 (*arr)[i++] = mkHReg(15, HRcFlt64, False);
172 /* FPR12 - FPR15 are also used as register pairs for 128-bit
173 floating point operations */
174}
175
176
177/* Return the real register that holds the guest state pointer */
178HReg
179s390_hreg_guest_state_pointer(void)
180{
181 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
182}
183
florian8844a632012-04-13 04:04:06 +0000184
sewardj2019a972011-03-07 16:04:07 +0000185/* Is VALUE within the domain of a 20-bit signed integer. */
186static __inline__ Bool
187fits_signed_20bit(Int value)
188{
189 return ((value << 12) >> 12) == value;
190}
191
192
193/* Is VALUE within the domain of a 12-bit unsigned integer. */
194static __inline__ Bool
195fits_unsigned_12bit(Int value)
196{
197 return (value & 0xFFF) == value;
198}
199
200/*------------------------------------------------------------*/
201/*--- Addressing modes (amodes) ---*/
202/*------------------------------------------------------------*/
203
204/* Construct a b12 amode. */
205s390_amode *
206s390_amode_b12(Int d, HReg b)
207{
208 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
209
210 vassert(fits_unsigned_12bit(d));
211
212 am->tag = S390_AMODE_B12;
213 am->d = d;
214 am->b = b;
215 am->x = 0; /* hregNumber(0) == 0 */
216
217 return am;
218}
219
220
221/* Construct a b20 amode. */
222s390_amode *
223s390_amode_b20(Int d, HReg b)
224{
225 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
226
227 vassert(fits_signed_20bit(d));
228
229 am->tag = S390_AMODE_B20;
230 am->d = d;
231 am->b = b;
232 am->x = 0; /* hregNumber(0) == 0 */
233
234 return am;
235}
236
237
238/* Construct a bx12 amode. */
239s390_amode *
240s390_amode_bx12(Int d, HReg b, HReg x)
241{
242 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
243
244 vassert(fits_unsigned_12bit(d));
245 vassert(b != 0);
246 vassert(x != 0);
247
248 am->tag = S390_AMODE_BX12;
249 am->d = d;
250 am->b = b;
251 am->x = x;
252
253 return am;
254}
255
256
257/* Construct a bx20 amode. */
258s390_amode *
259s390_amode_bx20(Int d, HReg b, HReg x)
260{
261 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
262
263 vassert(fits_signed_20bit(d));
264 vassert(b != 0);
265 vassert(x != 0);
266
267 am->tag = S390_AMODE_BX20;
268 am->d = d;
269 am->b = b;
270 am->x = x;
271
272 return am;
273}
274
275
276/* Construct an AMODE for accessing the guest state at OFFSET */
277s390_amode *
278s390_amode_for_guest_state(Int offset)
279{
280 if (fits_unsigned_12bit(offset))
281 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
sewardj2019a972011-03-07 16:04:07 +0000282
283 vpanic("invalid guest state offset");
284}
285
286
287/* Decompile the given amode into a static buffer and return it. */
288const HChar *
289s390_amode_as_string(const s390_amode *am)
290{
291 static HChar buf[30];
292 HChar *p;
293
294 buf[0] = '\0';
295 p = buf;
296
297 switch (am->tag) {
298 case S390_AMODE_B12:
299 case S390_AMODE_B20:
300 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
301 break;
302
303 case S390_AMODE_BX12:
304 case S390_AMODE_BX20:
305 /* s390_hreg_as_string returns pointer to local buffer. Need to
306 split this into two printfs */
307 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
308 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
309 break;
310
311 default:
312 vpanic("s390_amode_as_string");
313 }
314
315 return buf;
316}
317
318
319/* Helper function for s390_amode_is_sane */
320static __inline__ Bool
321is_virtual_gpr(HReg reg)
322{
323 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
324}
325
326
327/* Sanity check for an amode */
328Bool
329s390_amode_is_sane(const s390_amode *am)
330{
331 switch (am->tag) {
332 case S390_AMODE_B12:
333 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
334
335 case S390_AMODE_B20:
336 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
337
338 case S390_AMODE_BX12:
339 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
340 fits_unsigned_12bit(am->d);
341
342 case S390_AMODE_BX20:
343 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
344 fits_signed_20bit(am->d);
345
346 default:
347 vpanic("s390_amode_is_sane");
348 }
349}
350
351
352/* Record the register use of an amode */
florianb4df7682011-07-05 02:09:01 +0000353static void
sewardj2019a972011-03-07 16:04:07 +0000354s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
355{
356 switch (am->tag) {
357 case S390_AMODE_B12:
358 case S390_AMODE_B20:
359 addHRegUse(u, HRmRead, am->b);
360 return;
361
362 case S390_AMODE_BX12:
363 case S390_AMODE_BX20:
364 addHRegUse(u, HRmRead, am->b);
365 addHRegUse(u, HRmRead, am->x);
366 return;
367
368 default:
369 vpanic("s390_amode_get_reg_usage");
370 }
371}
372
373
florianb4df7682011-07-05 02:09:01 +0000374static void
sewardj2019a972011-03-07 16:04:07 +0000375s390_amode_map_regs(HRegRemap *m, s390_amode *am)
376{
377 switch (am->tag) {
378 case S390_AMODE_B12:
379 case S390_AMODE_B20:
380 am->b = lookupHRegRemap(m, am->b);
381 return;
382
383 case S390_AMODE_BX12:
384 case S390_AMODE_BX20:
385 am->b = lookupHRegRemap(m, am->b);
386 am->x = lookupHRegRemap(m, am->x);
387 return;
388
389 default:
390 vpanic("s390_amode_map_regs");
391 }
392}
393
394
sewardj2019a972011-03-07 16:04:07 +0000395void
florianb4df7682011-07-05 02:09:01 +0000396ppS390AMode(s390_amode *am)
sewardj2019a972011-03-07 16:04:07 +0000397{
398 vex_printf("%s", s390_amode_as_string(am));
399}
400
401void
florianb4df7682011-07-05 02:09:01 +0000402ppS390Instr(s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000403{
404 vex_printf("%s", s390_insn_as_string(insn));
405}
406
407void
408ppHRegS390(HReg reg)
409{
410 vex_printf("%s", s390_hreg_as_string(reg));
411}
412
413/*------------------------------------------------------------*/
414/*--- Helpers for register allocation ---*/
415/*------------------------------------------------------------*/
416
417/* Called once per translation. */
418void
419getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
420{
421 s390_hreg_get_allocable(nregs, arr);
422}
423
424
425/* Tell the register allocator how the given instruction uses the registers
426 it refers to. */
427void
florianb4df7682011-07-05 02:09:01 +0000428getRegUsage_S390Instr(HRegUsage *u, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000429{
430 s390_insn_get_reg_usage(u, insn);
431}
432
433
434/* Map the registers of the given instruction */
435void
florianb4df7682011-07-05 02:09:01 +0000436mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000437{
438 s390_insn_map_regs(m, insn);
439}
440
441
442/* Figure out if the given insn represents a reg-reg move, and if so
443 assign the source and destination to *src and *dst. If in doubt say No.
444 Used by the register allocator to do move coalescing. */
445Bool
florianb4df7682011-07-05 02:09:01 +0000446isMove_S390Instr(s390_insn *insn, HReg *src, HReg *dst)
sewardj2019a972011-03-07 16:04:07 +0000447{
448 return s390_insn_is_reg_reg_move(insn, src, dst);
449}
450
451
452/* Generate s390 spill/reload instructions under the direction of the
453 register allocator. Note it's critical these don't write the
454 condition codes. This is like an Ist_Put */
455void
456genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
457{
458 s390_amode *am;
459
460 vassert(offsetB >= 0);
461 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
462 vassert(!hregIsVirtual(rreg));
463
464 *i1 = *i2 = NULL;
465
466 am = s390_amode_for_guest_state(offsetB);
467
468 switch (hregClass(rreg)) {
469 case HRcInt64:
470 case HRcFlt64:
471 *i1 = s390_insn_store(8, am, rreg);
472 return;
473
474 default:
475 ppHRegClass(hregClass(rreg));
476 vpanic("genSpill_S390: unimplemented regclass");
477 }
478}
479
480
481/* This is like an Iex_Get */
482void
483genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
484{
485 s390_amode *am;
486
487 vassert(offsetB >= 0);
488 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
489 vassert(!hregIsVirtual(rreg));
490
491 *i1 = *i2 = NULL;
492
493 am = s390_amode_for_guest_state(offsetB);
494
495 switch (hregClass(rreg)) {
496 case HRcInt64:
497 case HRcFlt64:
498 *i1 = s390_insn_load(8, rreg, am);
499 return;
500
501 default:
502 ppHRegClass(hregClass(rreg));
503 vpanic("genReload_S390: unimplemented regclass");
504 }
505}
506
507/* Helper function for s390_insn_get_reg_usage */
508static void
509s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
510{
511 switch (op.tag) {
512 case S390_OPND_REG:
513 addHRegUse(u, HRmRead, op.variant.reg);
514 break;
515
516 case S390_OPND_AMODE:
517 s390_amode_get_reg_usage(u, op.variant.am);
518 break;
519
520 case S390_OPND_IMMEDIATE:
521 break;
522
523 default:
524 vpanic("s390_opnd_RMI_get_reg_usage");
525 }
526}
527
528
529/* Tell the register allocator how the given insn uses the registers */
florianb4df7682011-07-05 02:09:01 +0000530static void
sewardj2019a972011-03-07 16:04:07 +0000531s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
532{
533 initHRegUsage(u);
534
535 switch (insn->tag) {
536 case S390_INSN_LOAD:
537 addHRegUse(u, HRmWrite, insn->variant.load.dst);
538 s390_amode_get_reg_usage(u, insn->variant.load.src);
539 break;
540
541 case S390_INSN_LOAD_IMMEDIATE:
542 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
543 break;
544
545 case S390_INSN_STORE:
546 addHRegUse(u, HRmRead, insn->variant.store.src);
547 s390_amode_get_reg_usage(u, insn->variant.store.dst);
548 break;
549
550 case S390_INSN_MOVE:
551 addHRegUse(u, HRmRead, insn->variant.move.src);
552 addHRegUse(u, HRmWrite, insn->variant.move.dst);
553 break;
554
555 case S390_INSN_COND_MOVE:
556 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
557 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
558 break;
559
560 case S390_INSN_ALU:
561 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
562 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
563 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
564 break;
565
florianc4aa7ed2012-12-22 15:01:04 +0000566 case S390_INSN_SMUL:
567 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +0000568 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
569 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
570 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
571 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
572 break;
573
florianc4aa7ed2012-12-22 15:01:04 +0000574 case S390_INSN_SDIV:
575 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +0000576 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
577 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
578 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
579 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
580 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
581 break;
582
583 case S390_INSN_DIVS:
584 addHRegUse(u, HRmRead, insn->variant.divs.op1);
585 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
586 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
587 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
588 break;
589
sewardj611b06e2011-03-24 08:57:29 +0000590 case S390_INSN_CLZ:
591 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
592 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
593 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000594 break;
595
596 case S390_INSN_UNOP:
597 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
598 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
599 break;
600
601 case S390_INSN_TEST:
602 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
603 break;
604
605 case S390_INSN_CC2BOOL:
606 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
607 break;
608
609 case S390_INSN_CAS:
610 addHRegUse(u, HRmRead, insn->variant.cas.op1);
611 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
612 addHRegUse(u, HRmRead, insn->variant.cas.op3);
613 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
614 break;
615
florianc4aa7ed2012-12-22 15:01:04 +0000616 case S390_INSN_CDAS: {
617 s390_cdas *cdas = insn->variant.cdas.details;
618
619 addHRegUse(u, HRmRead, cdas->op1_high);
620 addHRegUse(u, HRmRead, cdas->op1_low);
621 s390_amode_get_reg_usage(u, cdas->op2);
622 addHRegUse(u, HRmRead, cdas->op3_high);
623 addHRegUse(u, HRmRead, cdas->op3_low);
624 addHRegUse(u, HRmWrite, cdas->old_mem_high);
625 addHRegUse(u, HRmWrite, cdas->old_mem_low);
626 addHRegUse(u, HRmWrite, cdas->scratch);
florian448cbba2012-06-06 02:26:01 +0000627 break;
florianc4aa7ed2012-12-22 15:01:04 +0000628 }
florian448cbba2012-06-06 02:26:01 +0000629
sewardj2019a972011-03-07 16:04:07 +0000630 case S390_INSN_COMPARE:
631 addHRegUse(u, HRmRead, insn->variant.compare.src1);
632 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
633 break;
634
sewardj2019a972011-03-07 16:04:07 +0000635 case S390_INSN_HELPER_CALL: {
636 UInt i;
637
638 /* Assume that all volatile registers are clobbered. ABI says,
639 volatile registers are: r0 - r5. Valgrind's register allocator
640 does not know about r0, so we can leave that out */
641 for (i = 1; i <= 5; ++i) {
642 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
643 }
florian01ed6e72012-05-27 16:52:43 +0000644 if (insn->variant.helper_call.dst != INVALID_HREG)
645 addHRegUse(u, HRmWrite, insn->variant.helper_call.dst);
sewardj2019a972011-03-07 16:04:07 +0000646
647 /* Ditto for floating point registers. f0 - f7 are volatile */
648 for (i = 0; i <= 7; ++i) {
649 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
650 }
651
652 /* The registers that are used for passing arguments will be read.
653 Not all of them may, but in general we need to assume that. */
654 for (i = 0; i < insn->variant.helper_call.num_args; ++i) {
655 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
656 HRcInt64, False));
657 }
658
659 /* s390_insn_helper_call_emit also reads / writes the link register
660 and stack pointer. But those registers are not visible to the
661 register allocator. So we don't need to do anything for them. */
662 break;
663 }
664
665 case S390_INSN_BFP_TRIOP:
666 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
667 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
668 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
669 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
670 break;
671
672 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000673 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_hi);
674 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_hi); /* left */
675 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_hi); /* right */
676 if (insn->size == 16) {
677 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_lo);
678 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_lo); /* left */
679 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_lo); /* right */
680 }
sewardj2019a972011-03-07 16:04:07 +0000681 break;
682
683 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +0000684 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi);
685 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_hi); /* operand */
686 if (insn->size == 16) {
687 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo);
688 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_lo); /* operand */
689 }
sewardj2019a972011-03-07 16:04:07 +0000690 break;
691
692 case S390_INSN_BFP_COMPARE:
693 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +0000694 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_hi); /* left */
695 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_hi); /* right */
696 if (insn->size == 16) {
697 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_lo); /* left */
698 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_lo); /* right */
699 }
sewardj2019a972011-03-07 16:04:07 +0000700 break;
701
florian9fcff4c2012-09-10 03:09:04 +0000702 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +0000703 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi);
704 if (insn->variant.bfp_convert.dst_lo != INVALID_HREG)
705 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo);
706 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_hi);
707 if (insn->variant.bfp_convert.op_lo != INVALID_HREG)
708 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +0000709 break;
710
florianc4aa7ed2012-12-22 15:01:04 +0000711 case S390_INSN_DFP_BINOP: {
712 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
713
714 addHRegUse(u, HRmWrite, dfp_binop->dst_hi);
715 addHRegUse(u, HRmRead, dfp_binop->op2_hi); /* left */
716 addHRegUse(u, HRmRead, dfp_binop->op3_hi); /* right */
florian12390202012-11-10 22:34:14 +0000717 if (insn->size == 16) {
florianc4aa7ed2012-12-22 15:01:04 +0000718 addHRegUse(u, HRmWrite, dfp_binop->dst_lo);
719 addHRegUse(u, HRmRead, dfp_binop->op2_lo); /* left */
720 addHRegUse(u, HRmRead, dfp_binop->op3_lo); /* right */
florian12390202012-11-10 22:34:14 +0000721 }
722 break;
florianc4aa7ed2012-12-22 15:01:04 +0000723 }
florian12390202012-11-10 22:34:14 +0000724
floriane38f6412012-12-21 17:32:12 +0000725 case S390_INSN_DFP_COMPARE:
726 addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst);
727 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_hi); /* left */
728 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_hi); /* right */
729 if (insn->size == 16) {
730 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_lo); /* left */
731 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_lo); /* right */
732 }
733 break;
734
735 case S390_INSN_DFP_CONVERT:
736 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_hi);
737 if (insn->variant.dfp_convert.dst_lo != INVALID_HREG)
738 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_lo);
739 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_hi); /* operand */
740 if (insn->variant.dfp_convert.op_lo != INVALID_HREG)
741 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_lo); /* operand */
742 break;
743
florianb93348d2012-12-27 00:59:43 +0000744 case S390_INSN_MIMM:
745 s390_amode_get_reg_usage(u, insn->variant.mimm.dst);
florian09bbba82012-12-11 04:09:43 +0000746 break;
747
florianf85fe3e2012-12-22 02:28:25 +0000748 case S390_INSN_MADD:
749 s390_amode_get_reg_usage(u, insn->variant.madd.dst);
750 break;
751
sewardja52e37e2011-04-28 18:48:06 +0000752 case S390_INSN_MFENCE:
753 break;
754
florian125e20d2012-10-07 15:42:37 +0000755 case S390_INSN_SET_FPC_BFPRM:
756 addHRegUse(u, HRmRead, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +0000757 break;
758
florianc8e4f562012-10-27 16:19:31 +0000759 case S390_INSN_SET_FPC_DFPRM:
760 addHRegUse(u, HRmRead, insn->variant.set_fpc_dfprm.mode);
761 break;
762
florian8844a632012-04-13 04:04:06 +0000763 case S390_INSN_EVCHECK:
764 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
765 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
766 break;
767
768 case S390_INSN_PROFINC:
769 /* Does not use any register visible to the register allocator */
770 break;
771
772 case S390_INSN_XDIRECT:
773 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
774 break;
775
776 case S390_INSN_XINDIR:
777 addHRegUse(u, HRmRead, insn->variant.xindir.dst);
778 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
779 break;
780
781 case S390_INSN_XASSISTED:
782 addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
783 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
784 break;
785
sewardj2019a972011-03-07 16:04:07 +0000786 default:
787 vpanic("s390_insn_get_reg_usage");
788 }
789}
790
791
792/* Helper function for s390_insn_map_regs */
793static void
794s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
795{
796 switch (op->tag) {
797 case S390_OPND_REG:
798 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
799 break;
800
801 case S390_OPND_IMMEDIATE:
802 break;
803
804 case S390_OPND_AMODE:
805 s390_amode_map_regs(m, op->variant.am);
806 break;
807
808 default:
809 vpanic("s390_opnd_RMI_map_regs");
810 }
811}
812
813
florianb4df7682011-07-05 02:09:01 +0000814static void
sewardj2019a972011-03-07 16:04:07 +0000815s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
816{
817 switch (insn->tag) {
818 case S390_INSN_LOAD:
819 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
820 s390_amode_map_regs(m, insn->variant.load.src);
821 break;
822
823 case S390_INSN_STORE:
824 s390_amode_map_regs(m, insn->variant.store.dst);
825 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
826 break;
827
828 case S390_INSN_MOVE:
829 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
830 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
831 break;
832
833 case S390_INSN_COND_MOVE:
834 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
835 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
836 break;
837
838 case S390_INSN_LOAD_IMMEDIATE:
839 insn->variant.load_immediate.dst =
840 lookupHRegRemap(m, insn->variant.load_immediate.dst);
841 break;
842
843 case S390_INSN_ALU:
844 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
845 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
846 break;
847
florianc4aa7ed2012-12-22 15:01:04 +0000848 case S390_INSN_SMUL:
849 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +0000850 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
851 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
852 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
853 break;
854
florianc4aa7ed2012-12-22 15:01:04 +0000855 case S390_INSN_SDIV:
856 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +0000857 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
858 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
859 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
860 break;
861
862 case S390_INSN_DIVS:
863 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
864 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
865 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
866 break;
867
sewardj611b06e2011-03-24 08:57:29 +0000868 case S390_INSN_CLZ:
869 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
870 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
871 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000872 break;
873
874 case S390_INSN_UNOP:
875 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
876 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
877 break;
878
879 case S390_INSN_TEST:
880 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
881 break;
882
883 case S390_INSN_CC2BOOL:
884 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
885 break;
886
887 case S390_INSN_CAS:
888 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
889 s390_amode_map_regs(m, insn->variant.cas.op2);
890 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
891 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
892 break;
893
florianc4aa7ed2012-12-22 15:01:04 +0000894 case S390_INSN_CDAS: {
895 s390_cdas *cdas = insn->variant.cdas.details;
896
897 cdas->op1_high = lookupHRegRemap(m, cdas->op1_high);
898 cdas->op1_low = lookupHRegRemap(m, cdas->op1_low);
899 s390_amode_map_regs(m, cdas->op2);
900 cdas->op3_high = lookupHRegRemap(m, cdas->op3_high);
901 cdas->op3_low = lookupHRegRemap(m, cdas->op3_low);
902 cdas->old_mem_high = lookupHRegRemap(m, cdas->old_mem_high);
903 cdas->old_mem_low = lookupHRegRemap(m, cdas->old_mem_low);
904 cdas->scratch = lookupHRegRemap(m, cdas->scratch);
florian448cbba2012-06-06 02:26:01 +0000905 break;
florianc4aa7ed2012-12-22 15:01:04 +0000906 }
florian448cbba2012-06-06 02:26:01 +0000907
sewardj2019a972011-03-07 16:04:07 +0000908 case S390_INSN_COMPARE:
909 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
910 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
911 break;
912
sewardj2019a972011-03-07 16:04:07 +0000913 case S390_INSN_HELPER_CALL:
914 /* s390_insn_helper_call_emit also reads / writes the link register
915 and stack pointer. But those registers are not visible to the
916 register allocator. So we don't need to do anything for them.
917 As for the arguments of the helper call -- they will be loaded into
918 non-virtual registers. Again, we don't need to do anything for those
919 here. */
florian01ed6e72012-05-27 16:52:43 +0000920 if (insn->variant.helper_call.dst != INVALID_HREG)
921 insn->variant.helper_call.dst = lookupHRegRemap(m, insn->variant.helper_call.dst);
sewardj2019a972011-03-07 16:04:07 +0000922 break;
923
924 case S390_INSN_BFP_TRIOP:
floriancc491a62012-09-10 23:44:37 +0000925 insn->variant.bfp_triop.dst =
926 lookupHRegRemap(m, insn->variant.bfp_triop.dst);
927 insn->variant.bfp_triop.op2 =
928 lookupHRegRemap(m, insn->variant.bfp_triop.op2);
929 insn->variant.bfp_triop.op3 =
930 lookupHRegRemap(m, insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +0000931 break;
932
933 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000934 insn->variant.bfp_binop.dst_hi =
935 lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi);
936 insn->variant.bfp_binop.op2_hi =
937 lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi);
938 if (insn->size == 16) {
floriana1659202012-09-19 16:01:21 +0000939 insn->variant.bfp_binop.dst_lo =
floriancc491a62012-09-10 23:44:37 +0000940 lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo);
floriana1659202012-09-19 16:01:21 +0000941 insn->variant.bfp_binop.op2_lo =
floriancc491a62012-09-10 23:44:37 +0000942 lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo);
943 }
sewardj2019a972011-03-07 16:04:07 +0000944 break;
945
946 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +0000947 insn->variant.bfp_unop.dst_hi =
948 lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi);
949 insn->variant.bfp_unop.op_hi =
950 lookupHRegRemap(m, insn->variant.bfp_unop.op_hi);
951 if (insn->size == 16) {
952 insn->variant.bfp_unop.dst_lo =
953 lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo);
954 insn->variant.bfp_unop.op_lo =
955 lookupHRegRemap(m, insn->variant.bfp_unop.op_lo);
956 }
sewardj2019a972011-03-07 16:04:07 +0000957 break;
958
959 case S390_INSN_BFP_COMPARE:
floriancc491a62012-09-10 23:44:37 +0000960 insn->variant.bfp_compare.dst =
961 lookupHRegRemap(m, insn->variant.bfp_compare.dst);
962 insn->variant.bfp_compare.op1_hi =
963 lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi);
964 insn->variant.bfp_compare.op2_hi =
965 lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi);
966 if (insn->size == 16) {
967 insn->variant.bfp_compare.op1_lo =
968 lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo);
969 insn->variant.bfp_compare.op2_lo =
970 lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo);
971 }
sewardj2019a972011-03-07 16:04:07 +0000972 break;
973
florian9fcff4c2012-09-10 03:09:04 +0000974 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +0000975 insn->variant.bfp_convert.dst_hi =
976 lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi);
977 if (insn->variant.bfp_convert.dst_lo != INVALID_HREG)
978 insn->variant.bfp_convert.dst_lo =
979 lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo);
980 insn->variant.bfp_convert.op_hi =
981 lookupHRegRemap(m, insn->variant.bfp_convert.op_hi);
982 if (insn->variant.bfp_convert.op_lo != INVALID_HREG)
983 insn->variant.bfp_convert.op_lo =
984 lookupHRegRemap(m, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +0000985 break;
986
florianc4aa7ed2012-12-22 15:01:04 +0000987 case S390_INSN_DFP_BINOP: {
988 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
989
990 dfp_binop->dst_hi = lookupHRegRemap(m, dfp_binop->dst_hi);
991 dfp_binop->op2_hi = lookupHRegRemap(m, dfp_binop->op2_hi);
992 dfp_binop->op3_hi = lookupHRegRemap(m, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +0000993 if (insn->size == 16) {
florianc4aa7ed2012-12-22 15:01:04 +0000994 dfp_binop->dst_lo = lookupHRegRemap(m, dfp_binop->dst_lo);
995 dfp_binop->op2_lo = lookupHRegRemap(m, dfp_binop->op2_lo);
996 dfp_binop->op3_lo = lookupHRegRemap(m, dfp_binop->op3_lo);
florian12390202012-11-10 22:34:14 +0000997 }
998 break;
florianc4aa7ed2012-12-22 15:01:04 +0000999 }
florian12390202012-11-10 22:34:14 +00001000
floriane38f6412012-12-21 17:32:12 +00001001 case S390_INSN_DFP_COMPARE:
1002 insn->variant.dfp_compare.dst =
1003 lookupHRegRemap(m, insn->variant.dfp_compare.dst);
1004 insn->variant.dfp_compare.op1_hi =
1005 lookupHRegRemap(m, insn->variant.dfp_compare.op1_hi);
1006 insn->variant.dfp_compare.op2_hi =
1007 lookupHRegRemap(m, insn->variant.dfp_compare.op2_hi);
1008 if (insn->size == 16) {
1009 insn->variant.dfp_compare.op1_lo =
1010 lookupHRegRemap(m, insn->variant.dfp_compare.op1_lo);
1011 insn->variant.dfp_compare.op2_lo =
1012 lookupHRegRemap(m, insn->variant.dfp_compare.op2_lo);
1013 }
1014 break;
1015
1016 case S390_INSN_DFP_CONVERT:
1017 insn->variant.dfp_convert.dst_hi =
1018 lookupHRegRemap(m, insn->variant.dfp_convert.dst_hi);
1019 if (insn->variant.dfp_convert.dst_lo != INVALID_HREG)
1020 insn->variant.dfp_convert.dst_lo =
1021 lookupHRegRemap(m, insn->variant.dfp_convert.dst_lo);
1022 insn->variant.dfp_convert.op_hi =
1023 lookupHRegRemap(m, insn->variant.dfp_convert.op_hi);
1024 if (insn->variant.dfp_convert.op_lo != INVALID_HREG)
1025 insn->variant.dfp_convert.op_lo =
1026 lookupHRegRemap(m, insn->variant.dfp_convert.op_lo);
1027 break;
1028
florianb93348d2012-12-27 00:59:43 +00001029 case S390_INSN_MIMM:
1030 s390_amode_map_regs(m, insn->variant.mimm.dst);
florian09bbba82012-12-11 04:09:43 +00001031 break;
1032
florianf85fe3e2012-12-22 02:28:25 +00001033 case S390_INSN_MADD:
1034 s390_amode_map_regs(m, insn->variant.madd.dst);
1035 break;
1036
sewardja52e37e2011-04-28 18:48:06 +00001037 case S390_INSN_MFENCE:
1038 break;
1039
florian125e20d2012-10-07 15:42:37 +00001040 case S390_INSN_SET_FPC_BFPRM:
1041 insn->variant.set_fpc_bfprm.mode =
1042 lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00001043 break;
1044
florianc8e4f562012-10-27 16:19:31 +00001045 case S390_INSN_SET_FPC_DFPRM:
1046 insn->variant.set_fpc_dfprm.mode =
1047 lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode);
1048 break;
1049
florian8844a632012-04-13 04:04:06 +00001050 case S390_INSN_EVCHECK:
1051 s390_amode_map_regs(m, insn->variant.evcheck.counter);
1052 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
1053 break;
1054
1055 case S390_INSN_PROFINC:
1056 /* Does not use any register visible to the register allocator */
1057 break;
1058
1059 case S390_INSN_XDIRECT:
1060 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
1061 break;
1062
1063 case S390_INSN_XINDIR:
1064 s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
1065 insn->variant.xindir.dst =
1066 lookupHRegRemap(m, insn->variant.xindir.dst);
1067 break;
1068
1069 case S390_INSN_XASSISTED:
1070 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
1071 insn->variant.xassisted.dst =
1072 lookupHRegRemap(m, insn->variant.xassisted.dst);
1073 break;
1074
sewardj2019a972011-03-07 16:04:07 +00001075 default:
1076 vpanic("s390_insn_map_regs");
1077 }
1078}
1079
1080
1081/* Return True, if INSN is a move between two registers of the same class.
1082 In that case assign the source and destination registers to SRC and DST,
1083 respectively. */
florianb4df7682011-07-05 02:09:01 +00001084static Bool
sewardj2019a972011-03-07 16:04:07 +00001085s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
1086{
1087 if (insn->tag == S390_INSN_MOVE &&
1088 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
1089 *src = insn->variant.move.src;
1090 *dst = insn->variant.move.dst;
1091 return True;
1092 }
1093
1094 return False;
1095}
1096
1097
sewardj2019a972011-03-07 16:04:07 +00001098/*------------------------------------------------------------*/
1099/*--- Functions to emit a sequence of bytes ---*/
1100/*------------------------------------------------------------*/
1101
sewardj2019a972011-03-07 16:04:07 +00001102static __inline__ UChar *
1103emit_2bytes(UChar *p, ULong val)
1104{
1105 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1106}
1107
1108
1109static __inline__ UChar *
1110emit_4bytes(UChar *p, ULong val)
1111{
1112 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1113}
1114
1115
1116static __inline__ UChar *
1117emit_6bytes(UChar *p, ULong val)
1118{
1119 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1120}
1121
1122
1123/*------------------------------------------------------------*/
1124/*--- Functions to emit various instruction formats ---*/
1125/*------------------------------------------------------------*/
1126
sewardj2019a972011-03-07 16:04:07 +00001127static UChar *
1128emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1129{
1130 ULong the_insn = op;
1131
1132 the_insn |= ((ULong)r1) << 20;
1133 the_insn |= ((ULong)i2) << 0;
1134
1135 return emit_4bytes(p, the_insn);
1136}
1137
1138
1139static UChar *
1140emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1141{
1142 ULong the_insn = op;
1143
1144 the_insn |= ((ULong)r1) << 36;
1145 the_insn |= ((ULong)i2) << 0;
1146
1147 return emit_6bytes(p, the_insn);
1148}
1149
1150
1151static UChar *
1152emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1153{
1154 ULong the_insn = op;
1155
1156 the_insn |= ((ULong)r1) << 4;
1157 the_insn |= ((ULong)r2) << 0;
1158
1159 return emit_2bytes(p, the_insn);
1160}
1161
1162
1163static UChar *
1164emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1165{
1166 ULong the_insn = op;
1167
1168 the_insn |= ((ULong)r1) << 4;
1169 the_insn |= ((ULong)r2) << 0;
1170
1171 return emit_4bytes(p, the_insn);
1172}
1173
1174
1175static UChar *
1176emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1177{
1178 ULong the_insn = op;
1179
1180 the_insn |= ((ULong)r1) << 12;
1181 the_insn |= ((ULong)r3) << 4;
1182 the_insn |= ((ULong)r2) << 0;
1183
1184 return emit_4bytes(p, the_insn);
1185}
1186
1187
1188static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00001189emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
1190{
1191 ULong the_insn = op;
1192
1193 the_insn |= ((ULong)m3) << 12;
1194 the_insn |= ((ULong)m4) << 8;
1195 the_insn |= ((ULong)r1) << 4;
1196 the_insn |= ((ULong)r2) << 0;
1197
1198 return emit_4bytes(p, the_insn);
1199}
1200
1201
1202static UChar *
sewardj2019a972011-03-07 16:04:07 +00001203emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1204{
1205 ULong the_insn = op;
1206
1207 the_insn |= ((ULong)r3) << 12;
1208 the_insn |= ((ULong)r1) << 4;
1209 the_insn |= ((ULong)r2) << 0;
1210
1211 return emit_4bytes(p, the_insn);
1212}
1213
1214
1215static UChar *
florian12390202012-11-10 22:34:14 +00001216emit_RRF4(UChar *p, UInt op, UChar r3, UChar m4, UChar r1, UChar r2)
1217{
1218 ULong the_insn = op;
1219
1220 the_insn |= ((ULong)r3) << 12;
1221 the_insn |= ((ULong)m4) << 8;
1222 the_insn |= ((ULong)r1) << 4;
1223 the_insn |= ((ULong)r2) << 0;
1224
1225 return emit_4bytes(p, the_insn);
1226}
1227
1228
1229static UChar *
floriane38f6412012-12-21 17:32:12 +00001230emit_RRF5(UChar *p, UInt op, UChar m4, UChar r1, UChar r2)
1231{
1232 ULong the_insn = op;
1233
1234 the_insn |= ((ULong)m4) << 8;
1235 the_insn |= ((ULong)r1) << 4;
1236 the_insn |= ((ULong)r2) << 0;
1237
1238 return emit_4bytes(p, the_insn);
1239}
1240
1241
1242static UChar *
sewardj2019a972011-03-07 16:04:07 +00001243emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1244{
1245 ULong the_insn = op;
1246
1247 the_insn |= ((ULong)r1) << 20;
1248 the_insn |= ((ULong)r3) << 16;
1249 the_insn |= ((ULong)b2) << 12;
1250 the_insn |= ((ULong)d2) << 0;
1251
1252 return emit_4bytes(p, the_insn);
1253}
1254
1255
1256static UChar *
1257emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1258{
1259 ULong the_insn = op;
1260
1261 the_insn |= ((ULong)r1) << 36;
1262 the_insn |= ((ULong)r3) << 32;
1263 the_insn |= ((ULong)b2) << 28;
1264 the_insn |= ((ULong)dl2) << 16;
1265 the_insn |= ((ULong)dh2) << 8;
1266
1267 return emit_6bytes(p, the_insn);
1268}
1269
1270
1271static UChar *
1272emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1273{
1274 ULong the_insn = op;
1275
1276 the_insn |= ((ULong)r1) << 20;
1277 the_insn |= ((ULong)x2) << 16;
1278 the_insn |= ((ULong)b2) << 12;
1279 the_insn |= ((ULong)d2) << 0;
1280
1281 return emit_4bytes(p, the_insn);
1282}
1283
1284
1285static UChar *
1286emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1287{
1288 ULong the_insn = op;
1289
1290 the_insn |= ((ULong)r1) << 36;
1291 the_insn |= ((ULong)x2) << 32;
1292 the_insn |= ((ULong)b2) << 28;
1293 the_insn |= ((ULong)dl2) << 16;
1294 the_insn |= ((ULong)dh2) << 8;
1295
1296 return emit_6bytes(p, the_insn);
1297}
1298
1299
1300static UChar *
1301emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1302{
1303 ULong the_insn = op;
1304
1305 the_insn |= ((ULong)b2) << 12;
1306 the_insn |= ((ULong)d2) << 0;
1307
1308 return emit_4bytes(p, the_insn);
1309}
1310
1311
florianad43b3a2012-02-20 15:01:14 +00001312static UChar *
florianb93348d2012-12-27 00:59:43 +00001313emit_SI(UChar *p, UInt op, UChar i2, UChar b1, UShort d1)
1314{
1315 ULong the_insn = op;
1316
1317 the_insn |= ((ULong)i2) << 16;
1318 the_insn |= ((ULong)b1) << 12;
1319 the_insn |= ((ULong)d1) << 0;
1320
1321 return emit_4bytes(p, the_insn);
1322}
1323
1324
1325static UChar *
1326emit_SIL(UChar *p, ULong op, UChar b1, UShort d1, UShort i2)
1327{
1328 ULong the_insn = op;
1329
1330 the_insn |= ((ULong)b1) << 28;
1331 the_insn |= ((ULong)d1) << 16;
1332 the_insn |= ((ULong)i2) << 0;
1333
1334 return emit_6bytes(p, the_insn);
1335}
1336
1337
1338static UChar *
florianad43b3a2012-02-20 15:01:14 +00001339emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1340{
1341 ULong the_insn = op;
1342
1343 the_insn |= ((ULong)i2) << 32;
1344 the_insn |= ((ULong)b1) << 28;
1345 the_insn |= ((ULong)dl1) << 16;
1346 the_insn |= ((ULong)dh1) << 8;
1347
1348 return emit_6bytes(p, the_insn);
1349}
1350
1351
1352static UChar *
1353emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1354{
1355 ULong the_insn = op;
1356
1357 the_insn |= ((ULong)l) << 32;
1358 the_insn |= ((ULong)b1) << 28;
1359 the_insn |= ((ULong)d1) << 16;
1360 the_insn |= ((ULong)b2) << 12;
1361 the_insn |= ((ULong)d2) << 0;
1362
1363 return emit_6bytes(p, the_insn);
1364}
1365
1366
sewardj2019a972011-03-07 16:04:07 +00001367/*------------------------------------------------------------*/
1368/*--- Functions to emit particular instructions ---*/
1369/*------------------------------------------------------------*/
1370
sewardj9d31dfd2011-03-15 12:36:44 +00001371static UChar *
sewardj2019a972011-03-07 16:04:07 +00001372s390_emit_AR(UChar *p, UChar r1, UChar r2)
1373{
sewardj7ee97522011-05-09 21:45:04 +00001374 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001375 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1376
1377 return emit_RR(p, 0x1a00, r1, r2);
1378}
1379
1380
sewardj9d31dfd2011-03-15 12:36:44 +00001381static UChar *
sewardj2019a972011-03-07 16:04:07 +00001382s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1383{
sewardj7ee97522011-05-09 21:45:04 +00001384 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001385 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1386
1387 return emit_RRE(p, 0xb9080000, r1, r2);
1388}
1389
1390
sewardj9d31dfd2011-03-15 12:36:44 +00001391static UChar *
sewardj2019a972011-03-07 16:04:07 +00001392s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1393{
sewardj7ee97522011-05-09 21:45:04 +00001394 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001395 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1396
1397 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1398}
1399
1400
sewardj9d31dfd2011-03-15 12:36:44 +00001401static UChar *
sewardj2019a972011-03-07 16:04:07 +00001402s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1403{
sewardj652b56a2011-04-13 15:38:17 +00001404 vassert(s390_host_has_ldisp);
1405
sewardj7ee97522011-05-09 21:45:04 +00001406 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001407 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1408
1409 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1410}
1411
1412
sewardj9d31dfd2011-03-15 12:36:44 +00001413static UChar *
sewardj2019a972011-03-07 16:04:07 +00001414s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1415{
sewardj652b56a2011-04-13 15:38:17 +00001416 vassert(s390_host_has_ldisp || dh2 == 0);
1417
sewardj7ee97522011-05-09 21:45:04 +00001418 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001419 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1420
1421 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1422}
1423
1424
sewardj9d31dfd2011-03-15 12:36:44 +00001425static UChar *
sewardj2019a972011-03-07 16:04:07 +00001426s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1427{
sewardj652b56a2011-04-13 15:38:17 +00001428 vassert(s390_host_has_eimm);
1429
sewardj7ee97522011-05-09 21:45:04 +00001430 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001431 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1432
1433 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1434}
1435
1436
sewardj9d31dfd2011-03-15 12:36:44 +00001437static UChar *
sewardj2019a972011-03-07 16:04:07 +00001438s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1439{
sewardj652b56a2011-04-13 15:38:17 +00001440 vassert(s390_host_has_eimm);
1441
sewardj7ee97522011-05-09 21:45:04 +00001442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001443 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1444
1445 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1446}
1447
1448
sewardj9d31dfd2011-03-15 12:36:44 +00001449static UChar *
sewardj2019a972011-03-07 16:04:07 +00001450s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1451{
sewardj7ee97522011-05-09 21:45:04 +00001452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001453 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1454
1455 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1456}
1457
1458
sewardj9d31dfd2011-03-15 12:36:44 +00001459static UChar *
sewardj2019a972011-03-07 16:04:07 +00001460s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1461{
sewardj652b56a2011-04-13 15:38:17 +00001462 vassert(s390_host_has_ldisp);
1463
sewardj7ee97522011-05-09 21:45:04 +00001464 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001465 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1466
1467 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1468}
1469
1470
sewardj9d31dfd2011-03-15 12:36:44 +00001471static UChar *
sewardj2019a972011-03-07 16:04:07 +00001472s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1473{
sewardj7ee97522011-05-09 21:45:04 +00001474 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001475 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1476
1477 return emit_RI(p, 0xa70a0000, r1, i2);
1478}
1479
1480
sewardj9d31dfd2011-03-15 12:36:44 +00001481static UChar *
sewardj2019a972011-03-07 16:04:07 +00001482s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1483{
sewardj7ee97522011-05-09 21:45:04 +00001484 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001485 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1486
1487 return emit_RI(p, 0xa70b0000, r1, i2);
1488}
1489
1490
sewardj9d31dfd2011-03-15 12:36:44 +00001491static UChar *
florianad43b3a2012-02-20 15:01:14 +00001492s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1493{
1494 vassert(s390_host_has_gie);
1495
1496 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001497 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
florianad43b3a2012-02-20 15:01:14 +00001498
1499 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
1500}
1501
1502
1503static UChar *
florian0e047d62012-04-21 16:06:04 +00001504s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1505{
1506 vassert(s390_host_has_gie);
1507
1508 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001509 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
florian0e047d62012-04-21 16:06:04 +00001510
1511 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
1512}
1513
1514
1515static UChar *
sewardj2019a972011-03-07 16:04:07 +00001516s390_emit_NR(UChar *p, UChar r1, UChar r2)
1517{
sewardj7ee97522011-05-09 21:45:04 +00001518 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001519 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1520
1521 return emit_RR(p, 0x1400, r1, r2);
1522}
1523
1524
sewardj9d31dfd2011-03-15 12:36:44 +00001525static UChar *
sewardj2019a972011-03-07 16:04:07 +00001526s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1527{
sewardj7ee97522011-05-09 21:45:04 +00001528 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001529 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1530
1531 return emit_RRE(p, 0xb9800000, r1, r2);
1532}
1533
1534
sewardj9d31dfd2011-03-15 12:36:44 +00001535static UChar *
sewardj2019a972011-03-07 16:04:07 +00001536s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1537{
sewardj7ee97522011-05-09 21:45:04 +00001538 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001539 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1540
1541 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1542}
1543
1544
sewardj9d31dfd2011-03-15 12:36:44 +00001545static UChar *
sewardj2019a972011-03-07 16:04:07 +00001546s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1547{
sewardj652b56a2011-04-13 15:38:17 +00001548 vassert(s390_host_has_ldisp);
1549
sewardj7ee97522011-05-09 21:45:04 +00001550 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001551 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1552
1553 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1554}
1555
1556
sewardj9d31dfd2011-03-15 12:36:44 +00001557static UChar *
sewardj2019a972011-03-07 16:04:07 +00001558s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1559{
sewardj652b56a2011-04-13 15:38:17 +00001560 vassert(s390_host_has_ldisp || dh2 == 0);
1561
sewardj7ee97522011-05-09 21:45:04 +00001562 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001563 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1564
1565 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1566}
1567
1568
sewardj9d31dfd2011-03-15 12:36:44 +00001569static UChar *
sewardj2019a972011-03-07 16:04:07 +00001570s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1571{
sewardj652b56a2011-04-13 15:38:17 +00001572 vassert(s390_host_has_eimm);
1573
sewardj7ee97522011-05-09 21:45:04 +00001574 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001575 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1576
1577 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1578}
1579
1580
sewardj9d31dfd2011-03-15 12:36:44 +00001581static UChar *
sewardj2019a972011-03-07 16:04:07 +00001582s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1583{
sewardj652b56a2011-04-13 15:38:17 +00001584 vassert(s390_host_has_eimm);
1585
sewardj7ee97522011-05-09 21:45:04 +00001586 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001587 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1588
1589 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1590}
1591
1592
sewardj9d31dfd2011-03-15 12:36:44 +00001593static UChar *
sewardj2019a972011-03-07 16:04:07 +00001594s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1595{
sewardj7ee97522011-05-09 21:45:04 +00001596 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001597 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1598
1599 return emit_RI(p, 0xa5070000, r1, i2);
1600}
1601
1602
sewardj9d31dfd2011-03-15 12:36:44 +00001603static UChar *
sewardj2019a972011-03-07 16:04:07 +00001604s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1605{
sewardj7ee97522011-05-09 21:45:04 +00001606 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001607 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1608
1609 return emit_RR(p, 0x0d00, r1, r2);
1610}
1611
1612
sewardj9d31dfd2011-03-15 12:36:44 +00001613static UChar *
sewardj2019a972011-03-07 16:04:07 +00001614s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1615{
sewardj7ee97522011-05-09 21:45:04 +00001616 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001617 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1618
1619 return emit_RR(p, 0x0700, r1, r2);
1620}
1621
1622
sewardj9d31dfd2011-03-15 12:36:44 +00001623static UChar *
sewardj2019a972011-03-07 16:04:07 +00001624s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1625{
sewardj7ee97522011-05-09 21:45:04 +00001626 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001627 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1628
1629 return emit_RI(p, 0xa7040000, r1, i2);
1630}
1631
1632
sewardj9d31dfd2011-03-15 12:36:44 +00001633static UChar *
florian8844a632012-04-13 04:04:06 +00001634s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
1635{
1636 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1637 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
1638
1639 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
1640}
1641
1642
1643static UChar *
sewardj2019a972011-03-07 16:04:07 +00001644s390_emit_CR(UChar *p, UChar r1, UChar r2)
1645{
sewardj7ee97522011-05-09 21:45:04 +00001646 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001647 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1648
1649 return emit_RR(p, 0x1900, r1, r2);
1650}
1651
1652
sewardj9d31dfd2011-03-15 12:36:44 +00001653static UChar *
sewardj2019a972011-03-07 16:04:07 +00001654s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1655{
sewardj7ee97522011-05-09 21:45:04 +00001656 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001657 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1658
1659 return emit_RRE(p, 0xb9200000, r1, r2);
1660}
1661
1662
sewardj9d31dfd2011-03-15 12:36:44 +00001663static UChar *
sewardj2019a972011-03-07 16:04:07 +00001664s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1665{
sewardj7ee97522011-05-09 21:45:04 +00001666 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001667 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1668
1669 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1670}
1671
1672
sewardj9d31dfd2011-03-15 12:36:44 +00001673static UChar *
sewardj2019a972011-03-07 16:04:07 +00001674s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1675{
sewardj652b56a2011-04-13 15:38:17 +00001676 vassert(s390_host_has_ldisp);
1677
sewardj7ee97522011-05-09 21:45:04 +00001678 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001679 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1680
1681 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1682}
1683
1684
sewardj9d31dfd2011-03-15 12:36:44 +00001685static UChar *
sewardj2019a972011-03-07 16:04:07 +00001686s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1687{
sewardj652b56a2011-04-13 15:38:17 +00001688 vassert(s390_host_has_ldisp || dh2 == 0);
1689
sewardj7ee97522011-05-09 21:45:04 +00001690 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001691 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1692
1693 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1694}
1695
1696
sewardj9d31dfd2011-03-15 12:36:44 +00001697static UChar *
sewardj2019a972011-03-07 16:04:07 +00001698s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1699{
sewardj652b56a2011-04-13 15:38:17 +00001700 vassert(s390_host_has_eimm);
1701
sewardj7ee97522011-05-09 21:45:04 +00001702 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001703 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1704
1705 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1706}
1707
1708
sewardj9d31dfd2011-03-15 12:36:44 +00001709static UChar *
florian07d34552012-05-26 01:59:21 +00001710s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
1711{
1712 vassert(s390_host_has_eimm);
1713
1714 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1715 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
1716
1717 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
1718}
1719
1720
1721static UChar *
sewardj2019a972011-03-07 16:04:07 +00001722s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1723{
sewardj7ee97522011-05-09 21:45:04 +00001724 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001725 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1726
1727 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1728}
1729
1730
sewardj9d31dfd2011-03-15 12:36:44 +00001731static UChar *
sewardj2019a972011-03-07 16:04:07 +00001732s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1733{
sewardj652b56a2011-04-13 15:38:17 +00001734 vassert(s390_host_has_ldisp);
1735
sewardj7ee97522011-05-09 21:45:04 +00001736 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001737 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1738
1739 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1740}
1741
1742
sewardj9d31dfd2011-03-15 12:36:44 +00001743static UChar *
sewardj2019a972011-03-07 16:04:07 +00001744s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1745{
sewardj652b56a2011-04-13 15:38:17 +00001746 vassert(s390_host_has_ldisp || dh2 == 0);
1747
sewardj7ee97522011-05-09 21:45:04 +00001748 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001749 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1750
1751 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1752}
1753
1754
sewardj9d31dfd2011-03-15 12:36:44 +00001755static UChar *
florian448cbba2012-06-06 02:26:01 +00001756s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1757{
1758 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1759 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
1760
1761 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
1762}
1763
1764
1765static UChar *
1766s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1767{
1768 vassert(s390_host_has_ldisp);
1769
1770 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1771 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
1772
1773 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
1774}
1775
1776
1777static UChar *
1778s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1779{
1780 vassert(s390_host_has_ldisp || dh2 == 0);
1781
1782 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1783 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
1784
1785 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
1786}
1787
1788
1789static UChar *
sewardj2019a972011-03-07 16:04:07 +00001790s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1791{
sewardj7ee97522011-05-09 21:45:04 +00001792 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001793 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1794
1795 return emit_RR(p, 0x1500, r1, r2);
1796}
1797
1798
sewardj9d31dfd2011-03-15 12:36:44 +00001799static UChar *
sewardj2019a972011-03-07 16:04:07 +00001800s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1801{
sewardj7ee97522011-05-09 21:45:04 +00001802 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001803 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1804
1805 return emit_RRE(p, 0xb9210000, r1, r2);
1806}
1807
1808
sewardj9d31dfd2011-03-15 12:36:44 +00001809static UChar *
sewardj2019a972011-03-07 16:04:07 +00001810s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1811{
sewardj7ee97522011-05-09 21:45:04 +00001812 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001813 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1814
1815 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1816}
1817
1818
sewardj9d31dfd2011-03-15 12:36:44 +00001819static UChar *
sewardj2019a972011-03-07 16:04:07 +00001820s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1821{
sewardj652b56a2011-04-13 15:38:17 +00001822 vassert(s390_host_has_ldisp);
1823
sewardj7ee97522011-05-09 21:45:04 +00001824 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001825 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1826
1827 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1828}
1829
1830
sewardj9d31dfd2011-03-15 12:36:44 +00001831static UChar *
sewardj2019a972011-03-07 16:04:07 +00001832s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1833{
sewardj652b56a2011-04-13 15:38:17 +00001834 vassert(s390_host_has_ldisp || dh2 == 0);
1835
sewardj7ee97522011-05-09 21:45:04 +00001836 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001837 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1838
1839 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1840}
1841
1842
sewardj9d31dfd2011-03-15 12:36:44 +00001843static UChar *
sewardj2019a972011-03-07 16:04:07 +00001844s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1845{
sewardj652b56a2011-04-13 15:38:17 +00001846 vassert(s390_host_has_eimm);
1847
sewardj7ee97522011-05-09 21:45:04 +00001848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001849 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1850
1851 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1852}
1853
1854
sewardj9d31dfd2011-03-15 12:36:44 +00001855static UChar *
florian07d34552012-05-26 01:59:21 +00001856s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
1857{
1858 vassert(s390_host_has_eimm);
1859
1860 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1861 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
1862
1863 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
1864}
1865
1866
1867static UChar *
sewardj2019a972011-03-07 16:04:07 +00001868s390_emit_DR(UChar *p, UChar r1, UChar r2)
1869{
sewardj7ee97522011-05-09 21:45:04 +00001870 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001871 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1872
1873 return emit_RR(p, 0x1d00, r1, r2);
1874}
1875
1876
sewardj9d31dfd2011-03-15 12:36:44 +00001877static UChar *
sewardj2019a972011-03-07 16:04:07 +00001878s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1879{
sewardj7ee97522011-05-09 21:45:04 +00001880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001881 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1882
1883 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1884}
1885
1886
sewardj9d31dfd2011-03-15 12:36:44 +00001887static UChar *
sewardj2019a972011-03-07 16:04:07 +00001888s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1889{
sewardj7ee97522011-05-09 21:45:04 +00001890 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001891 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1892
1893 return emit_RRE(p, 0xb9970000, r1, r2);
1894}
1895
1896
sewardj9d31dfd2011-03-15 12:36:44 +00001897static UChar *
sewardj2019a972011-03-07 16:04:07 +00001898s390_emit_DLGR(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), "dlgr", r1, r2);
1902
1903 return emit_RRE(p, 0xb9870000, r1, r2);
1904}
1905
1906
sewardj9d31dfd2011-03-15 12:36:44 +00001907static UChar *
sewardj2019a972011-03-07 16:04:07 +00001908s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1909{
sewardj652b56a2011-04-13 15:38:17 +00001910 vassert(s390_host_has_ldisp || dh2 == 0);
1911
sewardj7ee97522011-05-09 21:45:04 +00001912 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001913 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
1914
1915 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
1916}
1917
1918
sewardj9d31dfd2011-03-15 12:36:44 +00001919static UChar *
sewardj2019a972011-03-07 16:04:07 +00001920s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1921{
sewardj652b56a2011-04-13 15:38:17 +00001922 vassert(s390_host_has_ldisp || dh2 == 0);
1923
sewardj7ee97522011-05-09 21:45:04 +00001924 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001925 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
1926
1927 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
1928}
1929
1930
sewardj9d31dfd2011-03-15 12:36:44 +00001931static UChar *
sewardj2019a972011-03-07 16:04:07 +00001932s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
1933{
sewardj7ee97522011-05-09 21:45:04 +00001934 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001935 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
1936
1937 return emit_RRE(p, 0xb90d0000, r1, r2);
1938}
1939
1940
sewardj9d31dfd2011-03-15 12:36:44 +00001941static UChar *
sewardj2019a972011-03-07 16:04:07 +00001942s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1943{
sewardj652b56a2011-04-13 15:38:17 +00001944 vassert(s390_host_has_ldisp || dh2 == 0);
1945
sewardj7ee97522011-05-09 21:45:04 +00001946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001947 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
1948
1949 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
1950}
1951
1952
sewardj9d31dfd2011-03-15 12:36:44 +00001953static UChar *
sewardj2019a972011-03-07 16:04:07 +00001954s390_emit_XR(UChar *p, UChar r1, UChar r2)
1955{
sewardj7ee97522011-05-09 21:45:04 +00001956 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001957 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
1958
1959 return emit_RR(p, 0x1700, r1, r2);
1960}
1961
1962
sewardj9d31dfd2011-03-15 12:36:44 +00001963static UChar *
sewardj2019a972011-03-07 16:04:07 +00001964s390_emit_XGR(UChar *p, UChar r1, UChar r2)
1965{
sewardj7ee97522011-05-09 21:45:04 +00001966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001967 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
1968
1969 return emit_RRE(p, 0xb9820000, r1, r2);
1970}
1971
1972
sewardj9d31dfd2011-03-15 12:36:44 +00001973static UChar *
sewardj2019a972011-03-07 16:04:07 +00001974s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1975{
sewardj7ee97522011-05-09 21:45:04 +00001976 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001977 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
1978
1979 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
1980}
1981
1982
sewardj9d31dfd2011-03-15 12:36:44 +00001983static UChar *
sewardj2019a972011-03-07 16:04:07 +00001984s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1985{
sewardj652b56a2011-04-13 15:38:17 +00001986 vassert(s390_host_has_ldisp);
1987
sewardj7ee97522011-05-09 21:45:04 +00001988 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001989 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
1990
1991 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
1992}
1993
1994
sewardj9d31dfd2011-03-15 12:36:44 +00001995static UChar *
sewardj2019a972011-03-07 16:04:07 +00001996s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1997{
sewardj652b56a2011-04-13 15:38:17 +00001998 vassert(s390_host_has_ldisp || dh2 == 0);
1999
sewardj7ee97522011-05-09 21:45:04 +00002000 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002001 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
2002
2003 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
2004}
2005
2006
sewardj9d31dfd2011-03-15 12:36:44 +00002007static UChar *
sewardj2019a972011-03-07 16:04:07 +00002008s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
2009{
sewardj652b56a2011-04-13 15:38:17 +00002010 vassert(s390_host_has_eimm);
2011
sewardj7ee97522011-05-09 21:45:04 +00002012 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002013 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
2014
2015 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
2016}
2017
2018
sewardj9d31dfd2011-03-15 12:36:44 +00002019static UChar *
sewardj2019a972011-03-07 16:04:07 +00002020s390_emit_XILF(UChar *p, UChar r1, UInt i2)
2021{
sewardj652b56a2011-04-13 15:38:17 +00002022 vassert(s390_host_has_eimm);
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, UINT), "xilf", r1, i2);
2026
2027 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
2028}
2029
2030
sewardj9d31dfd2011-03-15 12:36:44 +00002031static UChar *
florianad43b3a2012-02-20 15:01:14 +00002032s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2033{
2034 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2035 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
2036
2037 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
2038}
2039
2040
2041static UChar *
sewardj2019a972011-03-07 16:04:07 +00002042s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
2043{
sewardj652b56a2011-04-13 15:38:17 +00002044 vassert(s390_host_has_eimm);
2045
sewardj7ee97522011-05-09 21:45:04 +00002046 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002047 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
2048
2049 return emit_RRE(p, 0xb9830000, r1, r2);
2050}
2051
2052
sewardj9d31dfd2011-03-15 12:36:44 +00002053static UChar *
sewardj2019a972011-03-07 16:04:07 +00002054s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2055{
sewardj7ee97522011-05-09 21:45:04 +00002056 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002057 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
2058
2059 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
2060}
2061
2062
sewardj9d31dfd2011-03-15 12:36:44 +00002063static UChar *
sewardj2019a972011-03-07 16:04:07 +00002064s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2065{
sewardj652b56a2011-04-13 15:38:17 +00002066 vassert(s390_host_has_ldisp);
2067
sewardj7ee97522011-05-09 21:45:04 +00002068 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002069 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
2070
2071 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
2072}
2073
2074
sewardj9d31dfd2011-03-15 12:36:44 +00002075static UChar *
sewardj2019a972011-03-07 16:04:07 +00002076s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
2077{
sewardj652b56a2011-04-13 15:38:17 +00002078 vassert(s390_host_has_eimm);
2079
sewardj7ee97522011-05-09 21:45:04 +00002080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002081 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
2082
2083 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
2084}
2085
2086
sewardj9d31dfd2011-03-15 12:36:44 +00002087static UChar *
sewardj2019a972011-03-07 16:04:07 +00002088s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
2089{
sewardj7ee97522011-05-09 21:45:04 +00002090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002091 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
2092
2093 return emit_RI(p, 0xa5000000, r1, i2);
2094}
2095
2096
sewardj9d31dfd2011-03-15 12:36:44 +00002097static UChar *
sewardj2019a972011-03-07 16:04:07 +00002098s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
2099{
sewardj7ee97522011-05-09 21:45:04 +00002100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002101 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
2102
2103 return emit_RI(p, 0xa5010000, r1, i2);
2104}
2105
2106
sewardj9d31dfd2011-03-15 12:36:44 +00002107static UChar *
sewardj2019a972011-03-07 16:04:07 +00002108s390_emit_IILF(UChar *p, UChar r1, UInt i2)
2109{
sewardj652b56a2011-04-13 15:38:17 +00002110 vassert(s390_host_has_eimm);
2111
sewardj7ee97522011-05-09 21:45:04 +00002112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002113 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
2114
2115 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
2116}
2117
2118
sewardj9d31dfd2011-03-15 12:36:44 +00002119static UChar *
sewardj2019a972011-03-07 16:04:07 +00002120s390_emit_IILH(UChar *p, UChar r1, UShort i2)
2121{
sewardj7ee97522011-05-09 21:45:04 +00002122 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002123 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
2124
2125 return emit_RI(p, 0xa5020000, r1, i2);
2126}
2127
2128
sewardj9d31dfd2011-03-15 12:36:44 +00002129static UChar *
sewardj2019a972011-03-07 16:04:07 +00002130s390_emit_IILL(UChar *p, UChar r1, UShort i2)
2131{
sewardj7ee97522011-05-09 21:45:04 +00002132 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002133 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
2134
2135 return emit_RI(p, 0xa5030000, r1, i2);
2136}
2137
2138
sewardj9d31dfd2011-03-15 12:36:44 +00002139static UChar *
sewardj2019a972011-03-07 16:04:07 +00002140s390_emit_IPM(UChar *p, UChar r1, UChar r2)
2141{
sewardj7ee97522011-05-09 21:45:04 +00002142 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002143 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
2144
2145 return emit_RRE(p, 0xb2220000, r1, r2);
2146}
2147
2148
sewardj9d31dfd2011-03-15 12:36:44 +00002149static UChar *
sewardj2019a972011-03-07 16:04:07 +00002150s390_emit_LR(UChar *p, UChar r1, UChar r2)
2151{
sewardj7ee97522011-05-09 21:45:04 +00002152 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002153 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
2154
2155 return emit_RR(p, 0x1800, r1, r2);
2156}
2157
2158
sewardj9d31dfd2011-03-15 12:36:44 +00002159static UChar *
sewardj2019a972011-03-07 16:04:07 +00002160s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2161{
sewardj7ee97522011-05-09 21:45:04 +00002162 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002163 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2164
2165 return emit_RRE(p, 0xb9040000, r1, r2);
2166}
2167
2168
sewardj9d31dfd2011-03-15 12:36:44 +00002169static UChar *
sewardj2019a972011-03-07 16:04:07 +00002170s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
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, GPR), "lgfr", r1, r2);
2174
2175 return emit_RRE(p, 0xb9140000, r1, r2);
2176}
2177
2178
sewardj9d31dfd2011-03-15 12:36:44 +00002179static UChar *
sewardj2019a972011-03-07 16:04:07 +00002180s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
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, UDXB), "l", r1, d2, x2, b2);
2184
2185 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2186}
2187
2188
sewardj9d31dfd2011-03-15 12:36:44 +00002189static UChar *
sewardj2019a972011-03-07 16:04:07 +00002190s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2191{
sewardj652b56a2011-04-13 15:38:17 +00002192 vassert(s390_host_has_ldisp);
2193
sewardj7ee97522011-05-09 21:45:04 +00002194 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002195 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2196
2197 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2198}
2199
2200
sewardj9d31dfd2011-03-15 12:36:44 +00002201static UChar *
sewardj2019a972011-03-07 16:04:07 +00002202s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2203{
sewardj652b56a2011-04-13 15:38:17 +00002204 vassert(s390_host_has_ldisp || dh2 == 0);
2205
sewardj7ee97522011-05-09 21:45:04 +00002206 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002207 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2208
2209 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2210}
2211
2212
sewardj9d31dfd2011-03-15 12:36:44 +00002213static UChar *
sewardj2019a972011-03-07 16:04:07 +00002214s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2215{
sewardj652b56a2011-04-13 15:38:17 +00002216 vassert(s390_host_has_ldisp || dh2 == 0);
2217
sewardj7ee97522011-05-09 21:45:04 +00002218 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002219 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2220
2221 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2222}
2223
2224
sewardj9d31dfd2011-03-15 12:36:44 +00002225static UChar *
sewardj2019a972011-03-07 16:04:07 +00002226s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2227{
sewardj652b56a2011-04-13 15:38:17 +00002228 vassert(s390_host_has_eimm);
2229
sewardj7ee97522011-05-09 21:45:04 +00002230 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002231 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2232
2233 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2234}
2235
2236
sewardj9d31dfd2011-03-15 12:36:44 +00002237static UChar *
sewardj2019a972011-03-07 16:04:07 +00002238s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2239{
sewardj7ee97522011-05-09 21:45:04 +00002240 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002241 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2242
2243 return emit_RR(p, 0x1200, r1, r2);
2244}
2245
2246
sewardj9d31dfd2011-03-15 12:36:44 +00002247static UChar *
sewardj2019a972011-03-07 16:04:07 +00002248s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2249{
sewardj7ee97522011-05-09 21:45:04 +00002250 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002251 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2252
2253 return emit_RRE(p, 0xb9020000, r1, r2);
2254}
2255
2256
sewardj9d31dfd2011-03-15 12:36:44 +00002257static UChar *
sewardj2019a972011-03-07 16:04:07 +00002258s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2259{
sewardj652b56a2011-04-13 15:38:17 +00002260 vassert(s390_host_has_eimm);
2261
sewardj7ee97522011-05-09 21:45:04 +00002262 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002263 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2264
2265 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2266}
2267
2268
sewardj9d31dfd2011-03-15 12:36:44 +00002269static UChar *
sewardj2019a972011-03-07 16:04:07 +00002270s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2271{
sewardj652b56a2011-04-13 15:38:17 +00002272 vassert(s390_host_has_eimm);
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, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2276
2277 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2278}
2279
2280
sewardj9d31dfd2011-03-15 12:36:44 +00002281static UChar *
sewardj2019a972011-03-07 16:04:07 +00002282s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2283{
sewardj652b56a2011-04-13 15:38:17 +00002284 vassert(s390_host_has_eimm);
2285
sewardj7ee97522011-05-09 21:45:04 +00002286 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002287 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2288
2289 return emit_RRE(p, 0xb9260000, r1, r2);
2290}
2291
2292
sewardj9d31dfd2011-03-15 12:36:44 +00002293static UChar *
sewardj2019a972011-03-07 16:04:07 +00002294s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2295{
sewardj652b56a2011-04-13 15:38:17 +00002296 vassert(s390_host_has_eimm);
2297
sewardj7ee97522011-05-09 21:45:04 +00002298 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002299 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2300
2301 return emit_RRE(p, 0xb9060000, r1, r2);
2302}
2303
2304
sewardj9d31dfd2011-03-15 12:36:44 +00002305static UChar *
sewardj2019a972011-03-07 16:04:07 +00002306s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2307{
sewardj652b56a2011-04-13 15:38:17 +00002308 vassert(s390_host_has_ldisp);
2309
sewardj7ee97522011-05-09 21:45:04 +00002310 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002311 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2312
2313 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2314}
2315
2316
sewardj9d31dfd2011-03-15 12:36:44 +00002317static UChar *
sewardj2019a972011-03-07 16:04:07 +00002318s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2319{
sewardj652b56a2011-04-13 15:38:17 +00002320 vassert(s390_host_has_ldisp);
2321
sewardj7ee97522011-05-09 21:45:04 +00002322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002323 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2324
2325 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2326}
2327
2328
sewardj9d31dfd2011-03-15 12:36:44 +00002329static UChar *
sewardj2019a972011-03-07 16:04:07 +00002330s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2331{
sewardj7ee97522011-05-09 21:45:04 +00002332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002333 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2334
2335 return emit_RR(p, 0x1300, r1, r2);
2336}
2337
2338
sewardj9d31dfd2011-03-15 12:36:44 +00002339static UChar *
sewardj2019a972011-03-07 16:04:07 +00002340s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2341{
sewardj7ee97522011-05-09 21:45:04 +00002342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002343 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2344
2345 return emit_RRE(p, 0xb9030000, r1, r2);
2346}
2347
2348
sewardj9d31dfd2011-03-15 12:36:44 +00002349static UChar *
sewardj2019a972011-03-07 16:04:07 +00002350s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2351{
sewardj652b56a2011-04-13 15:38:17 +00002352 vassert(s390_host_has_eimm);
2353
sewardj7ee97522011-05-09 21:45:04 +00002354 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002355 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2356
2357 return emit_RRE(p, 0xb9270000, r1, r2);
2358}
2359
2360
sewardj9d31dfd2011-03-15 12:36:44 +00002361static UChar *
sewardj2019a972011-03-07 16:04:07 +00002362s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2363{
sewardj652b56a2011-04-13 15:38:17 +00002364 vassert(s390_host_has_eimm);
2365
sewardj7ee97522011-05-09 21:45:04 +00002366 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002367 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2368
2369 return emit_RRE(p, 0xb9070000, r1, r2);
2370}
2371
2372
sewardj9d31dfd2011-03-15 12:36:44 +00002373static UChar *
sewardj2019a972011-03-07 16:04:07 +00002374s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2375{
sewardj7ee97522011-05-09 21:45:04 +00002376 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002377 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2378
2379 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2380}
2381
2382
sewardj9d31dfd2011-03-15 12:36:44 +00002383static UChar *
sewardj2019a972011-03-07 16:04:07 +00002384s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2385{
sewardj652b56a2011-04-13 15:38:17 +00002386 vassert(s390_host_has_ldisp);
2387
sewardj7ee97522011-05-09 21:45:04 +00002388 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002389 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2390
2391 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2392}
2393
2394
sewardj9d31dfd2011-03-15 12:36:44 +00002395static UChar *
sewardj2019a972011-03-07 16:04:07 +00002396s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2397{
sewardj652b56a2011-04-13 15:38:17 +00002398 vassert(s390_host_has_ldisp || dh2 == 0);
2399
sewardj7ee97522011-05-09 21:45:04 +00002400 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002401 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2402
2403 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2404}
2405
2406
sewardj9d31dfd2011-03-15 12:36:44 +00002407static UChar *
sewardj2019a972011-03-07 16:04:07 +00002408s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2409{
sewardj7ee97522011-05-09 21:45:04 +00002410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002411 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2412
2413 return emit_RI(p, 0xa7080000, r1, i2);
2414}
2415
2416
sewardj9d31dfd2011-03-15 12:36:44 +00002417static UChar *
sewardj2019a972011-03-07 16:04:07 +00002418s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2419{
sewardj7ee97522011-05-09 21:45:04 +00002420 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002421 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2422
2423 return emit_RI(p, 0xa7090000, r1, i2);
2424}
2425
2426
sewardj9d31dfd2011-03-15 12:36:44 +00002427static UChar *
sewardj2019a972011-03-07 16:04:07 +00002428s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2429{
sewardj7ee97522011-05-09 21:45:04 +00002430 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002431 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2432
2433 return emit_RRE(p, 0xb9160000, r1, r2);
2434}
2435
2436
sewardj9d31dfd2011-03-15 12:36:44 +00002437static UChar *
sewardj2019a972011-03-07 16:04:07 +00002438s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2439{
sewardj652b56a2011-04-13 15:38:17 +00002440 vassert(s390_host_has_ldisp || dh2 == 0);
2441
sewardj7ee97522011-05-09 21:45:04 +00002442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002443 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2444
2445 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2446}
2447
2448
sewardj9d31dfd2011-03-15 12:36:44 +00002449static UChar *
sewardj2019a972011-03-07 16:04:07 +00002450s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2451{
sewardj652b56a2011-04-13 15:38:17 +00002452 vassert(s390_host_has_eimm);
2453
sewardj7ee97522011-05-09 21:45:04 +00002454 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002455 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2456
2457 return emit_RRE(p, 0xb9940000, r1, r2);
2458}
2459
2460
sewardj9d31dfd2011-03-15 12:36:44 +00002461static UChar *
sewardj2019a972011-03-07 16:04:07 +00002462s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2463{
sewardj652b56a2011-04-13 15:38:17 +00002464 vassert(s390_host_has_eimm);
2465
sewardj7ee97522011-05-09 21:45:04 +00002466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002467 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2468
2469 return emit_RRE(p, 0xb9840000, r1, r2);
2470}
2471
2472
sewardj9d31dfd2011-03-15 12:36:44 +00002473static UChar *
sewardj2019a972011-03-07 16:04:07 +00002474s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2475{
sewardj652b56a2011-04-13 15:38:17 +00002476 vassert(s390_host_has_eimm);
2477
sewardj7ee97522011-05-09 21:45:04 +00002478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002479 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2480
2481 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2482}
2483
2484
sewardj9d31dfd2011-03-15 12:36:44 +00002485static UChar *
sewardj2019a972011-03-07 16:04:07 +00002486s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2487{
sewardj652b56a2011-04-13 15:38:17 +00002488 vassert(s390_host_has_ldisp || dh2 == 0);
2489
sewardj7ee97522011-05-09 21:45:04 +00002490 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002491 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2492
2493 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2494}
2495
2496
sewardj9d31dfd2011-03-15 12:36:44 +00002497static UChar *
sewardj2019a972011-03-07 16:04:07 +00002498s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2499{
sewardj652b56a2011-04-13 15:38:17 +00002500 vassert(s390_host_has_eimm);
2501
sewardj7ee97522011-05-09 21:45:04 +00002502 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002503 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2504
2505 return emit_RRE(p, 0xb9950000, r1, r2);
2506}
2507
2508
sewardj9d31dfd2011-03-15 12:36:44 +00002509static UChar *
sewardj2019a972011-03-07 16:04:07 +00002510s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2511{
sewardj652b56a2011-04-13 15:38:17 +00002512 vassert(s390_host_has_eimm);
2513
sewardj7ee97522011-05-09 21:45:04 +00002514 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002515 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2516
2517 return emit_RRE(p, 0xb9850000, r1, r2);
2518}
2519
2520
sewardj9d31dfd2011-03-15 12:36:44 +00002521static UChar *
sewardj2019a972011-03-07 16:04:07 +00002522s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2523{
sewardj652b56a2011-04-13 15:38:17 +00002524 vassert(s390_host_has_eimm);
2525
sewardj7ee97522011-05-09 21:45:04 +00002526 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002527 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2528
2529 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2530}
2531
2532
sewardj9d31dfd2011-03-15 12:36:44 +00002533static UChar *
sewardj2019a972011-03-07 16:04:07 +00002534s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2535{
sewardj652b56a2011-04-13 15:38:17 +00002536 vassert(s390_host_has_ldisp || dh2 == 0);
2537
sewardj7ee97522011-05-09 21:45:04 +00002538 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002539 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2540
2541 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2542}
2543
2544
sewardj9d31dfd2011-03-15 12:36:44 +00002545static UChar *
sewardj2019a972011-03-07 16:04:07 +00002546s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2547{
sewardj652b56a2011-04-13 15:38:17 +00002548 vassert(s390_host_has_eimm);
2549
sewardj7ee97522011-05-09 21:45:04 +00002550 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002551 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2552
2553 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2554}
2555
2556
sewardj9d31dfd2011-03-15 12:36:44 +00002557static UChar *
sewardj2019a972011-03-07 16:04:07 +00002558s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2559{
sewardj7ee97522011-05-09 21:45:04 +00002560 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002561 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2562
2563 return emit_RI(p, 0xa50e0000, r1, i2);
2564}
2565
2566
sewardj9d31dfd2011-03-15 12:36:44 +00002567static UChar *
sewardj2019a972011-03-07 16:04:07 +00002568s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2569{
sewardj7ee97522011-05-09 21:45:04 +00002570 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002571 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2572
2573 return emit_RI(p, 0xa50f0000, r1, i2);
2574}
2575
2576
sewardj9d31dfd2011-03-15 12:36:44 +00002577static UChar *
sewardj2019a972011-03-07 16:04:07 +00002578s390_emit_MR(UChar *p, UChar r1, UChar r2)
2579{
sewardj7ee97522011-05-09 21:45:04 +00002580 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002581 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2582
2583 return emit_RR(p, 0x1c00, r1, r2);
2584}
2585
2586
sewardj9d31dfd2011-03-15 12:36:44 +00002587static UChar *
sewardj2019a972011-03-07 16:04:07 +00002588s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2589{
sewardj7ee97522011-05-09 21:45:04 +00002590 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002591 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2592
2593 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2594}
2595
2596
sewardj9d31dfd2011-03-15 12:36:44 +00002597static UChar *
sewardj2019a972011-03-07 16:04:07 +00002598s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2599{
sewardj652b56a2011-04-13 15:38:17 +00002600 vassert(s390_host_has_gie);
2601
sewardj7ee97522011-05-09 21:45:04 +00002602 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002603 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2604
2605 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2606}
2607
2608
sewardj9d31dfd2011-03-15 12:36:44 +00002609static UChar *
sewardj2019a972011-03-07 16:04:07 +00002610s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2611{
sewardj7ee97522011-05-09 21:45:04 +00002612 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002613 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2614
2615 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2616}
2617
2618
sewardj9d31dfd2011-03-15 12:36:44 +00002619static UChar *
sewardj2019a972011-03-07 16:04:07 +00002620s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2621{
sewardj652b56a2011-04-13 15:38:17 +00002622 vassert(s390_host_has_gie);
2623
sewardj7ee97522011-05-09 21:45:04 +00002624 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002625 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2626
2627 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2628}
2629
2630
sewardj9d31dfd2011-03-15 12:36:44 +00002631static UChar *
sewardj2019a972011-03-07 16:04:07 +00002632s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2633{
sewardj7ee97522011-05-09 21:45:04 +00002634 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002635 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2636
2637 return emit_RI(p, 0xa70c0000, r1, i2);
2638}
2639
2640
sewardj9d31dfd2011-03-15 12:36:44 +00002641static UChar *
sewardj2019a972011-03-07 16:04:07 +00002642s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2643{
sewardj7ee97522011-05-09 21:45:04 +00002644 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002645 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2646
2647 return emit_RRE(p, 0xb9960000, r1, r2);
2648}
2649
2650
sewardj9d31dfd2011-03-15 12:36:44 +00002651static UChar *
sewardj2019a972011-03-07 16:04:07 +00002652s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2653{
sewardj7ee97522011-05-09 21:45:04 +00002654 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002655 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2656
2657 return emit_RRE(p, 0xb9860000, r1, r2);
2658}
2659
2660
sewardj9d31dfd2011-03-15 12:36:44 +00002661static UChar *
sewardj2019a972011-03-07 16:04:07 +00002662s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2663{
sewardj652b56a2011-04-13 15:38:17 +00002664 vassert(s390_host_has_ldisp || dh2 == 0);
2665
sewardj7ee97522011-05-09 21:45:04 +00002666 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002667 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2668
2669 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2670}
2671
2672
sewardj9d31dfd2011-03-15 12:36:44 +00002673static UChar *
sewardj2019a972011-03-07 16:04:07 +00002674s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2675{
sewardj652b56a2011-04-13 15:38:17 +00002676 vassert(s390_host_has_ldisp || dh2 == 0);
2677
sewardj7ee97522011-05-09 21:45:04 +00002678 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002679 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2680
2681 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2682}
2683
2684
sewardj9d31dfd2011-03-15 12:36:44 +00002685static UChar *
sewardj2019a972011-03-07 16:04:07 +00002686s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2687{
sewardj7ee97522011-05-09 21:45:04 +00002688 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002689 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2690
2691 return emit_RRE(p, 0xb2520000, r1, r2);
2692}
2693
2694
sewardj9d31dfd2011-03-15 12:36:44 +00002695static UChar *
sewardj2019a972011-03-07 16:04:07 +00002696s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2697{
sewardj7ee97522011-05-09 21:45:04 +00002698 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002699 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2700
2701 return emit_RRE(p, 0xb90c0000, r1, r2);
2702}
2703
2704
sewardj9d31dfd2011-03-15 12:36:44 +00002705static UChar *
sewardj2019a972011-03-07 16:04:07 +00002706s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2707{
sewardj7ee97522011-05-09 21:45:04 +00002708 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002709 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2710
2711 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2712}
2713
2714
sewardj9d31dfd2011-03-15 12:36:44 +00002715static UChar *
sewardj2019a972011-03-07 16:04:07 +00002716s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2717{
sewardj652b56a2011-04-13 15:38:17 +00002718 vassert(s390_host_has_ldisp);
2719
sewardj7ee97522011-05-09 21:45:04 +00002720 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002721 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2722
2723 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2724}
2725
2726
sewardj9d31dfd2011-03-15 12:36:44 +00002727static UChar *
sewardj2019a972011-03-07 16:04:07 +00002728s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2729{
sewardj652b56a2011-04-13 15:38:17 +00002730 vassert(s390_host_has_ldisp || dh2 == 0);
2731
sewardj7ee97522011-05-09 21:45:04 +00002732 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002733 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2734
2735 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2736}
2737
2738
sewardj9d31dfd2011-03-15 12:36:44 +00002739static UChar *
sewardj2019a972011-03-07 16:04:07 +00002740s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2741{
sewardj652b56a2011-04-13 15:38:17 +00002742 vassert(s390_host_has_gie);
2743
sewardj7ee97522011-05-09 21:45:04 +00002744 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002745 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2746
2747 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2748}
2749
2750
sewardj9d31dfd2011-03-15 12:36:44 +00002751static UChar *
sewardj2019a972011-03-07 16:04:07 +00002752s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2753{
sewardj652b56a2011-04-13 15:38:17 +00002754 vassert(s390_host_has_gie);
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, INT), "msgfi", r1, i2);
2758
2759 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2760}
2761
2762
sewardj9d31dfd2011-03-15 12:36:44 +00002763static UChar *
florianb93348d2012-12-27 00:59:43 +00002764s390_emit_MVI(UChar *p, UChar i2, UChar b1, UShort d1)
2765{
2766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2767 s390_disasm(ENC3(MNM, UDXB, INT), "mvi", b1, 0, d1, i2);
2768
2769 return emit_SI(p, 0x92000000, i2, b1, d1);
2770}
2771
2772
2773static UChar *
2774s390_emit_MVHHI(UChar *p, UChar b1, UShort d1, UShort i2)
2775{
2776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2777 s390_disasm(ENC3(MNM, UDXB, INT), "mvhhi", b1, 0, d1, i2);
2778
2779 return emit_SIL(p, 0xe54400000000ULL, b1, d1, i2);
2780}
2781
2782
2783static UChar *
2784s390_emit_MVHI(UChar *p, UChar b1, UShort d1, UShort i2)
2785{
2786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2787 s390_disasm(ENC3(MNM, UDXB, INT), "mvhi", b1, 0, d1, i2);
2788
2789 return emit_SIL(p, 0xe54c00000000ULL, b1, d1, i2);
2790}
2791
2792
2793static UChar *
2794s390_emit_MVGHI(UChar *p, UChar b1, UShort d1, UShort i2)
2795{
2796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2797 s390_disasm(ENC3(MNM, UDXB, INT), "mvghi", b1, 0, d1, i2);
2798
2799 return emit_SIL(p, 0xe54800000000ULL, b1, d1, i2);
2800}
2801
2802
2803static UChar *
sewardj2019a972011-03-07 16:04:07 +00002804s390_emit_OR(UChar *p, UChar r1, UChar r2)
2805{
sewardj7ee97522011-05-09 21:45:04 +00002806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002807 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2808
2809 return emit_RR(p, 0x1600, r1, r2);
2810}
2811
2812
sewardj9d31dfd2011-03-15 12:36:44 +00002813static UChar *
sewardj2019a972011-03-07 16:04:07 +00002814s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2815{
sewardj7ee97522011-05-09 21:45:04 +00002816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002817 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2818
2819 return emit_RRE(p, 0xb9810000, r1, r2);
2820}
2821
2822
sewardj9d31dfd2011-03-15 12:36:44 +00002823static UChar *
sewardj2019a972011-03-07 16:04:07 +00002824s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2825{
sewardj7ee97522011-05-09 21:45:04 +00002826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002827 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2828
2829 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2830}
2831
2832
sewardj9d31dfd2011-03-15 12:36:44 +00002833static UChar *
sewardj2019a972011-03-07 16:04:07 +00002834s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2835{
sewardj652b56a2011-04-13 15:38:17 +00002836 vassert(s390_host_has_ldisp);
2837
sewardj7ee97522011-05-09 21:45:04 +00002838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002839 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2840
2841 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2842}
2843
2844
sewardj9d31dfd2011-03-15 12:36:44 +00002845static UChar *
sewardj2019a972011-03-07 16:04:07 +00002846s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2847{
sewardj652b56a2011-04-13 15:38:17 +00002848 vassert(s390_host_has_ldisp || dh2 == 0);
2849
sewardj7ee97522011-05-09 21:45:04 +00002850 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002851 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2852
2853 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2854}
2855
2856
sewardj9d31dfd2011-03-15 12:36:44 +00002857static UChar *
sewardj2019a972011-03-07 16:04:07 +00002858s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2859{
sewardj652b56a2011-04-13 15:38:17 +00002860 vassert(s390_host_has_eimm);
2861
sewardj7ee97522011-05-09 21:45:04 +00002862 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002863 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2864
2865 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2866}
2867
2868
sewardj9d31dfd2011-03-15 12:36:44 +00002869static UChar *
sewardj2019a972011-03-07 16:04:07 +00002870s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2871{
sewardj652b56a2011-04-13 15:38:17 +00002872 vassert(s390_host_has_eimm);
2873
sewardj7ee97522011-05-09 21:45:04 +00002874 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002875 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2876
2877 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2878}
2879
2880
sewardj9d31dfd2011-03-15 12:36:44 +00002881static UChar *
sewardj2019a972011-03-07 16:04:07 +00002882s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2883{
sewardj7ee97522011-05-09 21:45:04 +00002884 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002885 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2886
2887 return emit_RI(p, 0xa50b0000, r1, i2);
2888}
2889
2890
sewardj9d31dfd2011-03-15 12:36:44 +00002891static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002892s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002893{
sewardj7ee97522011-05-09 21:45:04 +00002894 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002895 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2896
sewardj3c49aaa2011-04-05 14:00:37 +00002897 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002898}
2899
2900
sewardj9d31dfd2011-03-15 12:36:44 +00002901static UChar *
sewardj2019a972011-03-07 16:04:07 +00002902s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2903{
sewardj652b56a2011-04-13 15:38:17 +00002904 vassert(s390_host_has_ldisp || dh2 == 0);
2905
sewardj7ee97522011-05-09 21:45:04 +00002906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002907 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2908
2909 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2910}
2911
2912
sewardj9d31dfd2011-03-15 12:36:44 +00002913static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002914s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002915{
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, UDXB), "sra", r1, d2, 0, b2);
2918
sewardj3c49aaa2011-04-05 14:00:37 +00002919 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002920}
2921
2922
sewardj9d31dfd2011-03-15 12:36:44 +00002923static UChar *
sewardj2019a972011-03-07 16:04:07 +00002924s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2925{
sewardj652b56a2011-04-13 15:38:17 +00002926 vassert(s390_host_has_ldisp || dh2 == 0);
2927
sewardj7ee97522011-05-09 21:45:04 +00002928 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002929 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2930
2931 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2932}
2933
2934
sewardj9d31dfd2011-03-15 12:36:44 +00002935static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002936s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002937{
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, UDXB), "srl", r1, d2, 0, b2);
2940
sewardj3c49aaa2011-04-05 14:00:37 +00002941 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002942}
2943
2944
sewardj9d31dfd2011-03-15 12:36:44 +00002945static UChar *
sewardj2019a972011-03-07 16:04:07 +00002946s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2947{
sewardj652b56a2011-04-13 15:38:17 +00002948 vassert(s390_host_has_ldisp || dh2 == 0);
2949
sewardj7ee97522011-05-09 21:45:04 +00002950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002951 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
2952
2953 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
2954}
2955
2956
sewardj9d31dfd2011-03-15 12:36:44 +00002957static UChar *
sewardj2019a972011-03-07 16:04:07 +00002958s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2959{
sewardj7ee97522011-05-09 21:45:04 +00002960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002961 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
2962
2963 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
2964}
2965
2966
sewardj9d31dfd2011-03-15 12:36:44 +00002967static UChar *
sewardj2019a972011-03-07 16:04:07 +00002968s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2969{
sewardj652b56a2011-04-13 15:38:17 +00002970 vassert(s390_host_has_ldisp);
2971
sewardj7ee97522011-05-09 21:45:04 +00002972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002973 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
2974
2975 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
2976}
2977
2978
sewardj9d31dfd2011-03-15 12:36:44 +00002979static UChar *
sewardj2019a972011-03-07 16:04:07 +00002980s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2981{
sewardj652b56a2011-04-13 15:38:17 +00002982 vassert(s390_host_has_ldisp || dh2 == 0);
2983
sewardj7ee97522011-05-09 21:45:04 +00002984 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002985 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
2986
2987 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
2988}
2989
2990
sewardj9d31dfd2011-03-15 12:36:44 +00002991static UChar *
sewardj2019a972011-03-07 16:04:07 +00002992s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2993{
sewardj7ee97522011-05-09 21:45:04 +00002994 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002995 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
2996
2997 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
2998}
2999
3000
sewardj9d31dfd2011-03-15 12:36:44 +00003001static UChar *
sewardj2019a972011-03-07 16:04:07 +00003002s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3003{
sewardj652b56a2011-04-13 15:38:17 +00003004 vassert(s390_host_has_ldisp);
3005
sewardj7ee97522011-05-09 21:45:04 +00003006 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003007 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
3008
3009 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
3010}
3011
3012
sewardj9d31dfd2011-03-15 12:36:44 +00003013static UChar *
sewardj2019a972011-03-07 16:04:07 +00003014s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3015{
sewardj7ee97522011-05-09 21:45:04 +00003016 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003017 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
3018
3019 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
3020}
3021
3022
sewardj9d31dfd2011-03-15 12:36:44 +00003023static UChar *
sewardj2019a972011-03-07 16:04:07 +00003024s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3025{
sewardj652b56a2011-04-13 15:38:17 +00003026 vassert(s390_host_has_ldisp);
3027
sewardj7ee97522011-05-09 21:45:04 +00003028 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003029 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
3030
3031 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
3032}
3033
3034
sewardj9d31dfd2011-03-15 12:36:44 +00003035static UChar *
sewardj2019a972011-03-07 16:04:07 +00003036s390_emit_SR(UChar *p, UChar r1, UChar r2)
3037{
sewardj7ee97522011-05-09 21:45:04 +00003038 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003039 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
3040
3041 return emit_RR(p, 0x1b00, r1, r2);
3042}
3043
3044
sewardj9d31dfd2011-03-15 12:36:44 +00003045static UChar *
sewardj2019a972011-03-07 16:04:07 +00003046s390_emit_SGR(UChar *p, UChar r1, UChar r2)
3047{
sewardj7ee97522011-05-09 21:45:04 +00003048 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003049 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
3050
3051 return emit_RRE(p, 0xb9090000, r1, r2);
3052}
3053
3054
sewardj9d31dfd2011-03-15 12:36:44 +00003055static UChar *
sewardj2019a972011-03-07 16:04:07 +00003056s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3057{
sewardj7ee97522011-05-09 21:45:04 +00003058 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003059 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
3060
3061 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
3062}
3063
3064
sewardj9d31dfd2011-03-15 12:36:44 +00003065static UChar *
sewardj2019a972011-03-07 16:04:07 +00003066s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3067{
sewardj652b56a2011-04-13 15:38:17 +00003068 vassert(s390_host_has_ldisp);
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), "sy", r1, dh2, dl2, x2, b2);
3072
3073 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
3074}
3075
3076
sewardj9d31dfd2011-03-15 12:36:44 +00003077static UChar *
sewardj2019a972011-03-07 16:04:07 +00003078s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3079{
sewardj652b56a2011-04-13 15:38:17 +00003080 vassert(s390_host_has_ldisp || dh2 == 0);
3081
sewardj7ee97522011-05-09 21:45:04 +00003082 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003083 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
3084
3085 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
3086}
3087
3088
sewardj9d31dfd2011-03-15 12:36:44 +00003089static UChar *
sewardj2019a972011-03-07 16:04:07 +00003090s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3091{
sewardj7ee97522011-05-09 21:45:04 +00003092 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003093 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
3094
3095 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
3096}
3097
3098
sewardj9d31dfd2011-03-15 12:36:44 +00003099static UChar *
sewardj2019a972011-03-07 16:04:07 +00003100s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3101{
sewardj652b56a2011-04-13 15:38:17 +00003102 vassert(s390_host_has_ldisp);
3103
sewardj7ee97522011-05-09 21:45:04 +00003104 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003105 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
3106
3107 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
3108}
3109
3110
sewardj9d31dfd2011-03-15 12:36:44 +00003111static UChar *
sewardj2019a972011-03-07 16:04:07 +00003112s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
3113{
sewardj652b56a2011-04-13 15:38:17 +00003114 vassert(s390_host_has_eimm);
3115
sewardj7ee97522011-05-09 21:45:04 +00003116 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003117 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
3118
3119 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
3120}
3121
3122
sewardj9d31dfd2011-03-15 12:36:44 +00003123static UChar *
sewardjb13a92a2011-04-13 14:44:29 +00003124s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
3125{
sewardj7ee97522011-05-09 21:45:04 +00003126 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardjb13a92a2011-04-13 14:44:29 +00003127 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
3128
3129 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
3130}
3131
3132
3133static UChar *
sewardj2019a972011-03-07 16:04:07 +00003134s390_emit_LDR(UChar *p, UChar r1, UChar r2)
3135{
sewardj7ee97522011-05-09 21:45:04 +00003136 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003137 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
3138
3139 return emit_RR(p, 0x2800, r1, r2);
3140}
3141
3142
sewardj9d31dfd2011-03-15 12:36:44 +00003143static UChar *
sewardj2019a972011-03-07 16:04:07 +00003144s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3145{
sewardj7ee97522011-05-09 21:45:04 +00003146 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003147 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
3148
3149 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
3150}
3151
3152
sewardj9d31dfd2011-03-15 12:36:44 +00003153static UChar *
sewardj2019a972011-03-07 16:04:07 +00003154s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3155{
sewardj7ee97522011-05-09 21:45:04 +00003156 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003157 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
3158
3159 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
3160}
3161
3162
sewardj9d31dfd2011-03-15 12:36:44 +00003163static UChar *
sewardj2019a972011-03-07 16:04:07 +00003164s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3165{
sewardj652b56a2011-04-13 15:38:17 +00003166 vassert(s390_host_has_ldisp);
3167
sewardj7ee97522011-05-09 21:45:04 +00003168 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003169 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
3170
3171 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
3172}
3173
3174
sewardj9d31dfd2011-03-15 12:36:44 +00003175static UChar *
sewardj2019a972011-03-07 16:04:07 +00003176s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3177{
sewardj652b56a2011-04-13 15:38:17 +00003178 vassert(s390_host_has_ldisp);
3179
sewardj7ee97522011-05-09 21:45:04 +00003180 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003181 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
3182
3183 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
3184}
3185
3186
sewardj9d31dfd2011-03-15 12:36:44 +00003187static UChar *
sewardj2019a972011-03-07 16:04:07 +00003188s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
3189{
sewardj7ee97522011-05-09 21:45:04 +00003190 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003191 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
3192
3193 return emit_S(p, 0xb29d0000, b2, d2);
3194}
3195
3196
sewardj9d31dfd2011-03-15 12:36:44 +00003197static UChar *
sewardj2019a972011-03-07 16:04:07 +00003198s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3199{
sewardjd07b8562011-04-27 11:58:22 +00003200 vassert(s390_host_has_fgx);
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, GPR), "ldgr", r1, r2);
3204
3205 return emit_RRE(p, 0xb3c10000, r1, r2);
3206}
3207
3208
sewardj9d31dfd2011-03-15 12:36:44 +00003209static UChar *
sewardj2019a972011-03-07 16:04:07 +00003210s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3211{
sewardjd07b8562011-04-27 11:58:22 +00003212 vassert(s390_host_has_fgx);
3213
sewardj7ee97522011-05-09 21:45:04 +00003214 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003215 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3216
3217 return emit_RRE(p, 0xb3cd0000, r1, r2);
3218}
3219
3220
sewardj9d31dfd2011-03-15 12:36:44 +00003221static UChar *
sewardj2019a972011-03-07 16:04:07 +00003222s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3223{
sewardj7ee97522011-05-09 21:45:04 +00003224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003225 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3226
3227 return emit_RRE(p, 0xb3740000, r1, r2);
3228}
3229
3230
sewardj9d31dfd2011-03-15 12:36:44 +00003231static UChar *
sewardj2019a972011-03-07 16:04:07 +00003232s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3233{
sewardj7ee97522011-05-09 21:45:04 +00003234 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003235 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3236
3237 return emit_RRE(p, 0xb3750000, r1, r2);
3238}
3239
3240
sewardj9d31dfd2011-03-15 12:36:44 +00003241static UChar *
florian6d8e26e2012-09-12 19:52:16 +00003242s390_emit_SFPC(UChar *p, UChar r1)
sewardj2019a972011-03-07 16:04:07 +00003243{
sewardj7ee97522011-05-09 21:45:04 +00003244 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003245 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3246
florian6d8e26e2012-09-12 19:52:16 +00003247 return emit_RRE(p, 0xb3840000, r1, 0);
sewardj2019a972011-03-07 16:04:07 +00003248}
3249
3250
sewardj9d31dfd2011-03-15 12:36:44 +00003251static UChar *
sewardj2019a972011-03-07 16:04:07 +00003252s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
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, UDXB), "ste", r1, d2, x2, b2);
3256
3257 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3258}
3259
3260
sewardj9d31dfd2011-03-15 12:36:44 +00003261static UChar *
sewardj2019a972011-03-07 16:04:07 +00003262s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3263{
sewardj7ee97522011-05-09 21:45:04 +00003264 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003265 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3266
3267 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3268}
3269
3270
sewardj9d31dfd2011-03-15 12:36:44 +00003271static UChar *
sewardj2019a972011-03-07 16:04:07 +00003272s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3273{
sewardj652b56a2011-04-13 15:38:17 +00003274 vassert(s390_host_has_ldisp);
3275
sewardj7ee97522011-05-09 21:45:04 +00003276 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003277 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3278
3279 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3280}
3281
3282
sewardj9d31dfd2011-03-15 12:36:44 +00003283static UChar *
sewardj2019a972011-03-07 16:04:07 +00003284s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3285{
sewardj652b56a2011-04-13 15:38:17 +00003286 vassert(s390_host_has_ldisp);
3287
sewardj7ee97522011-05-09 21:45:04 +00003288 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003289 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3290
3291 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3292}
3293
3294
sewardj9d31dfd2011-03-15 12:36:44 +00003295static UChar *
sewardj2019a972011-03-07 16:04:07 +00003296s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3297{
sewardj7ee97522011-05-09 21:45:04 +00003298 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003299 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3300
3301 return emit_S(p, 0xb29c0000, b2, d2);
3302}
3303
3304
sewardj9d31dfd2011-03-15 12:36:44 +00003305static UChar *
sewardj2019a972011-03-07 16:04:07 +00003306s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3307{
sewardj7ee97522011-05-09 21:45:04 +00003308 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003309 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3310
3311 return emit_RRE(p, 0xb30a0000, r1, r2);
3312}
3313
3314
sewardj9d31dfd2011-03-15 12:36:44 +00003315static UChar *
sewardj2019a972011-03-07 16:04:07 +00003316s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3317{
sewardj7ee97522011-05-09 21:45:04 +00003318 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003319 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3320
3321 return emit_RRE(p, 0xb31a0000, r1, r2);
3322}
3323
3324
sewardj9d31dfd2011-03-15 12:36:44 +00003325static UChar *
sewardj2019a972011-03-07 16:04:07 +00003326s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3327{
sewardj7ee97522011-05-09 21:45:04 +00003328 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003329 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3330
3331 return emit_RRE(p, 0xb34a0000, r1, r2);
3332}
3333
3334
sewardj9d31dfd2011-03-15 12:36:44 +00003335static UChar *
sewardj2019a972011-03-07 16:04:07 +00003336s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3337{
sewardj7ee97522011-05-09 21:45:04 +00003338 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003339 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3340
3341 return emit_RRE(p, 0xb3090000, r1, r2);
3342}
3343
3344
sewardj9d31dfd2011-03-15 12:36:44 +00003345static UChar *
sewardj2019a972011-03-07 16:04:07 +00003346s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3347{
sewardj7ee97522011-05-09 21:45:04 +00003348 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003349 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3350
3351 return emit_RRE(p, 0xb3190000, r1, r2);
3352}
3353
3354
sewardj9d31dfd2011-03-15 12:36:44 +00003355static UChar *
sewardj2019a972011-03-07 16:04:07 +00003356s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3357{
sewardj7ee97522011-05-09 21:45:04 +00003358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003359 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3360
3361 return emit_RRE(p, 0xb3490000, r1, r2);
3362}
3363
3364
sewardj9d31dfd2011-03-15 12:36:44 +00003365static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003366s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003367{
florian8c3ccaf2012-09-09 18:18:25 +00003368 vassert(m4 == 0);
3369 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003370
florian8c3ccaf2012-09-09 18:18:25 +00003371 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3372 if (m3 == 0)
3373 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3374 else
3375 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3376 "cefbra", r1, m3, r2, m4);
3377 }
3378
3379 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003380}
3381
3382
sewardj9d31dfd2011-03-15 12:36:44 +00003383static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003384s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003385{
florian8c3ccaf2012-09-09 18:18:25 +00003386 vassert(m4 == 0);
3387 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003388
florian8c3ccaf2012-09-09 18:18:25 +00003389 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3390 if (m3 == 0)
3391 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3392 else
3393 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3394 "cdfbra", r1, m3, r2, m4);
3395 }
3396
3397 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003398}
3399
3400
sewardj9d31dfd2011-03-15 12:36:44 +00003401static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003402s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003403{
florian8c3ccaf2012-09-09 18:18:25 +00003404 vassert(m4 == 0);
3405 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003406
florian8c3ccaf2012-09-09 18:18:25 +00003407 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3408 if (m3 == 0)
3409 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3410 else
3411 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3412 "cxfbra", r1, m3, r2, m4);
3413 }
3414
3415 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003416}
3417
3418
sewardj9d31dfd2011-03-15 12:36:44 +00003419static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003420s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003421{
florian8c3ccaf2012-09-09 18:18:25 +00003422 vassert(m4 == 0);
3423 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003424
florian8c3ccaf2012-09-09 18:18:25 +00003425 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3426 if (m3 == 0)
3427 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3428 else
3429 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3430 "cegbra", r1, m3, r2, m4);
3431 }
3432
3433 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003434}
3435
3436
sewardj9d31dfd2011-03-15 12:36:44 +00003437static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003438s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003439{
florian8c3ccaf2012-09-09 18:18:25 +00003440 vassert(m4 == 0);
3441 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003442
florian8c3ccaf2012-09-09 18:18:25 +00003443 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3444 if (m3 == 0)
3445 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3446 else
3447 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3448 "cdgbra", r1, m3, r2, m4);
3449 }
3450
3451 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003452}
3453
3454
sewardj9d31dfd2011-03-15 12:36:44 +00003455static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003456s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003457{
florian8c3ccaf2012-09-09 18:18:25 +00003458 vassert(m4 == 0);
3459 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003460
florian8c3ccaf2012-09-09 18:18:25 +00003461 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3462 if (m3 == 0)
3463 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3464 else
3465 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3466 "cxgbra", r1, m3, r2, m4);
3467 }
3468
3469 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003470}
3471
3472
sewardj9d31dfd2011-03-15 12:36:44 +00003473static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00003474s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3475{
florian606dbeb2012-09-09 18:12:28 +00003476 vassert(m4 == 0);
3477 vassert(s390_host_has_fpext);
3478
florian1c8f7ff2012-09-01 00:12:11 +00003479 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3480 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
3481
3482 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
3483}
3484
3485
3486static UChar *
3487s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3488{
florian606dbeb2012-09-09 18:12:28 +00003489 vassert(m4 == 0);
3490 vassert(s390_host_has_fpext);
3491
florian1c8f7ff2012-09-01 00:12:11 +00003492 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3493 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
3494
3495 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
3496}
3497
3498
3499static UChar *
3500s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3501{
florian606dbeb2012-09-09 18:12:28 +00003502 vassert(m4 == 0);
3503 vassert(s390_host_has_fpext);
3504
florian1c8f7ff2012-09-01 00:12:11 +00003505 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3506 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
3507
3508 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
3509}
3510
3511
3512static UChar *
3513s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3514{
florian606dbeb2012-09-09 18:12:28 +00003515 vassert(m4 == 0);
3516 vassert(s390_host_has_fpext);
3517
florian1c8f7ff2012-09-01 00:12:11 +00003518 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3519 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
3520
3521 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
3522}
3523
3524
3525static UChar *
3526s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3527{
florian606dbeb2012-09-09 18:12:28 +00003528 vassert(m4 == 0);
3529 vassert(s390_host_has_fpext);
3530
florian1c8f7ff2012-09-01 00:12:11 +00003531 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3532 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
3533
3534 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
3535}
3536
3537
3538static UChar *
3539s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3540{
florian606dbeb2012-09-09 18:12:28 +00003541 vassert(m4 == 0);
3542 vassert(s390_host_has_fpext);
3543
florian1c8f7ff2012-09-01 00:12:11 +00003544 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3545 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
3546
3547 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
3548}
3549
3550
3551static UChar *
3552s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3553{
florian606dbeb2012-09-09 18:12:28 +00003554 vassert(m4 == 0);
3555 vassert(s390_host_has_fpext);
3556
florian1c8f7ff2012-09-01 00:12:11 +00003557 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3558 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
3559
3560 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
3561}
3562
3563
3564static UChar *
3565s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3566{
florian606dbeb2012-09-09 18:12:28 +00003567 vassert(m4 == 0);
3568 vassert(s390_host_has_fpext);
3569
florian1c8f7ff2012-09-01 00:12:11 +00003570 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3571 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
3572
3573 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
3574}
3575
3576
3577static UChar *
3578s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3579{
florian606dbeb2012-09-09 18:12:28 +00003580 vassert(m4 == 0);
3581 vassert(s390_host_has_fpext);
3582
florian1c8f7ff2012-09-01 00:12:11 +00003583 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3584 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
3585
3586 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
3587}
3588
3589
3590static UChar *
3591s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3592{
florian606dbeb2012-09-09 18:12:28 +00003593 vassert(m4 == 0);
3594 vassert(s390_host_has_fpext);
3595
florian1c8f7ff2012-09-01 00:12:11 +00003596 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3597 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
3598
3599 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
3600}
3601
3602
3603static UChar *
3604s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3605{
florian606dbeb2012-09-09 18:12:28 +00003606 vassert(m4 == 0);
3607 vassert(s390_host_has_fpext);
3608
florian1c8f7ff2012-09-01 00:12:11 +00003609 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3610 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
3611
3612 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
3613}
3614
3615
3616static UChar *
3617s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3618{
florian606dbeb2012-09-09 18:12:28 +00003619 vassert(m4 == 0);
3620 vassert(s390_host_has_fpext);
3621
florian1c8f7ff2012-09-01 00:12:11 +00003622 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3623 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
3624
3625 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
3626}
3627
3628
3629static UChar *
sewardj2019a972011-03-07 16:04:07 +00003630s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3631{
sewardj7ee97522011-05-09 21:45:04 +00003632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003633 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3634
3635 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3636}
3637
3638
sewardj9d31dfd2011-03-15 12:36:44 +00003639static UChar *
sewardj2019a972011-03-07 16:04:07 +00003640s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3641{
sewardj7ee97522011-05-09 21:45:04 +00003642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003643 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3644
3645 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3646}
3647
3648
sewardj9d31dfd2011-03-15 12:36:44 +00003649static UChar *
sewardj2019a972011-03-07 16:04:07 +00003650s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3651{
sewardj7ee97522011-05-09 21:45:04 +00003652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003653 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3654
3655 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3656}
3657
3658
sewardj9d31dfd2011-03-15 12:36:44 +00003659static UChar *
sewardj2019a972011-03-07 16:04:07 +00003660s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3661{
sewardj7ee97522011-05-09 21:45:04 +00003662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003663 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3664
3665 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3666}
3667
3668
sewardj9d31dfd2011-03-15 12:36:44 +00003669static UChar *
sewardj2019a972011-03-07 16:04:07 +00003670s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3671{
sewardj7ee97522011-05-09 21:45:04 +00003672 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003673 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3674
3675 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3676}
3677
3678
sewardj9d31dfd2011-03-15 12:36:44 +00003679static UChar *
sewardj2019a972011-03-07 16:04:07 +00003680s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3681{
sewardj7ee97522011-05-09 21:45:04 +00003682 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003683 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3684
3685 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3686}
3687
3688
sewardj9d31dfd2011-03-15 12:36:44 +00003689static UChar *
sewardj2019a972011-03-07 16:04:07 +00003690s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3691{
sewardj7ee97522011-05-09 21:45:04 +00003692 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003693 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3694
3695 return emit_RRE(p, 0xb30d0000, r1, r2);
3696}
3697
3698
sewardj9d31dfd2011-03-15 12:36:44 +00003699static UChar *
sewardj2019a972011-03-07 16:04:07 +00003700s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3701{
sewardj7ee97522011-05-09 21:45:04 +00003702 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003703 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3704
3705 return emit_RRE(p, 0xb31d0000, r1, r2);
3706}
3707
3708
sewardj9d31dfd2011-03-15 12:36:44 +00003709static UChar *
sewardj2019a972011-03-07 16:04:07 +00003710s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3711{
sewardj7ee97522011-05-09 21:45:04 +00003712 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003713 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3714
3715 return emit_RRE(p, 0xb34d0000, r1, r2);
3716}
3717
3718
sewardj9d31dfd2011-03-15 12:36:44 +00003719static UChar *
sewardj2019a972011-03-07 16:04:07 +00003720s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3721{
sewardj7ee97522011-05-09 21:45:04 +00003722 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003723 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3724
3725 return emit_RRE(p, 0xb3030000, r1, r2);
3726}
3727
3728
sewardj9d31dfd2011-03-15 12:36:44 +00003729static UChar *
sewardj2019a972011-03-07 16:04:07 +00003730s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3731{
sewardj7ee97522011-05-09 21:45:04 +00003732 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003733 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3734
3735 return emit_RRE(p, 0xb3130000, r1, r2);
3736}
3737
3738
sewardj9d31dfd2011-03-15 12:36:44 +00003739static UChar *
sewardj2019a972011-03-07 16:04:07 +00003740s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3741{
sewardj7ee97522011-05-09 21:45:04 +00003742 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003743 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3744
3745 return emit_RRE(p, 0xb3430000, r1, r2);
3746}
3747
3748
sewardj9d31dfd2011-03-15 12:36:44 +00003749static UChar *
sewardj2019a972011-03-07 16:04:07 +00003750s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3751{
sewardj7ee97522011-05-09 21:45:04 +00003752 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003753 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3754
3755 return emit_RRE(p, 0xb3040000, r1, r2);
3756}
3757
3758
sewardj9d31dfd2011-03-15 12:36:44 +00003759static UChar *
sewardj2019a972011-03-07 16:04:07 +00003760s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3761{
sewardj7ee97522011-05-09 21:45:04 +00003762 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003763 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3764
3765 return emit_RRE(p, 0xb3050000, r1, r2);
3766}
3767
3768
sewardj9d31dfd2011-03-15 12:36:44 +00003769static UChar *
sewardj2019a972011-03-07 16:04:07 +00003770s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3771{
sewardj7ee97522011-05-09 21:45:04 +00003772 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003773 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3774
3775 return emit_RRE(p, 0xb3060000, r1, r2);
3776}
3777
3778
sewardj9d31dfd2011-03-15 12:36:44 +00003779static UChar *
sewardj2019a972011-03-07 16:04:07 +00003780s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3781{
sewardj7ee97522011-05-09 21:45:04 +00003782 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003783 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3784
3785 return emit_RRE(p, 0xb3010000, r1, r2);
3786}
3787
3788
sewardj9d31dfd2011-03-15 12:36:44 +00003789static UChar *
sewardj2019a972011-03-07 16:04:07 +00003790s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3791{
sewardj7ee97522011-05-09 21:45:04 +00003792 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003793 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3794
3795 return emit_RRE(p, 0xb3110000, r1, r2);
3796}
3797
3798
sewardj9d31dfd2011-03-15 12:36:44 +00003799static UChar *
sewardj2019a972011-03-07 16:04:07 +00003800s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3801{
sewardj7ee97522011-05-09 21:45:04 +00003802 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003803 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3804
3805 return emit_RRE(p, 0xb3410000, r1, r2);
3806}
3807
3808
sewardj9d31dfd2011-03-15 12:36:44 +00003809static UChar *
sewardj2019a972011-03-07 16:04:07 +00003810s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3811{
sewardj7ee97522011-05-09 21:45:04 +00003812 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003813 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3814
3815 return emit_RRE(p, 0xb3000000, r1, r2);
3816}
3817
3818
sewardj9d31dfd2011-03-15 12:36:44 +00003819static UChar *
sewardj2019a972011-03-07 16:04:07 +00003820s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3821{
sewardj7ee97522011-05-09 21:45:04 +00003822 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003823 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3824
3825 return emit_RRE(p, 0xb3100000, r1, r2);
3826}
3827
3828
sewardj9d31dfd2011-03-15 12:36:44 +00003829static UChar *
sewardj2019a972011-03-07 16:04:07 +00003830s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3831{
sewardj7ee97522011-05-09 21:45:04 +00003832 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003833 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3834
3835 return emit_RRE(p, 0xb3400000, r1, r2);
3836}
3837
3838
sewardj9d31dfd2011-03-15 12:36:44 +00003839static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003840s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003841{
florian8c3ccaf2012-09-09 18:18:25 +00003842 vassert(m4 == 0);
3843 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003844
florian8c3ccaf2012-09-09 18:18:25 +00003845 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3846 if (m3 == 0)
3847 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3848 else
3849 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3850 "ledbra", r1, m3, r2, m4);
3851 }
3852
3853 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003854}
3855
3856
sewardj9d31dfd2011-03-15 12:36:44 +00003857static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003858s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003859{
florian8c3ccaf2012-09-09 18:18:25 +00003860 vassert(m4 == 0);
3861 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003862
florian8c3ccaf2012-09-09 18:18:25 +00003863 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3864 if (m3 == 0)
3865 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3866 else
3867 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3868 "ldxbra", r1, m3, r2, m4);
3869 }
3870
3871 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003872}
3873
3874
sewardj9d31dfd2011-03-15 12:36:44 +00003875static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003876s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003877{
florian8c3ccaf2012-09-09 18:18:25 +00003878 vassert(m4 == 0);
3879 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003880
florian8c3ccaf2012-09-09 18:18:25 +00003881 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3882 if (m3 == 0)
3883 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3884 else
3885 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3886 "lexbra", r1, m3, r2, m4);
3887 }
3888
3889 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003890}
3891
3892
sewardj9d31dfd2011-03-15 12:36:44 +00003893static UChar *
sewardj2019a972011-03-07 16:04:07 +00003894s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3895{
sewardj7ee97522011-05-09 21:45:04 +00003896 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003897 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3898
3899 return emit_RRE(p, 0xb3170000, r1, r2);
3900}
3901
3902
sewardj9d31dfd2011-03-15 12:36:44 +00003903static UChar *
sewardj2019a972011-03-07 16:04:07 +00003904s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3905{
sewardj7ee97522011-05-09 21:45:04 +00003906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003907 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3908
3909 return emit_RRE(p, 0xb31c0000, r1, r2);
3910}
3911
3912
sewardj9d31dfd2011-03-15 12:36:44 +00003913static UChar *
sewardj2019a972011-03-07 16:04:07 +00003914s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3915{
sewardj7ee97522011-05-09 21:45:04 +00003916 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003917 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3918
3919 return emit_RRE(p, 0xb34c0000, r1, r2);
3920}
3921
3922
sewardj9d31dfd2011-03-15 12:36:44 +00003923static UChar *
sewardj2019a972011-03-07 16:04:07 +00003924s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3925{
sewardj7ee97522011-05-09 21:45:04 +00003926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003927 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3928
3929 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3930}
3931
3932
sewardj9d31dfd2011-03-15 12:36:44 +00003933static UChar *
sewardj2019a972011-03-07 16:04:07 +00003934s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3935{
sewardj7ee97522011-05-09 21:45:04 +00003936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003937 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3938
3939 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3940}
3941
3942
sewardj9d31dfd2011-03-15 12:36:44 +00003943static UChar *
sewardj2019a972011-03-07 16:04:07 +00003944s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3945{
sewardj7ee97522011-05-09 21:45:04 +00003946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003947 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3948
3949 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3950}
3951
3952
sewardj9d31dfd2011-03-15 12:36:44 +00003953static UChar *
sewardj2019a972011-03-07 16:04:07 +00003954s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3955{
sewardj7ee97522011-05-09 21:45:04 +00003956 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003957 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3958
3959 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
3960}
3961
3962
sewardj9d31dfd2011-03-15 12:36:44 +00003963static UChar *
sewardj2019a972011-03-07 16:04:07 +00003964s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
3965{
sewardj7ee97522011-05-09 21:45:04 +00003966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003967 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
3968
3969 return emit_RRE(p, 0xb3140000, r1, r2);
3970}
3971
3972
sewardj9d31dfd2011-03-15 12:36:44 +00003973static UChar *
sewardj2019a972011-03-07 16:04:07 +00003974s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
3975{
sewardj7ee97522011-05-09 21:45:04 +00003976 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003977 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
3978
3979 return emit_RRE(p, 0xb3150000, r1, r2);
3980}
3981
3982
sewardj9d31dfd2011-03-15 12:36:44 +00003983static UChar *
sewardj2019a972011-03-07 16:04:07 +00003984s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
3985{
sewardj7ee97522011-05-09 21:45:04 +00003986 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003987 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
3988
3989 return emit_RRE(p, 0xb3160000, r1, r2);
3990}
3991
3992
sewardj9d31dfd2011-03-15 12:36:44 +00003993static UChar *
sewardj2019a972011-03-07 16:04:07 +00003994s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
3995{
sewardj7ee97522011-05-09 21:45:04 +00003996 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003997 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
3998
3999 return emit_RRE(p, 0xb30b0000, r1, r2);
4000}
4001
4002
sewardj9d31dfd2011-03-15 12:36:44 +00004003static UChar *
sewardj2019a972011-03-07 16:04:07 +00004004s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
4005{
sewardj7ee97522011-05-09 21:45:04 +00004006 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004007 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
4008
4009 return emit_RRE(p, 0xb31b0000, r1, r2);
4010}
4011
4012
sewardj9d31dfd2011-03-15 12:36:44 +00004013static UChar *
sewardj2019a972011-03-07 16:04:07 +00004014s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
4015{
sewardj7ee97522011-05-09 21:45:04 +00004016 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004017 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
4018
4019 return emit_RRE(p, 0xb34b0000, r1, r2);
4020}
4021
sewardj2019a972011-03-07 16:04:07 +00004022
florian12390202012-11-10 22:34:14 +00004023static UChar *
4024s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4025{
4026 vassert(s390_host_has_dfp);
4027 vassert(m4 == 0 || s390_host_has_fpext);
4028 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4029 if (m4 == 0)
4030 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
4031 else
florianb3764a92012-12-20 14:44:42 +00004032 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004033 }
4034
4035 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
4036}
4037
4038
4039static UChar *
floriane38f6412012-12-21 17:32:12 +00004040s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4041{
4042 vassert(s390_host_has_dfp);
4043 vassert(m4 == 0 || s390_host_has_fpext);
4044 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4045 if (m4 == 0)
4046 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
4047 else
4048 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
4049 }
4050
4051 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
4052}
4053
4054
4055static UChar *
4056s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
4057{
4058 vassert(s390_host_has_dfp);
4059 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4060 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
4061
4062 return emit_RRE(p, 0xb3e40000, r1, r2);
4063}
4064
4065
4066static UChar *
4067s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
4068{
4069 vassert(s390_host_has_dfp);
4070 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4071 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
4072
4073 return emit_RRE(p, 0xb3ec0000, r1, r2);
4074}
4075
4076
4077static UChar *
florian20c6bca2012-12-26 17:47:19 +00004078s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
4079{
4080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4081 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
4082
4083 return emit_RRE(p, 0xb3f40000, r1, r2);
4084}
4085
4086
4087static UChar *
4088s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
4089{
4090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4091 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
4092
4093 return emit_RRE(p, 0xb3fc0000, r1, r2);
4094}
4095
4096
4097static UChar *
florian12390202012-11-10 22:34:14 +00004098s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4099{
4100 vassert(s390_host_has_dfp);
4101 vassert(m4 == 0 || s390_host_has_fpext);
4102 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4103 if (m4 == 0)
4104 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
4105 else
florianb3764a92012-12-20 14:44:42 +00004106 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004107 }
4108
4109 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
4110}
4111
4112
4113static UChar *
floriane38f6412012-12-21 17:32:12 +00004114s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4115{
4116 vassert(s390_host_has_dfp);
4117 vassert(m4 == 0 || s390_host_has_fpext);
4118 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4119 if (m4 == 0)
4120 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
4121 else
4122 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
4123 }
4124
4125 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
4126}
4127
4128
4129static UChar *
4130s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
4131{
4132 vassert(s390_host_has_dfp);
4133 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4134 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
4135
4136 return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
4137}
4138
4139
4140static UChar *
4141s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
4142{
4143 vassert(s390_host_has_dfp);
4144 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4145 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
4146
4147 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
4148}
4149
4150
4151static UChar *
4152s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4153{
4154 vassert(s390_host_has_dfp);
4155 vassert(m4 == 0);
4156 vassert(m3 == 0 || s390_host_has_fpext);
4157
4158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4159 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4160 "ledtr", r1, m3, r2, m4);
4161 }
4162
4163 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
4164}
4165
4166
4167static UChar *
4168s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4169{
4170 vassert(s390_host_has_dfp);
4171 vassert(m4 == 0);
4172 vassert(m3 == 0 || s390_host_has_fpext);
4173
4174 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4175 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4176 "ldxtr", r1, m3, r2, m4);
4177 }
4178
4179 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
4180}
4181
4182
4183static UChar *
florian12390202012-11-10 22:34:14 +00004184s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4185{
4186 vassert(s390_host_has_dfp);
4187 vassert(m4 == 0 || s390_host_has_fpext);
4188 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4189 if (m4 == 0)
4190 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
4191 else
florianb3764a92012-12-20 14:44:42 +00004192 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004193 }
4194
4195 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
4196}
4197
4198
4199static UChar *
floriane38f6412012-12-21 17:32:12 +00004200s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4201{
4202 vassert(s390_host_has_dfp);
4203 vassert(m4 == 0 || s390_host_has_fpext);
4204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4205 if (m4 == 0)
4206 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
4207 else
4208 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
4209 }
4210
4211 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
4212}
4213
4214
4215static UChar *
florian12390202012-11-10 22:34:14 +00004216s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4217{
4218 vassert(s390_host_has_dfp);
4219 vassert(m4 == 0 || s390_host_has_fpext);
4220 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4221 if (m4 == 0)
4222 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
4223 else
florianb3764a92012-12-20 14:44:42 +00004224 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004225 }
4226
4227 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
4228}
4229
florian3a3d7f12012-12-03 13:32:05 +00004230
4231static UChar *
floriane38f6412012-12-21 17:32:12 +00004232s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4233{
4234 vassert(s390_host_has_dfp);
4235 vassert(m4 == 0 || s390_host_has_fpext);
4236 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4237 if (m4 == 0)
4238 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
4239 else
4240 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
4241 }
4242
4243 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
4244}
4245
4246
4247static UChar *
florian3a3d7f12012-12-03 13:32:05 +00004248s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
4249{
florianaec8e052012-12-09 17:26:32 +00004250 vassert(s390_host_has_lsc);
florian3a3d7f12012-12-03 13:32:05 +00004251 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4252 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
4253 }
4254
4255 return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
4256}
4257
4258
4259static UChar *
4260s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4261{
4262 vassert(s390_host_has_ldisp || dh2 == 0);
4263
4264 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4265 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
4266
4267 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
4268}
4269
4270
4271static UChar *
4272s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4273{
4274 vassert(s390_host_has_ldisp || dh2 == 0);
4275
4276 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4277 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
4278
4279 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
4280}
4281
4282
sewardj2019a972011-03-07 16:04:07 +00004283/* Provide a symbolic name for register "R0" */
4284#define R0 0
4285
4286/* Split up a 20-bit displacement into its high and low piece
4287 suitable for passing as function arguments */
sewardjcd2b0252011-05-09 20:35:41 +00004288#define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
sewardj2019a972011-03-07 16:04:07 +00004289
4290/*---------------------------------------------------------------*/
4291/*--- Helper functions ---*/
4292/*---------------------------------------------------------------*/
4293
4294static __inline__ Bool
4295uint_fits_signed_16bit(UInt val)
4296{
florianffbd84d2012-12-09 02:06:29 +00004297 Int v = val & 0xFFFFu;
sewardj2019a972011-03-07 16:04:07 +00004298
4299 /* sign extend */
4300 v = (v << 16) >> 16;
4301
4302 return val == (UInt)v;
4303}
4304
4305
4306static __inline__ Bool
4307ulong_fits_signed_16bit(ULong val)
4308{
4309 Long v = val & 0xFFFFu;
4310
4311 /* sign extend */
4312 v = (v << 48) >> 48;
4313
4314 return val == (ULong)v;
4315}
4316
4317
4318static __inline__ Bool
4319ulong_fits_signed_32bit(ULong val)
4320{
4321 Long v = val & 0xFFFFFFFFu;
4322
4323 /* sign extend */
4324 v = (v << 32) >> 32;
4325
4326 return val == (ULong)v;
4327}
4328
4329
4330static __inline__ Bool
4331ulong_fits_unsigned_32bit(ULong val)
4332{
4333 return (val & 0xFFFFFFFFu) == val;
4334}
4335
4336
4337/* Load a 64-bit immediate VAL into register REG. */
4338static UChar *
4339s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
4340{
4341 if (ulong_fits_signed_16bit(val)) {
4342 return s390_emit_LGHI(p, reg, val);
4343 }
4344
4345 if (s390_host_has_eimm) {
4346 if (ulong_fits_unsigned_32bit(val)) {
4347 return s390_emit_LLILF(p, reg, val);
4348 }
4349 if (ulong_fits_signed_32bit(val)) {
4350 /* LGFI's sign extension will recreate the correct 64-bit value */
4351 return s390_emit_LGFI(p, reg, val);
4352 }
4353 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
4354 p = s390_emit_IIHF(p, reg, val >> 32);
4355 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
4356 }
4357
4358 /* Fall back */
4359 if (ulong_fits_unsigned_32bit(val)) {
4360 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
4361 val[0:31] = 0 */
4362 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
4363 return p;
4364 }
4365
4366 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
4367 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
4368 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4369 p = s390_emit_IILL(p, reg, val & 0xFFFF);
4370
4371 return p;
4372}
4373
4374/* Load a 32-bit immediate VAL into register REG. */
4375static UChar *
4376s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
4377{
4378 if (uint_fits_signed_16bit(val)) {
4379 /* LHI's sign extension will recreate the correct 32-bit value */
4380 return s390_emit_LHI(p, reg, val);
4381 }
4382 if (s390_host_has_eimm) {
4383 return s390_emit_IILF(p, reg, val);
4384 }
4385 /* val[0:15] --> (val >> 16) & 0xFFFF
4386 val[16:31] --> val & 0xFFFF */
4387 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4388 return s390_emit_IILL(p, reg, val & 0xFFFF);
4389}
4390
4391/*------------------------------------------------------------*/
4392/*--- Wrapper functions ---*/
4393/*------------------------------------------------------------*/
4394
sewardjeae8db52011-03-24 09:01:50 +00004395/* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
sewardj2019a972011-03-07 16:04:07 +00004396static UChar *
4397s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4398{
4399 if (s390_host_has_gie) {
4400 return s390_emit_MFY(p, r1, x, b, dl, dh);
4401 }
4402
4403 /* Load from memory into R0, then MULTIPLY with R1 */
4404 p = s390_emit_LY(p, R0, x, b, dl, dh);
4405 return s390_emit_MR(p, r1, R0);
4406}
4407
sewardjeae8db52011-03-24 09:01:50 +00004408/* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
4409static UChar *
4410s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4411{
4412 if (s390_host_has_gie) {
4413 return s390_emit_MHY(p, r1, x, b, dl, dh);
4414 }
4415
4416 /* Load from memory into R0, then MULTIPLY with R1 */
4417 p = s390_emit_LHY(p, R0, x, b, dl, dh);
4418 return s390_emit_MSR(p, r1, R0);
4419}
4420
sewardj2019a972011-03-07 16:04:07 +00004421/* r1[32:63] = r1[32:63] * i2 */
4422static UChar *
4423s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
4424{
4425 if (s390_host_has_gie) {
4426 return s390_emit_MSFI(p, r1, i2);
4427 }
4428
4429 /* Load I2 into R0; then MULTIPLY R0 with R1 */
4430 p = s390_emit_load_32imm(p, R0, i2);
4431 return s390_emit_MSR(p, r1, R0);
4432}
4433
4434
4435/* r1[32:63] = r1[32:63] & i2 */
4436static UChar *
4437s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
4438{
4439 if (s390_host_has_eimm) {
4440 return s390_emit_NILF(p, r1, i2);
4441 }
4442
4443 /* Load I2 into R0; then AND R0 with R1 */
4444 p = s390_emit_load_32imm(p, R0, i2);
4445 return s390_emit_NR(p, r1, R0);
4446}
4447
4448
4449/* r1[32:63] = r1[32:63] | i2 */
4450static UChar *
4451s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
4452{
4453 if (s390_host_has_eimm) {
4454 return s390_emit_OILF(p, r1, i2);
4455 }
4456
4457 /* Load I2 into R0; then AND R0 with R1 */
4458 p = s390_emit_load_32imm(p, R0, i2);
4459 return s390_emit_OR(p, r1, R0);
4460}
4461
4462
4463/* r1[32:63] = r1[32:63] ^ i2 */
4464static UChar *
4465s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
4466{
4467 if (s390_host_has_eimm) {
4468 return s390_emit_XILF(p, r1, i2);
4469 }
4470
4471 /* Load I2 into R0; then AND R0 with R1 */
4472 p = s390_emit_load_32imm(p, R0, i2);
4473 return s390_emit_XR(p, r1, R0);
4474}
4475
4476
sewardj652b56a2011-04-13 15:38:17 +00004477/* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
4478static UChar *
4479s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
4480{
4481 vassert(s390_host_has_ldisp || dh2 == 0);
4482
4483 if (s390_host_has_ldisp) {
4484 return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
4485 }
4486
4487 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
4488 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4489 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
4490}
4491
4492
sewardj2019a972011-03-07 16:04:07 +00004493/* r1[32:63] = sign_extend(r2[56:63]) */
4494static UChar *
4495s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
4496{
4497 if (s390_host_has_eimm) {
4498 return s390_emit_LBR(p, r1, r2);
4499 }
4500
4501 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004502 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4503 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
sewardj2019a972011-03-07 16:04:07 +00004504}
4505
4506
sewardj652b56a2011-04-13 15:38:17 +00004507/* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
4508static UChar *
4509s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
4510{
4511 vassert(s390_host_has_ldisp || dh2 == 0);
4512
4513 if (s390_host_has_ldisp) {
4514 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
4515 }
4516
4517 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
4518 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4519 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4520}
4521
4522
sewardj2019a972011-03-07 16:04:07 +00004523/* r1[0:63] = sign_extend(r2[56:63]) */
4524static UChar *
4525s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
4526{
4527 if (s390_host_has_eimm) {
4528 return s390_emit_LGBR(p, r1, r2);
4529 }
4530
4531 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4532 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4533 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4534}
4535
4536
4537/* r1[32:63] = sign_extend(r2[48:63]) */
4538static UChar *
4539s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
4540{
4541 if (s390_host_has_eimm) {
4542 return s390_emit_LHR(p, r1, r2);
4543 }
4544
4545 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004546 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
4547 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
sewardj2019a972011-03-07 16:04:07 +00004548}
4549
4550
4551/* r1[0:63] = sign_extend(r2[48:63]) */
4552static UChar *
4553s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
4554{
4555 if (s390_host_has_eimm) {
4556 return s390_emit_LGHR(p, r1, r2);
4557 }
4558
4559 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4560 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
4561 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
4562}
4563
4564
4565/* r1[0:63] = sign_extend(i2) */
4566static UChar *
4567s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
4568{
4569 if (s390_host_has_eimm) {
4570 return s390_emit_LGFI(p, r1, i2);
4571 }
4572
4573 p = s390_emit_load_32imm(p, R0, i2);
4574 return s390_emit_LGFR(p, r1, R0);
4575}
4576
4577
4578/* r1[32:63] = zero_extend($r2[56:63]) */
4579static UChar *
4580s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
4581{
4582 if (s390_host_has_eimm) {
4583 return s390_emit_LLCR(p, r1, r2);
4584 }
4585
4586 p = s390_emit_LR(p, r1, r2);
4587 p = s390_emit_LHI(p, R0, 0xFF);
4588 return s390_emit_NR(p, r1, R0);
4589}
4590
4591
4592/* r1[0:63] = zero_extend($r2[56:63]) */
4593static UChar *
4594s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
4595{
4596 if (s390_host_has_eimm) {
4597 return s390_emit_LLGCR(p, r1, r2);
4598 }
4599
4600 p = s390_emit_LR(p, r1, r2);
4601 p = s390_emit_LLILL(p, R0, 0xFF);
4602 return s390_emit_NGR(p, r1, R0);
4603}
4604
4605
4606/* r1[32:63] = zero_extend(r2[48:63]) */
4607static UChar *
4608s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
4609{
4610 if (s390_host_has_eimm) {
4611 return s390_emit_LLHR(p, r1, r2);
4612 }
4613
4614 p = s390_emit_LR(p, r1, r2);
4615 p = s390_emit_LLILL(p, R0, 0xFFFF);
4616 return s390_emit_NR(p, r1, R0);
4617}
4618
4619
4620/* r1[0:63] = zero_extend(r2[48:63]) */
4621static UChar *
4622s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
4623{
4624 if (s390_host_has_eimm) {
4625 return s390_emit_LLGHR(p, r1, r2);
4626 }
4627
4628 p = s390_emit_LR(p, r1, r2);
4629 p = s390_emit_LLILL(p, R0, 0xFFFF);
4630 return s390_emit_NGR(p, r1, R0);
4631}
4632
4633
4634/* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
4635static UChar *
4636s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4637{
4638 if (s390_host_has_eimm) {
4639 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
4640 }
4641
4642 if (dh == 0) {
4643 p = s390_emit_IC(p, r1, x2, b2, dl);
4644 } else {
4645 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
4646 }
4647 p = s390_emit_LLILL(p, R0, 0xFF);
4648 return s390_emit_NR(p, r1, R0);
4649}
4650
4651
4652/* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
4653static UChar *
4654s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4655{
4656 if (s390_host_has_eimm) {
4657 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
4658 }
4659
4660 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
4661 p = s390_emit_LLILL(p, R0, 0xFFFF);
4662 return s390_emit_NR(p, r1, R0);
4663}
4664
4665
4666/* r1[0:63] = zero_extend(i2) */
4667static UChar *
4668s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
4669{
4670 if (s390_host_has_eimm) {
4671 return s390_emit_LLILF(p, r1, i2);
4672 }
4673
4674 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
4675 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
4676}
4677
4678
4679/* r1[32:63] = r1[32:63] + i2 */
4680static UChar *
4681s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
4682{
4683 if (s390_host_has_eimm) {
4684 return s390_emit_AFI(p, r1, i2);
4685 }
4686 /* Load 32 bit immediate to R0 then add */
4687 p = s390_emit_load_32imm(p, R0, i2);
4688 return s390_emit_AR(p, r1, R0);
4689}
4690
4691
4692/* r1[32:63] = r1[32:63] - i2 */
4693static UChar *
4694s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
4695{
4696 if (s390_host_has_eimm) {
4697 return s390_emit_SLFI(p, r1, i2);
4698 }
4699
4700 /* Load 32 bit immediate to R0 then subtract */
4701 p = s390_emit_load_32imm(p, R0, i2);
4702 return s390_emit_SR(p, r1, R0);
4703}
4704
4705
sewardjb13a92a2011-04-13 14:44:29 +00004706/* r1[0:63] = r1[0:63] - zero_extend(i2) */
4707static UChar *
4708s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
4709{
4710 if (s390_host_has_eimm) {
4711 return s390_emit_SLGFI(p, r1, i2);
4712 }
4713
4714 /* Load zero-extended 32 bit immediate to R0 then subtract */
4715 p = s390_emit_load_64imm(p, R0, i2);
4716 return s390_emit_SGR(p, r1, R0);
4717}
4718
4719
sewardj2019a972011-03-07 16:04:07 +00004720static UChar *
4721s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4722{
4723 if (s390_host_has_eimm) {
4724 return s390_emit_LT(p, r1, x2, b2, dl, dh);
4725 }
4726 /* Load 32 bit from memory to R0 then compare */
4727 if (dh == 0) {
4728 p = s390_emit_L(p, R0, x2, b2, dl);
4729 } else {
4730 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
4731 }
4732 return s390_emit_LTR(p, r1, R0);
4733}
4734
4735
4736static UChar *
4737s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4738{
4739 if (s390_host_has_eimm) {
4740 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
4741 }
4742 /* Load 64 bit from memory to R0 then compare */
4743 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
4744 return s390_emit_LTGR(p, r1, R0);
4745}
4746
4747
4748static UChar *
4749s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
4750{
4751 if (s390_host_has_eimm) {
4752 return s390_emit_CFI(p, r1, i2);
4753 }
4754 /* Load 32 bit immediate to R0 then compare */
4755 p = s390_emit_load_32imm(p, R0, i2);
4756 return s390_emit_CR(p, r1, R0);
4757}
4758
4759
4760static UChar *
4761s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
4762{
4763 if (s390_host_has_eimm) {
4764 return s390_emit_CLFI(p, r1, i2);
4765 }
4766 /* Load 32 bit immediate to R0 then compare */
4767 p = s390_emit_load_32imm(p, R0, i2);
4768 return s390_emit_CLR(p, r1, R0);
4769}
4770
sewardjd07b8562011-04-27 11:58:22 +00004771
4772static UChar *
4773s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
4774{
4775 if (s390_host_has_fgx) {
4776 return s390_emit_LGDR(p, r1, r2);
4777 }
4778
4779 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
4780 smaller addresses and is 8-byte aligned. Then load the GPR from that
4781 memory location/ */
4782 if (s390_host_has_ldisp) {
4783 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4784 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4785 }
4786
4787 /* No long displacement. Need to adjust SP explicitly as to avoid negative
4788 displacements. */
4789 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4790 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
4791 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4792 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4793}
4794
4795
4796static UChar *
4797s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
4798{
4799 if (s390_host_has_fgx) {
4800 return s390_emit_LDGR(p, r1, r2);
4801 }
4802
4803 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
4804 smaller addresses and is 8-byte aligned. Then load the FPR from that
4805 memory location/ */
4806 if (s390_host_has_ldisp) {
4807 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4808 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4809 }
4810
4811 /* No long displacement. Need to adjust SP explicitly as to avoid negative
4812 displacements. */
4813 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4814 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4815 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
4816 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4817}
4818
4819
sewardj2019a972011-03-07 16:04:07 +00004820/*---------------------------------------------------------------*/
4821/*--- Constructors for the various s390_insn kinds ---*/
4822/*---------------------------------------------------------------*/
4823
4824s390_insn *
4825s390_insn_load(UChar size, HReg dst, s390_amode *src)
4826{
4827 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4828
4829 insn->tag = S390_INSN_LOAD;
4830 insn->size = size;
4831 insn->variant.load.src = src;
4832 insn->variant.load.dst = dst;
4833
4834 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4835
4836 return insn;
4837}
4838
4839
4840s390_insn *
4841s390_insn_store(UChar size, s390_amode *dst, HReg src)
4842{
4843 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4844
4845 insn->tag = S390_INSN_STORE;
4846 insn->size = size;
4847 insn->variant.store.src = src;
4848 insn->variant.store.dst = dst;
4849
4850 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4851
4852 return insn;
4853}
4854
4855
4856s390_insn *
4857s390_insn_move(UChar size, HReg dst, HReg src)
4858{
4859 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4860
4861 insn->tag = S390_INSN_MOVE;
4862 insn->size = size;
4863 insn->variant.move.src = src;
4864 insn->variant.move.dst = dst;
4865
4866 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4867
4868 return insn;
4869}
4870
4871
4872s390_insn *
4873s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
4874{
4875 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4876
4877 insn->tag = S390_INSN_COND_MOVE;
4878 insn->size = size;
4879 insn->variant.cond_move.cond = cond;
4880 insn->variant.cond_move.src = src;
4881 insn->variant.cond_move.dst = dst;
4882
4883 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4884
4885 return insn;
4886}
4887
4888
4889s390_insn *
4890s390_insn_load_immediate(UChar size, HReg dst, ULong value)
4891{
4892 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4893
4894 insn->tag = S390_INSN_LOAD_IMMEDIATE;
4895 insn->size = size;
4896 insn->variant.load_immediate.dst = dst;
4897 insn->variant.load_immediate.value = value;
4898
4899 return insn;
4900}
4901
4902
4903s390_insn *
4904s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
4905{
4906 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4907
4908 insn->tag = S390_INSN_ALU;
4909 insn->size = size;
4910 insn->variant.alu.tag = tag;
4911 insn->variant.alu.dst = dst;
4912 insn->variant.alu.op2 = op2;
4913
4914 return insn;
4915}
4916
4917
4918s390_insn *
4919s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
4920 Bool signed_multiply)
4921{
4922 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4923
4924 vassert(! hregIsVirtual(dst_hi));
4925 vassert(! hregIsVirtual(dst_lo));
4926
florianc4aa7ed2012-12-22 15:01:04 +00004927 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
sewardj2019a972011-03-07 16:04:07 +00004928 insn->size = size;
4929 insn->variant.mul.dst_hi = dst_hi;
4930 insn->variant.mul.dst_lo = dst_lo;
4931 insn->variant.mul.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00004932
4933 return insn;
4934}
4935
4936
4937s390_insn *
4938s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
4939 Bool signed_divide)
4940{
4941 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4942
4943 vassert(size == 4 || size == 8);
4944 vassert(! hregIsVirtual(op1_hi));
4945 vassert(! hregIsVirtual(op1_lo));
4946
florianc4aa7ed2012-12-22 15:01:04 +00004947 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
sewardj2019a972011-03-07 16:04:07 +00004948 insn->size = size;
4949 insn->variant.div.op1_hi = op1_hi;
4950 insn->variant.div.op1_lo = op1_lo;
4951 insn->variant.div.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00004952
4953 return insn;
4954}
4955
4956
4957s390_insn *
4958s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
4959{
4960 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4961
4962 vassert(size == 8);
4963 vassert(! hregIsVirtual(op1));
4964 vassert(! hregIsVirtual(rem));
4965
4966 insn->tag = S390_INSN_DIVS;
4967 insn->size = size;
4968 insn->variant.divs.rem = rem; /* remainder */
4969 insn->variant.divs.op1 = op1; /* also quotient */
4970 insn->variant.divs.op2 = op2;
4971
4972 return insn;
4973}
4974
4975
4976s390_insn *
sewardj611b06e2011-03-24 08:57:29 +00004977s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
sewardj2019a972011-03-07 16:04:07 +00004978{
4979 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4980
4981 vassert(size == 8);
sewardj611b06e2011-03-24 08:57:29 +00004982 vassert(! hregIsVirtual(num_bits));
4983 vassert(! hregIsVirtual(clobber));
sewardj2019a972011-03-07 16:04:07 +00004984
sewardj611b06e2011-03-24 08:57:29 +00004985 insn->tag = S390_INSN_CLZ;
sewardj2019a972011-03-07 16:04:07 +00004986 insn->size = size;
sewardj611b06e2011-03-24 08:57:29 +00004987 insn->variant.clz.num_bits = num_bits;
4988 insn->variant.clz.clobber = clobber;
4989 insn->variant.clz.src = src;
sewardj2019a972011-03-07 16:04:07 +00004990
4991 return insn;
4992}
4993
4994
4995s390_insn *
4996s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
4997{
4998 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4999
5000 insn->tag = S390_INSN_UNOP;
5001 insn->size = size;
5002 insn->variant.unop.tag = tag;
5003 insn->variant.unop.dst = dst;
5004 insn->variant.unop.src = opnd;
5005
5006 return insn;
5007}
5008
5009
5010s390_insn *
5011s390_insn_test(UChar size, s390_opnd_RMI src)
5012{
5013 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5014
5015 vassert(size == 4 || size == 8);
5016
5017 insn->tag = S390_INSN_TEST;
5018 insn->size = size;
5019 insn->variant.test.src = src;
5020
5021 return insn;
5022}
5023
5024
5025s390_insn *
5026s390_insn_cc2bool(HReg dst, s390_cc_t cond)
5027{
5028 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5029
5030 insn->tag = S390_INSN_CC2BOOL;
5031 insn->size = 0; /* does not matter */
5032 insn->variant.cc2bool.cond = cond;
5033 insn->variant.cc2bool.dst = dst;
5034
5035 return insn;
5036}
5037
5038
5039s390_insn *
5040s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
5041{
5042 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5043
5044 vassert(size == 4 || size == 8);
5045 vassert(op2->x == 0);
5046
5047 insn->tag = S390_INSN_CAS;
5048 insn->size = size;
5049 insn->variant.cas.op1 = op1;
5050 insn->variant.cas.op2 = op2;
5051 insn->variant.cas.op3 = op3;
5052 insn->variant.cas.old_mem = old_mem;
5053
5054 return insn;
5055}
5056
5057
5058s390_insn *
florian448cbba2012-06-06 02:26:01 +00005059s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
5060 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
5061 HReg scratch)
5062{
5063 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005064 s390_cdas *cdas = LibVEX_Alloc(sizeof(s390_cdas));
florian448cbba2012-06-06 02:26:01 +00005065
5066 vassert(size == 4 || size == 8);
5067 vassert(op2->x == 0);
5068 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
5069
5070 insn->tag = S390_INSN_CDAS;
5071 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005072 insn->variant.cdas.details = cdas;
5073
5074 cdas->op1_high = op1_high;
5075 cdas->op1_low = op1_low;
5076 cdas->op2 = op2;
5077 cdas->op3_high = op3_high;
5078 cdas->op3_low = op3_low;
5079 cdas->old_mem_high = old_mem_high;
5080 cdas->old_mem_low = old_mem_low;
5081 cdas->scratch = scratch;
florian448cbba2012-06-06 02:26:01 +00005082
5083 return insn;
5084}
5085
5086
5087s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005088s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
5089 Bool signed_comparison)
5090{
5091 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5092
5093 vassert(size == 4 || size == 8);
5094
5095 insn->tag = S390_INSN_COMPARE;
5096 insn->size = size;
5097 insn->variant.compare.src1 = src1;
5098 insn->variant.compare.src2 = src2;
5099 insn->variant.compare.signed_comparison = signed_comparison;
5100
5101 return insn;
5102}
5103
5104
5105s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005106s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
florian1ff47562012-10-21 02:09:51 +00005107 const HChar *name, HReg dst)
sewardj2019a972011-03-07 16:04:07 +00005108{
5109 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5110
5111 insn->tag = S390_INSN_HELPER_CALL;
5112 insn->size = 0; /* does not matter */
5113 insn->variant.helper_call.cond = cond;
5114 insn->variant.helper_call.target = target;
5115 insn->variant.helper_call.num_args = num_args;
5116 insn->variant.helper_call.name = name;
florian01ed6e72012-05-27 16:52:43 +00005117 insn->variant.helper_call.dst = dst;
sewardj2019a972011-03-07 16:04:07 +00005118
5119 return insn;
5120}
5121
5122
5123s390_insn *
5124s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
florian2c74d242012-09-12 19:38:42 +00005125 HReg op3)
sewardj2019a972011-03-07 16:04:07 +00005126{
5127 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5128
floriancc491a62012-09-10 23:44:37 +00005129 vassert(size == 4 || size == 8);
5130
sewardj2019a972011-03-07 16:04:07 +00005131 insn->tag = S390_INSN_BFP_TRIOP;
5132 insn->size = size;
5133 insn->variant.bfp_triop.tag = tag;
5134 insn->variant.bfp_triop.dst = dst;
5135 insn->variant.bfp_triop.op2 = op2;
5136 insn->variant.bfp_triop.op3 = op3;
sewardj2019a972011-03-07 16:04:07 +00005137
5138 return insn;
5139}
5140
5141
5142s390_insn *
florian2c74d242012-09-12 19:38:42 +00005143s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
sewardj2019a972011-03-07 16:04:07 +00005144{
5145 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5146
floriancc491a62012-09-10 23:44:37 +00005147 vassert(size == 4 || size == 8);
5148
sewardj2019a972011-03-07 16:04:07 +00005149 insn->tag = S390_INSN_BFP_BINOP;
5150 insn->size = size;
5151 insn->variant.bfp_binop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005152 insn->variant.bfp_binop.dst_hi = dst;
5153 insn->variant.bfp_binop.op2_hi = op2;
5154 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
5155 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005156
5157 return insn;
5158}
5159
5160
5161s390_insn *
florian2c74d242012-09-12 19:38:42 +00005162s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
sewardj2019a972011-03-07 16:04:07 +00005163{
5164 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5165
floriancc491a62012-09-10 23:44:37 +00005166 vassert(size == 4 || size == 8);
5167
sewardj2019a972011-03-07 16:04:07 +00005168 insn->tag = S390_INSN_BFP_UNOP;
5169 insn->size = size;
5170 insn->variant.bfp_unop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005171 insn->variant.bfp_unop.dst_hi = dst;
5172 insn->variant.bfp_unop.op_hi = op;
5173 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
5174 insn->variant.bfp_unop.op_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005175
5176 return insn;
5177}
5178
5179
5180s390_insn *
5181s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
5182{
5183 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5184
5185 vassert(size == 4 || size == 8);
5186
5187 insn->tag = S390_INSN_BFP_COMPARE;
5188 insn->size = size;
5189 insn->variant.bfp_compare.dst = dst;
floriancc491a62012-09-10 23:44:37 +00005190 insn->variant.bfp_compare.op1_hi = op1;
5191 insn->variant.bfp_compare.op2_hi = op2;
5192 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
5193 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005194
5195 return insn;
5196}
5197
5198
5199s390_insn *
florian6dc90242012-12-21 21:43:00 +00005200s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
florian125e20d2012-10-07 15:42:37 +00005201 s390_bfp_round_t rounding_mode)
florian9fcff4c2012-09-10 03:09:04 +00005202{
5203 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5204
floriancc491a62012-09-10 23:44:37 +00005205 vassert(size == 4 || size == 8);
5206
florian9fcff4c2012-09-10 03:09:04 +00005207 insn->tag = S390_INSN_BFP_CONVERT;
5208 insn->size = size;
5209 insn->variant.bfp_convert.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005210 insn->variant.bfp_convert.dst_hi = dst;
5211 insn->variant.bfp_convert.op_hi = op;
5212 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
5213 insn->variant.bfp_convert.op_lo = INVALID_HREG;
florian9fcff4c2012-09-10 03:09:04 +00005214 insn->variant.bfp_convert.rounding_mode = rounding_mode;
5215
5216 return insn;
5217}
5218
5219
floriane38f6412012-12-21 17:32:12 +00005220/* Check validity of a register pair for 128-bit FP. Valid register
floriancc491a62012-09-10 23:44:37 +00005221 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
5222 and (13, 15). */
5223static Bool
floriane38f6412012-12-21 17:32:12 +00005224is_valid_fp128_regpair(HReg hi, HReg lo)
floriancc491a62012-09-10 23:44:37 +00005225{
5226 UInt hi_regno = hregNumber(hi);
5227 UInt lo_regno = hregNumber(lo);
5228
5229 if (lo_regno != hi_regno + 2) return False;
5230 if ((hi_regno & 0x2) != 0) return False;
5231
5232 return True;
5233}
5234
florian9fcff4c2012-09-10 03:09:04 +00005235s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005236s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005237 HReg dst_lo, HReg op2_hi, HReg op2_lo)
sewardj2019a972011-03-07 16:04:07 +00005238{
5239 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5240
floriancc491a62012-09-10 23:44:37 +00005241 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005242 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5243 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005244
5245 insn->tag = S390_INSN_BFP_BINOP;
sewardj2019a972011-03-07 16:04:07 +00005246 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005247 insn->variant.bfp_binop.tag = tag;
5248 insn->variant.bfp_binop.dst_hi = dst_hi;
5249 insn->variant.bfp_binop.dst_lo = dst_lo;
5250 insn->variant.bfp_binop.op2_hi = op2_hi;
5251 insn->variant.bfp_binop.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005252
5253 return insn;
5254}
5255
5256
5257s390_insn *
sewardja970c402011-04-28 18:38:42 +00005258s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005259 HReg dst_lo, HReg op_hi, HReg op_lo)
sewardj2019a972011-03-07 16:04:07 +00005260{
5261 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5262
floriancc491a62012-09-10 23:44:37 +00005263 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005264 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5265 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005266
5267 insn->tag = S390_INSN_BFP_UNOP;
sewardj2019a972011-03-07 16:04:07 +00005268 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005269 insn->variant.bfp_unop.tag = tag;
5270 insn->variant.bfp_unop.dst_hi = dst_hi;
5271 insn->variant.bfp_unop.dst_lo = dst_lo;
5272 insn->variant.bfp_unop.op_hi = op_hi;
5273 insn->variant.bfp_unop.op_lo = op_lo;
sewardj2019a972011-03-07 16:04:07 +00005274
5275 return insn;
5276}
5277
5278
5279s390_insn *
5280s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
5281 HReg op2_hi, HReg op2_lo)
5282{
5283 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5284
floriancc491a62012-09-10 23:44:37 +00005285 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005286 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
5287 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005288
5289 insn->tag = S390_INSN_BFP_COMPARE;
sewardj2019a972011-03-07 16:04:07 +00005290 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005291 insn->variant.bfp_compare.dst = dst;
5292 insn->variant.bfp_compare.op1_hi = op1_hi;
5293 insn->variant.bfp_compare.op1_lo = op1_lo;
5294 insn->variant.bfp_compare.op2_hi = op2_hi;
5295 insn->variant.bfp_compare.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005296
5297 return insn;
5298}
5299
5300
florian9fcff4c2012-09-10 03:09:04 +00005301static s390_insn *
florian6dc90242012-12-21 21:43:00 +00005302s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005303 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005304 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005305{
5306 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5307
floriancc491a62012-09-10 23:44:37 +00005308 if (size == 16) {
5309 /* From smaller size to 16 bytes */
floriane38f6412012-12-21 17:32:12 +00005310 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
floriancc491a62012-09-10 23:44:37 +00005311 vassert(op_lo == INVALID_HREG);
5312 } else {
5313 /* From 16 bytes to smaller size */
floriane38f6412012-12-21 17:32:12 +00005314 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005315 vassert(dst_lo == INVALID_HREG);
5316 }
5317
5318 insn->tag = S390_INSN_BFP_CONVERT;
sewardj2019a972011-03-07 16:04:07 +00005319 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005320 insn->variant.bfp_convert.tag = tag;
5321 insn->variant.bfp_convert.dst_hi = dst_hi;
5322 insn->variant.bfp_convert.dst_lo = dst_lo;
5323 insn->variant.bfp_convert.op_hi = op_hi;
5324 insn->variant.bfp_convert.op_lo = op_lo;
5325 insn->variant.bfp_convert.rounding_mode = rounding_mode;
sewardj2019a972011-03-07 16:04:07 +00005326
5327 return insn;
5328}
5329
5330
5331s390_insn *
florian6dc90242012-12-21 21:43:00 +00005332s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005333 HReg dst_lo, HReg op)
5334{
5335 /* Conversion to bfp128 never requires a rounding mode. Provide default
5336 rounding mode. It will not be used when emitting insns. */
florian125e20d2012-10-07 15:42:37 +00005337 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
florian9fcff4c2012-09-10 03:09:04 +00005338
5339 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
5340 INVALID_HREG, rounding_mode);
5341}
5342
5343
5344s390_insn *
florian6dc90242012-12-21 21:43:00 +00005345s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst,
sewardj2019a972011-03-07 16:04:07 +00005346 HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005347 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005348{
florian9fcff4c2012-09-10 03:09:04 +00005349 return s390_insn_bfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
5350 rounding_mode);
sewardj2019a972011-03-07 16:04:07 +00005351}
5352
5353
sewardja52e37e2011-04-28 18:48:06 +00005354s390_insn *
florian12390202012-11-10 22:34:14 +00005355s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
5356 HReg op3, s390_dfp_round_t rounding_mode)
5357{
5358 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005359 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop));
florian12390202012-11-10 22:34:14 +00005360
5361 vassert(size == 8);
5362
5363 insn->tag = S390_INSN_DFP_BINOP;
5364 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005365 insn->variant.dfp_binop.details = dfp_binop;
5366
5367 dfp_binop->tag = tag;
5368 dfp_binop->dst_hi = dst;
5369 dfp_binop->op2_hi = op2;
5370 dfp_binop->op3_hi = op3;
5371 dfp_binop->dst_lo = INVALID_HREG;
5372 dfp_binop->op2_lo = INVALID_HREG;
5373 dfp_binop->op3_lo = INVALID_HREG;
5374 dfp_binop->rounding_mode = rounding_mode;
florian12390202012-11-10 22:34:14 +00005375
5376 return insn;
5377}
5378
5379
5380s390_insn *
florian20c6bca2012-12-26 17:47:19 +00005381s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
5382 HReg op1, HReg op2)
floriane38f6412012-12-21 17:32:12 +00005383{
5384 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5385
5386 vassert(size == 8);
5387
5388 insn->tag = S390_INSN_DFP_COMPARE;
5389 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00005390 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00005391 insn->variant.dfp_compare.dst = dst;
5392 insn->variant.dfp_compare.op1_hi = op1;
5393 insn->variant.dfp_compare.op2_hi = op2;
5394 insn->variant.dfp_compare.op1_lo = INVALID_HREG;
5395 insn->variant.dfp_compare.op2_lo = INVALID_HREG;
5396
5397 return insn;
5398}
5399
5400
5401s390_insn *
5402s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
5403 s390_dfp_round_t rounding_mode)
5404{
5405 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5406
florian06dfe212012-12-22 02:09:40 +00005407 vassert(size == 4 || size == 8);
floriane38f6412012-12-21 17:32:12 +00005408
5409 insn->tag = S390_INSN_DFP_CONVERT;
5410 insn->size = size;
5411 insn->variant.dfp_convert.tag = tag;
5412 insn->variant.dfp_convert.dst_hi = dst;
5413 insn->variant.dfp_convert.op_hi = op;
5414 insn->variant.dfp_convert.dst_lo = INVALID_HREG;
5415 insn->variant.dfp_convert.op_lo = INVALID_HREG;
5416 insn->variant.dfp_convert.rounding_mode = rounding_mode;
5417
5418 return insn;
5419}
5420
5421
5422s390_insn *
5423s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
5424 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
5425 HReg op3_lo, s390_dfp_round_t rounding_mode)
5426{
5427 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005428 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop));
floriane38f6412012-12-21 17:32:12 +00005429
5430 vassert(size == 16);
5431 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5432 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
5433 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
5434
floriane38f6412012-12-21 17:32:12 +00005435 insn->tag = S390_INSN_DFP_BINOP;
5436 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005437 insn->variant.dfp_binop.details = dfp_binop;
5438
5439 dfp_binop->tag = tag;
5440 dfp_binop->dst_hi = dst_hi;
5441 dfp_binop->dst_lo = dst_lo;
5442 dfp_binop->op2_hi = op2_hi;
5443 dfp_binop->op2_lo = op2_lo;
5444 dfp_binop->op3_hi = op3_hi;
5445 dfp_binop->op3_lo = op3_lo;
5446 dfp_binop->rounding_mode = rounding_mode;
floriane38f6412012-12-21 17:32:12 +00005447
5448 return insn;
5449}
5450
5451
5452s390_insn *
florian20c6bca2012-12-26 17:47:19 +00005453s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
5454 HReg op1_lo, HReg op2_hi, HReg op2_lo)
floriane38f6412012-12-21 17:32:12 +00005455{
5456 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5457
5458 vassert(size == 16);
5459 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
5460 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
5461
5462 insn->tag = S390_INSN_DFP_COMPARE;
5463 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00005464 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00005465 insn->variant.dfp_compare.dst = dst;
5466 insn->variant.dfp_compare.op1_hi = op1_hi;
5467 insn->variant.dfp_compare.op1_lo = op1_lo;
5468 insn->variant.dfp_compare.op2_hi = op2_hi;
5469 insn->variant.dfp_compare.op2_lo = op2_lo;
5470
5471 return insn;
5472}
5473
5474
5475static s390_insn *
5476s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
5477 HReg dst_lo, HReg op_hi, HReg op_lo,
5478 s390_dfp_round_t rounding_mode)
5479{
5480 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5481
5482 if (size == 16) {
5483 /* From smaller size to 16 bytes */
5484 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5485 vassert(op_lo == INVALID_HREG);
5486 } else {
5487 /* From 16 bytes to smaller size */
5488 vassert(is_valid_fp128_regpair(op_hi, op_lo));
5489 vassert(dst_lo == INVALID_HREG);
5490 }
5491
5492 insn->tag = S390_INSN_DFP_CONVERT;
5493 insn->size = size;
5494 insn->variant.dfp_convert.tag = tag;
5495 insn->variant.dfp_convert.dst_hi = dst_hi;
5496 insn->variant.dfp_convert.dst_lo = dst_lo;
5497 insn->variant.dfp_convert.op_hi = op_hi;
5498 insn->variant.dfp_convert.op_lo = op_lo;
5499 insn->variant.dfp_convert.rounding_mode = rounding_mode;
5500
5501 return insn;
5502}
5503
5504
5505s390_insn *
5506s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
5507 HReg dst_lo, HReg op)
5508{
5509 /* Conversion to dfp128 never requires a rounding mode. Provide default
5510 rounding mode. It will not be used when emitting insns. */
5511 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
5512
5513 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
5514 INVALID_HREG, rounding_mode);
5515}
5516
5517
5518s390_insn *
5519s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst,
5520 HReg op_hi, HReg op_lo,
5521 s390_dfp_round_t rounding_mode)
5522{
5523 return s390_insn_dfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
5524 rounding_mode);
5525}
5526
5527
5528s390_insn *
sewardja52e37e2011-04-28 18:48:06 +00005529s390_insn_mfence(void)
5530{
5531 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5532
5533 insn->tag = S390_INSN_MFENCE;
5534 insn->size = 0; /* not needed */
5535
5536 return insn;
5537}
5538
5539
florianad43b3a2012-02-20 15:01:14 +00005540s390_insn *
florianb93348d2012-12-27 00:59:43 +00005541s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
florianad43b3a2012-02-20 15:01:14 +00005542{
5543 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5544
florianb93348d2012-12-27 00:59:43 +00005545 /* This insn will be mapped to insns that require base register
florian09bbba82012-12-11 04:09:43 +00005546 plus 12-bit displacement */
5547 vassert(dst->tag == S390_AMODE_B12);
5548
florianb93348d2012-12-27 00:59:43 +00005549 insn->tag = S390_INSN_MIMM;
florianad43b3a2012-02-20 15:01:14 +00005550 insn->size = size;
florianb93348d2012-12-27 00:59:43 +00005551 insn->variant.mimm.dst = dst;
5552 insn->variant.mimm.value = value;
florianad43b3a2012-02-20 15:01:14 +00005553
5554 return insn;
5555}
5556
5557
5558s390_insn *
florianf85fe3e2012-12-22 02:28:25 +00005559s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
florianad43b3a2012-02-20 15:01:14 +00005560{
5561 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5562
florianf85fe3e2012-12-22 02:28:25 +00005563 vassert(size == 4 || size == 8);
5564
5565 /* This insn will be mapped to an ASI or AGSI so we can only allow base
5566 register plus 12-bit / 20-bit displacement. */
5567 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
5568
5569 insn->tag = S390_INSN_MADD;
florianad43b3a2012-02-20 15:01:14 +00005570 insn->size = size;
florianf85fe3e2012-12-22 02:28:25 +00005571 insn->variant.madd.dst = dst;
5572 insn->variant.madd.delta = delta;
5573 insn->variant.madd.value = value;
florianad43b3a2012-02-20 15:01:14 +00005574
5575 return insn;
5576}
5577
5578
florian8844a632012-04-13 04:04:06 +00005579s390_insn *
florian125e20d2012-10-07 15:42:37 +00005580s390_insn_set_fpc_bfprm(UChar size, HReg mode)
florian2c74d242012-09-12 19:38:42 +00005581{
5582 vassert(size == 4);
5583
5584 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5585
florian125e20d2012-10-07 15:42:37 +00005586 insn->tag = S390_INSN_SET_FPC_BFPRM;
florian2c74d242012-09-12 19:38:42 +00005587 insn->size = size;
florian125e20d2012-10-07 15:42:37 +00005588 insn->variant.set_fpc_bfprm.mode = mode;
florian2c74d242012-09-12 19:38:42 +00005589
5590 return insn;
5591}
5592
5593
5594s390_insn *
florianc8e4f562012-10-27 16:19:31 +00005595s390_insn_set_fpc_dfprm(UChar size, HReg mode)
5596{
5597 vassert(size == 4);
5598
5599 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5600
5601 insn->tag = S390_INSN_SET_FPC_DFPRM;
5602 insn->size = size;
5603 insn->variant.set_fpc_dfprm.mode = mode;
5604
5605 return insn;
5606}
5607
5608
5609s390_insn *
florian8844a632012-04-13 04:04:06 +00005610s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
5611 Bool to_fast_entry)
5612{
5613 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5614
5615 insn->tag = S390_INSN_XDIRECT;
5616 insn->size = 0; /* does not matter */
5617
5618 insn->variant.xdirect.cond = cond;
5619 insn->variant.xdirect.dst = dst;
5620 insn->variant.xdirect.guest_IA = guest_IA;
5621 insn->variant.xdirect.to_fast_entry = to_fast_entry;
5622
5623 return insn;
5624}
5625
5626
5627s390_insn *
5628s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
5629{
5630 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5631
florian7346c7a2012-04-13 21:14:24 +00005632 insn->tag = S390_INSN_XINDIR;
florian8844a632012-04-13 04:04:06 +00005633 insn->size = 0; /* does not matter */
5634
florian7346c7a2012-04-13 21:14:24 +00005635 insn->variant.xindir.cond = cond;
5636 insn->variant.xindir.dst = dst;
5637 insn->variant.xindir.guest_IA = guest_IA;
florian8844a632012-04-13 04:04:06 +00005638
5639 return insn;
5640}
5641
5642
5643s390_insn *
5644s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
5645 IRJumpKind kind)
5646{
5647 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5648
5649 insn->tag = S390_INSN_XASSISTED;
5650 insn->size = 0; /* does not matter */
5651
5652 insn->variant.xassisted.cond = cond;
5653 insn->variant.xassisted.dst = dst;
5654 insn->variant.xassisted.guest_IA = guest_IA;
5655 insn->variant.xassisted.kind = kind;
5656
5657 return insn;
5658}
5659
5660
5661s390_insn *
5662s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
5663{
5664 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5665
florianbf516d12012-04-21 15:53:13 +00005666 vassert(counter->tag == S390_AMODE_B12);
5667 vassert(fail_addr->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00005668
5669 insn->tag = S390_INSN_EVCHECK;
5670 insn->size = 0; /* does not matter */
5671
5672 insn->variant.evcheck.counter = counter;
5673 insn->variant.evcheck.fail_addr = fail_addr;
5674
5675 return insn;
5676}
5677
5678
5679s390_insn *
5680s390_insn_profinc(void)
5681{
5682 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5683
5684 insn->tag = S390_INSN_PROFINC;
5685 insn->size = 0; /* does not matter */
5686
5687 return insn;
5688}
5689
5690
sewardj2019a972011-03-07 16:04:07 +00005691/*---------------------------------------------------------------*/
5692/*--- Debug print ---*/
5693/*---------------------------------------------------------------*/
5694
5695static const HChar *
5696s390_cc_as_string(s390_cc_t cc)
5697{
5698 switch (cc) {
5699 case S390_CC_NEVER: return "never";
5700 case S390_CC_OVFL: return "overflow";
5701 case S390_CC_H: return "greater than"; /* A > B ; high */
5702 case S390_CC_NLE: return "not low or equal";
5703 case S390_CC_L: return "less than"; /* A < B ; low */
5704 case S390_CC_NHE: return "not high or equal";
5705 case S390_CC_LH: return "low or high";
5706 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
5707 case S390_CC_E: return "equal"; /* A == B ; zero */
5708 case S390_CC_NLH: return "not low or high";
5709 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
5710 case S390_CC_NL: return "not low"; /* not low */
5711 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
5712 case S390_CC_NH: return "not high";
5713 case S390_CC_NO: return "not overflow";
5714 case S390_CC_ALWAYS: return "always";
5715 default:
5716 vpanic("s390_cc_as_string");
5717 }
5718}
5719
5720
florian8844a632012-04-13 04:04:06 +00005721static const HChar *
5722s390_jump_kind_as_string(IRJumpKind kind)
5723{
5724 switch (kind) {
5725 case Ijk_Boring: return "Boring";
5726 case Ijk_Call: return "Call";
5727 case Ijk_Ret: return "Return";
5728 case Ijk_ClientReq: return "ClientReq";
5729 case Ijk_Yield: return "Yield";
5730 case Ijk_EmWarn: return "EmWarn";
5731 case Ijk_EmFail: return "EmFail";
5732 case Ijk_NoDecode: return "NoDecode";
5733 case Ijk_MapFail: return "MapFail";
5734 case Ijk_TInval: return "Invalidate";
5735 case Ijk_NoRedir: return "NoRedir";
5736 case Ijk_SigTRAP: return "SigTRAP";
5737 case Ijk_SigSEGV: return "SigSEGV";
5738 case Ijk_SigBUS: return "SigBUS";
5739 case Ijk_Sys_syscall: return "Sys_syscall";
5740 default:
5741 vpanic("s390_jump_kind_as_string");
5742 }
5743}
5744
5745
sewardj2019a972011-03-07 16:04:07 +00005746/* Helper function for writing out a V insn */
5747static void
florian55085f82012-11-21 00:36:55 +00005748s390_sprintf(HChar *buf, const HChar *fmt, ...)
sewardj2019a972011-03-07 16:04:07 +00005749{
5750 HChar *p;
5751 ULong value;
5752 va_list args;
5753 va_start(args, fmt);
5754
5755 p = buf;
5756 for ( ; *fmt; ++fmt) {
5757 Int c = *fmt;
5758
5759 if (c != '%') {
5760 *p++ = c;
5761 continue;
5762 }
5763
5764 c = *++fmt; /* next char */
5765 switch (c) {
5766 case '%':
5767 *p++ = c; /* %% */
5768 continue;
5769
5770 case 's': /* %s */
5771 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
5772 continue;
5773
5774 case 'M': /* %M = mnemonic */
5775 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
5776 continue;
5777
5778 case 'R': /* %R = register */
5779 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
5780 continue;
5781
5782 case 'A': /* %A = amode */
5783 p += vex_sprintf(p, "%s",
5784 s390_amode_as_string(va_arg(args, s390_amode *)));
5785 continue;
5786
florianad43b3a2012-02-20 15:01:14 +00005787 case 'G': /* %G = guest state @ offset */
5788 p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt));
5789 continue;
5790
sewardj2019a972011-03-07 16:04:07 +00005791 case 'C': /* %C = condition code */
5792 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
5793 continue;
5794
florian8844a632012-04-13 04:04:06 +00005795 case 'J': /* &J = jump kind */
5796 p += vex_sprintf(p, "%s",
5797 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
5798 continue;
5799
sewardj2019a972011-03-07 16:04:07 +00005800 case 'L': { /* %L = argument list in helper call*/
5801 UInt i, num_args;
5802
5803 num_args = va_arg(args, UInt);
5804
5805 for (i = 0; i < num_args; ++i) {
5806 if (i != 0) p += vex_sprintf(p, ", ");
5807 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
5808 }
5809 continue;
5810 }
5811
5812 case 'O': { /* %O = RMI operand */
5813 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
5814
5815 switch (op->tag) {
5816 case S390_OPND_REG:
5817 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
5818 continue;
5819
5820 case S390_OPND_AMODE:
5821 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
5822 continue;
5823
5824 case S390_OPND_IMMEDIATE:
5825 value = op->variant.imm;
5826 goto print_value;
5827
5828 default:
5829 goto fail;
5830 }
5831 }
5832
5833 case 'I': /* %I = immediate value */
5834 value = va_arg(args, ULong);
5835 goto print_value;
5836
5837 print_value:
5838 if ((Long)value < 0)
5839 p += vex_sprintf(p, "%lld", (Long)value);
5840 else if (value < 100)
5841 p += vex_sprintf(p, "%llu", value);
5842 else
5843 p += vex_sprintf(p, "0x%llx", value);
5844 continue;
5845
5846 default:
5847 goto fail;
5848 }
5849 }
5850 *p = '\0';
5851 va_end(args);
5852
5853 return;
5854
5855 fail: vpanic("s390_printf");
5856}
5857
5858
5859/* Decompile the given insn into a static buffer and return it */
5860const HChar *
5861s390_insn_as_string(const s390_insn *insn)
5862{
5863 static HChar buf[300];
5864 const HChar *op;
5865 HChar *p;
5866
5867 buf[0] = '\0';
5868
5869 switch (insn->tag) {
5870 case S390_INSN_LOAD:
5871 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
5872 insn->variant.load.src);
5873 break;
5874
5875 case S390_INSN_STORE:
5876 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
5877 insn->variant.store.dst);
5878 break;
5879
5880 case S390_INSN_MOVE:
5881 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
5882 insn->variant.move.src);
5883 break;
5884
5885 case S390_INSN_COND_MOVE:
5886 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
5887 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
5888 &insn->variant.cond_move.src);
5889 break;
5890
5891 case S390_INSN_LOAD_IMMEDIATE:
5892 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
5893 insn->variant.load_immediate.value);
5894 break;
5895
5896 case S390_INSN_ALU:
5897 switch (insn->variant.alu.tag) {
5898 case S390_ALU_ADD: op = "v-add"; break;
5899 case S390_ALU_SUB: op = "v-sub"; break;
5900 case S390_ALU_MUL: op = "v-mul"; break;
5901 case S390_ALU_AND: op = "v-and"; break;
5902 case S390_ALU_OR: op = "v-or"; break;
5903 case S390_ALU_XOR: op = "v-xor"; break;
5904 case S390_ALU_LSH: op = "v-lsh"; break;
5905 case S390_ALU_RSH: op = "v-rsh"; break;
5906 case S390_ALU_RSHA: op = "v-rsha"; break;
5907 default: goto fail;
5908 }
florian043af212012-06-06 02:44:53 +00005909 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
sewardj2019a972011-03-07 16:04:07 +00005910 &insn->variant.alu.op2);
5911 break;
5912
florianc4aa7ed2012-12-22 15:01:04 +00005913 case S390_INSN_SMUL:
5914 case S390_INSN_UMUL:
5915 if (insn->tag == S390_INSN_SMUL) {
sewardj2019a972011-03-07 16:04:07 +00005916 op = "v-muls";
5917 } else {
5918 op = "v-mulu";
5919 }
5920 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
5921 &insn->variant.mul.op2);
5922 break;
5923
florianc4aa7ed2012-12-22 15:01:04 +00005924 case S390_INSN_SDIV:
5925 case S390_INSN_UDIV:
5926 if (insn->tag == S390_INSN_SDIV) {
sewardj2019a972011-03-07 16:04:07 +00005927 op = "v-divs";
5928 } else {
5929 op = "v-divu";
5930 }
5931 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
5932 &insn->variant.div.op2);
5933 break;
5934
5935 case S390_INSN_DIVS:
5936 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
5937 &insn->variant.divs.op2);
5938 break;
5939
sewardj611b06e2011-03-24 08:57:29 +00005940 case S390_INSN_CLZ:
5941 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
5942 &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +00005943 break;
5944
5945 case S390_INSN_UNOP:
5946 switch (insn->variant.unop.tag) {
5947 case S390_ZERO_EXTEND_8:
5948 case S390_ZERO_EXTEND_16:
5949 case S390_ZERO_EXTEND_32:
5950 op = "v-zerox";
5951 break;
5952
5953 case S390_SIGN_EXTEND_8:
5954 case S390_SIGN_EXTEND_16:
5955 case S390_SIGN_EXTEND_32:
5956 op = "v-signx";
5957 break;
5958
5959 case S390_NEGATE:
5960 op = "v-neg";
5961 break;
5962
5963 default:
5964 goto fail;
5965 }
5966 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
5967 &insn->variant.unop.src);
5968 break;
5969
5970 case S390_INSN_TEST:
5971 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
5972 break;
5973
5974 case S390_INSN_CC2BOOL:
5975 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
5976 insn->variant.cc2bool.cond);
5977 break;
5978
5979 case S390_INSN_CAS:
5980 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
5981 insn->variant.cas.op2, insn->variant.cas.op3,
5982 insn->variant.cas.old_mem);
5983 break;
5984
florianc4aa7ed2012-12-22 15:01:04 +00005985 case S390_INSN_CDAS: {
5986 s390_cdas *cdas = insn->variant.cdas.details;
5987
florian448cbba2012-06-06 02:26:01 +00005988 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
florianc4aa7ed2012-12-22 15:01:04 +00005989 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
5990 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
florian448cbba2012-06-06 02:26:01 +00005991 break;
florianc4aa7ed2012-12-22 15:01:04 +00005992 }
florian448cbba2012-06-06 02:26:01 +00005993
sewardj2019a972011-03-07 16:04:07 +00005994 case S390_INSN_COMPARE:
5995 if (insn->variant.compare.signed_comparison) {
5996 op = "v-cmps";
5997 } else {
5998 op = "v-cmpu";
5999 }
6000 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
6001 &insn->variant.compare.src2);
6002 break;
6003
sewardj2019a972011-03-07 16:04:07 +00006004 case S390_INSN_HELPER_CALL: {
florian01ed6e72012-05-27 16:52:43 +00006005 if (insn->variant.helper_call.dst != INVALID_HREG) {
6006 s390_sprintf(buf, "%M if (%C) %R = %s{%I}(%L)", "v-call",
6007 insn->variant.helper_call.cond,
6008 insn->variant.helper_call.dst,
6009 insn->variant.helper_call.name,
6010 insn->variant.helper_call.target,
6011 insn->variant.helper_call.num_args);
6012 } else {
6013 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
6014 insn->variant.helper_call.cond,
6015 insn->variant.helper_call.name,
6016 insn->variant.helper_call.target,
6017 insn->variant.helper_call.num_args);
6018 }
florian8844a632012-04-13 04:04:06 +00006019 return buf; /* avoid printing "size = ..." which is meaningless */
sewardj2019a972011-03-07 16:04:07 +00006020 }
6021
6022 case S390_INSN_BFP_TRIOP:
6023 switch (insn->variant.bfp_triop.tag) {
6024 case S390_BFP_MADD: op = "v-fmadd"; break;
6025 case S390_BFP_MSUB: op = "v-fmsub"; break;
6026 default: goto fail;
6027 }
florian043af212012-06-06 02:44:53 +00006028 s390_sprintf(buf, "%M %R,%R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00006029 insn->variant.bfp_triop.dst /* op1 same as dst */,
6030 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
6031 break;
6032
6033 case S390_INSN_BFP_BINOP:
6034 switch (insn->variant.bfp_binop.tag) {
6035 case S390_BFP_ADD: op = "v-fadd"; break;
6036 case S390_BFP_SUB: op = "v-fsub"; break;
6037 case S390_BFP_MUL: op = "v-fmul"; break;
6038 case S390_BFP_DIV: op = "v-fdiv"; break;
6039 default: goto fail;
6040 }
florian043af212012-06-06 02:44:53 +00006041 s390_sprintf(buf, "%M %R,%R", op,
floriancc491a62012-09-10 23:44:37 +00006042 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
6043 insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00006044 break;
6045
6046 case S390_INSN_BFP_COMPARE:
6047 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
floriancc491a62012-09-10 23:44:37 +00006048 insn->variant.bfp_compare.op1_hi,
6049 insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00006050 break;
6051
6052 case S390_INSN_BFP_UNOP:
6053 switch (insn->variant.bfp_unop.tag) {
6054 case S390_BFP_ABS: op = "v-fabs"; break;
6055 case S390_BFP_NABS: op = "v-fnabs"; break;
6056 case S390_BFP_NEG: op = "v-fneg"; break;
6057 case S390_BFP_SQRT: op = "v-fsqrt"; break;
florian9fcff4c2012-09-10 03:09:04 +00006058 default: goto fail;
6059 }
floriancc491a62012-09-10 23:44:37 +00006060 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
6061 insn->variant.bfp_unop.op_hi);
florian9fcff4c2012-09-10 03:09:04 +00006062 break;
6063
6064 case S390_INSN_BFP_CONVERT:
6065 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00006066 case S390_BFP_I32_TO_F32:
6067 case S390_BFP_I32_TO_F64:
6068 case S390_BFP_I32_TO_F128:
6069 case S390_BFP_I64_TO_F32:
6070 case S390_BFP_I64_TO_F64:
6071 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006072 case S390_BFP_U32_TO_F32:
6073 case S390_BFP_U32_TO_F64:
6074 case S390_BFP_U32_TO_F128:
6075 case S390_BFP_U64_TO_F32:
6076 case S390_BFP_U64_TO_F64:
6077 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
sewardj2019a972011-03-07 16:04:07 +00006078 case S390_BFP_F32_TO_I32:
6079 case S390_BFP_F32_TO_I64:
6080 case S390_BFP_F64_TO_I32:
6081 case S390_BFP_F64_TO_I64:
6082 case S390_BFP_F128_TO_I32:
6083 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006084 case S390_BFP_F32_TO_U32:
6085 case S390_BFP_F32_TO_U64:
6086 case S390_BFP_F64_TO_U32:
6087 case S390_BFP_F64_TO_U64:
6088 case S390_BFP_F128_TO_U32:
6089 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
sewardj2019a972011-03-07 16:04:07 +00006090 case S390_BFP_F32_TO_F64:
6091 case S390_BFP_F32_TO_F128:
6092 case S390_BFP_F64_TO_F32:
6093 case S390_BFP_F64_TO_F128:
6094 case S390_BFP_F128_TO_F32:
6095 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
6096 default: goto fail;
6097 }
floriancc491a62012-09-10 23:44:37 +00006098 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
6099 insn->variant.bfp_convert.op_hi);
sewardj2019a972011-03-07 16:04:07 +00006100 break;
6101
florianc4aa7ed2012-12-22 15:01:04 +00006102 case S390_INSN_DFP_BINOP: {
6103 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
6104
6105 switch (dfp_binop->tag) {
florian12390202012-11-10 22:34:14 +00006106 case S390_DFP_ADD: op = "v-dadd"; break;
6107 case S390_DFP_SUB: op = "v-dsub"; break;
6108 case S390_DFP_MUL: op = "v-dmul"; break;
6109 case S390_DFP_DIV: op = "v-ddiv"; break;
6110 default: goto fail;
6111 }
florianc4aa7ed2012-12-22 15:01:04 +00006112 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
6113 dfp_binop->op2_hi, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +00006114 break;
florianc4aa7ed2012-12-22 15:01:04 +00006115 }
florian12390202012-11-10 22:34:14 +00006116
floriane38f6412012-12-21 17:32:12 +00006117 case S390_INSN_DFP_COMPARE:
florian20c6bca2012-12-26 17:47:19 +00006118 switch (insn->variant.dfp_compare.tag) {
6119 case S390_DFP_COMPARE: op = "v-dcmp"; break;
6120 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
6121 default: goto fail;
6122 }
6123 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
floriane38f6412012-12-21 17:32:12 +00006124 insn->variant.dfp_compare.op1_hi,
6125 insn->variant.dfp_compare.op2_hi);
6126 break;
6127
6128 case S390_INSN_DFP_CONVERT:
6129 switch (insn->variant.dfp_convert.tag) {
6130 case S390_DFP_D32_TO_D64:
6131 case S390_DFP_D64_TO_D32:
6132 case S390_DFP_D64_TO_D128:
6133 case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
6134 default: goto fail;
6135 }
6136 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
6137 insn->variant.dfp_convert.op_hi);
6138 break;
6139
sewardja52e37e2011-04-28 18:48:06 +00006140 case S390_INSN_MFENCE:
6141 s390_sprintf(buf, "%M", "v-mfence");
6142 return buf; /* avoid printing "size = ..." which is meaningless */
6143
florianb93348d2012-12-27 00:59:43 +00006144 case S390_INSN_MIMM:
6145 s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
6146 insn->variant.mimm.value);
florianad43b3a2012-02-20 15:01:14 +00006147 break;
6148
florianf85fe3e2012-12-22 02:28:25 +00006149 case S390_INSN_MADD:
6150 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd",
6151 insn->variant.madd.dst,
6152 (Long)(Char)insn->variant.madd.delta,
6153 insn->variant.madd.value);
florianad43b3a2012-02-20 15:01:14 +00006154 break;
6155
florian125e20d2012-10-07 15:42:37 +00006156 case S390_INSN_SET_FPC_BFPRM:
6157 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
6158 insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00006159 break;
6160
florianc8e4f562012-10-27 16:19:31 +00006161 case S390_INSN_SET_FPC_DFPRM:
6162 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
6163 insn->variant.set_fpc_dfprm.mode);
6164 break;
6165
florian8844a632012-04-13 04:04:06 +00006166 case S390_INSN_EVCHECK:
6167 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
6168 insn->variant.evcheck.counter,
6169 insn->variant.evcheck.fail_addr);
6170 return buf; /* avoid printing "size = ..." which is meaningless */
6171
6172 case S390_INSN_PROFINC:
6173 s390_sprintf(buf, "%M", "v-profinc");
6174 return buf; /* avoid printing "size = ..." which is meaningless */
6175
6176 case S390_INSN_XDIRECT:
6177 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
6178 insn->variant.xdirect.cond,
6179 insn->variant.xdirect.guest_IA,
6180 insn->variant.xdirect.dst,
6181 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
6182 return buf; /* avoid printing "size = ..." which is meaningless */
6183
6184 case S390_INSN_XINDIR:
6185 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
6186 insn->variant.xindir.cond,
6187 insn->variant.xindir.guest_IA,
6188 insn->variant.xindir.dst);
6189 return buf; /* avoid printing "size = ..." which is meaningless */
6190
6191 case S390_INSN_XASSISTED:
6192 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
6193 insn->variant.xassisted.cond,
6194 insn->variant.xassisted.kind,
6195 insn->variant.xassisted.guest_IA,
6196 insn->variant.xassisted.dst);
6197 return buf; /* avoid printing "size = ..." which is meaningless */
6198
sewardj2019a972011-03-07 16:04:07 +00006199 default: goto fail;
6200 }
6201
6202 /* Write out how many bytes are involved in the operation */
6203
6204 {
6205 UInt len, i;
6206
6207 for (p = buf; *p; ++p)
6208 continue;
6209
6210 len = p - buf;
6211
6212 if (len < 32) {
6213 for (i = len; i < 32; ++i)
6214 p += vex_sprintf(p, " ");
6215 } else {
6216 p += vex_sprintf(p, "\t");
6217 }
6218 }
6219
6220 /* Special cases first */
6221 switch (insn->tag) {
6222 case S390_INSN_UNOP:
6223 switch (insn->variant.unop.tag) {
6224 case S390_SIGN_EXTEND_8:
6225 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
6226 case S390_SIGN_EXTEND_16:
6227 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
6228 case S390_SIGN_EXTEND_32:
6229 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
6230 default:
6231 goto common;
6232 }
6233
floriancc491a62012-09-10 23:44:37 +00006234 case S390_INSN_BFP_CONVERT:
6235 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00006236 case S390_BFP_I32_TO_F32:
6237 case S390_BFP_I32_TO_F64:
6238 case S390_BFP_I32_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00006239 case S390_BFP_U32_TO_F32:
6240 case S390_BFP_U32_TO_F64:
6241 case S390_BFP_U32_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00006242 case S390_BFP_F32_TO_I32:
6243 case S390_BFP_F32_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006244 case S390_BFP_F32_TO_U32:
6245 case S390_BFP_F32_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006246 case S390_BFP_F32_TO_F64:
6247 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
6248 case S390_BFP_I64_TO_F32:
6249 case S390_BFP_I64_TO_F64:
6250 case S390_BFP_I64_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00006251 case S390_BFP_U64_TO_F32:
6252 case S390_BFP_U64_TO_F64:
6253 case S390_BFP_U64_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00006254 case S390_BFP_F64_TO_I32:
6255 case S390_BFP_F64_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006256 case S390_BFP_F64_TO_U32:
6257 case S390_BFP_F64_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006258 case S390_BFP_F64_TO_F32:
6259 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
6260 case S390_BFP_F128_TO_I32:
6261 case S390_BFP_F128_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006262 case S390_BFP_F128_TO_U32:
6263 case S390_BFP_F128_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006264 case S390_BFP_F128_TO_F32:
6265 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
6266 default:
6267 goto common;
6268 }
6269
floriane38f6412012-12-21 17:32:12 +00006270 case S390_INSN_DFP_CONVERT:
6271 switch (insn->variant.dfp_convert.tag) {
6272 case S390_DFP_D32_TO_D64: p += vex_sprintf(p, "4 -> "); goto common;
6273 case S390_DFP_D64_TO_D32:
6274 case S390_DFP_D64_TO_D128:p += vex_sprintf(p, "8 -> "); goto common;
6275 case S390_DFP_D128_TO_D64:p += vex_sprintf(p, "16 -> "); goto common;
6276 default:
6277 goto common;
6278 }
6279
sewardj2019a972011-03-07 16:04:07 +00006280 default:
6281 goto common;
6282 }
6283
6284 /* Common case */
6285 common:
6286 vex_sprintf(p, "%u bytes", (UInt)insn->size);
6287
6288 return buf;
6289
6290 fail: vpanic("s390_insn_as_string");
6291}
6292
6293
6294
6295/* Load NUM bytes from memory into register REG using addressing mode AM. */
6296static UChar *
6297s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
6298{
6299 UInt b = hregNumber(am->b);
6300 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
6301 UInt d = am->d;
6302
6303 switch (am->tag) {
6304 case S390_AMODE_B12:
6305 case S390_AMODE_BX12:
6306 switch (num) {
6307 case 1: return s390_emit_IC(p, reg, x, b, d);
6308 case 2: return s390_emit_LH(p, reg, x, b, d);
6309 case 4: return s390_emit_L(p, reg, x, b, d);
6310 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
6311 default: goto fail;
6312 }
6313 break;
6314
6315 case S390_AMODE_B20:
6316 case S390_AMODE_BX20:
6317 switch (num) {
6318 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
6319 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
6320 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
6321 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
6322 default: goto fail;
6323 }
6324 break;
6325
6326 default: goto fail;
6327 }
6328
6329 fail:
6330 vpanic("s390_emit_load_mem");
6331}
6332
6333
6334/* Load condition code into register REG */
6335static UChar *
6336s390_emit_load_cc(UChar *p, UChar reg)
6337{
6338 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
6339 p = s390_emit_IPM(p, reg, reg);
6340 /* Shift 28 bits to the right --> [0,1,2,3] */
sewardjf74c86f2011-04-05 14:04:53 +00006341 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
sewardj2019a972011-03-07 16:04:07 +00006342}
6343
6344
6345/*---------------------------------------------------------------*/
6346/*--- Code generation ---*/
6347/*---------------------------------------------------------------*/
6348
6349/* Do not load more bytes than requested. */
6350static UChar *
6351s390_insn_load_emit(UChar *buf, const s390_insn *insn)
6352{
6353 UInt r, x, b, d;
6354 const s390_amode *src;
6355
6356 src = insn->variant.load.src;
6357
6358 r = hregNumber(insn->variant.load.dst);
6359
6360 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
6361 b = hregNumber(src->b);
6362 x = hregNumber(src->x); /* 0 for B12 and B20 */
6363 d = src->d;
6364
6365 switch (insn->size) {
6366
6367 case 4:
6368 switch (src->tag) {
6369 case S390_AMODE_B12:
6370 case S390_AMODE_BX12:
6371 return s390_emit_LE(buf, r, x, b, d);
6372
6373 case S390_AMODE_B20:
6374 case S390_AMODE_BX20:
6375 return s390_emit_LEY(buf, r, x, b, DISP20(d));
6376 }
6377 break;
6378
6379 case 8:
6380 switch (src->tag) {
6381 case S390_AMODE_B12:
6382 case S390_AMODE_BX12:
6383 return s390_emit_LD(buf, r, x, b, d);
6384
6385 case S390_AMODE_B20:
6386 case S390_AMODE_BX20:
6387 return s390_emit_LDY(buf, r, x, b, DISP20(d));
6388 }
6389 break;
6390 }
6391 vpanic("s390_insn_load_emit");
6392 }
6393
6394 /* Integer stuff */
6395 return s390_emit_load_mem(buf, insn->size, r, src);
6396}
6397
6398
6399static UChar *
6400s390_insn_store_emit(UChar *buf, const s390_insn *insn)
6401{
6402 UInt r, x, b, d;
6403 const s390_amode *dst;
6404
6405 dst = insn->variant.store.dst;
6406
6407 r = hregNumber(insn->variant.store.src);
6408 b = hregNumber(dst->b);
6409 x = hregNumber(dst->x); /* 0 for B12 and B20 */
6410 d = dst->d;
6411
6412 if (hregClass(insn->variant.store.src) == HRcFlt64) {
6413 switch (insn->size) {
6414
6415 case 4:
6416 switch (dst->tag) {
6417 case S390_AMODE_B12:
6418 case S390_AMODE_BX12:
6419 return s390_emit_STE(buf, r, x, b, d);
6420
6421 case S390_AMODE_B20:
6422 case S390_AMODE_BX20:
6423 return s390_emit_STEY(buf, r, x, b, DISP20(d));
6424 }
6425 break;
6426
6427 case 8:
6428 switch (dst->tag) {
6429 case S390_AMODE_B12:
6430 case S390_AMODE_BX12:
6431 return s390_emit_STD(buf, r, x, b, d);
6432
6433 case S390_AMODE_B20:
6434 case S390_AMODE_BX20:
6435 return s390_emit_STDY(buf, r, x, b, DISP20(d));
6436 }
6437 break;
6438 }
6439 vpanic("s390_insn_store_emit");
6440 }
6441
6442 /* Integer stuff */
6443 switch (insn->size) {
6444 case 1:
6445 switch (dst->tag) {
6446 case S390_AMODE_B12:
6447 case S390_AMODE_BX12:
6448 return s390_emit_STC(buf, r, x, b, d);
6449
6450 case S390_AMODE_B20:
6451 case S390_AMODE_BX20:
6452 return s390_emit_STCY(buf, r, x, b, DISP20(d));
6453 }
6454 break;
6455
6456 case 2:
6457 switch (dst->tag) {
6458 case S390_AMODE_B12:
6459 case S390_AMODE_BX12:
6460 return s390_emit_STH(buf, r, x, b, d);
6461
6462 case S390_AMODE_B20:
6463 case S390_AMODE_BX20:
6464 return s390_emit_STHY(buf, r, x, b, DISP20(d));
6465 }
6466 break;
6467
6468 case 4:
6469 switch (dst->tag) {
6470 case S390_AMODE_B12:
6471 case S390_AMODE_BX12:
6472 return s390_emit_ST(buf, r, x, b, d);
6473
6474 case S390_AMODE_B20:
6475 case S390_AMODE_BX20:
6476 return s390_emit_STY(buf, r, x, b, DISP20(d));
6477 }
6478 break;
6479
6480 case 8:
6481 return s390_emit_STG(buf, r, x, b, DISP20(d));
6482
6483 default:
6484 break;
6485 }
6486
6487 vpanic("s390_insn_store_emit");
6488}
6489
6490
6491static UChar *
6492s390_insn_move_emit(UChar *buf, const s390_insn *insn)
6493{
6494 UInt dst, src;
6495 HRegClass dst_class, src_class;
6496
6497 dst = hregNumber(insn->variant.move.dst);
6498 src = hregNumber(insn->variant.move.src);
6499
6500 dst_class = hregClass(insn->variant.move.dst);
6501 src_class = hregClass(insn->variant.move.src);
6502
6503 if (dst_class == src_class) {
6504 if (dst_class == HRcInt64)
6505 return s390_emit_LGR(buf, dst, src);
6506 if (dst_class == HRcFlt64)
6507 return s390_emit_LDR(buf, dst, src);
6508 } else {
floriana782a172011-12-18 15:51:54 +00006509 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
6510 if (insn->size == 4) {
6511 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
6512 return s390_emit_LDGRw(buf, dst, R0);
6513 } else {
6514 return s390_emit_LDGRw(buf, dst, src);
6515 }
6516 }
6517 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
6518 if (insn->size == 4) {
6519 buf = s390_emit_LGDRw(buf, dst, src);
6520 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
6521 } else {
6522 return s390_emit_LGDRw(buf, dst, src);
6523 }
6524 }
sewardj2019a972011-03-07 16:04:07 +00006525 /* A move between floating point registers and general purpose
6526 registers of different size should never occur and indicates
6527 an error elsewhere. */
6528 }
6529
6530 vpanic("s390_insn_move_emit");
6531}
6532
6533
6534static UChar *
6535s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
6536{
6537 UInt r;
6538 ULong value = insn->variant.load_immediate.value;
6539
6540 r = hregNumber(insn->variant.load_immediate.dst);
6541
6542 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
6543 vassert(value == 0);
6544 switch (insn->size) {
6545 case 4: return s390_emit_LZER(buf, r, value);
6546 case 8: return s390_emit_LZDR(buf, r, value);
6547 }
6548 vpanic("s390_insn_load_immediate_emit");
6549 }
6550
6551 switch (insn->size) {
6552 case 1:
6553 case 2:
6554 /* Load the immediate values as a 4 byte value. That does not hurt as
6555 those extra bytes will not be looked at. Fall through .... */
6556 case 4:
6557 return s390_emit_load_32imm(buf, r, value);
6558
6559 case 8:
6560 return s390_emit_load_64imm(buf, r, value);
6561 }
6562
6563 vpanic("s390_insn_load_immediate_emit");
6564}
6565
6566
6567/* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
6568 So we simply perform a 4-byte operation. Doing so uses possibly undefined
6569 bits and produces an undefined result in those extra bit positions. But
6570 upstream does not look at those positions, so this is OK. */
6571static UChar *
6572s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
6573{
6574 s390_opnd_RMI op2;
6575 UInt dst;
6576
6577 dst = hregNumber(insn->variant.alu.dst);
6578 op2 = insn->variant.alu.op2;
6579
6580 /* Second operand is in a register */
6581 if (op2.tag == S390_OPND_REG) {
6582 UInt r2 = hregNumber(op2.variant.reg);
6583
6584 switch (insn->size) {
6585 case 1:
6586 case 2:
6587 case 4:
6588 switch (insn->variant.alu.tag) {
6589 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
6590 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
6591 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
6592 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
6593 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
6594 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
sewardj3c49aaa2011-04-05 14:00:37 +00006595 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
6596 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
6597 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
sewardj2019a972011-03-07 16:04:07 +00006598 }
6599 goto fail;
6600
6601 case 8:
6602 switch (insn->variant.alu.tag) {
6603 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
6604 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
6605 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
6606 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
6607 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
6608 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
6609 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
6610 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
6611 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
6612 }
6613 goto fail;
6614 }
6615 goto fail;
6616 }
6617
6618 /* 2nd operand is in memory */
6619 if (op2.tag == S390_OPND_AMODE) {
6620 UInt b, x, d;
6621 const s390_amode *src = op2.variant.am;
6622
6623 b = hregNumber(src->b);
6624 x = hregNumber(src->x); /* 0 for B12 and B20 */
6625 d = src->d;
6626
6627 /* Shift operands are special here as there are no opcodes that
sewardje0dd77e2011-04-27 12:07:01 +00006628 allow a memory operand. So we first load the 2nd operand into
6629 some register. R0 is used to save restore the contents of the
6630 chosen register.. */
sewardj652b56a2011-04-13 15:38:17 +00006631
sewardj2019a972011-03-07 16:04:07 +00006632 if (insn->variant.alu.tag == S390_ALU_LSH ||
6633 insn->variant.alu.tag == S390_ALU_RSH ||
6634 insn->variant.alu.tag == S390_ALU_RSHA) {
sewardje0dd77e2011-04-27 12:07:01 +00006635 UInt b2;
sewardj2019a972011-03-07 16:04:07 +00006636
sewardje0dd77e2011-04-27 12:07:01 +00006637 /* Choose a register (other than DST or R0) into which to stick the
6638 shift amount. The following works because r15 is reserved and
6639 thusly dst != 15. */
6640 vassert(dst != 15); /* extra paranoia */
6641 b2 = (dst + 1) % 16;
6642
6643 buf = s390_emit_LGR(buf, R0, b2); /* save */
6644
6645 /* Loading SRC to B2 does not modify R0. */
6646 buf = s390_emit_load_mem(buf, insn->size, b2, src);
sewardj2019a972011-03-07 16:04:07 +00006647
6648 if (insn->size == 8) {
sewardje0dd77e2011-04-27 12:07:01 +00006649 switch (insn->variant.alu.tag) {
6650 case S390_ALU_LSH:
6651 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
6652 break;
6653 case S390_ALU_RSH:
6654 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
6655 break;
6656 case S390_ALU_RSHA:
6657 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
6658 break;
6659 default: /* unreachable */
6660 goto fail;
6661 }
sewardj2019a972011-03-07 16:04:07 +00006662 } else {
sewardje0dd77e2011-04-27 12:07:01 +00006663 switch (insn->variant.alu.tag) {
6664 case S390_ALU_LSH:
6665 buf = s390_emit_SLL(buf, dst, b2, 0);
6666 break;
6667 case S390_ALU_RSH:
6668 buf = s390_emit_SRL(buf, dst, b2, 0);
6669 break;
6670 case S390_ALU_RSHA:
6671 buf = s390_emit_SRA(buf, dst, b2, 0);
6672 break;
6673 default: /* unreachable */
6674 goto fail;
6675 }
sewardj2019a972011-03-07 16:04:07 +00006676 }
sewardje0dd77e2011-04-27 12:07:01 +00006677 return s390_emit_LGR(buf, b2, R0); /* restore */
sewardj2019a972011-03-07 16:04:07 +00006678 }
6679
6680 switch (insn->size) {
6681 case 1:
6682 /* Move the byte from memory into scratch register r0 */
6683 buf = s390_emit_load_mem(buf, 1, R0, src);
6684
6685 switch (insn->variant.alu.tag) {
6686 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
6687 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
6688 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
6689 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
6690 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
6691 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
6692 case S390_ALU_LSH:
6693 case S390_ALU_RSH:
6694 case S390_ALU_RSHA: ; /* avoid GCC warning */
6695 }
6696 goto fail;
6697
6698 case 2:
6699 switch (src->tag) {
6700 case S390_AMODE_B12:
6701 case S390_AMODE_BX12:
6702 switch (insn->variant.alu.tag) {
6703 case S390_ALU_ADD:
6704 return s390_emit_AH(buf, dst, x, b, d);
6705
6706 case S390_ALU_SUB:
6707 return s390_emit_SH(buf, dst, x, b, d);
6708
6709 case S390_ALU_MUL:
6710 return s390_emit_MH(buf, dst, x, b, d);
6711
6712 /* For bitwise operations: Move two bytes from memory into scratch
6713 register r0; then perform operation */
6714 case S390_ALU_AND:
6715 buf = s390_emit_LH(buf, R0, x, b, d);
6716 return s390_emit_NR(buf, dst, R0);
6717
6718 case S390_ALU_OR:
6719 buf = s390_emit_LH(buf, R0, x, b, d);
6720 return s390_emit_OR(buf, dst, R0);
6721
6722 case S390_ALU_XOR:
6723 buf = s390_emit_LH(buf, R0, x, b, d);
6724 return s390_emit_XR(buf, dst, R0);
6725
6726 case S390_ALU_LSH:
6727 case S390_ALU_RSH:
6728 case S390_ALU_RSHA: ; /* avoid GCC warning */
6729 }
6730 goto fail;
6731
6732 case S390_AMODE_B20:
6733 case S390_AMODE_BX20:
6734 switch (insn->variant.alu.tag) {
6735 case S390_ALU_ADD:
6736 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
6737
6738 case S390_ALU_SUB:
6739 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
6740
6741 case S390_ALU_MUL:
sewardjeae8db52011-03-24 09:01:50 +00006742 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006743
6744 /* For bitwise operations: Move two bytes from memory into scratch
6745 register r0; then perform operation */
6746 case S390_ALU_AND:
6747 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6748 return s390_emit_NR(buf, dst, R0);
6749
6750 case S390_ALU_OR:
6751 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6752 return s390_emit_OR(buf, dst, R0);
6753
6754 case S390_ALU_XOR:
6755 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6756 return s390_emit_XR(buf, dst, R0);
6757
6758 case S390_ALU_LSH:
6759 case S390_ALU_RSH:
6760 case S390_ALU_RSHA: ; /* avoid GCC warning */
6761 }
6762 goto fail;
6763 }
6764 goto fail;
6765
6766 case 4:
6767 switch (src->tag) {
6768 case S390_AMODE_B12:
6769 case S390_AMODE_BX12:
6770 switch (insn->variant.alu.tag) {
6771 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
6772 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
6773 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
6774 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
6775 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
6776 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
6777 case S390_ALU_LSH:
6778 case S390_ALU_RSH:
6779 case S390_ALU_RSHA: ; /* avoid GCC warning */
6780 }
6781 goto fail;
6782
6783 case S390_AMODE_B20:
6784 case S390_AMODE_BX20:
6785 switch (insn->variant.alu.tag) {
6786 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
6787 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
6788 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
6789 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
6790 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
6791 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
6792 case S390_ALU_LSH:
6793 case S390_ALU_RSH:
6794 case S390_ALU_RSHA: ; /* avoid GCC warning */
6795 }
6796 goto fail;
6797 }
6798 goto fail;
6799
6800 case 8:
6801 switch (insn->variant.alu.tag) {
6802 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
6803 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
6804 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
6805 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
6806 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
6807 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
6808 case S390_ALU_LSH:
6809 case S390_ALU_RSH:
6810 case S390_ALU_RSHA: ; /* avoid GCC warning */
6811 }
6812 goto fail;
6813 }
6814 goto fail;
6815 }
6816
6817 /* 2nd operand is an immediate value */
6818 if (op2.tag == S390_OPND_IMMEDIATE) {
6819 ULong value;
6820
6821 /* No masking of the value is required as it is not sign extended */
6822 value = op2.variant.imm;
6823
6824 switch (insn->size) {
6825 case 1:
6826 case 2:
6827 /* There is no 1-byte opcode. Do the computation in
6828 2 bytes. The extra byte will be ignored. */
6829 switch (insn->variant.alu.tag) {
6830 case S390_ALU_ADD:
6831 return s390_emit_AHI(buf, dst, value);
6832
6833 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00006834 return s390_emit_SLFIw(buf, dst, value);
sewardj2019a972011-03-07 16:04:07 +00006835
6836 case S390_ALU_MUL:
6837 return s390_emit_MHI(buf, dst, value);
6838
6839 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
6840 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
6841 case S390_ALU_XOR:
6842 /* There is no XILL instruction. Load the immediate value into
6843 R0 and combine with the destination register. */
6844 buf = s390_emit_LHI(buf, R0, value);
6845 return s390_emit_XR(buf, dst, R0);
6846
6847 case S390_ALU_LSH:
sewardj3c49aaa2011-04-05 14:00:37 +00006848 return s390_emit_SLL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006849
6850 case S390_ALU_RSH:
sewardj3c49aaa2011-04-05 14:00:37 +00006851 return s390_emit_SRL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006852
6853 case S390_ALU_RSHA:
sewardj3c49aaa2011-04-05 14:00:37 +00006854 return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006855 }
6856 goto fail;
6857
6858 case 4:
6859 switch (insn->variant.alu.tag) {
6860 case S390_ALU_ADD:
6861 if (uint_fits_signed_16bit(value)) {
6862 return s390_emit_AHI(buf, dst, value);
6863 }
6864 return s390_emit_AFIw(buf, dst, value);
6865
6866 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
6867 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
6868 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
6869 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
6870 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
sewardj3c49aaa2011-04-05 14:00:37 +00006871 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
6872 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
6873 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006874 }
6875 goto fail;
6876
6877 case 8:
6878 switch (insn->variant.alu.tag) {
6879 case S390_ALU_ADD:
6880 if (ulong_fits_signed_16bit(value)) {
6881 return s390_emit_AGHI(buf, dst, value);
6882 }
6883 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
6884 return s390_emit_AGFI(buf, dst, value);
6885 }
6886 /* Load constant into R0 then add */
6887 buf = s390_emit_load_64imm(buf, R0, value);
6888 return s390_emit_AGR(buf, dst, R0);
6889
6890 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00006891 if (ulong_fits_unsigned_32bit(value)) {
6892 return s390_emit_SLGFIw(buf, dst, value);
6893 }
sewardj2019a972011-03-07 16:04:07 +00006894 /* Load value into R0; then subtract from destination reg */
6895 buf = s390_emit_load_64imm(buf, R0, value);
6896 return s390_emit_SGR(buf, dst, R0);
6897
6898 case S390_ALU_MUL:
6899 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
6900 return s390_emit_MSGFI(buf, dst, value);
6901 }
6902 /* Load constant into R0 then add */
6903 buf = s390_emit_load_64imm(buf, R0, value);
6904 return s390_emit_MSGR(buf, dst, R0);
6905
6906 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
6907 case S390_ALU_AND:
6908 if (s390_host_has_eimm) {
6909 buf = s390_emit_NIHF(buf, dst, value >> 32);
6910 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
6911 }
6912 /* Load value into R0; then combine with destination reg */
6913 buf = s390_emit_load_64imm(buf, R0, value);
6914 return s390_emit_NGR(buf, dst, R0);
6915
6916 case S390_ALU_OR:
6917 if (s390_host_has_eimm) {
6918 buf = s390_emit_OIHF(buf, dst, value >> 32);
6919 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
6920 }
6921 /* Load value into R0; then combine with destination reg */
6922 buf = s390_emit_load_64imm(buf, R0, value);
6923 return s390_emit_OGR(buf, dst, R0);
6924
6925 case S390_ALU_XOR:
6926 if (s390_host_has_eimm) {
6927 buf = s390_emit_XIHF(buf, dst, value >> 32);
6928 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
6929 }
6930 /* Load value into R0; then combine with destination reg */
6931 buf = s390_emit_load_64imm(buf, R0, value);
6932 return s390_emit_XGR(buf, dst, R0);
6933
sewardj652b56a2011-04-13 15:38:17 +00006934 /* No special considerations for long displacement here. Only the six
6935 least significant bits of VALUE will be taken; all other bits are
6936 ignored. So the DH2 bits are irrelevant and do not influence the
6937 shift operation, independent of whether long-displacement is available
6938 or not. */
sewardj2019a972011-03-07 16:04:07 +00006939 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
6940 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
6941 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
6942 }
6943 goto fail;
6944 }
6945 goto fail;
6946 }
6947
6948 fail:
6949 vpanic("s390_insn_alu_emit");
6950}
6951
6952
6953static UChar *
6954s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
6955 Bool sign_extend)
6956{
sewardj06122e72011-03-28 12:14:48 +00006957 s390_opnd_RMI opnd = insn->variant.unop.src;
sewardj2019a972011-03-07 16:04:07 +00006958
6959 switch (opnd.tag) {
6960 case S390_OPND_REG: {
6961 UChar r1 = hregNumber(insn->variant.unop.dst);
6962 UChar r2 = hregNumber(opnd.variant.reg);
6963
6964 switch (from_size) {
6965 case 1:
6966 /* Widening to a half-word is implemented like widening to a word
6967 because the upper half-word will not be looked at. */
6968 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
6969 if (sign_extend)
6970 return s390_emit_LBRw(buf, r1, r2);
6971 else
6972 return s390_emit_LLCRw(buf, r1, r2);
6973 }
6974 if (insn->size == 8) { /* 8 --> 64 */
6975 if (sign_extend)
6976 return s390_emit_LGBRw(buf, r1, r2);
6977 else
6978 return s390_emit_LLGCRw(buf, r1, r2);
6979 }
6980 goto fail;
6981
6982 case 2:
6983 if (insn->size == 4) { /* 16 --> 32 */
6984 if (sign_extend)
6985 return s390_emit_LHRw(buf, r1, r2);
6986 else
6987 return s390_emit_LLHRw(buf, r1, r2);
6988 }
6989 if (insn->size == 8) { /* 16 --> 64 */
6990 if (sign_extend)
6991 return s390_emit_LGHRw(buf, r1, r2);
6992 else
6993 return s390_emit_LLGHRw(buf, r1, r2);
6994 }
6995 goto fail;
6996
6997 case 4:
6998 if (insn->size == 8) { /* 32 --> 64 */
6999 if (sign_extend)
7000 return s390_emit_LGFR(buf, r1, r2);
7001 else
7002 return s390_emit_LLGFR(buf, r1, r2);
7003 }
7004 goto fail;
7005
7006 default: /* unexpected "from" size */
7007 goto fail;
7008 }
7009 }
7010
7011 case S390_OPND_AMODE: {
7012 UChar r1 = hregNumber(insn->variant.unop.dst);
7013 const s390_amode *src = opnd.variant.am;
7014 UChar b = hregNumber(src->b);
7015 UChar x = hregNumber(src->x);
7016 Int d = src->d;
7017
7018 switch (from_size) {
7019 case 1:
7020 if (insn->size == 4 || insn->size == 2) {
7021 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00007022 return s390_emit_LBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007023 else
7024 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
7025 }
7026 if (insn->size == 8) {
7027 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00007028 return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007029 else
sewardj2019a972011-03-07 16:04:07 +00007030 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
7031 }
7032 goto fail;
7033
7034 case 2:
7035 if (insn->size == 4) { /* 16 --> 32 */
7036 if (sign_extend == 0)
7037 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
7038
7039 switch (src->tag) {
7040 case S390_AMODE_B12:
7041 case S390_AMODE_BX12:
7042 return s390_emit_LH(buf, r1, x, b, d);
7043
7044 case S390_AMODE_B20:
7045 case S390_AMODE_BX20:
7046 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
7047 }
7048 goto fail;
7049 }
7050 if (insn->size == 8) { /* 16 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00007051 if (sign_extend)
7052 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
7053 else
7054 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
7055 }
7056 goto fail;
7057
7058 case 4:
7059 if (insn->size == 8) { /* 32 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00007060 if (sign_extend)
7061 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
7062 else
7063 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
7064 }
7065 goto fail;
7066
7067 default: /* unexpected "from" size */
7068 goto fail;
7069 }
7070 }
7071
7072 case S390_OPND_IMMEDIATE: {
7073 UChar r1 = hregNumber(insn->variant.unop.dst);
7074 ULong value = opnd.variant.imm;
7075
7076 switch (from_size) {
7077 case 1:
7078 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7079 if (sign_extend) {
7080 /* host can do the sign extension to 16-bit; LHI does the rest */
7081 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
7082 } else {
7083 return s390_emit_LHI(buf, r1, value);
7084 }
7085 }
7086 if (insn->size == 8) { /* 8 --> 64 */
7087 if (sign_extend) {
7088 /* host can do the sign extension to 16-bit; LGHI does the rest */
7089 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
7090 } else {
7091 return s390_emit_LGHI(buf, r1, value);
7092 }
7093 }
7094 goto fail;
7095
7096 case 2:
7097 if (insn->size == 4) { /* 16 --> 32 */
7098 return s390_emit_LHI(buf, r1, value);
7099 }
7100 if (insn->size == 8) { /* 16 --> 64 */
7101 if (sign_extend)
7102 return s390_emit_LGHI(buf, r1, value);
7103 else
7104 return s390_emit_LLILL(buf, r1, value);
7105 }
7106 goto fail;
7107
7108 case 4:
7109 if (insn->size == 8) { /* 32 --> 64 */
7110 if (sign_extend)
7111 return s390_emit_LGFIw(buf, r1, value);
7112 else
7113 return s390_emit_LLILFw(buf, r1, value);
7114 }
7115 goto fail;
7116
7117 default: /* unexpected "from" size */
7118 goto fail;
7119 }
7120 }
7121 }
7122
7123 fail:
7124 vpanic("s390_widen_emit");
7125}
7126
7127
7128static UChar *
7129s390_negate_emit(UChar *buf, const s390_insn *insn)
7130{
7131 s390_opnd_RMI opnd;
7132
7133 opnd = insn->variant.unop.src;
7134
7135 switch (opnd.tag) {
7136 case S390_OPND_REG: {
7137 UChar r1 = hregNumber(insn->variant.unop.dst);
7138 UChar r2 = hregNumber(opnd.variant.reg);
7139
7140 switch (insn->size) {
7141 case 1:
7142 case 2:
7143 case 4:
7144 return s390_emit_LCR(buf, r1, r2);
7145
7146 case 8:
7147 return s390_emit_LCGR(buf, r1, r2);
7148
7149 default:
7150 goto fail;
7151 }
7152 }
7153
7154 case S390_OPND_AMODE: {
7155 UChar r1 = hregNumber(insn->variant.unop.dst);
7156
7157 /* Load bytes into scratch register R0, then negate */
7158 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
7159
7160 switch (insn->size) {
7161 case 1:
7162 case 2:
7163 case 4:
7164 return s390_emit_LCR(buf, r1, R0);
7165
7166 case 8:
7167 return s390_emit_LCGR(buf, r1, R0);
7168
7169 default:
7170 goto fail;
7171 }
7172 }
7173
7174 case S390_OPND_IMMEDIATE: {
7175 UChar r1 = hregNumber(insn->variant.unop.dst);
7176 ULong value = opnd.variant.imm;
7177
7178 value = ~value + 1; /* two's complement */
7179
7180 switch (insn->size) {
7181 case 1:
7182 case 2:
7183 /* Load the immediate values as a 4 byte value. That does not hurt as
7184 those extra bytes will not be looked at. Fall through .... */
7185 case 4:
7186 return s390_emit_load_32imm(buf, r1, value);
7187
7188 case 8:
7189 return s390_emit_load_64imm(buf, r1, value);
7190
7191 default:
7192 goto fail;
7193 }
7194 }
7195 }
7196
7197 fail:
7198 vpanic("s390_negate_emit");
7199}
7200
7201
7202static UChar *
7203s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
7204{
7205 switch (insn->variant.unop.tag) {
7206 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
7207 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
7208 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
7209
7210 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
7211 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
7212 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
7213
7214 case S390_NEGATE: return s390_negate_emit(buf, insn);
7215 }
7216
7217 vpanic("s390_insn_unop_emit");
7218}
7219
7220
7221/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
7222 comparisons will have been converted to 4-byte comparisons in
7223 s390_isel_cc and should not occur here. */
7224static UChar *
7225s390_insn_test_emit(UChar *buf, const s390_insn *insn)
7226{
7227 s390_opnd_RMI opnd;
7228
7229 opnd = insn->variant.test.src;
7230
7231 switch (opnd.tag) {
7232 case S390_OPND_REG: {
7233 UInt reg = hregNumber(opnd.variant.reg);
7234
7235 switch (insn->size) {
7236 case 4:
7237 return s390_emit_LTR(buf, reg, reg);
7238
7239 case 8:
7240 return s390_emit_LTGR(buf, reg, reg);
7241
7242 default:
7243 goto fail;
7244 }
7245 }
7246
7247 case S390_OPND_AMODE: {
7248 const s390_amode *am = opnd.variant.am;
7249 UChar b = hregNumber(am->b);
7250 UChar x = hregNumber(am->x);
7251 Int d = am->d;
7252
7253 switch (insn->size) {
7254 case 4:
7255 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
7256
7257 case 8:
7258 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
7259
7260 default:
7261 goto fail;
7262 }
7263 }
7264
7265 case S390_OPND_IMMEDIATE: {
7266 ULong value = opnd.variant.imm;
7267
7268 switch (insn->size) {
7269 case 4:
7270 buf = s390_emit_load_32imm(buf, R0, value);
7271 return s390_emit_LTR(buf, R0, R0);
7272
7273 case 8:
7274 buf = s390_emit_load_64imm(buf, R0, value);
7275 return s390_emit_LTGR(buf, R0, R0);
7276
7277 default:
7278 goto fail;
7279 }
7280 }
7281
7282 default:
7283 goto fail;
7284 }
7285
7286 fail:
7287 vpanic("s390_insn_test_emit");
7288}
7289
7290
7291static UChar *
7292s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
7293{
7294 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
7295 s390_cc_t cond = insn->variant.cc2bool.cond;
7296
7297 /* Make the destination register be 1 or 0, depending on whether
7298 the relevant condition holds. A 64-bit value is computed. */
7299 if (cond == S390_CC_ALWAYS)
7300 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
7301
7302 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
7303 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
7304 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
7305 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
7306 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
7307
7308 return buf;
7309}
7310
7311
7312/* Only 4-byte and 8-byte operands are handled. */
7313static UChar *
7314s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
7315{
7316 UChar r1, r3, b, old;
7317 Int d;
7318 s390_amode *am;
7319
7320 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
7321 r3 = hregNumber(insn->variant.cas.op3);
7322 old= hregNumber(insn->variant.cas.old_mem);
7323 am = insn->variant.cas.op2;
7324 b = hregNumber(am->b);
7325 d = am->d;
7326
7327 switch (insn->size) {
7328 case 4:
7329 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
7330 buf = s390_emit_LR(buf, R0, r1);
7331 if (am->tag == S390_AMODE_B12)
7332 buf = s390_emit_CS(buf, R0, r3, b, d);
7333 else
7334 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
7335 /* Now copy R0 which has the old memory value to OLD */
7336 return s390_emit_LR(buf, old, R0);
7337
7338 case 8:
7339 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
7340 buf = s390_emit_LGR(buf, R0, r1);
7341 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
7342 /* Now copy R0 which has the old memory value to OLD */
7343 return s390_emit_LGR(buf, old, R0);
7344
7345 default:
7346 goto fail;
7347 }
7348
7349 fail:
7350 vpanic("s390_insn_cas_emit");
7351}
7352
7353
florian448cbba2012-06-06 02:26:01 +00007354/* Only 4-byte and 8-byte operands are handled. */
7355static UChar *
7356s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
7357{
sewardja90622a2012-06-19 13:29:00 +00007358 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
florian448cbba2012-06-06 02:26:01 +00007359 Int d;
7360 s390_amode *am;
florianc4aa7ed2012-12-22 15:01:04 +00007361 s390_cdas *cdas = insn->variant.cdas.details;
florian448cbba2012-06-06 02:26:01 +00007362
florianc4aa7ed2012-12-22 15:01:04 +00007363 r1 = hregNumber(cdas->op1_high); /* expected value */
7364 r1p1 = hregNumber(cdas->op1_low); /* expected value */
7365 r3 = hregNumber(cdas->op3_high);
7366 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
7367 old_high = hregNumber(cdas->old_mem_high);
7368 old_low = hregNumber(cdas->old_mem_low);
7369 scratch = hregNumber(cdas->scratch);
7370 am = cdas->op2;
florian448cbba2012-06-06 02:26:01 +00007371 b = hregNumber(am->b);
7372 d = am->d;
7373
7374 vassert(scratch == 1);
7375
7376 switch (insn->size) {
7377 case 4:
7378 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
7379 and let CDS/CDSY clobber it */
7380 buf = s390_emit_LR(buf, R0, r1);
7381 buf = s390_emit_LR(buf, scratch, r1p1);
7382
7383 if (am->tag == S390_AMODE_B12)
7384 buf = s390_emit_CDS(buf, R0, r3, b, d);
7385 else
7386 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
7387
7388 /* Now copy R0,scratch which has the old memory value to OLD */
7389 buf = s390_emit_LR(buf, old_high, R0);
7390 buf = s390_emit_LR(buf, old_low, scratch);
7391 return buf;
7392
7393 case 8:
7394 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
7395 and let CDSG clobber it */
7396 buf = s390_emit_LGR(buf, R0, r1);
7397 buf = s390_emit_LGR(buf, scratch, r1p1);
7398
7399 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
7400
7401 /* Now copy R0,scratch which has the old memory value to OLD */
7402 buf = s390_emit_LGR(buf, old_high, R0);
7403 buf = s390_emit_LGR(buf, old_low, scratch);
7404 return buf;
7405
7406 default:
7407 goto fail;
7408 }
7409
7410 fail:
florianbb5aa782012-12-01 21:29:07 +00007411 vpanic("s390_insn_cdas_emit");
florian448cbba2012-06-06 02:26:01 +00007412}
7413
7414
sewardj2019a972011-03-07 16:04:07 +00007415/* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
7416 comparisons will have been converted to 4-byte comparisons in
7417 s390_isel_cc and should not occur here. */
7418static UChar *
7419s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
7420{
7421 s390_opnd_RMI op2;
7422 HReg op1;
7423 Bool signed_comparison;
7424
7425 op1 = insn->variant.compare.src1;
7426 op2 = insn->variant.compare.src2;
7427 signed_comparison = insn->variant.compare.signed_comparison;
7428
7429 switch (op2.tag) {
7430 case S390_OPND_REG: {
7431 UInt r1 = hregNumber(op1);
7432 UInt r2 = hregNumber(op2.variant.reg);
7433
7434 switch (insn->size) {
7435 case 4:
7436 if (signed_comparison)
7437 return s390_emit_CR(buf, r1, r2);
7438 else
7439 return s390_emit_CLR(buf, r1, r2);
7440
7441 case 8:
7442 if (signed_comparison)
7443 return s390_emit_CGR(buf, r1, r2);
7444 else
7445 return s390_emit_CLGR(buf, r1, r2);
7446
7447 default:
7448 goto fail;
7449 }
7450 }
7451
7452 case S390_OPND_AMODE: {
7453 UChar r1 = hregNumber(op1);
7454 const s390_amode *am = op2.variant.am;
7455 UChar b = hregNumber(am->b);
7456 UChar x = hregNumber(am->x);
7457 Int d = am->d;
7458
7459 switch (insn->size) {
7460 case 4:
7461 switch (am->tag) {
7462 case S390_AMODE_B12:
7463 case S390_AMODE_BX12:
7464 if (signed_comparison)
7465 return s390_emit_C(buf, r1, x, b, d);
7466 else
7467 return s390_emit_CL(buf, r1, x, b, d);
7468
7469 case S390_AMODE_B20:
7470 case S390_AMODE_BX20:
7471 if (signed_comparison)
7472 return s390_emit_CY(buf, r1, x, b, DISP20(d));
7473 else
7474 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
7475 }
7476 goto fail;
7477
7478 case 8:
7479 if (signed_comparison)
7480 return s390_emit_CG(buf, r1, x, b, DISP20(d));
7481 else
7482 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
7483
7484 default:
7485 goto fail;
7486 }
7487 }
7488
7489 case S390_OPND_IMMEDIATE: {
7490 UChar r1 = hregNumber(op1);
7491 ULong value = op2.variant.imm;
7492
7493 switch (insn->size) {
7494 case 4:
7495 if (signed_comparison)
7496 return s390_emit_CFIw(buf, r1, value);
7497 else
7498 return s390_emit_CLFIw(buf, r1, value);
7499
7500 case 8:
florian07d34552012-05-26 01:59:21 +00007501 if (s390_host_has_eimm) {
7502 if (signed_comparison) {
7503 if (ulong_fits_signed_32bit(value))
7504 return s390_emit_CGFI(buf, r1, value);
7505 } else {
7506 if (ulong_fits_unsigned_32bit(value))
7507 return s390_emit_CLGFI(buf, r1, value);
7508 }
7509 }
sewardj2019a972011-03-07 16:04:07 +00007510 buf = s390_emit_load_64imm(buf, R0, value);
7511 if (signed_comparison)
7512 return s390_emit_CGR(buf, r1, R0);
7513 else
7514 return s390_emit_CLGR(buf, r1, R0);
7515
7516 default:
7517 goto fail;
7518 }
7519 }
7520
7521 default:
7522 goto fail;
7523 }
7524
7525 fail:
7526 vpanic("s390_insn_compare_emit");
7527}
7528
7529
7530static UChar *
7531s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
7532{
7533 s390_opnd_RMI op2;
7534 UChar r1;
7535 Bool signed_multiply;
7536
7537 /* The register number identifying the register pair */
7538 r1 = hregNumber(insn->variant.mul.dst_hi);
7539
7540 op2 = insn->variant.mul.op2;
florianc4aa7ed2012-12-22 15:01:04 +00007541 signed_multiply = insn->tag == S390_INSN_SMUL;
sewardj2019a972011-03-07 16:04:07 +00007542
7543 switch (op2.tag) {
7544 case S390_OPND_REG: {
7545 UInt r2 = hregNumber(op2.variant.reg);
7546
7547 switch (insn->size) {
7548 case 1:
7549 case 2:
7550 case 4:
7551 if (signed_multiply)
7552 return s390_emit_MR(buf, r1, r2);
7553 else
7554 return s390_emit_MLR(buf, r1, r2);
7555
7556 case 8:
7557 if (signed_multiply)
7558 vpanic("s390_insn_mul_emit");
7559 else
7560 return s390_emit_MLGR(buf, r1, r2);
7561
7562 default:
7563 goto fail;
7564 }
7565 }
7566
7567 case S390_OPND_AMODE: {
7568 const s390_amode *am = op2.variant.am;
7569 UChar b = hregNumber(am->b);
7570 UChar x = hregNumber(am->x);
7571 Int d = am->d;
7572
7573 switch (insn->size) {
7574 case 1:
7575 case 2:
7576 /* Load bytes into scratch register R0, then multiply */
7577 buf = s390_emit_load_mem(buf, insn->size, R0, am);
7578 if (signed_multiply)
7579 return s390_emit_MR(buf, r1, R0);
7580 else
7581 return s390_emit_MLR(buf, r1, R0);
7582
7583 case 4:
7584 switch (am->tag) {
7585 case S390_AMODE_B12:
7586 case S390_AMODE_BX12:
7587 if (signed_multiply)
7588 return s390_emit_M(buf, r1, x, b, d);
7589 else
7590 return s390_emit_ML(buf, r1, x, b, DISP20(d));
7591
7592 case S390_AMODE_B20:
7593 case S390_AMODE_BX20:
7594 if (signed_multiply)
7595 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
7596 else
sewardjb13a92a2011-04-13 14:44:29 +00007597 return s390_emit_ML(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007598 }
7599 goto fail;
7600
7601 case 8:
7602 if (signed_multiply)
7603 vpanic("s390_insn_mul_emit");
7604 else
7605 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
7606
7607 default:
7608 goto fail;
7609 }
7610 }
7611
7612 case S390_OPND_IMMEDIATE: {
7613 ULong value = op2.variant.imm;
7614
7615 switch (insn->size) {
7616 case 1:
7617 case 2:
7618 case 4:
7619 buf = s390_emit_load_32imm(buf, R0, value);
7620 if (signed_multiply)
7621 return s390_emit_MR(buf, r1, R0);
7622 else
7623 return s390_emit_MLR(buf, r1, R0);
7624
7625 case 8:
7626 buf = s390_emit_load_64imm(buf, R0, value);
7627 if (signed_multiply)
7628 vpanic("s390_insn_mul_emit");
7629 else
7630 return s390_emit_MLGR(buf, r1, R0);
7631
7632 default:
7633 goto fail;
7634 }
7635 }
7636
7637 default:
7638 goto fail;
7639 }
7640
7641 fail:
7642 vpanic("s390_insn_mul_emit");
7643}
7644
7645
7646static UChar *
7647s390_insn_div_emit(UChar *buf, const s390_insn *insn)
7648{
7649 s390_opnd_RMI op2;
7650 UChar r1;
7651 Bool signed_divide;
7652
7653 r1 = hregNumber(insn->variant.div.op1_hi);
7654 op2 = insn->variant.div.op2;
florianc4aa7ed2012-12-22 15:01:04 +00007655 signed_divide = insn->tag == S390_INSN_SDIV;
sewardj2019a972011-03-07 16:04:07 +00007656
7657 switch (op2.tag) {
7658 case S390_OPND_REG: {
7659 UInt r2 = hregNumber(op2.variant.reg);
7660
7661 switch (insn->size) {
7662 case 4:
7663 if (signed_divide)
7664 return s390_emit_DR(buf, r1, r2);
7665 else
7666 return s390_emit_DLR(buf, r1, r2);
7667
7668 case 8:
7669 if (signed_divide)
7670 vpanic("s390_insn_div_emit");
7671 else
7672 return s390_emit_DLGR(buf, r1, r2);
7673
7674 default:
7675 goto fail;
7676 }
7677 }
7678
7679 case S390_OPND_AMODE: {
7680 const s390_amode *am = op2.variant.am;
7681 UChar b = hregNumber(am->b);
7682 UChar x = hregNumber(am->x);
7683 Int d = am->d;
7684
7685 switch (insn->size) {
7686 case 4:
7687 switch (am->tag) {
7688 case S390_AMODE_B12:
7689 case S390_AMODE_BX12:
7690 if (signed_divide)
7691 return s390_emit_D(buf, r1, x, b, d);
7692 else
7693 return s390_emit_DL(buf, r1, x, b, DISP20(d));
7694
7695 case S390_AMODE_B20:
7696 case S390_AMODE_BX20:
sewardjb13a92a2011-04-13 14:44:29 +00007697 if (signed_divide) {
7698 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007699 return s390_emit_DR(buf, r1, R0);
sewardjb13a92a2011-04-13 14:44:29 +00007700 } else
7701 return s390_emit_DL(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007702 }
7703 goto fail;
7704
7705 case 8:
7706 if (signed_divide)
7707 vpanic("s390_insn_div_emit");
7708 else
7709 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
7710
7711 default:
7712 goto fail;
7713 }
7714 }
7715
7716 case S390_OPND_IMMEDIATE: {
7717 ULong value = op2.variant.imm;
7718
7719 switch (insn->size) {
7720 case 4:
7721 buf = s390_emit_load_32imm(buf, R0, value);
7722 if (signed_divide)
7723 return s390_emit_DR(buf, r1, R0);
7724 else
7725 return s390_emit_DLR(buf, r1, R0);
7726
7727 case 8:
7728 buf = s390_emit_load_64imm(buf, R0, value);
7729 if (signed_divide)
7730 vpanic("s390_insn_div_emit");
7731 else
7732 return s390_emit_DLGR(buf, r1, R0);
7733
7734 default:
7735 goto fail;
7736 }
7737 }
7738
7739 default:
7740 goto fail;
7741 }
7742
7743 fail:
7744 vpanic("s390_insn_div_emit");
7745}
7746
7747
7748static UChar *
7749s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
7750{
7751 s390_opnd_RMI op2;
7752 UChar r1;
7753
7754 r1 = hregNumber(insn->variant.divs.rem);
7755 op2 = insn->variant.divs.op2;
7756
7757 switch (op2.tag) {
7758 case S390_OPND_REG: {
7759 UInt r2 = hregNumber(op2.variant.reg);
7760
7761 return s390_emit_DSGR(buf, r1, r2);
7762 }
7763
7764 case S390_OPND_AMODE: {
7765 const s390_amode *am = op2.variant.am;
7766 UChar b = hregNumber(am->b);
7767 UChar x = hregNumber(am->x);
7768 Int d = am->d;
7769
7770 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
7771 }
7772
7773 case S390_OPND_IMMEDIATE: {
7774 ULong value = op2.variant.imm;
7775
7776 buf = s390_emit_load_64imm(buf, R0, value);
7777 return s390_emit_DSGR(buf, r1, R0);
7778 }
7779
7780 default:
7781 goto fail;
7782 }
7783
7784 fail:
7785 vpanic("s390_insn_divs_emit");
7786}
7787
7788
7789static UChar *
sewardj611b06e2011-03-24 08:57:29 +00007790s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
sewardj2019a972011-03-07 16:04:07 +00007791{
7792 s390_opnd_RMI src;
sewardj611b06e2011-03-24 08:57:29 +00007793 UChar r1, r1p1, r2, *p;
sewardj2019a972011-03-07 16:04:07 +00007794
sewardj611b06e2011-03-24 08:57:29 +00007795 r1 = hregNumber(insn->variant.clz.num_bits);
7796 r1p1 = hregNumber(insn->variant.clz.clobber);
sewardj2019a972011-03-07 16:04:07 +00007797
7798 vassert((r1 & 0x1) == 0);
7799 vassert(r1p1 == r1 + 1);
7800
sewardj611b06e2011-03-24 08:57:29 +00007801 p = buf;
7802 src = insn->variant.clz.src;
sewardj2019a972011-03-07 16:04:07 +00007803
sewardj611b06e2011-03-24 08:57:29 +00007804 /* Get operand and move it to r2 */
sewardj2019a972011-03-07 16:04:07 +00007805 switch (src.tag) {
sewardj611b06e2011-03-24 08:57:29 +00007806 case S390_OPND_REG:
7807 r2 = hregNumber(src.variant.reg);
7808 break;
sewardj2019a972011-03-07 16:04:07 +00007809
7810 case S390_OPND_AMODE: {
7811 const s390_amode *am = src.variant.am;
7812 UChar b = hregNumber(am->b);
7813 UChar x = hregNumber(am->x);
7814 Int d = am->d;
7815
sewardj611b06e2011-03-24 08:57:29 +00007816 p = s390_emit_LG(p, R0, x, b, DISP20(d));
7817 r2 = R0;
7818 break;
sewardj2019a972011-03-07 16:04:07 +00007819 }
7820
7821 case S390_OPND_IMMEDIATE: {
7822 ULong value = src.variant.imm;
7823
sewardj611b06e2011-03-24 08:57:29 +00007824 p = s390_emit_load_64imm(p, R0, value);
7825 r2 = R0;
7826 break;
sewardj2019a972011-03-07 16:04:07 +00007827 }
7828
7829 default:
7830 goto fail;
7831 }
7832
sewardj611b06e2011-03-24 08:57:29 +00007833 /* Use FLOGR if you can */
7834 if (s390_host_has_eimm) {
7835 return s390_emit_FLOGR(p, r1, r2);
7836 }
7837
7838 /*
7839 r0 = r2;
7840 r1 = 64;
7841 while (r0 != 0) {
7842 r1 -= 1;
7843 r0 >>= 1;
7844 }
7845 */
7846 p = s390_emit_LTGR(p, R0, r2);
7847 p = s390_emit_LLILL(p, r1, 64);
7848
7849 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
7850 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
7851 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
7852 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
7853 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
7854 (UShort)(-(4 + 6 + 4) / 2));
7855 return p;
7856
sewardj2019a972011-03-07 16:04:07 +00007857 fail:
sewardj611b06e2011-03-24 08:57:29 +00007858 vpanic("s390_insn_clz_emit");
sewardj2019a972011-03-07 16:04:07 +00007859}
7860
7861
7862static UChar *
sewardj2019a972011-03-07 16:04:07 +00007863s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
7864{
7865 s390_cc_t cond;
7866 ULong target;
7867 UChar *ptmp = buf;
7868
7869 cond = insn->variant.helper_call.cond;
7870 target = insn->variant.helper_call.target;
7871
7872 if (cond != S390_CC_ALWAYS) {
7873 /* So we have something like this
7874 if (cond) call X;
7875 Y: ...
7876 We convert this into
7877 if (! cond) goto Y; // BRC opcode; 4 bytes
7878 call X;
7879 Y:
7880 */
7881 /* 4 bytes (a BRC insn) to be filled in here */
7882 buf += 4;
7883 }
7884
7885 /* Load the target address into a register, that
7886 (a) is not used for passing parameters to the helper and
7887 (b) can be clobbered by the callee
florianc9e90e52012-05-27 17:20:47 +00007888 (c) is not special to the BASR insn
7889 r1 is the only choice.
sewardj2019a972011-03-07 16:04:07 +00007890 Also, need to arrange for the return address be put into the
7891 link-register */
7892 buf = s390_emit_load_64imm(buf, 1, target);
7893
7894 /* Stash away the client's FPC register because the helper might change it. */
7895 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
7896
7897 /* Before we can call the helper, we need to save the link register,
7898 because the BASR will overwrite it. We cannot use a register for that.
7899 (a) Volatile registers will be modified by the helper.
7900 (b) For saved registers the client code assumes that they have not
7901 changed after the function returns. So we cannot use it to store
7902 the link register.
7903 In the dispatcher, before calling the client code, we have arranged for
7904 a location on the stack for this purpose. See dispatch-s390x-linux.S. */
7905 buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR
7906 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
7907 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
florian01ed6e72012-05-27 16:52:43 +00007908
7909 /* Move the return value to the destination register */
7910 if (insn->variant.helper_call.dst != INVALID_HREG) {
7911 buf = s390_emit_LGR(buf, hregNumber(insn->variant.helper_call.dst),
7912 S390_REGNO_RETURN_VALUE);
7913 }
7914
sewardj2019a972011-03-07 16:04:07 +00007915 buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR
7916 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
7917 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
7918 S390_OFFSET_SAVED_FPC_C);
7919
7920 if (cond != S390_CC_ALWAYS) {
7921 Int delta = buf - ptmp;
7922
7923 delta >>= 1; /* immediate constant is #half-words */
7924 vassert(delta > 0 && delta < (1 << 16));
7925 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7926 }
7927
7928 return buf;
7929}
7930
7931
7932static UChar *
7933s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
7934{
7935 HReg dst;
7936 s390_opnd_RMI src;
7937 s390_cc_t cond;
7938 UChar *p, *ptmp = 0; /* avoid compiler warnings */
7939
7940 cond = insn->variant.cond_move.cond;
7941 dst = insn->variant.cond_move.dst;
7942 src = insn->variant.cond_move.src;
7943
florian3a3d7f12012-12-03 13:32:05 +00007944 if (cond == S390_CC_NEVER) return buf;
7945
sewardj2019a972011-03-07 16:04:07 +00007946 p = buf;
7947
florianaec8e052012-12-09 17:26:32 +00007948 if (s390_host_has_lsc) {
florian3a3d7f12012-12-03 13:32:05 +00007949 /* LOCx is not the preferred way to implement an unconditional load. */
7950 if (cond != S390_CC_ALWAYS) goto use_branch_insn;
7951
7952 switch (src.tag) {
7953 case S390_OPND_REG:
7954 return s390_emit_LOCGR(p, cond, hregNumber(dst),
7955 hregNumber(src.variant.reg));
7956
7957 case S390_OPND_AMODE: {
7958 const s390_amode *am = src.variant.am;
7959
7960 /* We cannot use LOCx for loads less than 4 bytes. In that case
7961 load into R0 and then use LOCGR. Do the same if the amode uses
7962 an index register. */
7963 if (insn->size < 4 ||
7964 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
7965 p = s390_emit_load_mem(p, insn->size, R0, am);
7966 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
7967 return p;
7968 }
7969
7970 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
7971 vassert(insn->size == 4 || insn->size == 8);
7972
7973 UInt b = hregNumber(am->b);
7974 UInt d = am->d;
7975
7976 if (insn->size == 4) {
7977 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
7978 }
7979 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
7980 }
7981
7982 case S390_OPND_IMMEDIATE: {
7983 ULong value = src.variant.imm;
7984
7985 /* Load value into R0, then use LOCGR */
7986 if (insn->size <= 4) {
7987 p = s390_emit_load_32imm(p, R0, value);
7988 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
7989 }
7990
7991 vassert(insn->size == 8);
7992 p = s390_emit_load_64imm(p, R0, value);
7993 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
7994 }
7995 }
7996 }
7997
7998use_branch_insn:
sewardj2019a972011-03-07 16:04:07 +00007999 /* Branch (if cond fails) over move instrs */
8000 if (cond != S390_CC_ALWAYS) {
8001 /* Don't know how many bytes to jump over yet.
8002 Make space for a BRC instruction (4 bytes) and fill in later. */
8003 ptmp = p; /* to be filled in here */
8004 p += 4;
8005 }
8006
8007 // cond true: move src => dst
8008
8009 switch (src.tag) {
8010 case S390_OPND_REG:
8011 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
8012 break;
8013
8014 case S390_OPND_AMODE:
8015 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
8016 break;
8017
8018 case S390_OPND_IMMEDIATE: {
8019 ULong value = src.variant.imm;
8020 UInt r = hregNumber(dst);
8021
8022 switch (insn->size) {
8023 case 1:
8024 case 2:
8025 /* Load the immediate values as a 4 byte value. That does not hurt as
8026 those extra bytes will not be looked at. Fall through .... */
8027 case 4:
8028 p = s390_emit_load_32imm(p, r, value);
8029 break;
8030
8031 case 8:
8032 p = s390_emit_load_64imm(p, r, value);
8033 break;
8034 }
8035 break;
8036 }
8037
8038 default:
8039 goto fail;
8040 }
8041
8042 if (cond != S390_CC_ALWAYS) {
8043 Int delta = p - ptmp;
8044
8045 delta >>= 1; /* immediate constant is #half-words */
8046 vassert(delta > 0 && delta < (1 << 16));
8047 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8048 }
8049
8050 return p;
8051
8052 fail:
8053 vpanic("s390_insn_cond_move_emit");
8054}
8055
8056
sewardj2019a972011-03-07 16:04:07 +00008057static UChar *
8058s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
8059{
8060 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
8061 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
8062 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +00008063
8064 switch (insn->size) {
8065 case 4:
8066 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008067 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
8068 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008069 default: goto fail;
8070 }
8071 break;
8072
8073 case 8:
8074 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008075 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
8076 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008077 default: goto fail;
8078 }
8079 break;
8080
8081 default: goto fail;
8082 }
8083
sewardj2019a972011-03-07 16:04:07 +00008084 fail:
8085 vpanic("s390_insn_bfp_triop_emit");
8086}
8087
8088
8089static UChar *
8090s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
8091{
floriancc491a62012-09-10 23:44:37 +00008092 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
8093 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00008094
8095 switch (insn->size) {
8096 case 4:
8097 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008098 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
8099 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
8100 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
8101 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008102 default: goto fail;
8103 }
8104 break;
8105
8106 case 8:
8107 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008108 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
8109 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
8110 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
8111 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008112 default: goto fail;
8113 }
8114 break;
8115
floriancc491a62012-09-10 23:44:37 +00008116 case 16:
8117 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008118 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
8119 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
8120 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
8121 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008122 default: goto fail;
8123 }
8124 break;
8125
sewardj2019a972011-03-07 16:04:07 +00008126 default: goto fail;
8127 }
8128
sewardj2019a972011-03-07 16:04:07 +00008129 fail:
8130 vpanic("s390_insn_bfp_binop_emit");
8131}
8132
8133
8134static UChar *
8135s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
8136{
floriancc491a62012-09-10 23:44:37 +00008137 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
8138 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
sewardj2019a972011-03-07 16:04:07 +00008139
8140 switch (insn->variant.bfp_unop.tag) {
8141 case S390_BFP_ABS:
8142 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008143 case 4: return s390_emit_LPEBR(buf, r1, r2);
8144 case 8: return s390_emit_LPDBR(buf, r1, r2);
8145 case 16: return s390_emit_LPXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008146 default: goto fail;
8147 }
8148 break;
8149
8150 case S390_BFP_NABS:
8151 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008152 case 4: return s390_emit_LNEBR(buf, r1, r2);
8153 case 8: return s390_emit_LNDBR(buf, r1, r2);
8154 case 16: return s390_emit_LNXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008155 default: goto fail;
8156 }
8157 break;
8158
8159 case S390_BFP_NEG:
8160 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008161 case 4: return s390_emit_LCEBR(buf, r1, r2);
8162 case 8: return s390_emit_LCDBR(buf, r1, r2);
8163 case 16: return s390_emit_LCXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008164 default: goto fail;
8165 }
8166 break;
8167
8168 case S390_BFP_SQRT:
8169 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008170 case 4: return s390_emit_SQEBR(buf, r1, r2);
8171 case 8: return s390_emit_SQDBR(buf, r1, r2);
8172 case 16: return s390_emit_SQXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008173 default: goto fail;
8174 }
8175 break;
8176
florian9fcff4c2012-09-10 03:09:04 +00008177 default: goto fail;
8178 }
8179
florian9fcff4c2012-09-10 03:09:04 +00008180 fail:
8181 vpanic("s390_insn_bfp_unop_emit");
8182}
8183
8184
8185static UChar *
8186s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
8187{
floriancc491a62012-09-10 23:44:37 +00008188 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
8189 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
florian125e20d2012-10-07 15:42:37 +00008190 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
florian2c74d242012-09-12 19:38:42 +00008191 /* The IEEE-inexact-exception control is not modelled. So the
8192 m4 field is 0 (which is what GCC does, too) */
8193 const UInt m4 = 0;
florian9fcff4c2012-09-10 03:09:04 +00008194
florian9fcff4c2012-09-10 03:09:04 +00008195 switch (insn->variant.bfp_convert.tag) {
floriancc491a62012-09-10 23:44:37 +00008196 /* Convert to fixed */
florian9fcff4c2012-09-10 03:09:04 +00008197 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
8198 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008199 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008200 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
8201 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008202 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008203
floriancc491a62012-09-10 23:44:37 +00008204 /* Convert to logical */
florian2c74d242012-09-12 19:38:42 +00008205 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
8206 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
8207 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
8208 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
8209 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
8210 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008211
florian2c74d242012-09-12 19:38:42 +00008212 /* Convert from fixed */
8213 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
8214 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
8215 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
8216 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
8217 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
8218 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
8219
8220 /* Convert from logical */
8221 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
8222 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
8223 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
8224 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
8225 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
8226 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
8227
8228 /* Load lengthened */
8229 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008230 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
8231 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008232
florian2c74d242012-09-12 19:38:42 +00008233 /* Load rounded */
8234 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
8235 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
8236 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008237
sewardj2019a972011-03-07 16:04:07 +00008238 default: goto fail;
8239 }
8240
sewardj2019a972011-03-07 16:04:07 +00008241 fail:
florian9fcff4c2012-09-10 03:09:04 +00008242 vpanic("s390_insn_bfp_convert_emit");
sewardj2019a972011-03-07 16:04:07 +00008243}
8244
8245
8246static UChar *
8247s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
8248{
8249 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +00008250 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
8251 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00008252
8253 switch (insn->size) {
floriancc491a62012-09-10 23:44:37 +00008254 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
8255 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
8256 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
sewardj2019a972011-03-07 16:04:07 +00008257 default: goto fail;
8258 }
8259
8260 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
8261
8262 fail:
8263 vpanic("s390_insn_bfp_compare_emit");
8264}
8265
8266
8267static UChar *
florian12390202012-11-10 22:34:14 +00008268s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
8269{
florianc4aa7ed2012-12-22 15:01:04 +00008270 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
8271
8272 UInt r1 = hregNumber(dfp_binop->dst_hi);
8273 UInt r2 = hregNumber(dfp_binop->op2_hi);
8274 UInt r3 = hregNumber(dfp_binop->op3_hi);
8275 UInt m4 = hregNumber(dfp_binop->rounding_mode);
florian12390202012-11-10 22:34:14 +00008276
8277 switch (insn->size) {
8278 case 8:
florianc4aa7ed2012-12-22 15:01:04 +00008279 switch (dfp_binop->tag) {
florian12390202012-11-10 22:34:14 +00008280 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2); break;
8281 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2); break;
8282 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2); break;
8283 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2); break;
8284 default: goto fail;
8285 }
8286 break;
floriane38f6412012-12-21 17:32:12 +00008287
8288 case 16:
florianc4aa7ed2012-12-22 15:01:04 +00008289 switch (dfp_binop->tag) {
floriane38f6412012-12-21 17:32:12 +00008290 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2);
8291 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2);
8292 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2);
8293 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2);
8294 default: goto fail;
8295 }
8296 break;
8297
florian12390202012-11-10 22:34:14 +00008298 default: goto fail;
8299 }
8300
8301 fail:
8302 vpanic("s390_insn_dfp_binop_emit");
8303}
8304
8305
8306static UChar *
floriane38f6412012-12-21 17:32:12 +00008307s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
8308{
8309 UInt dst = hregNumber(insn->variant.dfp_compare.dst);
8310 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi);
8311 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi);
8312
8313 switch (insn->size) {
florian20c6bca2012-12-26 17:47:19 +00008314 case 8:
8315 switch(insn->variant.dfp_compare.tag) {
8316 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break;
8317 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
8318 default: goto fail;
8319 }
8320 break;
8321
8322 case 16:
8323 switch(insn->variant.dfp_compare.tag) {
8324 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break;
8325 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
8326 default: goto fail;
8327 }
8328 break;
8329
floriane38f6412012-12-21 17:32:12 +00008330 default: goto fail;
8331 }
8332
8333 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
8334
8335 fail:
8336 vpanic("s390_insn_dfp_compare_emit");
8337}
8338
8339
8340static UChar *
8341s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
8342{
8343 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
8344 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi);
8345 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
8346 /* The IEEE-inexact-exception control is not modelled. So the
8347 m4 field is 0 (which is what GCC does, too) */
8348 const UInt m4 = 0;
8349
8350 switch (insn->variant.dfp_convert.tag) {
8351
8352 /* Load lengthened */
8353 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2);
8354 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2);
8355
8356 /* Load rounded */
8357 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2);
8358 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2);
8359
8360 default: goto fail;
8361 }
8362
8363 fail:
8364 vpanic("s390_insn_dfp_convert_emit");
8365}
8366
8367
8368static UChar *
sewardja52e37e2011-04-28 18:48:06 +00008369s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
8370{
8371 return s390_emit_BCR(buf, 0xF, 0x0);
8372}
8373
8374
florianad43b3a2012-02-20 15:01:14 +00008375static UChar *
florianb93348d2012-12-27 00:59:43 +00008376s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00008377{
florianb93348d2012-12-27 00:59:43 +00008378 s390_amode *am = insn->variant.mimm.dst;
8379 ULong value = insn->variant.mimm.value;
florian09bbba82012-12-11 04:09:43 +00008380
florianb93348d2012-12-27 00:59:43 +00008381 if (value == 0) {
8382 return s390_emit_XC(buf, insn->size - 1, am->b, am->d, am->b, am->d);
8383 }
8384
8385 if (insn->size == 1) {
8386 return s390_emit_MVI(buf, value & 0xFF, am->b, am->d);
8387 }
8388
8389 if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
8390 value &= 0xFFFF;
8391 switch (insn->size) {
8392 case 2: return s390_emit_MVHHI(buf, am->b, am->d, value);
8393 case 4: return s390_emit_MVHI(buf, am->b, am->d, value);
8394 case 8: return s390_emit_MVGHI(buf, am->b, am->d, value);
8395 }
8396 } else {
8397 // Load value to R0, then store.
8398 switch (insn->size) {
8399 case 2:
8400 buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
8401 return s390_emit_STH(buf, R0, 0, am->b, am->d);
8402 case 4:
8403 buf = s390_emit_load_32imm(buf, R0, value);
8404 return s390_emit_ST(buf, R0, 0, am->b, am->d);
8405 case 8:
8406 buf = s390_emit_load_64imm(buf, R0, value);
8407 return s390_emit_STG(buf, R0, 0, am->b, DISP20(am->d));
8408 }
8409 }
8410
8411 vpanic("s390_insn_mimm_emit");
florianad43b3a2012-02-20 15:01:14 +00008412}
8413
8414
8415static UChar *
florianf85fe3e2012-12-22 02:28:25 +00008416s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00008417{
florianf85fe3e2012-12-22 02:28:25 +00008418 s390_amode *am = insn->variant.madd.dst;
8419
8420 if (insn->size == 4) {
8421 return s390_emit_ASI(buf, insn->variant.madd.delta, am->b,
8422 DISP20(am->d));
8423 }
8424
8425 return s390_emit_AGSI(buf, insn->variant.madd.delta, am->b, DISP20(am->d));
florianad43b3a2012-02-20 15:01:14 +00008426}
8427
8428
florian2c74d242012-09-12 19:38:42 +00008429static UChar *
florian125e20d2012-10-07 15:42:37 +00008430s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
florian2c74d242012-09-12 19:38:42 +00008431{
florian125e20d2012-10-07 15:42:37 +00008432 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00008433
8434 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
8435 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
8436 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
8437
8438 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
8439 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
florian6d8e26e2012-09-12 19:52:16 +00008440 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
florian2c74d242012-09-12 19:38:42 +00008441
8442 return buf;
8443}
8444
8445
florianc8e4f562012-10-27 16:19:31 +00008446static UChar *
8447s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
8448{
8449 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
8450
8451 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
8452 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
8453 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
8454
8455 /* DFP rounding mode is set at bit position 25:27 in FPC register */
8456 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
8457 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
8458 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
8459 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
8460
8461 return buf;
8462}
8463
8464
florian8844a632012-04-13 04:04:06 +00008465/* Define convenience functions needed for translation chaining.
8466 Any changes need to be applied to the functions in concert. */
8467
florian1c857042012-04-15 04:11:07 +00008468static __inline__ Bool
8469s390_insn_is_BRCL(const UChar *p, UChar condition)
8470{
8471 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
8472}
8473
8474static __inline__ Bool
8475s390_insn_is_BR(const UChar *p, UChar reg)
8476{
8477 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
8478}
8479
florianebaf8d92012-04-22 17:38:46 +00008480
8481/* The length of the BASR insn */
8482#define S390_BASR_LEN 2
8483
florian1c857042012-04-15 04:11:07 +00008484
florian8844a632012-04-13 04:04:06 +00008485/* Load the 64-bit VALUE into REG. Note that this function must NOT
8486 optimise the generated code by looking at the value. I.e. using
floriane09e8bb2012-05-07 03:28:18 +00008487 LGHI if value == 0 would be very wrong. */
florian8844a632012-04-13 04:04:06 +00008488static UChar *
8489s390_tchain_load64(UChar *buf, UChar regno, ULong value)
8490{
florian1c857042012-04-15 04:11:07 +00008491 UChar *begin = buf;
8492
florian1c2b4db2012-04-22 17:46:31 +00008493 if (s390_host_has_eimm) {
8494 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
8495 buf = s390_emit_IIHF(buf, regno, value >> 32);
8496 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
8497 } else {
8498 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
8499 value >>= 16;
8500 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
8501 value >>= 16;
8502 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
8503 value >>= 16;
8504 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
8505 }
florian8844a632012-04-13 04:04:06 +00008506
florian1c857042012-04-15 04:11:07 +00008507 vassert(buf - begin == s390_tchain_load64_len());
8508
florian8844a632012-04-13 04:04:06 +00008509 return buf;
8510}
8511
8512/* Return number of bytes generated by s390_tchain_load64 */
8513static UInt
8514s390_tchain_load64_len(void)
8515{
florian1c2b4db2012-04-22 17:46:31 +00008516 if (s390_host_has_eimm) {
8517 return 6 + 6; /* IIHF + IILF */
8518 }
florianebaf8d92012-04-22 17:38:46 +00008519 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
florian8844a632012-04-13 04:04:06 +00008520}
8521
8522/* Verify that CODE is the code sequence generated by s390_tchain_load64
8523 to load VALUE into REGNO. Return pointer to the byte following the
8524 insn sequence. */
8525static const UChar *
8526s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
8527{
8528 UInt regmask = regno << 4;
8529 UInt hw;
8530
florian1c2b4db2012-04-22 17:46:31 +00008531 if (s390_host_has_eimm) {
8532 /* Check for IIHF */
8533 vassert(code[0] == 0xC0);
8534 vassert(code[1] == (0x08 | regmask));
8535 vassert(*(const UInt *)&code[2] == (value >> 32));
8536 /* Check for IILF */
8537 vassert(code[6] == 0xC0);
8538 vassert(code[7] == (0x09 | regmask));
8539 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
8540 } else {
8541 /* Check for IILL */
8542 hw = value & 0xFFFF;
8543 vassert(code[0] == 0xA5);
8544 vassert(code[1] == (0x03 | regmask));
8545 vassert(code[2] == (hw >> 8));
8546 vassert(code[3] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00008547
florian1c2b4db2012-04-22 17:46:31 +00008548 /* Check for IILH */
8549 hw = (value >> 16) & 0xFFFF;
8550 vassert(code[4] == 0xA5);
8551 vassert(code[5] == (0x02 | regmask));
8552 vassert(code[6] == (hw >> 8));
8553 vassert(code[7] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00008554
florian1c2b4db2012-04-22 17:46:31 +00008555 /* Check for IIHL */
8556 hw = (value >> 32) & 0xFFFF;
8557 vassert(code[8] == 0xA5);
8558 vassert(code[9] == (0x01 | regmask));
8559 vassert(code[10] == (hw >> 8));
8560 vassert(code[11] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00008561
florian1c2b4db2012-04-22 17:46:31 +00008562 /* Check for IIHH */
8563 hw = (value >> 48) & 0xFFFF;
8564 vassert(code[12] == 0xA5);
8565 vassert(code[13] == (0x00 | regmask));
8566 vassert(code[14] == (hw >> 8));
8567 vassert(code[15] == (hw & 0xFF));
8568 }
florian8844a632012-04-13 04:04:06 +00008569
florian1c857042012-04-15 04:11:07 +00008570 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00008571}
8572
8573/* CODE points to the code sequence as generated by s390_tchain_load64.
florian5ea257b2012-09-29 17:05:46 +00008574 Change the loaded value to IMM64. Return pointer to the byte following
florian8844a632012-04-13 04:04:06 +00008575 the patched code sequence. */
8576static UChar *
8577s390_tchain_patch_load64(UChar *code, ULong imm64)
8578{
florian1c2b4db2012-04-22 17:46:31 +00008579 if (s390_host_has_eimm) {
8580 /* Patch IIHF */
8581 *(UInt *)&code[2] = imm64 >> 32;
8582 /* Patch IILF */
8583 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
8584 } else {
8585 code[3] = imm64 & 0xFF; imm64 >>= 8;
8586 code[2] = imm64 & 0xFF; imm64 >>= 8;
8587 code[7] = imm64 & 0xFF; imm64 >>= 8;
8588 code[6] = imm64 & 0xFF; imm64 >>= 8;
8589 code[11] = imm64 & 0xFF; imm64 >>= 8;
8590 code[10] = imm64 & 0xFF; imm64 >>= 8;
8591 code[15] = imm64 & 0xFF; imm64 >>= 8;
8592 code[14] = imm64 & 0xFF; imm64 >>= 8;
8593 }
florian8844a632012-04-13 04:04:06 +00008594
florian1c857042012-04-15 04:11:07 +00008595 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00008596}
8597
8598
8599/* NB: what goes on here has to be very closely coordinated with the
8600 chainXDirect_S390 and unchainXDirect_S390 below. */
8601static UChar *
8602s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
8603 void *disp_cp_chain_me_to_slowEP,
8604 void *disp_cp_chain_me_to_fastEP)
8605{
8606 /* We're generating chain-me requests here, so we need to be
8607 sure this is actually allowed -- no-redir translations can't
8608 use chain-me's. Hence: */
8609 vassert(disp_cp_chain_me_to_slowEP != NULL);
8610 vassert(disp_cp_chain_me_to_fastEP != NULL);
8611
8612 /* Use ptmp for backpatching conditional jumps. */
8613 UChar *ptmp = buf;
8614
8615 /* First off, if this is conditional, create a conditional
8616 jump over the rest of it. */
8617 s390_cc_t cond = insn->variant.xdirect.cond;
8618
8619 if (cond != S390_CC_ALWAYS) {
8620 /* So we have something like this
8621 if (cond) do_xdirect;
8622 Y: ...
8623 We convert this into
8624 if (! cond) goto Y; // BRC opcode; 4 bytes
8625 do_xdirect;
8626 Y:
8627 */
8628 /* 4 bytes (a BRC insn) to be filled in here */
8629 buf += 4;
8630 }
8631
8632 /* Update the guest IA. */
8633 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
8634
8635 const s390_amode *amode = insn->variant.xdirect.guest_IA;
florianbf516d12012-04-21 15:53:13 +00008636 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00008637 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008638 UInt d = amode->d;
8639
florianbf516d12012-04-21 15:53:13 +00008640 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00008641
florian8844a632012-04-13 04:04:06 +00008642 /* Load the chosen entry point into the scratch reg */
8643 void *disp_cp_chain_me;
8644
8645 disp_cp_chain_me =
8646 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
8647 : disp_cp_chain_me_to_slowEP;
florianebaf8d92012-04-22 17:38:46 +00008648 /* Get the address of the beginning of the load64 code sequence into %r1.
8649 Do not change the register! This is part of the protocol with the
8650 dispatcher. */
8651 buf = s390_emit_BASR(buf, 1, R0);
florian8844a632012-04-13 04:04:06 +00008652
florianebaf8d92012-04-22 17:38:46 +00008653 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
florian8844a632012-04-13 04:04:06 +00008654 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
8655 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
8656
florianebaf8d92012-04-22 17:38:46 +00008657 /* goto *tchain_scratch */
8658 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00008659
8660 /* --- END of PATCHABLE BYTES --- */
8661
8662 /* Fix up the conditional jump, if there was one. */
8663 if (cond != S390_CC_ALWAYS) {
8664 Int delta = buf - ptmp;
8665
8666 delta >>= 1; /* immediate constant is #half-words */
8667 vassert(delta > 0 && delta < (1 << 16));
8668 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8669 }
8670
8671 return buf;
8672}
8673
8674/* Return the number of patchable bytes from an xdirect insn. */
8675static UInt
8676s390_xdirect_patchable_len(void)
8677{
florianebaf8d92012-04-22 17:38:46 +00008678 return s390_tchain_load64_len() + S390_BASR_LEN;
florian8844a632012-04-13 04:04:06 +00008679}
8680
8681
8682static UChar *
8683s390_insn_xindir_emit(UChar *buf, const s390_insn *insn, void *disp_cp_xindir)
8684{
8685 /* We're generating transfers that could lead indirectly to a
8686 chain-me, so we need to be sure this is actually allowed --
8687 no-redir translations are not allowed to reach normal
8688 translations without going through the scheduler. That means
8689 no XDirects or XIndirs out from no-redir translations.
8690 Hence: */
8691 vassert(disp_cp_xindir != NULL);
8692
8693 /* Use ptmp for backpatching conditional jumps. */
8694 UChar *ptmp = buf;
8695
8696 /* First off, if this is conditional, create a conditional
8697 jump over the rest of it. */
8698 s390_cc_t cond = insn->variant.xdirect.cond;
8699
8700 if (cond != S390_CC_ALWAYS) {
8701 /* So we have something like this
8702 if (cond) do_xdirect;
8703 Y: ...
8704 We convert this into
8705 if (! cond) goto Y; // BRC opcode; 4 bytes
8706 do_xdirect;
8707 Y:
8708 */
8709 /* 4 bytes (a BRC insn) to be filled in here */
8710 buf += 4;
8711 }
8712
8713 /* Update the guest IA with the address in xdirect.dst. */
florian7346c7a2012-04-13 21:14:24 +00008714 const s390_amode *amode = insn->variant.xindir.guest_IA;
florian8844a632012-04-13 04:04:06 +00008715
florianbf516d12012-04-21 15:53:13 +00008716 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00008717 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008718 UInt d = amode->d;
florian7346c7a2012-04-13 21:14:24 +00008719 UInt regno = hregNumber(insn->variant.xindir.dst);
florian8844a632012-04-13 04:04:06 +00008720
florianbf516d12012-04-21 15:53:13 +00008721 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00008722
8723 /* load tchain_scratch, #disp_indir */
8724 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
8725 Ptr_to_ULong(disp_cp_xindir));
florianebaf8d92012-04-22 17:38:46 +00008726 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00008727 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
8728
8729 /* Fix up the conditional jump, if there was one. */
8730 if (cond != S390_CC_ALWAYS) {
8731 Int delta = buf - ptmp;
8732
8733 delta >>= 1; /* immediate constant is #half-words */
8734 vassert(delta > 0 && delta < (1 << 16));
8735 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8736 }
8737
8738 return buf;
8739}
8740
8741static UChar *
8742s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
8743 void *disp_cp_xassisted)
8744{
8745 /* Use ptmp for backpatching conditional jumps. */
8746 UChar *ptmp = buf;
8747
8748 /* First off, if this is conditional, create a conditional
8749 jump over the rest of it. */
8750 s390_cc_t cond = insn->variant.xdirect.cond;
8751
8752 if (cond != S390_CC_ALWAYS) {
8753 /* So we have something like this
8754 if (cond) do_xdirect;
8755 Y: ...
8756 We convert this into
8757 if (! cond) goto Y; // BRC opcode; 4 bytes
8758 do_xdirect;
8759 Y:
8760 */
8761 /* 4 bytes (a BRC insn) to be filled in here */
8762 buf += 4;
8763 }
8764
8765 /* Update the guest IA with the address in xassisted.dst. */
8766 const s390_amode *amode = insn->variant.xassisted.guest_IA;
8767
florianbf516d12012-04-21 15:53:13 +00008768 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00008769 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008770 UInt d = amode->d;
8771 UInt regno = hregNumber(insn->variant.xassisted.dst);
8772
florianbf516d12012-04-21 15:53:13 +00008773 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00008774
8775 UInt trcval = 0;
8776
8777 switch (insn->variant.xassisted.kind) {
8778 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
8779 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
florian8844a632012-04-13 04:04:06 +00008780 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
8781 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
florian4e0083e2012-08-26 03:41:56 +00008782 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
florian8844a632012-04-13 04:04:06 +00008783 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
8784 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
8785 case Ijk_TInval: trcval = VEX_TRC_JMP_TINVAL; break;
8786 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
8787 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
8788 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
8789 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
8790 /* We don't expect to see the following being assisted. */
8791 case Ijk_Ret:
8792 case Ijk_Call:
8793 /* fallthrough */
8794 default:
8795 ppIRJumpKind(insn->variant.xassisted.kind);
8796 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
8797 }
8798
8799 vassert(trcval != 0);
8800
8801 /* guest_state_pointer = trcval */
8802 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
8803
8804 /* load tchain_scratch, #disp_assisted */
8805 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
8806 Ptr_to_ULong(disp_cp_xassisted));
8807
florianebaf8d92012-04-22 17:38:46 +00008808 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00008809 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
8810
8811 /* Fix up the conditional jump, if there was one. */
8812 if (cond != S390_CC_ALWAYS) {
8813 Int delta = buf - ptmp;
8814
8815 delta >>= 1; /* immediate constant is #half-words */
8816 vassert(delta > 0 && delta < (1 << 16));
8817 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8818 }
8819
8820 return buf;
8821}
8822
8823
8824/* Pseudo code:
8825
8826 guest_state[host_EvC_COUNTER] -= 1;
8827 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
8828 goto guest_state[host_EvC_FAILADDR];
8829 nofail: ;
8830
8831 The dispatch counter is a 32-bit value. */
8832static UChar *
8833s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn)
8834{
8835 s390_amode *amode;
florianbf516d12012-04-21 15:53:13 +00008836 UInt b, d;
florian8844a632012-04-13 04:04:06 +00008837 UChar *code_begin, *code_end;
8838
8839 code_begin = buf;
8840
8841 amode = insn->variant.evcheck.counter;
florianbf516d12012-04-21 15:53:13 +00008842 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00008843 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008844 d = amode->d;
8845
8846 /* Decrement the dispatch counter in the guest state */
florian0e047d62012-04-21 16:06:04 +00008847 if (s390_host_has_gie) {
8848 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
8849 } else {
8850 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
8851 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
8852 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
8853 }
florian8844a632012-04-13 04:04:06 +00008854
8855 /* Jump over the next insn if >= 0 */
8856 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
8857
8858 /* Computed goto to fail_address */
8859 amode = insn->variant.evcheck.fail_addr;
8860 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008861 d = amode->d;
florianbf516d12012-04-21 15:53:13 +00008862 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
florian8844a632012-04-13 04:04:06 +00008863 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
8864
8865 code_end = buf;
8866
8867 /* Make sure the size of the generated code is identical to the size
8868 returned by evCheckSzB_S390 */
8869 vassert(evCheckSzB_S390() == code_end - code_begin);
8870
8871 return buf;
8872}
8873
8874
8875static UChar *
8876s390_insn_profinc_emit(UChar *buf,
8877 const s390_insn *insn __attribute__((unused)))
8878{
8879 /* Generate a code template to increment a memory location whose
8880 address will be known later as an immediate value. This code
8881 template will be patched once the memory location is known.
8882 For now we do this with address == 0. */
8883 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
florian0e047d62012-04-21 16:06:04 +00008884 if (s390_host_has_gie) {
8885 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8886 } else {
8887 buf = s390_emit_LGHI(buf, R0, 1);
8888 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8889 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8890 }
florian8844a632012-04-13 04:04:06 +00008891
8892 return buf;
8893}
8894
8895
sewardj2019a972011-03-07 16:04:07 +00008896Int
florian8844a632012-04-13 04:04:06 +00008897emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, s390_insn *insn,
8898 Bool mode64, void *disp_cp_chain_me_to_slowEP,
8899 void *disp_cp_chain_me_to_fastEP, void *disp_cp_xindir,
8900 void *disp_cp_xassisted)
sewardj2019a972011-03-07 16:04:07 +00008901{
8902 UChar *end;
8903
florianc4aa7ed2012-12-22 15:01:04 +00008904 /* Used to be 48 bytes. Make sure it stays low */
8905 vassert(sizeof(s390_insn) == 32);
8906
sewardj2019a972011-03-07 16:04:07 +00008907 switch (insn->tag) {
8908 case S390_INSN_LOAD:
8909 end = s390_insn_load_emit(buf, insn);
8910 break;
8911
8912 case S390_INSN_STORE:
8913 end = s390_insn_store_emit(buf, insn);
8914 break;
8915
8916 case S390_INSN_MOVE:
8917 end = s390_insn_move_emit(buf, insn);
8918 break;
8919
8920 case S390_INSN_COND_MOVE:
8921 end = s390_insn_cond_move_emit(buf, insn);
8922 break;
8923
8924 case S390_INSN_LOAD_IMMEDIATE:
8925 end = s390_insn_load_immediate_emit(buf, insn);
8926 break;
8927
8928 case S390_INSN_ALU:
8929 end = s390_insn_alu_emit(buf, insn);
8930 break;
8931
florianc4aa7ed2012-12-22 15:01:04 +00008932 case S390_INSN_SMUL:
8933 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +00008934 end = s390_insn_mul_emit(buf, insn);
8935 break;
8936
florianc4aa7ed2012-12-22 15:01:04 +00008937 case S390_INSN_SDIV:
8938 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +00008939 end = s390_insn_div_emit(buf, insn);
8940 break;
8941
8942 case S390_INSN_DIVS:
8943 end = s390_insn_divs_emit(buf, insn);
8944 break;
8945
sewardj611b06e2011-03-24 08:57:29 +00008946 case S390_INSN_CLZ:
8947 end = s390_insn_clz_emit(buf, insn);
sewardj2019a972011-03-07 16:04:07 +00008948 break;
8949
8950 case S390_INSN_UNOP:
8951 end = s390_insn_unop_emit(buf, insn);
8952 break;
8953
8954 case S390_INSN_TEST:
8955 end = s390_insn_test_emit(buf, insn);
8956 break;
8957
8958 case S390_INSN_CC2BOOL:
8959 end = s390_insn_cc2bool_emit(buf, insn);
8960 break;
8961
8962 case S390_INSN_CAS:
8963 end = s390_insn_cas_emit(buf, insn);
8964 break;
8965
florian448cbba2012-06-06 02:26:01 +00008966 case S390_INSN_CDAS:
8967 end = s390_insn_cdas_emit(buf, insn);
8968 break;
8969
sewardj2019a972011-03-07 16:04:07 +00008970 case S390_INSN_COMPARE:
8971 end = s390_insn_compare_emit(buf, insn);
8972 break;
8973
sewardj2019a972011-03-07 16:04:07 +00008974 case S390_INSN_HELPER_CALL:
8975 end = s390_insn_helper_call_emit(buf, insn);
8976 break;
8977
8978 case S390_INSN_BFP_TRIOP:
8979 end = s390_insn_bfp_triop_emit(buf, insn);
8980 break;
8981
8982 case S390_INSN_BFP_BINOP:
8983 end = s390_insn_bfp_binop_emit(buf, insn);
8984 break;
8985
8986 case S390_INSN_BFP_UNOP:
8987 end = s390_insn_bfp_unop_emit(buf, insn);
8988 break;
8989
8990 case S390_INSN_BFP_COMPARE:
8991 end = s390_insn_bfp_compare_emit(buf, insn);
8992 break;
8993
florian9fcff4c2012-09-10 03:09:04 +00008994 case S390_INSN_BFP_CONVERT:
8995 end = s390_insn_bfp_convert_emit(buf, insn);
8996 break;
8997
florian12390202012-11-10 22:34:14 +00008998 case S390_INSN_DFP_BINOP:
8999 end = s390_insn_dfp_binop_emit(buf, insn);
9000 break;
9001
floriane38f6412012-12-21 17:32:12 +00009002 case S390_INSN_DFP_COMPARE:
9003 end = s390_insn_dfp_compare_emit(buf, insn);
9004 break;
9005
9006 case S390_INSN_DFP_CONVERT:
9007 end = s390_insn_dfp_convert_emit(buf, insn);
9008 break;
9009
sewardja52e37e2011-04-28 18:48:06 +00009010 case S390_INSN_MFENCE:
9011 end = s390_insn_mfence_emit(buf, insn);
9012 break;
9013
florianb93348d2012-12-27 00:59:43 +00009014 case S390_INSN_MIMM:
9015 end = s390_insn_mimm_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +00009016 break;
9017
florianf85fe3e2012-12-22 02:28:25 +00009018 case S390_INSN_MADD:
9019 end = s390_insn_madd_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +00009020 break;
9021
florian125e20d2012-10-07 15:42:37 +00009022 case S390_INSN_SET_FPC_BFPRM:
9023 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
florian2c74d242012-09-12 19:38:42 +00009024 break;
9025
florianc8e4f562012-10-27 16:19:31 +00009026 case S390_INSN_SET_FPC_DFPRM:
9027 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
9028 break;
9029
florian8844a632012-04-13 04:04:06 +00009030 case S390_INSN_PROFINC:
9031 end = s390_insn_profinc_emit(buf, insn);
9032 /* Tell the caller .. */
9033 vassert(*is_profinc == False);
9034 *is_profinc = True;
9035 break;
9036
9037 case S390_INSN_EVCHECK:
9038 end = s390_insn_evcheck_emit(buf, insn);
9039 break;
9040
9041 case S390_INSN_XDIRECT:
9042 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
9043 disp_cp_chain_me_to_fastEP);
9044 break;
9045
9046 case S390_INSN_XINDIR:
9047 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
9048 break;
9049
9050 case S390_INSN_XASSISTED:
9051 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
9052 break;
9053
sewardj2019a972011-03-07 16:04:07 +00009054 default:
florian616458b2012-03-25 16:17:18 +00009055 vpanic("emit_S390Instr");
sewardj2019a972011-03-07 16:04:07 +00009056 }
9057
9058 vassert(end - buf <= nbuf);
9059
9060 return end - buf;
9061}
9062
9063
florian8844a632012-04-13 04:04:06 +00009064/* Return the number of bytes emitted for an S390_INSN_EVCHECK.
9065 See s390_insn_evcheck_emit */
9066Int
9067evCheckSzB_S390(void)
9068{
florian0e047d62012-04-21 16:06:04 +00009069 return s390_host_has_gie ? 18 : 24;
florian8844a632012-04-13 04:04:06 +00009070}
9071
9072
9073/* Patch the counter address into CODE_TO_PATCH as previously
9074 generated by s390_insn_profinc_emit. */
9075VexInvalRange
9076patchProfInc_S390(void *code_to_patch, ULong *location_of_counter)
9077{
9078 vassert(sizeof(ULong *) == 8);
9079
9080 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
9081
florian5ea257b2012-09-29 17:05:46 +00009082 UChar *p = s390_tchain_patch_load64(code_to_patch,
9083 Ptr_to_ULong(location_of_counter));
florian8844a632012-04-13 04:04:06 +00009084
florian5ea257b2012-09-29 17:05:46 +00009085 UInt len = p - (UChar *)code_to_patch;
9086 VexInvalRange vir = { (HWord)code_to_patch, len };
florian8844a632012-04-13 04:04:06 +00009087 return vir;
9088}
9089
9090
9091/* NB: what goes on here has to be very closely coordinated with the
9092 s390_insn_xdirect_emit code above. */
9093VexInvalRange
9094chainXDirect_S390(void *place_to_chain,
9095 void *disp_cp_chain_me_EXPECTED,
9096 void *place_to_jump_to)
9097{
florianebaf8d92012-04-22 17:38:46 +00009098 /* What we're expecting to see @ PLACE_TO_CHAIN is:
florian8844a632012-04-13 04:04:06 +00009099
florianebaf8d92012-04-22 17:38:46 +00009100 load tchain_scratch, #disp_cp_chain_me_EXPECTED
9101 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009102 */
9103 const UChar *next;
9104 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
9105 Ptr_to_ULong(disp_cp_chain_me_EXPECTED));
florianebaf8d92012-04-22 17:38:46 +00009106 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +00009107
9108 /* And what we want to change it to is either:
9109 (general case):
9110
florianebaf8d92012-04-22 17:38:46 +00009111 load tchain_scratch, #place_to_jump_to
9112 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009113
9114 ---OR---
9115
9116 in the case where the displacement is small enough
9117
9118 BRCL delta where delta is in half-words
9119 invalid opcodes
9120
9121 In both cases the replacement has the same length as the original.
9122 To remain sane & verifiable,
9123 (1) limit the displacement for the short form to
9124 (say) +/- one billion, so as to avoid wraparound
9125 off-by-ones
9126 (2) even if the short form is applicable, once every (say)
9127 1024 times use the long form anyway, so as to maintain
9128 verifiability
9129 */
9130
9131 /* This is the delta we need to put into a BRCL insn. Note, that the
9132 offset in BRCL is in half-words. Hence division by 2. */
9133 Long delta = (Long)((UChar *)place_to_jump_to - (UChar *)place_to_chain) / 2;
9134 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
9135
9136 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
9137 if (shortOK) {
9138 shortCTR++; // thread safety bleh
9139 if (0 == (shortCTR & 0x3FF)) {
9140 shortOK = False;
9141 if (0)
9142 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
9143 "using long jmp\n", shortCTR);
9144 }
9145 }
9146
9147 /* And make the modifications. */
9148 UChar *p = (UChar *)place_to_chain;
9149 if (shortOK) {
9150 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
9151
florian48cb9612012-04-20 02:50:28 +00009152 /* Make sure that BRCL fits into the patchable part of an xdirect
florian1c857042012-04-15 04:11:07 +00009153 code sequence */
florian48cb9612012-04-20 02:50:28 +00009154 vassert(6 <= s390_xdirect_patchable_len());
florian1c857042012-04-15 04:11:07 +00009155
florian8844a632012-04-13 04:04:06 +00009156 /* Fill remaining bytes with 0x00 (invalid opcode) */
9157 Int i;
9158 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
9159 p[i] = 0x00;
9160 } else {
florian1c857042012-04-15 04:11:07 +00009161 /*
florianebaf8d92012-04-22 17:38:46 +00009162 load tchain_scratch, #place_to_jump_to
9163 goto *tchain_scratch
florian1c857042012-04-15 04:11:07 +00009164 */
9165 ULong addr = Ptr_to_ULong(place_to_jump_to);
9166 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +00009167 /* There is not need to emit a BCR here, as it is already there. */
florian8844a632012-04-13 04:04:06 +00009168 }
9169
florian5ea257b2012-09-29 17:05:46 +00009170 UInt len = p - (UChar *)place_to_chain;
9171 VexInvalRange vir = { (HWord)place_to_chain, len };
florian8844a632012-04-13 04:04:06 +00009172 return vir;
9173}
9174
9175
9176/* NB: what goes on here has to be very closely coordinated with the
9177 s390_insn_xdirect_emit code above. */
9178VexInvalRange
9179unchainXDirect_S390(void *place_to_unchain,
9180 void *place_to_jump_to_EXPECTED,
9181 void *disp_cp_chain_me)
9182{
9183 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
9184
florianebaf8d92012-04-22 17:38:46 +00009185 load tchain_scratch, #place_to_jump_to_EXPECTED
9186 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009187
9188 ---OR---
9189 in the case where the displacement falls within 32 bits
9190
9191 BRCL delta
9192 invalid opcodes
9193 */
9194 UChar *p = place_to_unchain;
florian1c857042012-04-15 04:11:07 +00009195
florianebaf8d92012-04-22 17:38:46 +00009196 Bool uses_short_form = False;
9197
florian1c857042012-04-15 04:11:07 +00009198 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
florian8844a632012-04-13 04:04:06 +00009199 /* Looks like the short form */
9200 Int num_hw = *(Int *)&p[2];
9201 Int delta = 2 *num_hw;
9202
9203 vassert(p + delta == place_to_jump_to_EXPECTED);
9204
florian8844a632012-04-13 04:04:06 +00009205 Int i;
9206 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
florian1c857042012-04-15 04:11:07 +00009207 vassert(p[6+i] == 0x00);
florianebaf8d92012-04-22 17:38:46 +00009208 uses_short_form = True;
florian8844a632012-04-13 04:04:06 +00009209 } else {
9210 /* Should be the long form */
9211 const UChar *next;
9212
9213 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
9214 Ptr_to_ULong(place_to_jump_to_EXPECTED));
9215 /* Check for BR *tchain_scratch */
florian1c857042012-04-15 04:11:07 +00009216 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +00009217 }
9218
9219 /* And what we want to change it to is:
9220
9221 load tchain_scratch, #disp_cp_chain_me
florianebaf8d92012-04-22 17:38:46 +00009222 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009223 */
florianebaf8d92012-04-22 17:38:46 +00009224
9225 /* Get the address of the beginning of the load64 code sequence into %r1.
9226 Do not change the register! This is part of the protocol with the
9227 dispatcher.
9228 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
9229 load64 insn sequence. That sequence is prefixed with a BASR to get its
9230 address (see s390_insn_xdirect_emit). */
9231 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
9232
florian8844a632012-04-13 04:04:06 +00009233 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
9234 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +00009235
9236 /* Emit the BCR in case the short form was used. In case of the long
9237 form, the BCR is already there. */
9238 if (uses_short_form)
9239 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00009240
florian5ea257b2012-09-29 17:05:46 +00009241 UInt len = p - (UChar *)place_to_unchain;
9242 VexInvalRange vir = { (HWord)place_to_unchain, len };
florian8844a632012-04-13 04:04:06 +00009243 return vir;
9244}
9245
sewardj2019a972011-03-07 16:04:07 +00009246/*---------------------------------------------------------------*/
9247/*--- end host_s390_defs.c ---*/
9248/*---------------------------------------------------------------*/