blob: 3a822222bafd0686f3895752caf136a28f0e9ea2 [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
florian09bbba82012-12-11 04:09:43 +0000744 case S390_INSN_MZERO:
745 s390_amode_get_reg_usage(u, insn->variant.mzero.dst);
746 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
florian09bbba82012-12-11 04:09:43 +00001029 case S390_INSN_MZERO:
1030 s390_amode_map_regs(m, insn->variant.mzero.dst);
1031 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 *
1313emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1314{
1315 ULong the_insn = op;
1316
1317 the_insn |= ((ULong)i2) << 32;
1318 the_insn |= ((ULong)b1) << 28;
1319 the_insn |= ((ULong)dl1) << 16;
1320 the_insn |= ((ULong)dh1) << 8;
1321
1322 return emit_6bytes(p, the_insn);
1323}
1324
1325
1326static UChar *
1327emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1328{
1329 ULong the_insn = op;
1330
1331 the_insn |= ((ULong)l) << 32;
1332 the_insn |= ((ULong)b1) << 28;
1333 the_insn |= ((ULong)d1) << 16;
1334 the_insn |= ((ULong)b2) << 12;
1335 the_insn |= ((ULong)d2) << 0;
1336
1337 return emit_6bytes(p, the_insn);
1338}
1339
1340
sewardj2019a972011-03-07 16:04:07 +00001341/*------------------------------------------------------------*/
1342/*--- Functions to emit particular instructions ---*/
1343/*------------------------------------------------------------*/
1344
sewardj9d31dfd2011-03-15 12:36:44 +00001345static UChar *
sewardj2019a972011-03-07 16:04:07 +00001346s390_emit_AR(UChar *p, UChar r1, UChar r2)
1347{
sewardj7ee97522011-05-09 21:45:04 +00001348 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001349 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1350
1351 return emit_RR(p, 0x1a00, r1, r2);
1352}
1353
1354
sewardj9d31dfd2011-03-15 12:36:44 +00001355static UChar *
sewardj2019a972011-03-07 16:04:07 +00001356s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1357{
sewardj7ee97522011-05-09 21:45:04 +00001358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001359 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1360
1361 return emit_RRE(p, 0xb9080000, r1, r2);
1362}
1363
1364
sewardj9d31dfd2011-03-15 12:36:44 +00001365static UChar *
sewardj2019a972011-03-07 16:04:07 +00001366s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1367{
sewardj7ee97522011-05-09 21:45:04 +00001368 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001369 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1370
1371 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1372}
1373
1374
sewardj9d31dfd2011-03-15 12:36:44 +00001375static UChar *
sewardj2019a972011-03-07 16:04:07 +00001376s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1377{
sewardj652b56a2011-04-13 15:38:17 +00001378 vassert(s390_host_has_ldisp);
1379
sewardj7ee97522011-05-09 21:45:04 +00001380 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001381 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1382
1383 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1384}
1385
1386
sewardj9d31dfd2011-03-15 12:36:44 +00001387static UChar *
sewardj2019a972011-03-07 16:04:07 +00001388s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1389{
sewardj652b56a2011-04-13 15:38:17 +00001390 vassert(s390_host_has_ldisp || dh2 == 0);
1391
sewardj7ee97522011-05-09 21:45:04 +00001392 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001393 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1394
1395 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1396}
1397
1398
sewardj9d31dfd2011-03-15 12:36:44 +00001399static UChar *
sewardj2019a972011-03-07 16:04:07 +00001400s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1401{
sewardj652b56a2011-04-13 15:38:17 +00001402 vassert(s390_host_has_eimm);
1403
sewardj7ee97522011-05-09 21:45:04 +00001404 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001405 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1406
1407 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1408}
1409
1410
sewardj9d31dfd2011-03-15 12:36:44 +00001411static UChar *
sewardj2019a972011-03-07 16:04:07 +00001412s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1413{
sewardj652b56a2011-04-13 15:38:17 +00001414 vassert(s390_host_has_eimm);
1415
sewardj7ee97522011-05-09 21:45:04 +00001416 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001417 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1418
1419 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1420}
1421
1422
sewardj9d31dfd2011-03-15 12:36:44 +00001423static UChar *
sewardj2019a972011-03-07 16:04:07 +00001424s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1425{
sewardj7ee97522011-05-09 21:45:04 +00001426 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001427 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1428
1429 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1430}
1431
1432
sewardj9d31dfd2011-03-15 12:36:44 +00001433static UChar *
sewardj2019a972011-03-07 16:04:07 +00001434s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1435{
sewardj652b56a2011-04-13 15:38:17 +00001436 vassert(s390_host_has_ldisp);
1437
sewardj7ee97522011-05-09 21:45:04 +00001438 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001439 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1440
1441 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1442}
1443
1444
sewardj9d31dfd2011-03-15 12:36:44 +00001445static UChar *
sewardj2019a972011-03-07 16:04:07 +00001446s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1447{
sewardj7ee97522011-05-09 21:45:04 +00001448 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001449 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1450
1451 return emit_RI(p, 0xa70a0000, r1, i2);
1452}
1453
1454
sewardj9d31dfd2011-03-15 12:36:44 +00001455static UChar *
sewardj2019a972011-03-07 16:04:07 +00001456s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1457{
sewardj7ee97522011-05-09 21:45:04 +00001458 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001459 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1460
1461 return emit_RI(p, 0xa70b0000, r1, i2);
1462}
1463
1464
sewardj9d31dfd2011-03-15 12:36:44 +00001465static UChar *
florianad43b3a2012-02-20 15:01:14 +00001466s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1467{
1468 vassert(s390_host_has_gie);
1469
1470 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001471 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
florianad43b3a2012-02-20 15:01:14 +00001472
1473 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
1474}
1475
1476
1477static UChar *
florian0e047d62012-04-21 16:06:04 +00001478s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1479{
1480 vassert(s390_host_has_gie);
1481
1482 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001483 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
florian0e047d62012-04-21 16:06:04 +00001484
1485 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
1486}
1487
1488
1489static UChar *
sewardj2019a972011-03-07 16:04:07 +00001490s390_emit_NR(UChar *p, UChar r1, UChar r2)
1491{
sewardj7ee97522011-05-09 21:45:04 +00001492 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001493 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1494
1495 return emit_RR(p, 0x1400, r1, r2);
1496}
1497
1498
sewardj9d31dfd2011-03-15 12:36:44 +00001499static UChar *
sewardj2019a972011-03-07 16:04:07 +00001500s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1501{
sewardj7ee97522011-05-09 21:45:04 +00001502 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001503 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1504
1505 return emit_RRE(p, 0xb9800000, r1, r2);
1506}
1507
1508
sewardj9d31dfd2011-03-15 12:36:44 +00001509static UChar *
sewardj2019a972011-03-07 16:04:07 +00001510s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1511{
sewardj7ee97522011-05-09 21:45:04 +00001512 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001513 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1514
1515 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1516}
1517
1518
sewardj9d31dfd2011-03-15 12:36:44 +00001519static UChar *
sewardj2019a972011-03-07 16:04:07 +00001520s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1521{
sewardj652b56a2011-04-13 15:38:17 +00001522 vassert(s390_host_has_ldisp);
1523
sewardj7ee97522011-05-09 21:45:04 +00001524 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001525 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1526
1527 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1528}
1529
1530
sewardj9d31dfd2011-03-15 12:36:44 +00001531static UChar *
sewardj2019a972011-03-07 16:04:07 +00001532s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1533{
sewardj652b56a2011-04-13 15:38:17 +00001534 vassert(s390_host_has_ldisp || dh2 == 0);
1535
sewardj7ee97522011-05-09 21:45:04 +00001536 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001537 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1538
1539 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1540}
1541
1542
sewardj9d31dfd2011-03-15 12:36:44 +00001543static UChar *
sewardj2019a972011-03-07 16:04:07 +00001544s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1545{
sewardj652b56a2011-04-13 15:38:17 +00001546 vassert(s390_host_has_eimm);
1547
sewardj7ee97522011-05-09 21:45:04 +00001548 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001549 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1550
1551 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1552}
1553
1554
sewardj9d31dfd2011-03-15 12:36:44 +00001555static UChar *
sewardj2019a972011-03-07 16:04:07 +00001556s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1557{
sewardj652b56a2011-04-13 15:38:17 +00001558 vassert(s390_host_has_eimm);
1559
sewardj7ee97522011-05-09 21:45:04 +00001560 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001561 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1562
1563 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1564}
1565
1566
sewardj9d31dfd2011-03-15 12:36:44 +00001567static UChar *
sewardj2019a972011-03-07 16:04:07 +00001568s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1569{
sewardj7ee97522011-05-09 21:45:04 +00001570 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001571 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1572
1573 return emit_RI(p, 0xa5070000, r1, i2);
1574}
1575
1576
sewardj9d31dfd2011-03-15 12:36:44 +00001577static UChar *
sewardj2019a972011-03-07 16:04:07 +00001578s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1579{
sewardj7ee97522011-05-09 21:45:04 +00001580 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001581 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1582
1583 return emit_RR(p, 0x0d00, r1, r2);
1584}
1585
1586
sewardj9d31dfd2011-03-15 12:36:44 +00001587static UChar *
sewardj2019a972011-03-07 16:04:07 +00001588s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1589{
sewardj7ee97522011-05-09 21:45:04 +00001590 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001591 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1592
1593 return emit_RR(p, 0x0700, r1, r2);
1594}
1595
1596
sewardj9d31dfd2011-03-15 12:36:44 +00001597static UChar *
sewardj2019a972011-03-07 16:04:07 +00001598s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1599{
sewardj7ee97522011-05-09 21:45:04 +00001600 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001601 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1602
1603 return emit_RI(p, 0xa7040000, r1, i2);
1604}
1605
1606
sewardj9d31dfd2011-03-15 12:36:44 +00001607static UChar *
florian8844a632012-04-13 04:04:06 +00001608s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
1609{
1610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1611 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
1612
1613 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
1614}
1615
1616
1617static UChar *
sewardj2019a972011-03-07 16:04:07 +00001618s390_emit_CR(UChar *p, UChar r1, UChar r2)
1619{
sewardj7ee97522011-05-09 21:45:04 +00001620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001621 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1622
1623 return emit_RR(p, 0x1900, r1, r2);
1624}
1625
1626
sewardj9d31dfd2011-03-15 12:36:44 +00001627static UChar *
sewardj2019a972011-03-07 16:04:07 +00001628s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1629{
sewardj7ee97522011-05-09 21:45:04 +00001630 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001631 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1632
1633 return emit_RRE(p, 0xb9200000, r1, r2);
1634}
1635
1636
sewardj9d31dfd2011-03-15 12:36:44 +00001637static UChar *
sewardj2019a972011-03-07 16:04:07 +00001638s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1639{
sewardj7ee97522011-05-09 21:45:04 +00001640 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001641 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1642
1643 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1644}
1645
1646
sewardj9d31dfd2011-03-15 12:36:44 +00001647static UChar *
sewardj2019a972011-03-07 16:04:07 +00001648s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1649{
sewardj652b56a2011-04-13 15:38:17 +00001650 vassert(s390_host_has_ldisp);
1651
sewardj7ee97522011-05-09 21:45:04 +00001652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001653 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1654
1655 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1656}
1657
1658
sewardj9d31dfd2011-03-15 12:36:44 +00001659static UChar *
sewardj2019a972011-03-07 16:04:07 +00001660s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1661{
sewardj652b56a2011-04-13 15:38:17 +00001662 vassert(s390_host_has_ldisp || dh2 == 0);
1663
sewardj7ee97522011-05-09 21:45:04 +00001664 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001665 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1666
1667 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1668}
1669
1670
sewardj9d31dfd2011-03-15 12:36:44 +00001671static UChar *
sewardj2019a972011-03-07 16:04:07 +00001672s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1673{
sewardj652b56a2011-04-13 15:38:17 +00001674 vassert(s390_host_has_eimm);
1675
sewardj7ee97522011-05-09 21:45:04 +00001676 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001677 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1678
1679 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1680}
1681
1682
sewardj9d31dfd2011-03-15 12:36:44 +00001683static UChar *
florian07d34552012-05-26 01:59:21 +00001684s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
1685{
1686 vassert(s390_host_has_eimm);
1687
1688 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1689 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
1690
1691 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
1692}
1693
1694
1695static UChar *
sewardj2019a972011-03-07 16:04:07 +00001696s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1697{
sewardj7ee97522011-05-09 21:45:04 +00001698 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001699 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1700
1701 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1702}
1703
1704
sewardj9d31dfd2011-03-15 12:36:44 +00001705static UChar *
sewardj2019a972011-03-07 16:04:07 +00001706s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1707{
sewardj652b56a2011-04-13 15:38:17 +00001708 vassert(s390_host_has_ldisp);
1709
sewardj7ee97522011-05-09 21:45:04 +00001710 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001711 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1712
1713 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1714}
1715
1716
sewardj9d31dfd2011-03-15 12:36:44 +00001717static UChar *
sewardj2019a972011-03-07 16:04:07 +00001718s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1719{
sewardj652b56a2011-04-13 15:38:17 +00001720 vassert(s390_host_has_ldisp || dh2 == 0);
1721
sewardj7ee97522011-05-09 21:45:04 +00001722 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001723 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1724
1725 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1726}
1727
1728
sewardj9d31dfd2011-03-15 12:36:44 +00001729static UChar *
florian448cbba2012-06-06 02:26:01 +00001730s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1731{
1732 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1733 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
1734
1735 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
1736}
1737
1738
1739static UChar *
1740s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1741{
1742 vassert(s390_host_has_ldisp);
1743
1744 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1745 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
1746
1747 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
1748}
1749
1750
1751static UChar *
1752s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1753{
1754 vassert(s390_host_has_ldisp || dh2 == 0);
1755
1756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1757 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
1758
1759 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
1760}
1761
1762
1763static UChar *
sewardj2019a972011-03-07 16:04:07 +00001764s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1765{
sewardj7ee97522011-05-09 21:45:04 +00001766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001767 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1768
1769 return emit_RR(p, 0x1500, r1, r2);
1770}
1771
1772
sewardj9d31dfd2011-03-15 12:36:44 +00001773static UChar *
sewardj2019a972011-03-07 16:04:07 +00001774s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1775{
sewardj7ee97522011-05-09 21:45:04 +00001776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001777 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1778
1779 return emit_RRE(p, 0xb9210000, r1, r2);
1780}
1781
1782
sewardj9d31dfd2011-03-15 12:36:44 +00001783static UChar *
sewardj2019a972011-03-07 16:04:07 +00001784s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1785{
sewardj7ee97522011-05-09 21:45:04 +00001786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001787 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1788
1789 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1790}
1791
1792
sewardj9d31dfd2011-03-15 12:36:44 +00001793static UChar *
sewardj2019a972011-03-07 16:04:07 +00001794s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1795{
sewardj652b56a2011-04-13 15:38:17 +00001796 vassert(s390_host_has_ldisp);
1797
sewardj7ee97522011-05-09 21:45:04 +00001798 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001799 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1800
1801 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1802}
1803
1804
sewardj9d31dfd2011-03-15 12:36:44 +00001805static UChar *
sewardj2019a972011-03-07 16:04:07 +00001806s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1807{
sewardj652b56a2011-04-13 15:38:17 +00001808 vassert(s390_host_has_ldisp || dh2 == 0);
1809
sewardj7ee97522011-05-09 21:45:04 +00001810 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001811 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1812
1813 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1814}
1815
1816
sewardj9d31dfd2011-03-15 12:36:44 +00001817static UChar *
sewardj2019a972011-03-07 16:04:07 +00001818s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1819{
sewardj652b56a2011-04-13 15:38:17 +00001820 vassert(s390_host_has_eimm);
1821
sewardj7ee97522011-05-09 21:45:04 +00001822 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001823 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1824
1825 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1826}
1827
1828
sewardj9d31dfd2011-03-15 12:36:44 +00001829static UChar *
florian07d34552012-05-26 01:59:21 +00001830s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
1831{
1832 vassert(s390_host_has_eimm);
1833
1834 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1835 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
1836
1837 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
1838}
1839
1840
1841static UChar *
sewardj2019a972011-03-07 16:04:07 +00001842s390_emit_DR(UChar *p, UChar r1, UChar r2)
1843{
sewardj7ee97522011-05-09 21:45:04 +00001844 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001845 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1846
1847 return emit_RR(p, 0x1d00, r1, r2);
1848}
1849
1850
sewardj9d31dfd2011-03-15 12:36:44 +00001851static UChar *
sewardj2019a972011-03-07 16:04:07 +00001852s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1853{
sewardj7ee97522011-05-09 21:45:04 +00001854 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001855 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1856
1857 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1858}
1859
1860
sewardj9d31dfd2011-03-15 12:36:44 +00001861static UChar *
sewardj2019a972011-03-07 16:04:07 +00001862s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1863{
sewardj7ee97522011-05-09 21:45:04 +00001864 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001865 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1866
1867 return emit_RRE(p, 0xb9970000, r1, r2);
1868}
1869
1870
sewardj9d31dfd2011-03-15 12:36:44 +00001871static UChar *
sewardj2019a972011-03-07 16:04:07 +00001872s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
1873{
sewardj7ee97522011-05-09 21:45:04 +00001874 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001875 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
1876
1877 return emit_RRE(p, 0xb9870000, r1, r2);
1878}
1879
1880
sewardj9d31dfd2011-03-15 12:36:44 +00001881static UChar *
sewardj2019a972011-03-07 16:04:07 +00001882s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1883{
sewardj652b56a2011-04-13 15:38:17 +00001884 vassert(s390_host_has_ldisp || dh2 == 0);
1885
sewardj7ee97522011-05-09 21:45:04 +00001886 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001887 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
1888
1889 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
1890}
1891
1892
sewardj9d31dfd2011-03-15 12:36:44 +00001893static UChar *
sewardj2019a972011-03-07 16:04:07 +00001894s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1895{
sewardj652b56a2011-04-13 15:38:17 +00001896 vassert(s390_host_has_ldisp || dh2 == 0);
1897
sewardj7ee97522011-05-09 21:45:04 +00001898 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001899 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
1900
1901 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
1902}
1903
1904
sewardj9d31dfd2011-03-15 12:36:44 +00001905static UChar *
sewardj2019a972011-03-07 16:04:07 +00001906s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
1907{
sewardj7ee97522011-05-09 21:45:04 +00001908 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001909 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
1910
1911 return emit_RRE(p, 0xb90d0000, r1, r2);
1912}
1913
1914
sewardj9d31dfd2011-03-15 12:36:44 +00001915static UChar *
sewardj2019a972011-03-07 16:04:07 +00001916s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1917{
sewardj652b56a2011-04-13 15:38:17 +00001918 vassert(s390_host_has_ldisp || dh2 == 0);
1919
sewardj7ee97522011-05-09 21:45:04 +00001920 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001921 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
1922
1923 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
1924}
1925
1926
sewardj9d31dfd2011-03-15 12:36:44 +00001927static UChar *
sewardj2019a972011-03-07 16:04:07 +00001928s390_emit_XR(UChar *p, UChar r1, UChar r2)
1929{
sewardj7ee97522011-05-09 21:45:04 +00001930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001931 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
1932
1933 return emit_RR(p, 0x1700, r1, r2);
1934}
1935
1936
sewardj9d31dfd2011-03-15 12:36:44 +00001937static UChar *
sewardj2019a972011-03-07 16:04:07 +00001938s390_emit_XGR(UChar *p, UChar r1, UChar r2)
1939{
sewardj7ee97522011-05-09 21:45:04 +00001940 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001941 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
1942
1943 return emit_RRE(p, 0xb9820000, r1, r2);
1944}
1945
1946
sewardj9d31dfd2011-03-15 12:36:44 +00001947static UChar *
sewardj2019a972011-03-07 16:04:07 +00001948s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1949{
sewardj7ee97522011-05-09 21:45:04 +00001950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001951 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
1952
1953 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
1954}
1955
1956
sewardj9d31dfd2011-03-15 12:36:44 +00001957static UChar *
sewardj2019a972011-03-07 16:04:07 +00001958s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1959{
sewardj652b56a2011-04-13 15:38:17 +00001960 vassert(s390_host_has_ldisp);
1961
sewardj7ee97522011-05-09 21:45:04 +00001962 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001963 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
1964
1965 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
1966}
1967
1968
sewardj9d31dfd2011-03-15 12:36:44 +00001969static UChar *
sewardj2019a972011-03-07 16:04:07 +00001970s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1971{
sewardj652b56a2011-04-13 15:38:17 +00001972 vassert(s390_host_has_ldisp || dh2 == 0);
1973
sewardj7ee97522011-05-09 21:45:04 +00001974 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001975 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
1976
1977 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
1978}
1979
1980
sewardj9d31dfd2011-03-15 12:36:44 +00001981static UChar *
sewardj2019a972011-03-07 16:04:07 +00001982s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
1983{
sewardj652b56a2011-04-13 15:38:17 +00001984 vassert(s390_host_has_eimm);
1985
sewardj7ee97522011-05-09 21:45:04 +00001986 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001987 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
1988
1989 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
1990}
1991
1992
sewardj9d31dfd2011-03-15 12:36:44 +00001993static UChar *
sewardj2019a972011-03-07 16:04:07 +00001994s390_emit_XILF(UChar *p, UChar r1, UInt i2)
1995{
sewardj652b56a2011-04-13 15:38:17 +00001996 vassert(s390_host_has_eimm);
1997
sewardj7ee97522011-05-09 21:45:04 +00001998 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001999 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
2000
2001 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
2002}
2003
2004
sewardj9d31dfd2011-03-15 12:36:44 +00002005static UChar *
florianad43b3a2012-02-20 15:01:14 +00002006s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2007{
2008 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2009 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
2010
2011 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
2012}
2013
2014
2015static UChar *
sewardj2019a972011-03-07 16:04:07 +00002016s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
2017{
sewardj652b56a2011-04-13 15:38:17 +00002018 vassert(s390_host_has_eimm);
2019
sewardj7ee97522011-05-09 21:45:04 +00002020 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002021 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
2022
2023 return emit_RRE(p, 0xb9830000, r1, r2);
2024}
2025
2026
sewardj9d31dfd2011-03-15 12:36:44 +00002027static UChar *
sewardj2019a972011-03-07 16:04:07 +00002028s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2029{
sewardj7ee97522011-05-09 21:45:04 +00002030 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002031 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
2032
2033 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
2034}
2035
2036
sewardj9d31dfd2011-03-15 12:36:44 +00002037static UChar *
sewardj2019a972011-03-07 16:04:07 +00002038s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2039{
sewardj652b56a2011-04-13 15:38:17 +00002040 vassert(s390_host_has_ldisp);
2041
sewardj7ee97522011-05-09 21:45:04 +00002042 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002043 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
2044
2045 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
2046}
2047
2048
sewardj9d31dfd2011-03-15 12:36:44 +00002049static UChar *
sewardj2019a972011-03-07 16:04:07 +00002050s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
2051{
sewardj652b56a2011-04-13 15:38:17 +00002052 vassert(s390_host_has_eimm);
2053
sewardj7ee97522011-05-09 21:45:04 +00002054 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002055 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
2056
2057 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
2058}
2059
2060
sewardj9d31dfd2011-03-15 12:36:44 +00002061static UChar *
sewardj2019a972011-03-07 16:04:07 +00002062s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
2063{
sewardj7ee97522011-05-09 21:45:04 +00002064 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002065 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
2066
2067 return emit_RI(p, 0xa5000000, r1, i2);
2068}
2069
2070
sewardj9d31dfd2011-03-15 12:36:44 +00002071static UChar *
sewardj2019a972011-03-07 16:04:07 +00002072s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
2073{
sewardj7ee97522011-05-09 21:45:04 +00002074 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002075 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
2076
2077 return emit_RI(p, 0xa5010000, r1, i2);
2078}
2079
2080
sewardj9d31dfd2011-03-15 12:36:44 +00002081static UChar *
sewardj2019a972011-03-07 16:04:07 +00002082s390_emit_IILF(UChar *p, UChar r1, UInt i2)
2083{
sewardj652b56a2011-04-13 15:38:17 +00002084 vassert(s390_host_has_eimm);
2085
sewardj7ee97522011-05-09 21:45:04 +00002086 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002087 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
2088
2089 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
2090}
2091
2092
sewardj9d31dfd2011-03-15 12:36:44 +00002093static UChar *
sewardj2019a972011-03-07 16:04:07 +00002094s390_emit_IILH(UChar *p, UChar r1, UShort i2)
2095{
sewardj7ee97522011-05-09 21:45:04 +00002096 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002097 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
2098
2099 return emit_RI(p, 0xa5020000, r1, i2);
2100}
2101
2102
sewardj9d31dfd2011-03-15 12:36:44 +00002103static UChar *
sewardj2019a972011-03-07 16:04:07 +00002104s390_emit_IILL(UChar *p, UChar r1, UShort i2)
2105{
sewardj7ee97522011-05-09 21:45:04 +00002106 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002107 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
2108
2109 return emit_RI(p, 0xa5030000, r1, i2);
2110}
2111
2112
sewardj9d31dfd2011-03-15 12:36:44 +00002113static UChar *
sewardj2019a972011-03-07 16:04:07 +00002114s390_emit_IPM(UChar *p, UChar r1, UChar r2)
2115{
sewardj7ee97522011-05-09 21:45:04 +00002116 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002117 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
2118
2119 return emit_RRE(p, 0xb2220000, r1, r2);
2120}
2121
2122
sewardj9d31dfd2011-03-15 12:36:44 +00002123static UChar *
sewardj2019a972011-03-07 16:04:07 +00002124s390_emit_LR(UChar *p, UChar r1, UChar r2)
2125{
sewardj7ee97522011-05-09 21:45:04 +00002126 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002127 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
2128
2129 return emit_RR(p, 0x1800, r1, r2);
2130}
2131
2132
sewardj9d31dfd2011-03-15 12:36:44 +00002133static UChar *
sewardj2019a972011-03-07 16:04:07 +00002134s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2135{
sewardj7ee97522011-05-09 21:45:04 +00002136 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002137 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2138
2139 return emit_RRE(p, 0xb9040000, r1, r2);
2140}
2141
2142
sewardj9d31dfd2011-03-15 12:36:44 +00002143static UChar *
sewardj2019a972011-03-07 16:04:07 +00002144s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2145{
sewardj7ee97522011-05-09 21:45:04 +00002146 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002147 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2148
2149 return emit_RRE(p, 0xb9140000, r1, r2);
2150}
2151
2152
sewardj9d31dfd2011-03-15 12:36:44 +00002153static UChar *
sewardj2019a972011-03-07 16:04:07 +00002154s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2155{
sewardj7ee97522011-05-09 21:45:04 +00002156 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002157 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2158
2159 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2160}
2161
2162
sewardj9d31dfd2011-03-15 12:36:44 +00002163static UChar *
sewardj2019a972011-03-07 16:04:07 +00002164s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2165{
sewardj652b56a2011-04-13 15:38:17 +00002166 vassert(s390_host_has_ldisp);
2167
sewardj7ee97522011-05-09 21:45:04 +00002168 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002169 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2170
2171 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2172}
2173
2174
sewardj9d31dfd2011-03-15 12:36:44 +00002175static UChar *
sewardj2019a972011-03-07 16:04:07 +00002176s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2177{
sewardj652b56a2011-04-13 15:38:17 +00002178 vassert(s390_host_has_ldisp || dh2 == 0);
2179
sewardj7ee97522011-05-09 21:45:04 +00002180 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002181 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2182
2183 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2184}
2185
2186
sewardj9d31dfd2011-03-15 12:36:44 +00002187static UChar *
sewardj2019a972011-03-07 16:04:07 +00002188s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2189{
sewardj652b56a2011-04-13 15:38:17 +00002190 vassert(s390_host_has_ldisp || dh2 == 0);
2191
sewardj7ee97522011-05-09 21:45:04 +00002192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002193 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2194
2195 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2196}
2197
2198
sewardj9d31dfd2011-03-15 12:36:44 +00002199static UChar *
sewardj2019a972011-03-07 16:04:07 +00002200s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2201{
sewardj652b56a2011-04-13 15:38:17 +00002202 vassert(s390_host_has_eimm);
2203
sewardj7ee97522011-05-09 21:45:04 +00002204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002205 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2206
2207 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2208}
2209
2210
sewardj9d31dfd2011-03-15 12:36:44 +00002211static UChar *
sewardj2019a972011-03-07 16:04:07 +00002212s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2213{
sewardj7ee97522011-05-09 21:45:04 +00002214 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002215 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2216
2217 return emit_RR(p, 0x1200, r1, r2);
2218}
2219
2220
sewardj9d31dfd2011-03-15 12:36:44 +00002221static UChar *
sewardj2019a972011-03-07 16:04:07 +00002222s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2223{
sewardj7ee97522011-05-09 21:45:04 +00002224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002225 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2226
2227 return emit_RRE(p, 0xb9020000, r1, r2);
2228}
2229
2230
sewardj9d31dfd2011-03-15 12:36:44 +00002231static UChar *
sewardj2019a972011-03-07 16:04:07 +00002232s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2233{
sewardj652b56a2011-04-13 15:38:17 +00002234 vassert(s390_host_has_eimm);
2235
sewardj7ee97522011-05-09 21:45:04 +00002236 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002237 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2238
2239 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2240}
2241
2242
sewardj9d31dfd2011-03-15 12:36:44 +00002243static UChar *
sewardj2019a972011-03-07 16:04:07 +00002244s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2245{
sewardj652b56a2011-04-13 15:38:17 +00002246 vassert(s390_host_has_eimm);
2247
sewardj7ee97522011-05-09 21:45:04 +00002248 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002249 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2250
2251 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2252}
2253
2254
sewardj9d31dfd2011-03-15 12:36:44 +00002255static UChar *
sewardj2019a972011-03-07 16:04:07 +00002256s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2257{
sewardj652b56a2011-04-13 15:38:17 +00002258 vassert(s390_host_has_eimm);
2259
sewardj7ee97522011-05-09 21:45:04 +00002260 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002261 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2262
2263 return emit_RRE(p, 0xb9260000, r1, r2);
2264}
2265
2266
sewardj9d31dfd2011-03-15 12:36:44 +00002267static UChar *
sewardj2019a972011-03-07 16:04:07 +00002268s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2269{
sewardj652b56a2011-04-13 15:38:17 +00002270 vassert(s390_host_has_eimm);
2271
sewardj7ee97522011-05-09 21:45:04 +00002272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002273 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2274
2275 return emit_RRE(p, 0xb9060000, r1, r2);
2276}
2277
2278
sewardj9d31dfd2011-03-15 12:36:44 +00002279static UChar *
sewardj2019a972011-03-07 16:04:07 +00002280s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2281{
sewardj652b56a2011-04-13 15:38:17 +00002282 vassert(s390_host_has_ldisp);
2283
sewardj7ee97522011-05-09 21:45:04 +00002284 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002285 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2286
2287 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2288}
2289
2290
sewardj9d31dfd2011-03-15 12:36:44 +00002291static UChar *
sewardj2019a972011-03-07 16:04:07 +00002292s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2293{
sewardj652b56a2011-04-13 15:38:17 +00002294 vassert(s390_host_has_ldisp);
2295
sewardj7ee97522011-05-09 21:45:04 +00002296 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002297 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2298
2299 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2300}
2301
2302
sewardj9d31dfd2011-03-15 12:36:44 +00002303static UChar *
sewardj2019a972011-03-07 16:04:07 +00002304s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2305{
sewardj7ee97522011-05-09 21:45:04 +00002306 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002307 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2308
2309 return emit_RR(p, 0x1300, r1, r2);
2310}
2311
2312
sewardj9d31dfd2011-03-15 12:36:44 +00002313static UChar *
sewardj2019a972011-03-07 16:04:07 +00002314s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2315{
sewardj7ee97522011-05-09 21:45:04 +00002316 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002317 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2318
2319 return emit_RRE(p, 0xb9030000, r1, r2);
2320}
2321
2322
sewardj9d31dfd2011-03-15 12:36:44 +00002323static UChar *
sewardj2019a972011-03-07 16:04:07 +00002324s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2325{
sewardj652b56a2011-04-13 15:38:17 +00002326 vassert(s390_host_has_eimm);
2327
sewardj7ee97522011-05-09 21:45:04 +00002328 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002329 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2330
2331 return emit_RRE(p, 0xb9270000, r1, r2);
2332}
2333
2334
sewardj9d31dfd2011-03-15 12:36:44 +00002335static UChar *
sewardj2019a972011-03-07 16:04:07 +00002336s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2337{
sewardj652b56a2011-04-13 15:38:17 +00002338 vassert(s390_host_has_eimm);
2339
sewardj7ee97522011-05-09 21:45:04 +00002340 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002341 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2342
2343 return emit_RRE(p, 0xb9070000, r1, r2);
2344}
2345
2346
sewardj9d31dfd2011-03-15 12:36:44 +00002347static UChar *
sewardj2019a972011-03-07 16:04:07 +00002348s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2349{
sewardj7ee97522011-05-09 21:45:04 +00002350 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002351 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2352
2353 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2354}
2355
2356
sewardj9d31dfd2011-03-15 12:36:44 +00002357static UChar *
sewardj2019a972011-03-07 16:04:07 +00002358s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2359{
sewardj652b56a2011-04-13 15:38:17 +00002360 vassert(s390_host_has_ldisp);
2361
sewardj7ee97522011-05-09 21:45:04 +00002362 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002363 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2364
2365 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2366}
2367
2368
sewardj9d31dfd2011-03-15 12:36:44 +00002369static UChar *
sewardj2019a972011-03-07 16:04:07 +00002370s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2371{
sewardj652b56a2011-04-13 15:38:17 +00002372 vassert(s390_host_has_ldisp || dh2 == 0);
2373
sewardj7ee97522011-05-09 21:45:04 +00002374 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002375 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2376
2377 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2378}
2379
2380
sewardj9d31dfd2011-03-15 12:36:44 +00002381static UChar *
sewardj2019a972011-03-07 16:04:07 +00002382s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2383{
sewardj7ee97522011-05-09 21:45:04 +00002384 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002385 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2386
2387 return emit_RI(p, 0xa7080000, r1, i2);
2388}
2389
2390
sewardj9d31dfd2011-03-15 12:36:44 +00002391static UChar *
sewardj2019a972011-03-07 16:04:07 +00002392s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2393{
sewardj7ee97522011-05-09 21:45:04 +00002394 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002395 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2396
2397 return emit_RI(p, 0xa7090000, r1, i2);
2398}
2399
2400
sewardj9d31dfd2011-03-15 12:36:44 +00002401static UChar *
sewardj2019a972011-03-07 16:04:07 +00002402s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2403{
sewardj7ee97522011-05-09 21:45:04 +00002404 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002405 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2406
2407 return emit_RRE(p, 0xb9160000, r1, r2);
2408}
2409
2410
sewardj9d31dfd2011-03-15 12:36:44 +00002411static UChar *
sewardj2019a972011-03-07 16:04:07 +00002412s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2413{
sewardj652b56a2011-04-13 15:38:17 +00002414 vassert(s390_host_has_ldisp || dh2 == 0);
2415
sewardj7ee97522011-05-09 21:45:04 +00002416 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002417 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2418
2419 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2420}
2421
2422
sewardj9d31dfd2011-03-15 12:36:44 +00002423static UChar *
sewardj2019a972011-03-07 16:04:07 +00002424s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2425{
sewardj652b56a2011-04-13 15:38:17 +00002426 vassert(s390_host_has_eimm);
2427
sewardj7ee97522011-05-09 21:45:04 +00002428 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002429 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2430
2431 return emit_RRE(p, 0xb9940000, r1, r2);
2432}
2433
2434
sewardj9d31dfd2011-03-15 12:36:44 +00002435static UChar *
sewardj2019a972011-03-07 16:04:07 +00002436s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2437{
sewardj652b56a2011-04-13 15:38:17 +00002438 vassert(s390_host_has_eimm);
2439
sewardj7ee97522011-05-09 21:45:04 +00002440 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002441 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2442
2443 return emit_RRE(p, 0xb9840000, r1, r2);
2444}
2445
2446
sewardj9d31dfd2011-03-15 12:36:44 +00002447static UChar *
sewardj2019a972011-03-07 16:04:07 +00002448s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2449{
sewardj652b56a2011-04-13 15:38:17 +00002450 vassert(s390_host_has_eimm);
2451
sewardj7ee97522011-05-09 21:45:04 +00002452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002453 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2454
2455 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2456}
2457
2458
sewardj9d31dfd2011-03-15 12:36:44 +00002459static UChar *
sewardj2019a972011-03-07 16:04:07 +00002460s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2461{
sewardj652b56a2011-04-13 15:38:17 +00002462 vassert(s390_host_has_ldisp || dh2 == 0);
2463
sewardj7ee97522011-05-09 21:45:04 +00002464 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002465 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2466
2467 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2468}
2469
2470
sewardj9d31dfd2011-03-15 12:36:44 +00002471static UChar *
sewardj2019a972011-03-07 16:04:07 +00002472s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2473{
sewardj652b56a2011-04-13 15:38:17 +00002474 vassert(s390_host_has_eimm);
2475
sewardj7ee97522011-05-09 21:45:04 +00002476 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002477 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2478
2479 return emit_RRE(p, 0xb9950000, r1, r2);
2480}
2481
2482
sewardj9d31dfd2011-03-15 12:36:44 +00002483static UChar *
sewardj2019a972011-03-07 16:04:07 +00002484s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2485{
sewardj652b56a2011-04-13 15:38:17 +00002486 vassert(s390_host_has_eimm);
2487
sewardj7ee97522011-05-09 21:45:04 +00002488 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002489 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2490
2491 return emit_RRE(p, 0xb9850000, r1, r2);
2492}
2493
2494
sewardj9d31dfd2011-03-15 12:36:44 +00002495static UChar *
sewardj2019a972011-03-07 16:04:07 +00002496s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2497{
sewardj652b56a2011-04-13 15:38:17 +00002498 vassert(s390_host_has_eimm);
2499
sewardj7ee97522011-05-09 21:45:04 +00002500 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002501 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2502
2503 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2504}
2505
2506
sewardj9d31dfd2011-03-15 12:36:44 +00002507static UChar *
sewardj2019a972011-03-07 16:04:07 +00002508s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2509{
sewardj652b56a2011-04-13 15:38:17 +00002510 vassert(s390_host_has_ldisp || dh2 == 0);
2511
sewardj7ee97522011-05-09 21:45:04 +00002512 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002513 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2514
2515 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2516}
2517
2518
sewardj9d31dfd2011-03-15 12:36:44 +00002519static UChar *
sewardj2019a972011-03-07 16:04:07 +00002520s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2521{
sewardj652b56a2011-04-13 15:38:17 +00002522 vassert(s390_host_has_eimm);
2523
sewardj7ee97522011-05-09 21:45:04 +00002524 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002525 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2526
2527 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2528}
2529
2530
sewardj9d31dfd2011-03-15 12:36:44 +00002531static UChar *
sewardj2019a972011-03-07 16:04:07 +00002532s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2533{
sewardj7ee97522011-05-09 21:45:04 +00002534 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002535 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2536
2537 return emit_RI(p, 0xa50e0000, r1, i2);
2538}
2539
2540
sewardj9d31dfd2011-03-15 12:36:44 +00002541static UChar *
sewardj2019a972011-03-07 16:04:07 +00002542s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2543{
sewardj7ee97522011-05-09 21:45:04 +00002544 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002545 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2546
2547 return emit_RI(p, 0xa50f0000, r1, i2);
2548}
2549
2550
sewardj9d31dfd2011-03-15 12:36:44 +00002551static UChar *
sewardj2019a972011-03-07 16:04:07 +00002552s390_emit_MR(UChar *p, UChar r1, UChar r2)
2553{
sewardj7ee97522011-05-09 21:45:04 +00002554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002555 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2556
2557 return emit_RR(p, 0x1c00, r1, r2);
2558}
2559
2560
sewardj9d31dfd2011-03-15 12:36:44 +00002561static UChar *
sewardj2019a972011-03-07 16:04:07 +00002562s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2563{
sewardj7ee97522011-05-09 21:45:04 +00002564 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002565 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2566
2567 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2568}
2569
2570
sewardj9d31dfd2011-03-15 12:36:44 +00002571static UChar *
sewardj2019a972011-03-07 16:04:07 +00002572s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2573{
sewardj652b56a2011-04-13 15:38:17 +00002574 vassert(s390_host_has_gie);
2575
sewardj7ee97522011-05-09 21:45:04 +00002576 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002577 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2578
2579 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2580}
2581
2582
sewardj9d31dfd2011-03-15 12:36:44 +00002583static UChar *
sewardj2019a972011-03-07 16:04:07 +00002584s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2585{
sewardj7ee97522011-05-09 21:45:04 +00002586 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002587 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2588
2589 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2590}
2591
2592
sewardj9d31dfd2011-03-15 12:36:44 +00002593static UChar *
sewardj2019a972011-03-07 16:04:07 +00002594s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2595{
sewardj652b56a2011-04-13 15:38:17 +00002596 vassert(s390_host_has_gie);
2597
sewardj7ee97522011-05-09 21:45:04 +00002598 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002599 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2600
2601 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2602}
2603
2604
sewardj9d31dfd2011-03-15 12:36:44 +00002605static UChar *
sewardj2019a972011-03-07 16:04:07 +00002606s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2607{
sewardj7ee97522011-05-09 21:45:04 +00002608 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002609 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2610
2611 return emit_RI(p, 0xa70c0000, r1, i2);
2612}
2613
2614
sewardj9d31dfd2011-03-15 12:36:44 +00002615static UChar *
sewardj2019a972011-03-07 16:04:07 +00002616s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2617{
sewardj7ee97522011-05-09 21:45:04 +00002618 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002619 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2620
2621 return emit_RRE(p, 0xb9960000, r1, r2);
2622}
2623
2624
sewardj9d31dfd2011-03-15 12:36:44 +00002625static UChar *
sewardj2019a972011-03-07 16:04:07 +00002626s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2627{
sewardj7ee97522011-05-09 21:45:04 +00002628 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002629 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2630
2631 return emit_RRE(p, 0xb9860000, r1, r2);
2632}
2633
2634
sewardj9d31dfd2011-03-15 12:36:44 +00002635static UChar *
sewardj2019a972011-03-07 16:04:07 +00002636s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2637{
sewardj652b56a2011-04-13 15:38:17 +00002638 vassert(s390_host_has_ldisp || dh2 == 0);
2639
sewardj7ee97522011-05-09 21:45:04 +00002640 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002641 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2642
2643 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2644}
2645
2646
sewardj9d31dfd2011-03-15 12:36:44 +00002647static UChar *
sewardj2019a972011-03-07 16:04:07 +00002648s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2649{
sewardj652b56a2011-04-13 15:38:17 +00002650 vassert(s390_host_has_ldisp || dh2 == 0);
2651
sewardj7ee97522011-05-09 21:45:04 +00002652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002653 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2654
2655 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2656}
2657
2658
sewardj9d31dfd2011-03-15 12:36:44 +00002659static UChar *
sewardj2019a972011-03-07 16:04:07 +00002660s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2661{
sewardj7ee97522011-05-09 21:45:04 +00002662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002663 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2664
2665 return emit_RRE(p, 0xb2520000, r1, r2);
2666}
2667
2668
sewardj9d31dfd2011-03-15 12:36:44 +00002669static UChar *
sewardj2019a972011-03-07 16:04:07 +00002670s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2671{
sewardj7ee97522011-05-09 21:45:04 +00002672 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002673 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2674
2675 return emit_RRE(p, 0xb90c0000, r1, r2);
2676}
2677
2678
sewardj9d31dfd2011-03-15 12:36:44 +00002679static UChar *
sewardj2019a972011-03-07 16:04:07 +00002680s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2681{
sewardj7ee97522011-05-09 21:45:04 +00002682 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002683 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2684
2685 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2686}
2687
2688
sewardj9d31dfd2011-03-15 12:36:44 +00002689static UChar *
sewardj2019a972011-03-07 16:04:07 +00002690s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2691{
sewardj652b56a2011-04-13 15:38:17 +00002692 vassert(s390_host_has_ldisp);
2693
sewardj7ee97522011-05-09 21:45:04 +00002694 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002695 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2696
2697 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2698}
2699
2700
sewardj9d31dfd2011-03-15 12:36:44 +00002701static UChar *
sewardj2019a972011-03-07 16:04:07 +00002702s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2703{
sewardj652b56a2011-04-13 15:38:17 +00002704 vassert(s390_host_has_ldisp || dh2 == 0);
2705
sewardj7ee97522011-05-09 21:45:04 +00002706 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002707 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2708
2709 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2710}
2711
2712
sewardj9d31dfd2011-03-15 12:36:44 +00002713static UChar *
sewardj2019a972011-03-07 16:04:07 +00002714s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2715{
sewardj652b56a2011-04-13 15:38:17 +00002716 vassert(s390_host_has_gie);
2717
sewardj7ee97522011-05-09 21:45:04 +00002718 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002719 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2720
2721 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2722}
2723
2724
sewardj9d31dfd2011-03-15 12:36:44 +00002725static UChar *
sewardj2019a972011-03-07 16:04:07 +00002726s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2727{
sewardj652b56a2011-04-13 15:38:17 +00002728 vassert(s390_host_has_gie);
2729
sewardj7ee97522011-05-09 21:45:04 +00002730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002731 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2732
2733 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2734}
2735
2736
sewardj9d31dfd2011-03-15 12:36:44 +00002737static UChar *
sewardj2019a972011-03-07 16:04:07 +00002738s390_emit_OR(UChar *p, UChar r1, UChar r2)
2739{
sewardj7ee97522011-05-09 21:45:04 +00002740 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002741 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2742
2743 return emit_RR(p, 0x1600, r1, r2);
2744}
2745
2746
sewardj9d31dfd2011-03-15 12:36:44 +00002747static UChar *
sewardj2019a972011-03-07 16:04:07 +00002748s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2749{
sewardj7ee97522011-05-09 21:45:04 +00002750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002751 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2752
2753 return emit_RRE(p, 0xb9810000, r1, r2);
2754}
2755
2756
sewardj9d31dfd2011-03-15 12:36:44 +00002757static UChar *
sewardj2019a972011-03-07 16:04:07 +00002758s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2759{
sewardj7ee97522011-05-09 21:45:04 +00002760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002761 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2762
2763 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2764}
2765
2766
sewardj9d31dfd2011-03-15 12:36:44 +00002767static UChar *
sewardj2019a972011-03-07 16:04:07 +00002768s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2769{
sewardj652b56a2011-04-13 15:38:17 +00002770 vassert(s390_host_has_ldisp);
2771
sewardj7ee97522011-05-09 21:45:04 +00002772 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002773 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2774
2775 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2776}
2777
2778
sewardj9d31dfd2011-03-15 12:36:44 +00002779static UChar *
sewardj2019a972011-03-07 16:04:07 +00002780s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2781{
sewardj652b56a2011-04-13 15:38:17 +00002782 vassert(s390_host_has_ldisp || dh2 == 0);
2783
sewardj7ee97522011-05-09 21:45:04 +00002784 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002785 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2786
2787 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2788}
2789
2790
sewardj9d31dfd2011-03-15 12:36:44 +00002791static UChar *
sewardj2019a972011-03-07 16:04:07 +00002792s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2793{
sewardj652b56a2011-04-13 15:38:17 +00002794 vassert(s390_host_has_eimm);
2795
sewardj7ee97522011-05-09 21:45:04 +00002796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002797 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2798
2799 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2800}
2801
2802
sewardj9d31dfd2011-03-15 12:36:44 +00002803static UChar *
sewardj2019a972011-03-07 16:04:07 +00002804s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2805{
sewardj652b56a2011-04-13 15:38:17 +00002806 vassert(s390_host_has_eimm);
2807
sewardj7ee97522011-05-09 21:45:04 +00002808 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002809 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2810
2811 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2812}
2813
2814
sewardj9d31dfd2011-03-15 12:36:44 +00002815static UChar *
sewardj2019a972011-03-07 16:04:07 +00002816s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2817{
sewardj7ee97522011-05-09 21:45:04 +00002818 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002819 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2820
2821 return emit_RI(p, 0xa50b0000, r1, i2);
2822}
2823
2824
sewardj9d31dfd2011-03-15 12:36:44 +00002825static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002826s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002827{
sewardj7ee97522011-05-09 21:45:04 +00002828 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002829 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2830
sewardj3c49aaa2011-04-05 14:00:37 +00002831 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002832}
2833
2834
sewardj9d31dfd2011-03-15 12:36:44 +00002835static UChar *
sewardj2019a972011-03-07 16:04:07 +00002836s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2837{
sewardj652b56a2011-04-13 15:38:17 +00002838 vassert(s390_host_has_ldisp || dh2 == 0);
2839
sewardj7ee97522011-05-09 21:45:04 +00002840 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002841 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2842
2843 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2844}
2845
2846
sewardj9d31dfd2011-03-15 12:36:44 +00002847static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002848s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002849{
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, UDXB), "sra", r1, d2, 0, b2);
2852
sewardj3c49aaa2011-04-05 14:00:37 +00002853 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002854}
2855
2856
sewardj9d31dfd2011-03-15 12:36:44 +00002857static UChar *
sewardj2019a972011-03-07 16:04:07 +00002858s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2859{
sewardj652b56a2011-04-13 15:38:17 +00002860 vassert(s390_host_has_ldisp || dh2 == 0);
2861
sewardj7ee97522011-05-09 21:45:04 +00002862 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002863 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2864
2865 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2866}
2867
2868
sewardj9d31dfd2011-03-15 12:36:44 +00002869static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002870s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002871{
sewardj7ee97522011-05-09 21:45:04 +00002872 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002873 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
2874
sewardj3c49aaa2011-04-05 14:00:37 +00002875 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002876}
2877
2878
sewardj9d31dfd2011-03-15 12:36:44 +00002879static UChar *
sewardj2019a972011-03-07 16:04:07 +00002880s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2881{
sewardj652b56a2011-04-13 15:38:17 +00002882 vassert(s390_host_has_ldisp || dh2 == 0);
2883
sewardj7ee97522011-05-09 21:45:04 +00002884 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002885 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
2886
2887 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
2888}
2889
2890
sewardj9d31dfd2011-03-15 12:36:44 +00002891static UChar *
sewardj2019a972011-03-07 16:04:07 +00002892s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2893{
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), "st", r1, d2, x2, b2);
2896
2897 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
2898}
2899
2900
sewardj9d31dfd2011-03-15 12:36:44 +00002901static UChar *
sewardj2019a972011-03-07 16:04:07 +00002902s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2903{
sewardj652b56a2011-04-13 15:38:17 +00002904 vassert(s390_host_has_ldisp);
2905
sewardj7ee97522011-05-09 21:45:04 +00002906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002907 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
2908
2909 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
2910}
2911
2912
sewardj9d31dfd2011-03-15 12:36:44 +00002913static UChar *
sewardj2019a972011-03-07 16:04:07 +00002914s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2915{
sewardj652b56a2011-04-13 15:38:17 +00002916 vassert(s390_host_has_ldisp || dh2 == 0);
2917
sewardj7ee97522011-05-09 21:45:04 +00002918 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002919 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
2920
2921 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
2922}
2923
2924
sewardj9d31dfd2011-03-15 12:36:44 +00002925static UChar *
sewardj2019a972011-03-07 16:04:07 +00002926s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2927{
sewardj7ee97522011-05-09 21:45:04 +00002928 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002929 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
2930
2931 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
2932}
2933
2934
sewardj9d31dfd2011-03-15 12:36:44 +00002935static UChar *
sewardj2019a972011-03-07 16:04:07 +00002936s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2937{
sewardj652b56a2011-04-13 15:38:17 +00002938 vassert(s390_host_has_ldisp);
2939
sewardj7ee97522011-05-09 21:45:04 +00002940 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002941 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
2942
2943 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
2944}
2945
2946
sewardj9d31dfd2011-03-15 12:36:44 +00002947static UChar *
sewardj2019a972011-03-07 16:04:07 +00002948s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2949{
sewardj7ee97522011-05-09 21:45:04 +00002950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002951 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
2952
2953 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
2954}
2955
2956
sewardj9d31dfd2011-03-15 12:36:44 +00002957static UChar *
sewardj2019a972011-03-07 16:04:07 +00002958s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2959{
sewardj652b56a2011-04-13 15:38:17 +00002960 vassert(s390_host_has_ldisp);
2961
sewardj7ee97522011-05-09 21:45:04 +00002962 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002963 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
2964
2965 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
2966}
2967
2968
sewardj9d31dfd2011-03-15 12:36:44 +00002969static UChar *
sewardj2019a972011-03-07 16:04:07 +00002970s390_emit_SR(UChar *p, UChar r1, UChar r2)
2971{
sewardj7ee97522011-05-09 21:45:04 +00002972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002973 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
2974
2975 return emit_RR(p, 0x1b00, r1, r2);
2976}
2977
2978
sewardj9d31dfd2011-03-15 12:36:44 +00002979static UChar *
sewardj2019a972011-03-07 16:04:07 +00002980s390_emit_SGR(UChar *p, UChar r1, UChar r2)
2981{
sewardj7ee97522011-05-09 21:45:04 +00002982 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002983 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
2984
2985 return emit_RRE(p, 0xb9090000, r1, r2);
2986}
2987
2988
sewardj9d31dfd2011-03-15 12:36:44 +00002989static UChar *
sewardj2019a972011-03-07 16:04:07 +00002990s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2991{
sewardj7ee97522011-05-09 21:45:04 +00002992 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002993 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
2994
2995 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
2996}
2997
2998
sewardj9d31dfd2011-03-15 12:36:44 +00002999static UChar *
sewardj2019a972011-03-07 16:04:07 +00003000s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3001{
sewardj652b56a2011-04-13 15:38:17 +00003002 vassert(s390_host_has_ldisp);
3003
sewardj7ee97522011-05-09 21:45:04 +00003004 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003005 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
3006
3007 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
3008}
3009
3010
sewardj9d31dfd2011-03-15 12:36:44 +00003011static UChar *
sewardj2019a972011-03-07 16:04:07 +00003012s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3013{
sewardj652b56a2011-04-13 15:38:17 +00003014 vassert(s390_host_has_ldisp || dh2 == 0);
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, SDXB), "sg", r1, dh2, dl2, x2, b2);
3018
3019 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
3020}
3021
3022
sewardj9d31dfd2011-03-15 12:36:44 +00003023static UChar *
sewardj2019a972011-03-07 16:04:07 +00003024s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3025{
sewardj7ee97522011-05-09 21:45:04 +00003026 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003027 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
3028
3029 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
3030}
3031
3032
sewardj9d31dfd2011-03-15 12:36:44 +00003033static UChar *
sewardj2019a972011-03-07 16:04:07 +00003034s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3035{
sewardj652b56a2011-04-13 15:38:17 +00003036 vassert(s390_host_has_ldisp);
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, SDXB), "shy", r1, dh2, dl2, x2, b2);
3040
3041 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
3042}
3043
3044
sewardj9d31dfd2011-03-15 12:36:44 +00003045static UChar *
sewardj2019a972011-03-07 16:04:07 +00003046s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
3047{
sewardj652b56a2011-04-13 15:38:17 +00003048 vassert(s390_host_has_eimm);
3049
sewardj7ee97522011-05-09 21:45:04 +00003050 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003051 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
3052
3053 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
3054}
3055
3056
sewardj9d31dfd2011-03-15 12:36:44 +00003057static UChar *
sewardjb13a92a2011-04-13 14:44:29 +00003058s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
3059{
sewardj7ee97522011-05-09 21:45:04 +00003060 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardjb13a92a2011-04-13 14:44:29 +00003061 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
3062
3063 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
3064}
3065
3066
3067static UChar *
sewardj2019a972011-03-07 16:04:07 +00003068s390_emit_LDR(UChar *p, UChar r1, UChar r2)
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, FPR, FPR), "ldr", r1, r2);
3072
3073 return emit_RR(p, 0x2800, r1, r2);
3074}
3075
3076
sewardj9d31dfd2011-03-15 12:36:44 +00003077static UChar *
sewardj2019a972011-03-07 16:04:07 +00003078s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3079{
sewardj7ee97522011-05-09 21:45:04 +00003080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003081 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
3082
3083 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
3084}
3085
3086
sewardj9d31dfd2011-03-15 12:36:44 +00003087static UChar *
sewardj2019a972011-03-07 16:04:07 +00003088s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3089{
sewardj7ee97522011-05-09 21:45:04 +00003090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003091 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
3092
3093 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
3094}
3095
3096
sewardj9d31dfd2011-03-15 12:36:44 +00003097static UChar *
sewardj2019a972011-03-07 16:04:07 +00003098s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3099{
sewardj652b56a2011-04-13 15:38:17 +00003100 vassert(s390_host_has_ldisp);
3101
sewardj7ee97522011-05-09 21:45:04 +00003102 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003103 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
3104
3105 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
3106}
3107
3108
sewardj9d31dfd2011-03-15 12:36:44 +00003109static UChar *
sewardj2019a972011-03-07 16:04:07 +00003110s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3111{
sewardj652b56a2011-04-13 15:38:17 +00003112 vassert(s390_host_has_ldisp);
3113
sewardj7ee97522011-05-09 21:45:04 +00003114 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003115 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
3116
3117 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
3118}
3119
3120
sewardj9d31dfd2011-03-15 12:36:44 +00003121static UChar *
sewardj2019a972011-03-07 16:04:07 +00003122s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
3123{
sewardj7ee97522011-05-09 21:45:04 +00003124 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003125 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
3126
3127 return emit_S(p, 0xb29d0000, b2, d2);
3128}
3129
3130
sewardj9d31dfd2011-03-15 12:36:44 +00003131static UChar *
sewardj2019a972011-03-07 16:04:07 +00003132s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3133{
sewardjd07b8562011-04-27 11:58:22 +00003134 vassert(s390_host_has_fgx);
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, GPR), "ldgr", r1, r2);
3138
3139 return emit_RRE(p, 0xb3c10000, r1, r2);
3140}
3141
3142
sewardj9d31dfd2011-03-15 12:36:44 +00003143static UChar *
sewardj2019a972011-03-07 16:04:07 +00003144s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3145{
sewardjd07b8562011-04-27 11:58:22 +00003146 vassert(s390_host_has_fgx);
3147
sewardj7ee97522011-05-09 21:45:04 +00003148 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003149 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3150
3151 return emit_RRE(p, 0xb3cd0000, r1, r2);
3152}
3153
3154
sewardj9d31dfd2011-03-15 12:36:44 +00003155static UChar *
sewardj2019a972011-03-07 16:04:07 +00003156s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3157{
sewardj7ee97522011-05-09 21:45:04 +00003158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003159 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3160
3161 return emit_RRE(p, 0xb3740000, r1, r2);
3162}
3163
3164
sewardj9d31dfd2011-03-15 12:36:44 +00003165static UChar *
sewardj2019a972011-03-07 16:04:07 +00003166s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3167{
sewardj7ee97522011-05-09 21:45:04 +00003168 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003169 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3170
3171 return emit_RRE(p, 0xb3750000, r1, r2);
3172}
3173
3174
sewardj9d31dfd2011-03-15 12:36:44 +00003175static UChar *
florian6d8e26e2012-09-12 19:52:16 +00003176s390_emit_SFPC(UChar *p, UChar r1)
sewardj2019a972011-03-07 16:04:07 +00003177{
sewardj7ee97522011-05-09 21:45:04 +00003178 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003179 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3180
florian6d8e26e2012-09-12 19:52:16 +00003181 return emit_RRE(p, 0xb3840000, r1, 0);
sewardj2019a972011-03-07 16:04:07 +00003182}
3183
3184
sewardj9d31dfd2011-03-15 12:36:44 +00003185static UChar *
sewardj2019a972011-03-07 16:04:07 +00003186s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3187{
sewardj7ee97522011-05-09 21:45:04 +00003188 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003189 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3190
3191 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3192}
3193
3194
sewardj9d31dfd2011-03-15 12:36:44 +00003195static UChar *
sewardj2019a972011-03-07 16:04:07 +00003196s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3197{
sewardj7ee97522011-05-09 21:45:04 +00003198 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003199 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3200
3201 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3202}
3203
3204
sewardj9d31dfd2011-03-15 12:36:44 +00003205static UChar *
sewardj2019a972011-03-07 16:04:07 +00003206s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3207{
sewardj652b56a2011-04-13 15:38:17 +00003208 vassert(s390_host_has_ldisp);
3209
sewardj7ee97522011-05-09 21:45:04 +00003210 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003211 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3212
3213 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3214}
3215
3216
sewardj9d31dfd2011-03-15 12:36:44 +00003217static UChar *
sewardj2019a972011-03-07 16:04:07 +00003218s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3219{
sewardj652b56a2011-04-13 15:38:17 +00003220 vassert(s390_host_has_ldisp);
3221
sewardj7ee97522011-05-09 21:45:04 +00003222 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003223 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3224
3225 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3226}
3227
3228
sewardj9d31dfd2011-03-15 12:36:44 +00003229static UChar *
sewardj2019a972011-03-07 16:04:07 +00003230s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3231{
sewardj7ee97522011-05-09 21:45:04 +00003232 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003233 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3234
3235 return emit_S(p, 0xb29c0000, b2, d2);
3236}
3237
3238
sewardj9d31dfd2011-03-15 12:36:44 +00003239static UChar *
sewardj2019a972011-03-07 16:04:07 +00003240s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3241{
sewardj7ee97522011-05-09 21:45:04 +00003242 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003243 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3244
3245 return emit_RRE(p, 0xb30a0000, r1, r2);
3246}
3247
3248
sewardj9d31dfd2011-03-15 12:36:44 +00003249static UChar *
sewardj2019a972011-03-07 16:04:07 +00003250s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3251{
sewardj7ee97522011-05-09 21:45:04 +00003252 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003253 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3254
3255 return emit_RRE(p, 0xb31a0000, r1, r2);
3256}
3257
3258
sewardj9d31dfd2011-03-15 12:36:44 +00003259static UChar *
sewardj2019a972011-03-07 16:04:07 +00003260s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3261{
sewardj7ee97522011-05-09 21:45:04 +00003262 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003263 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3264
3265 return emit_RRE(p, 0xb34a0000, r1, r2);
3266}
3267
3268
sewardj9d31dfd2011-03-15 12:36:44 +00003269static UChar *
sewardj2019a972011-03-07 16:04:07 +00003270s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3271{
sewardj7ee97522011-05-09 21:45:04 +00003272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003273 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3274
3275 return emit_RRE(p, 0xb3090000, r1, r2);
3276}
3277
3278
sewardj9d31dfd2011-03-15 12:36:44 +00003279static UChar *
sewardj2019a972011-03-07 16:04:07 +00003280s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3281{
sewardj7ee97522011-05-09 21:45:04 +00003282 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003283 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3284
3285 return emit_RRE(p, 0xb3190000, r1, r2);
3286}
3287
3288
sewardj9d31dfd2011-03-15 12:36:44 +00003289static UChar *
sewardj2019a972011-03-07 16:04:07 +00003290s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3291{
sewardj7ee97522011-05-09 21:45:04 +00003292 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003293 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3294
3295 return emit_RRE(p, 0xb3490000, r1, r2);
3296}
3297
3298
sewardj9d31dfd2011-03-15 12:36:44 +00003299static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003300s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003301{
florian8c3ccaf2012-09-09 18:18:25 +00003302 vassert(m4 == 0);
3303 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003304
florian8c3ccaf2012-09-09 18:18:25 +00003305 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3306 if (m3 == 0)
3307 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3308 else
3309 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3310 "cefbra", r1, m3, r2, m4);
3311 }
3312
3313 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003314}
3315
3316
sewardj9d31dfd2011-03-15 12:36:44 +00003317static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003318s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003319{
florian8c3ccaf2012-09-09 18:18:25 +00003320 vassert(m4 == 0);
3321 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003322
florian8c3ccaf2012-09-09 18:18:25 +00003323 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3324 if (m3 == 0)
3325 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3326 else
3327 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3328 "cdfbra", r1, m3, r2, m4);
3329 }
3330
3331 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003332}
3333
3334
sewardj9d31dfd2011-03-15 12:36:44 +00003335static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003336s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003337{
florian8c3ccaf2012-09-09 18:18:25 +00003338 vassert(m4 == 0);
3339 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003340
florian8c3ccaf2012-09-09 18:18:25 +00003341 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3342 if (m3 == 0)
3343 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3344 else
3345 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3346 "cxfbra", r1, m3, r2, m4);
3347 }
3348
3349 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003350}
3351
3352
sewardj9d31dfd2011-03-15 12:36:44 +00003353static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003354s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003355{
florian8c3ccaf2012-09-09 18:18:25 +00003356 vassert(m4 == 0);
3357 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003358
florian8c3ccaf2012-09-09 18:18:25 +00003359 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3360 if (m3 == 0)
3361 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3362 else
3363 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3364 "cegbra", r1, m3, r2, m4);
3365 }
3366
3367 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003368}
3369
3370
sewardj9d31dfd2011-03-15 12:36:44 +00003371static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003372s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003373{
florian8c3ccaf2012-09-09 18:18:25 +00003374 vassert(m4 == 0);
3375 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003376
florian8c3ccaf2012-09-09 18:18:25 +00003377 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3378 if (m3 == 0)
3379 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3380 else
3381 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3382 "cdgbra", r1, m3, r2, m4);
3383 }
3384
3385 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003386}
3387
3388
sewardj9d31dfd2011-03-15 12:36:44 +00003389static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003390s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003391{
florian8c3ccaf2012-09-09 18:18:25 +00003392 vassert(m4 == 0);
3393 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003394
florian8c3ccaf2012-09-09 18:18:25 +00003395 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3396 if (m3 == 0)
3397 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3398 else
3399 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3400 "cxgbra", r1, m3, r2, m4);
3401 }
3402
3403 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003404}
3405
3406
sewardj9d31dfd2011-03-15 12:36:44 +00003407static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00003408s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3409{
florian606dbeb2012-09-09 18:12:28 +00003410 vassert(m4 == 0);
3411 vassert(s390_host_has_fpext);
3412
florian1c8f7ff2012-09-01 00:12:11 +00003413 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3414 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
3415
3416 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
3417}
3418
3419
3420static UChar *
3421s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3422{
florian606dbeb2012-09-09 18:12:28 +00003423 vassert(m4 == 0);
3424 vassert(s390_host_has_fpext);
3425
florian1c8f7ff2012-09-01 00:12:11 +00003426 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3427 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
3428
3429 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
3430}
3431
3432
3433static UChar *
3434s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3435{
florian606dbeb2012-09-09 18:12:28 +00003436 vassert(m4 == 0);
3437 vassert(s390_host_has_fpext);
3438
florian1c8f7ff2012-09-01 00:12:11 +00003439 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3440 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
3441
3442 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
3443}
3444
3445
3446static UChar *
3447s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3448{
florian606dbeb2012-09-09 18:12:28 +00003449 vassert(m4 == 0);
3450 vassert(s390_host_has_fpext);
3451
florian1c8f7ff2012-09-01 00:12:11 +00003452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3453 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
3454
3455 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
3456}
3457
3458
3459static UChar *
3460s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3461{
florian606dbeb2012-09-09 18:12:28 +00003462 vassert(m4 == 0);
3463 vassert(s390_host_has_fpext);
3464
florian1c8f7ff2012-09-01 00:12:11 +00003465 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3466 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
3467
3468 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
3469}
3470
3471
3472static UChar *
3473s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3474{
florian606dbeb2012-09-09 18:12:28 +00003475 vassert(m4 == 0);
3476 vassert(s390_host_has_fpext);
3477
florian1c8f7ff2012-09-01 00:12:11 +00003478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3479 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
3480
3481 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
3482}
3483
3484
3485static UChar *
3486s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3487{
florian606dbeb2012-09-09 18:12:28 +00003488 vassert(m4 == 0);
3489 vassert(s390_host_has_fpext);
3490
florian1c8f7ff2012-09-01 00:12:11 +00003491 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3492 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
3493
3494 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
3495}
3496
3497
3498static UChar *
3499s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3500{
florian606dbeb2012-09-09 18:12:28 +00003501 vassert(m4 == 0);
3502 vassert(s390_host_has_fpext);
3503
florian1c8f7ff2012-09-01 00:12:11 +00003504 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3505 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
3506
3507 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
3508}
3509
3510
3511static UChar *
3512s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3513{
florian606dbeb2012-09-09 18:12:28 +00003514 vassert(m4 == 0);
3515 vassert(s390_host_has_fpext);
3516
florian1c8f7ff2012-09-01 00:12:11 +00003517 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3518 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
3519
3520 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
3521}
3522
3523
3524static UChar *
3525s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3526{
florian606dbeb2012-09-09 18:12:28 +00003527 vassert(m4 == 0);
3528 vassert(s390_host_has_fpext);
3529
florian1c8f7ff2012-09-01 00:12:11 +00003530 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3531 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
3532
3533 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
3534}
3535
3536
3537static UChar *
3538s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3539{
florian606dbeb2012-09-09 18:12:28 +00003540 vassert(m4 == 0);
3541 vassert(s390_host_has_fpext);
3542
florian1c8f7ff2012-09-01 00:12:11 +00003543 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3544 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
3545
3546 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
3547}
3548
3549
3550static UChar *
3551s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3552{
florian606dbeb2012-09-09 18:12:28 +00003553 vassert(m4 == 0);
3554 vassert(s390_host_has_fpext);
3555
florian1c8f7ff2012-09-01 00:12:11 +00003556 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3557 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
3558
3559 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
3560}
3561
3562
3563static UChar *
sewardj2019a972011-03-07 16:04:07 +00003564s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3565{
sewardj7ee97522011-05-09 21:45:04 +00003566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003567 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3568
3569 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3570}
3571
3572
sewardj9d31dfd2011-03-15 12:36:44 +00003573static UChar *
sewardj2019a972011-03-07 16:04:07 +00003574s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3575{
sewardj7ee97522011-05-09 21:45:04 +00003576 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003577 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3578
3579 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3580}
3581
3582
sewardj9d31dfd2011-03-15 12:36:44 +00003583static UChar *
sewardj2019a972011-03-07 16:04:07 +00003584s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3585{
sewardj7ee97522011-05-09 21:45:04 +00003586 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003587 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3588
3589 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3590}
3591
3592
sewardj9d31dfd2011-03-15 12:36:44 +00003593static UChar *
sewardj2019a972011-03-07 16:04:07 +00003594s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3595{
sewardj7ee97522011-05-09 21:45:04 +00003596 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003597 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3598
3599 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3600}
3601
3602
sewardj9d31dfd2011-03-15 12:36:44 +00003603static UChar *
sewardj2019a972011-03-07 16:04:07 +00003604s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3605{
sewardj7ee97522011-05-09 21:45:04 +00003606 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003607 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3608
3609 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3610}
3611
3612
sewardj9d31dfd2011-03-15 12:36:44 +00003613static UChar *
sewardj2019a972011-03-07 16:04:07 +00003614s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3615{
sewardj7ee97522011-05-09 21:45:04 +00003616 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003617 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3618
3619 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3620}
3621
3622
sewardj9d31dfd2011-03-15 12:36:44 +00003623static UChar *
sewardj2019a972011-03-07 16:04:07 +00003624s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3625{
sewardj7ee97522011-05-09 21:45:04 +00003626 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003627 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3628
3629 return emit_RRE(p, 0xb30d0000, r1, r2);
3630}
3631
3632
sewardj9d31dfd2011-03-15 12:36:44 +00003633static UChar *
sewardj2019a972011-03-07 16:04:07 +00003634s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3635{
sewardj7ee97522011-05-09 21:45:04 +00003636 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003637 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3638
3639 return emit_RRE(p, 0xb31d0000, r1, r2);
3640}
3641
3642
sewardj9d31dfd2011-03-15 12:36:44 +00003643static UChar *
sewardj2019a972011-03-07 16:04:07 +00003644s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3645{
sewardj7ee97522011-05-09 21:45:04 +00003646 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003647 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3648
3649 return emit_RRE(p, 0xb34d0000, r1, r2);
3650}
3651
3652
sewardj9d31dfd2011-03-15 12:36:44 +00003653static UChar *
sewardj2019a972011-03-07 16:04:07 +00003654s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3655{
sewardj7ee97522011-05-09 21:45:04 +00003656 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003657 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3658
3659 return emit_RRE(p, 0xb3030000, r1, r2);
3660}
3661
3662
sewardj9d31dfd2011-03-15 12:36:44 +00003663static UChar *
sewardj2019a972011-03-07 16:04:07 +00003664s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3665{
sewardj7ee97522011-05-09 21:45:04 +00003666 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003667 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3668
3669 return emit_RRE(p, 0xb3130000, r1, r2);
3670}
3671
3672
sewardj9d31dfd2011-03-15 12:36:44 +00003673static UChar *
sewardj2019a972011-03-07 16:04:07 +00003674s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3675{
sewardj7ee97522011-05-09 21:45:04 +00003676 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003677 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3678
3679 return emit_RRE(p, 0xb3430000, r1, r2);
3680}
3681
3682
sewardj9d31dfd2011-03-15 12:36:44 +00003683static UChar *
sewardj2019a972011-03-07 16:04:07 +00003684s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3685{
sewardj7ee97522011-05-09 21:45:04 +00003686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003687 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3688
3689 return emit_RRE(p, 0xb3040000, r1, r2);
3690}
3691
3692
sewardj9d31dfd2011-03-15 12:36:44 +00003693static UChar *
sewardj2019a972011-03-07 16:04:07 +00003694s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3695{
sewardj7ee97522011-05-09 21:45:04 +00003696 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003697 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3698
3699 return emit_RRE(p, 0xb3050000, r1, r2);
3700}
3701
3702
sewardj9d31dfd2011-03-15 12:36:44 +00003703static UChar *
sewardj2019a972011-03-07 16:04:07 +00003704s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3705{
sewardj7ee97522011-05-09 21:45:04 +00003706 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003707 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3708
3709 return emit_RRE(p, 0xb3060000, r1, r2);
3710}
3711
3712
sewardj9d31dfd2011-03-15 12:36:44 +00003713static UChar *
sewardj2019a972011-03-07 16:04:07 +00003714s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3715{
sewardj7ee97522011-05-09 21:45:04 +00003716 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003717 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3718
3719 return emit_RRE(p, 0xb3010000, r1, r2);
3720}
3721
3722
sewardj9d31dfd2011-03-15 12:36:44 +00003723static UChar *
sewardj2019a972011-03-07 16:04:07 +00003724s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3725{
sewardj7ee97522011-05-09 21:45:04 +00003726 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003727 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3728
3729 return emit_RRE(p, 0xb3110000, r1, r2);
3730}
3731
3732
sewardj9d31dfd2011-03-15 12:36:44 +00003733static UChar *
sewardj2019a972011-03-07 16:04:07 +00003734s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3735{
sewardj7ee97522011-05-09 21:45:04 +00003736 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003737 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3738
3739 return emit_RRE(p, 0xb3410000, r1, r2);
3740}
3741
3742
sewardj9d31dfd2011-03-15 12:36:44 +00003743static UChar *
sewardj2019a972011-03-07 16:04:07 +00003744s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3745{
sewardj7ee97522011-05-09 21:45:04 +00003746 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003747 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3748
3749 return emit_RRE(p, 0xb3000000, r1, r2);
3750}
3751
3752
sewardj9d31dfd2011-03-15 12:36:44 +00003753static UChar *
sewardj2019a972011-03-07 16:04:07 +00003754s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3755{
sewardj7ee97522011-05-09 21:45:04 +00003756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003757 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3758
3759 return emit_RRE(p, 0xb3100000, r1, r2);
3760}
3761
3762
sewardj9d31dfd2011-03-15 12:36:44 +00003763static UChar *
sewardj2019a972011-03-07 16:04:07 +00003764s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3765{
sewardj7ee97522011-05-09 21:45:04 +00003766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003767 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3768
3769 return emit_RRE(p, 0xb3400000, r1, r2);
3770}
3771
3772
sewardj9d31dfd2011-03-15 12:36:44 +00003773static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003774s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003775{
florian8c3ccaf2012-09-09 18:18:25 +00003776 vassert(m4 == 0);
3777 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003778
florian8c3ccaf2012-09-09 18:18:25 +00003779 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3780 if (m3 == 0)
3781 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3782 else
3783 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3784 "ledbra", r1, m3, r2, m4);
3785 }
3786
3787 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003788}
3789
3790
sewardj9d31dfd2011-03-15 12:36:44 +00003791static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003792s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003793{
florian8c3ccaf2012-09-09 18:18:25 +00003794 vassert(m4 == 0);
3795 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003796
florian8c3ccaf2012-09-09 18:18:25 +00003797 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3798 if (m3 == 0)
3799 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3800 else
3801 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3802 "ldxbra", r1, m3, r2, m4);
3803 }
3804
3805 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003806}
3807
3808
sewardj9d31dfd2011-03-15 12:36:44 +00003809static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003810s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003811{
florian8c3ccaf2012-09-09 18:18:25 +00003812 vassert(m4 == 0);
3813 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003814
florian8c3ccaf2012-09-09 18:18:25 +00003815 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3816 if (m3 == 0)
3817 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3818 else
3819 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3820 "lexbra", r1, m3, r2, m4);
3821 }
3822
3823 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003824}
3825
3826
sewardj9d31dfd2011-03-15 12:36:44 +00003827static UChar *
sewardj2019a972011-03-07 16:04:07 +00003828s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3829{
sewardj7ee97522011-05-09 21:45:04 +00003830 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003831 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3832
3833 return emit_RRE(p, 0xb3170000, r1, r2);
3834}
3835
3836
sewardj9d31dfd2011-03-15 12:36:44 +00003837static UChar *
sewardj2019a972011-03-07 16:04:07 +00003838s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3839{
sewardj7ee97522011-05-09 21:45:04 +00003840 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003841 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3842
3843 return emit_RRE(p, 0xb31c0000, r1, r2);
3844}
3845
3846
sewardj9d31dfd2011-03-15 12:36:44 +00003847static UChar *
sewardj2019a972011-03-07 16:04:07 +00003848s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3849{
sewardj7ee97522011-05-09 21:45:04 +00003850 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003851 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3852
3853 return emit_RRE(p, 0xb34c0000, r1, r2);
3854}
3855
3856
sewardj9d31dfd2011-03-15 12:36:44 +00003857static UChar *
sewardj2019a972011-03-07 16:04:07 +00003858s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3859{
sewardj7ee97522011-05-09 21:45:04 +00003860 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003861 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3862
3863 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3864}
3865
3866
sewardj9d31dfd2011-03-15 12:36:44 +00003867static UChar *
sewardj2019a972011-03-07 16:04:07 +00003868s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3869{
sewardj7ee97522011-05-09 21:45:04 +00003870 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003871 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3872
3873 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3874}
3875
3876
sewardj9d31dfd2011-03-15 12:36:44 +00003877static UChar *
sewardj2019a972011-03-07 16:04:07 +00003878s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3879{
sewardj7ee97522011-05-09 21:45:04 +00003880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003881 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3882
3883 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3884}
3885
3886
sewardj9d31dfd2011-03-15 12:36:44 +00003887static UChar *
sewardj2019a972011-03-07 16:04:07 +00003888s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3889{
sewardj7ee97522011-05-09 21:45:04 +00003890 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003891 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3892
3893 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
3894}
3895
3896
sewardj9d31dfd2011-03-15 12:36:44 +00003897static UChar *
sewardj2019a972011-03-07 16:04:07 +00003898s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
3899{
sewardj7ee97522011-05-09 21:45:04 +00003900 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003901 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
3902
3903 return emit_RRE(p, 0xb3140000, r1, r2);
3904}
3905
3906
sewardj9d31dfd2011-03-15 12:36:44 +00003907static UChar *
sewardj2019a972011-03-07 16:04:07 +00003908s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
3909{
sewardj7ee97522011-05-09 21:45:04 +00003910 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003911 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
3912
3913 return emit_RRE(p, 0xb3150000, r1, r2);
3914}
3915
3916
sewardj9d31dfd2011-03-15 12:36:44 +00003917static UChar *
sewardj2019a972011-03-07 16:04:07 +00003918s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
3919{
sewardj7ee97522011-05-09 21:45:04 +00003920 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003921 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
3922
3923 return emit_RRE(p, 0xb3160000, r1, r2);
3924}
3925
3926
sewardj9d31dfd2011-03-15 12:36:44 +00003927static UChar *
sewardj2019a972011-03-07 16:04:07 +00003928s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
3929{
sewardj7ee97522011-05-09 21:45:04 +00003930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003931 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
3932
3933 return emit_RRE(p, 0xb30b0000, r1, r2);
3934}
3935
3936
sewardj9d31dfd2011-03-15 12:36:44 +00003937static UChar *
sewardj2019a972011-03-07 16:04:07 +00003938s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
3939{
sewardj7ee97522011-05-09 21:45:04 +00003940 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003941 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
3942
3943 return emit_RRE(p, 0xb31b0000, r1, r2);
3944}
3945
3946
sewardj9d31dfd2011-03-15 12:36:44 +00003947static UChar *
sewardj2019a972011-03-07 16:04:07 +00003948s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
3949{
sewardj7ee97522011-05-09 21:45:04 +00003950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003951 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
3952
3953 return emit_RRE(p, 0xb34b0000, r1, r2);
3954}
3955
sewardj2019a972011-03-07 16:04:07 +00003956
florian12390202012-11-10 22:34:14 +00003957static UChar *
3958s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
3959{
3960 vassert(s390_host_has_dfp);
3961 vassert(m4 == 0 || s390_host_has_fpext);
3962 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3963 if (m4 == 0)
3964 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
3965 else
florianb3764a92012-12-20 14:44:42 +00003966 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00003967 }
3968
3969 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
3970}
3971
3972
3973static UChar *
floriane38f6412012-12-21 17:32:12 +00003974s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
3975{
3976 vassert(s390_host_has_dfp);
3977 vassert(m4 == 0 || s390_host_has_fpext);
3978 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3979 if (m4 == 0)
3980 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
3981 else
3982 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
3983 }
3984
3985 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
3986}
3987
3988
3989static UChar *
3990s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
3991{
3992 vassert(s390_host_has_dfp);
3993 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3994 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
3995
3996 return emit_RRE(p, 0xb3e40000, r1, r2);
3997}
3998
3999
4000static UChar *
4001s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
4002{
4003 vassert(s390_host_has_dfp);
4004 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4005 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
4006
4007 return emit_RRE(p, 0xb3ec0000, r1, r2);
4008}
4009
4010
4011static UChar *
florian20c6bca2012-12-26 17:47:19 +00004012s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
4013{
4014 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4015 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
4016
4017 return emit_RRE(p, 0xb3f40000, r1, r2);
4018}
4019
4020
4021static UChar *
4022s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
4023{
4024 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4025 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
4026
4027 return emit_RRE(p, 0xb3fc0000, r1, r2);
4028}
4029
4030
4031static UChar *
florian12390202012-11-10 22:34:14 +00004032s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4033{
4034 vassert(s390_host_has_dfp);
4035 vassert(m4 == 0 || s390_host_has_fpext);
4036 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4037 if (m4 == 0)
4038 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
4039 else
florianb3764a92012-12-20 14:44:42 +00004040 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004041 }
4042
4043 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
4044}
4045
4046
4047static UChar *
floriane38f6412012-12-21 17:32:12 +00004048s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4049{
4050 vassert(s390_host_has_dfp);
4051 vassert(m4 == 0 || s390_host_has_fpext);
4052 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4053 if (m4 == 0)
4054 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
4055 else
4056 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
4057 }
4058
4059 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
4060}
4061
4062
4063static UChar *
4064s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
4065{
4066 vassert(s390_host_has_dfp);
4067 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4068 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
4069
4070 return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
4071}
4072
4073
4074static UChar *
4075s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
4076{
4077 vassert(s390_host_has_dfp);
4078 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4079 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
4080
4081 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
4082}
4083
4084
4085static UChar *
4086s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4087{
4088 vassert(s390_host_has_dfp);
4089 vassert(m4 == 0);
4090 vassert(m3 == 0 || s390_host_has_fpext);
4091
4092 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4093 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4094 "ledtr", r1, m3, r2, m4);
4095 }
4096
4097 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
4098}
4099
4100
4101static UChar *
4102s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4103{
4104 vassert(s390_host_has_dfp);
4105 vassert(m4 == 0);
4106 vassert(m3 == 0 || s390_host_has_fpext);
4107
4108 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4109 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4110 "ldxtr", r1, m3, r2, m4);
4111 }
4112
4113 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
4114}
4115
4116
4117static UChar *
florian12390202012-11-10 22:34:14 +00004118s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4119{
4120 vassert(s390_host_has_dfp);
4121 vassert(m4 == 0 || s390_host_has_fpext);
4122 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4123 if (m4 == 0)
4124 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
4125 else
florianb3764a92012-12-20 14:44:42 +00004126 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004127 }
4128
4129 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
4130}
4131
4132
4133static UChar *
floriane38f6412012-12-21 17:32:12 +00004134s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4135{
4136 vassert(s390_host_has_dfp);
4137 vassert(m4 == 0 || s390_host_has_fpext);
4138 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4139 if (m4 == 0)
4140 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
4141 else
4142 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
4143 }
4144
4145 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
4146}
4147
4148
4149static UChar *
florian12390202012-11-10 22:34:14 +00004150s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4151{
4152 vassert(s390_host_has_dfp);
4153 vassert(m4 == 0 || s390_host_has_fpext);
4154 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4155 if (m4 == 0)
4156 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
4157 else
florianb3764a92012-12-20 14:44:42 +00004158 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004159 }
4160
4161 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
4162}
4163
florian3a3d7f12012-12-03 13:32:05 +00004164
4165static UChar *
floriane38f6412012-12-21 17:32:12 +00004166s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4167{
4168 vassert(s390_host_has_dfp);
4169 vassert(m4 == 0 || s390_host_has_fpext);
4170 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4171 if (m4 == 0)
4172 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
4173 else
4174 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
4175 }
4176
4177 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
4178}
4179
4180
4181static UChar *
florian3a3d7f12012-12-03 13:32:05 +00004182s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
4183{
florianaec8e052012-12-09 17:26:32 +00004184 vassert(s390_host_has_lsc);
florian3a3d7f12012-12-03 13:32:05 +00004185 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4186 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
4187 }
4188
4189 return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
4190}
4191
4192
4193static UChar *
4194s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4195{
4196 vassert(s390_host_has_ldisp || dh2 == 0);
4197
4198 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4199 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
4200
4201 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
4202}
4203
4204
4205static UChar *
4206s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4207{
4208 vassert(s390_host_has_ldisp || dh2 == 0);
4209
4210 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4211 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
4212
4213 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
4214}
4215
4216
sewardj2019a972011-03-07 16:04:07 +00004217/* Provide a symbolic name for register "R0" */
4218#define R0 0
4219
4220/* Split up a 20-bit displacement into its high and low piece
4221 suitable for passing as function arguments */
sewardjcd2b0252011-05-09 20:35:41 +00004222#define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
sewardj2019a972011-03-07 16:04:07 +00004223
4224/*---------------------------------------------------------------*/
4225/*--- Helper functions ---*/
4226/*---------------------------------------------------------------*/
4227
4228static __inline__ Bool
4229uint_fits_signed_16bit(UInt val)
4230{
florianffbd84d2012-12-09 02:06:29 +00004231 Int v = val & 0xFFFFu;
sewardj2019a972011-03-07 16:04:07 +00004232
4233 /* sign extend */
4234 v = (v << 16) >> 16;
4235
4236 return val == (UInt)v;
4237}
4238
4239
4240static __inline__ Bool
4241ulong_fits_signed_16bit(ULong val)
4242{
4243 Long v = val & 0xFFFFu;
4244
4245 /* sign extend */
4246 v = (v << 48) >> 48;
4247
4248 return val == (ULong)v;
4249}
4250
4251
4252static __inline__ Bool
4253ulong_fits_signed_32bit(ULong val)
4254{
4255 Long v = val & 0xFFFFFFFFu;
4256
4257 /* sign extend */
4258 v = (v << 32) >> 32;
4259
4260 return val == (ULong)v;
4261}
4262
4263
4264static __inline__ Bool
4265ulong_fits_unsigned_32bit(ULong val)
4266{
4267 return (val & 0xFFFFFFFFu) == val;
4268}
4269
4270
4271/* Load a 64-bit immediate VAL into register REG. */
4272static UChar *
4273s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
4274{
4275 if (ulong_fits_signed_16bit(val)) {
4276 return s390_emit_LGHI(p, reg, val);
4277 }
4278
4279 if (s390_host_has_eimm) {
4280 if (ulong_fits_unsigned_32bit(val)) {
4281 return s390_emit_LLILF(p, reg, val);
4282 }
4283 if (ulong_fits_signed_32bit(val)) {
4284 /* LGFI's sign extension will recreate the correct 64-bit value */
4285 return s390_emit_LGFI(p, reg, val);
4286 }
4287 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
4288 p = s390_emit_IIHF(p, reg, val >> 32);
4289 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
4290 }
4291
4292 /* Fall back */
4293 if (ulong_fits_unsigned_32bit(val)) {
4294 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
4295 val[0:31] = 0 */
4296 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
4297 return p;
4298 }
4299
4300 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
4301 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
4302 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4303 p = s390_emit_IILL(p, reg, val & 0xFFFF);
4304
4305 return p;
4306}
4307
4308/* Load a 32-bit immediate VAL into register REG. */
4309static UChar *
4310s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
4311{
4312 if (uint_fits_signed_16bit(val)) {
4313 /* LHI's sign extension will recreate the correct 32-bit value */
4314 return s390_emit_LHI(p, reg, val);
4315 }
4316 if (s390_host_has_eimm) {
4317 return s390_emit_IILF(p, reg, val);
4318 }
4319 /* val[0:15] --> (val >> 16) & 0xFFFF
4320 val[16:31] --> val & 0xFFFF */
4321 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4322 return s390_emit_IILL(p, reg, val & 0xFFFF);
4323}
4324
4325/*------------------------------------------------------------*/
4326/*--- Wrapper functions ---*/
4327/*------------------------------------------------------------*/
4328
sewardjeae8db52011-03-24 09:01:50 +00004329/* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
sewardj2019a972011-03-07 16:04:07 +00004330static UChar *
4331s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4332{
4333 if (s390_host_has_gie) {
4334 return s390_emit_MFY(p, r1, x, b, dl, dh);
4335 }
4336
4337 /* Load from memory into R0, then MULTIPLY with R1 */
4338 p = s390_emit_LY(p, R0, x, b, dl, dh);
4339 return s390_emit_MR(p, r1, R0);
4340}
4341
sewardjeae8db52011-03-24 09:01:50 +00004342/* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
4343static UChar *
4344s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4345{
4346 if (s390_host_has_gie) {
4347 return s390_emit_MHY(p, r1, x, b, dl, dh);
4348 }
4349
4350 /* Load from memory into R0, then MULTIPLY with R1 */
4351 p = s390_emit_LHY(p, R0, x, b, dl, dh);
4352 return s390_emit_MSR(p, r1, R0);
4353}
4354
sewardj2019a972011-03-07 16:04:07 +00004355/* r1[32:63] = r1[32:63] * i2 */
4356static UChar *
4357s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
4358{
4359 if (s390_host_has_gie) {
4360 return s390_emit_MSFI(p, r1, i2);
4361 }
4362
4363 /* Load I2 into R0; then MULTIPLY R0 with R1 */
4364 p = s390_emit_load_32imm(p, R0, i2);
4365 return s390_emit_MSR(p, r1, R0);
4366}
4367
4368
4369/* r1[32:63] = r1[32:63] & i2 */
4370static UChar *
4371s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
4372{
4373 if (s390_host_has_eimm) {
4374 return s390_emit_NILF(p, r1, i2);
4375 }
4376
4377 /* Load I2 into R0; then AND R0 with R1 */
4378 p = s390_emit_load_32imm(p, R0, i2);
4379 return s390_emit_NR(p, r1, R0);
4380}
4381
4382
4383/* r1[32:63] = r1[32:63] | i2 */
4384static UChar *
4385s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
4386{
4387 if (s390_host_has_eimm) {
4388 return s390_emit_OILF(p, r1, i2);
4389 }
4390
4391 /* Load I2 into R0; then AND R0 with R1 */
4392 p = s390_emit_load_32imm(p, R0, i2);
4393 return s390_emit_OR(p, r1, R0);
4394}
4395
4396
4397/* r1[32:63] = r1[32:63] ^ i2 */
4398static UChar *
4399s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
4400{
4401 if (s390_host_has_eimm) {
4402 return s390_emit_XILF(p, r1, i2);
4403 }
4404
4405 /* Load I2 into R0; then AND R0 with R1 */
4406 p = s390_emit_load_32imm(p, R0, i2);
4407 return s390_emit_XR(p, r1, R0);
4408}
4409
4410
sewardj652b56a2011-04-13 15:38:17 +00004411/* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
4412static UChar *
4413s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
4414{
4415 vassert(s390_host_has_ldisp || dh2 == 0);
4416
4417 if (s390_host_has_ldisp) {
4418 return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
4419 }
4420
4421 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
4422 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4423 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
4424}
4425
4426
sewardj2019a972011-03-07 16:04:07 +00004427/* r1[32:63] = sign_extend(r2[56:63]) */
4428static UChar *
4429s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
4430{
4431 if (s390_host_has_eimm) {
4432 return s390_emit_LBR(p, r1, r2);
4433 }
4434
4435 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004436 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4437 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
sewardj2019a972011-03-07 16:04:07 +00004438}
4439
4440
sewardj652b56a2011-04-13 15:38:17 +00004441/* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
4442static UChar *
4443s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
4444{
4445 vassert(s390_host_has_ldisp || dh2 == 0);
4446
4447 if (s390_host_has_ldisp) {
4448 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
4449 }
4450
4451 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
4452 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4453 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4454}
4455
4456
sewardj2019a972011-03-07 16:04:07 +00004457/* r1[0:63] = sign_extend(r2[56:63]) */
4458static UChar *
4459s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
4460{
4461 if (s390_host_has_eimm) {
4462 return s390_emit_LGBR(p, r1, r2);
4463 }
4464
4465 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4466 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4467 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4468}
4469
4470
4471/* r1[32:63] = sign_extend(r2[48:63]) */
4472static UChar *
4473s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
4474{
4475 if (s390_host_has_eimm) {
4476 return s390_emit_LHR(p, r1, r2);
4477 }
4478
4479 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004480 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
4481 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
sewardj2019a972011-03-07 16:04:07 +00004482}
4483
4484
4485/* r1[0:63] = sign_extend(r2[48:63]) */
4486static UChar *
4487s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
4488{
4489 if (s390_host_has_eimm) {
4490 return s390_emit_LGHR(p, r1, r2);
4491 }
4492
4493 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4494 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
4495 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
4496}
4497
4498
4499/* r1[0:63] = sign_extend(i2) */
4500static UChar *
4501s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
4502{
4503 if (s390_host_has_eimm) {
4504 return s390_emit_LGFI(p, r1, i2);
4505 }
4506
4507 p = s390_emit_load_32imm(p, R0, i2);
4508 return s390_emit_LGFR(p, r1, R0);
4509}
4510
4511
4512/* r1[32:63] = zero_extend($r2[56:63]) */
4513static UChar *
4514s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
4515{
4516 if (s390_host_has_eimm) {
4517 return s390_emit_LLCR(p, r1, r2);
4518 }
4519
4520 p = s390_emit_LR(p, r1, r2);
4521 p = s390_emit_LHI(p, R0, 0xFF);
4522 return s390_emit_NR(p, r1, R0);
4523}
4524
4525
4526/* r1[0:63] = zero_extend($r2[56:63]) */
4527static UChar *
4528s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
4529{
4530 if (s390_host_has_eimm) {
4531 return s390_emit_LLGCR(p, r1, r2);
4532 }
4533
4534 p = s390_emit_LR(p, r1, r2);
4535 p = s390_emit_LLILL(p, R0, 0xFF);
4536 return s390_emit_NGR(p, r1, R0);
4537}
4538
4539
4540/* r1[32:63] = zero_extend(r2[48:63]) */
4541static UChar *
4542s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
4543{
4544 if (s390_host_has_eimm) {
4545 return s390_emit_LLHR(p, r1, r2);
4546 }
4547
4548 p = s390_emit_LR(p, r1, r2);
4549 p = s390_emit_LLILL(p, R0, 0xFFFF);
4550 return s390_emit_NR(p, r1, R0);
4551}
4552
4553
4554/* r1[0:63] = zero_extend(r2[48:63]) */
4555static UChar *
4556s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
4557{
4558 if (s390_host_has_eimm) {
4559 return s390_emit_LLGHR(p, r1, r2);
4560 }
4561
4562 p = s390_emit_LR(p, r1, r2);
4563 p = s390_emit_LLILL(p, R0, 0xFFFF);
4564 return s390_emit_NGR(p, r1, R0);
4565}
4566
4567
4568/* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
4569static UChar *
4570s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4571{
4572 if (s390_host_has_eimm) {
4573 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
4574 }
4575
4576 if (dh == 0) {
4577 p = s390_emit_IC(p, r1, x2, b2, dl);
4578 } else {
4579 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
4580 }
4581 p = s390_emit_LLILL(p, R0, 0xFF);
4582 return s390_emit_NR(p, r1, R0);
4583}
4584
4585
4586/* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
4587static UChar *
4588s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4589{
4590 if (s390_host_has_eimm) {
4591 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
4592 }
4593
4594 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
4595 p = s390_emit_LLILL(p, R0, 0xFFFF);
4596 return s390_emit_NR(p, r1, R0);
4597}
4598
4599
4600/* r1[0:63] = zero_extend(i2) */
4601static UChar *
4602s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
4603{
4604 if (s390_host_has_eimm) {
4605 return s390_emit_LLILF(p, r1, i2);
4606 }
4607
4608 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
4609 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
4610}
4611
4612
4613/* r1[32:63] = r1[32:63] + i2 */
4614static UChar *
4615s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
4616{
4617 if (s390_host_has_eimm) {
4618 return s390_emit_AFI(p, r1, i2);
4619 }
4620 /* Load 32 bit immediate to R0 then add */
4621 p = s390_emit_load_32imm(p, R0, i2);
4622 return s390_emit_AR(p, r1, R0);
4623}
4624
4625
4626/* r1[32:63] = r1[32:63] - i2 */
4627static UChar *
4628s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
4629{
4630 if (s390_host_has_eimm) {
4631 return s390_emit_SLFI(p, r1, i2);
4632 }
4633
4634 /* Load 32 bit immediate to R0 then subtract */
4635 p = s390_emit_load_32imm(p, R0, i2);
4636 return s390_emit_SR(p, r1, R0);
4637}
4638
4639
sewardjb13a92a2011-04-13 14:44:29 +00004640/* r1[0:63] = r1[0:63] - zero_extend(i2) */
4641static UChar *
4642s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
4643{
4644 if (s390_host_has_eimm) {
4645 return s390_emit_SLGFI(p, r1, i2);
4646 }
4647
4648 /* Load zero-extended 32 bit immediate to R0 then subtract */
4649 p = s390_emit_load_64imm(p, R0, i2);
4650 return s390_emit_SGR(p, r1, R0);
4651}
4652
4653
sewardj2019a972011-03-07 16:04:07 +00004654static UChar *
4655s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4656{
4657 if (s390_host_has_eimm) {
4658 return s390_emit_LT(p, r1, x2, b2, dl, dh);
4659 }
4660 /* Load 32 bit from memory to R0 then compare */
4661 if (dh == 0) {
4662 p = s390_emit_L(p, R0, x2, b2, dl);
4663 } else {
4664 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
4665 }
4666 return s390_emit_LTR(p, r1, R0);
4667}
4668
4669
4670static UChar *
4671s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4672{
4673 if (s390_host_has_eimm) {
4674 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
4675 }
4676 /* Load 64 bit from memory to R0 then compare */
4677 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
4678 return s390_emit_LTGR(p, r1, R0);
4679}
4680
4681
4682static UChar *
4683s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
4684{
4685 if (s390_host_has_eimm) {
4686 return s390_emit_CFI(p, r1, i2);
4687 }
4688 /* Load 32 bit immediate to R0 then compare */
4689 p = s390_emit_load_32imm(p, R0, i2);
4690 return s390_emit_CR(p, r1, R0);
4691}
4692
4693
4694static UChar *
4695s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
4696{
4697 if (s390_host_has_eimm) {
4698 return s390_emit_CLFI(p, r1, i2);
4699 }
4700 /* Load 32 bit immediate to R0 then compare */
4701 p = s390_emit_load_32imm(p, R0, i2);
4702 return s390_emit_CLR(p, r1, R0);
4703}
4704
sewardjd07b8562011-04-27 11:58:22 +00004705
4706static UChar *
4707s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
4708{
4709 if (s390_host_has_fgx) {
4710 return s390_emit_LGDR(p, r1, r2);
4711 }
4712
4713 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
4714 smaller addresses and is 8-byte aligned. Then load the GPR from that
4715 memory location/ */
4716 if (s390_host_has_ldisp) {
4717 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4718 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4719 }
4720
4721 /* No long displacement. Need to adjust SP explicitly as to avoid negative
4722 displacements. */
4723 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4724 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
4725 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4726 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4727}
4728
4729
4730static UChar *
4731s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
4732{
4733 if (s390_host_has_fgx) {
4734 return s390_emit_LDGR(p, r1, r2);
4735 }
4736
4737 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
4738 smaller addresses and is 8-byte aligned. Then load the FPR from that
4739 memory location/ */
4740 if (s390_host_has_ldisp) {
4741 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4742 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4743 }
4744
4745 /* No long displacement. Need to adjust SP explicitly as to avoid negative
4746 displacements. */
4747 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4748 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4749 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
4750 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4751}
4752
4753
sewardj2019a972011-03-07 16:04:07 +00004754/*---------------------------------------------------------------*/
4755/*--- Constructors for the various s390_insn kinds ---*/
4756/*---------------------------------------------------------------*/
4757
4758s390_insn *
4759s390_insn_load(UChar size, HReg dst, s390_amode *src)
4760{
4761 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4762
4763 insn->tag = S390_INSN_LOAD;
4764 insn->size = size;
4765 insn->variant.load.src = src;
4766 insn->variant.load.dst = dst;
4767
4768 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4769
4770 return insn;
4771}
4772
4773
4774s390_insn *
4775s390_insn_store(UChar size, s390_amode *dst, HReg src)
4776{
4777 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4778
4779 insn->tag = S390_INSN_STORE;
4780 insn->size = size;
4781 insn->variant.store.src = src;
4782 insn->variant.store.dst = dst;
4783
4784 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4785
4786 return insn;
4787}
4788
4789
4790s390_insn *
4791s390_insn_move(UChar size, HReg dst, HReg src)
4792{
4793 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4794
4795 insn->tag = S390_INSN_MOVE;
4796 insn->size = size;
4797 insn->variant.move.src = src;
4798 insn->variant.move.dst = dst;
4799
4800 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4801
4802 return insn;
4803}
4804
4805
4806s390_insn *
4807s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
4808{
4809 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4810
4811 insn->tag = S390_INSN_COND_MOVE;
4812 insn->size = size;
4813 insn->variant.cond_move.cond = cond;
4814 insn->variant.cond_move.src = src;
4815 insn->variant.cond_move.dst = dst;
4816
4817 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4818
4819 return insn;
4820}
4821
4822
4823s390_insn *
4824s390_insn_load_immediate(UChar size, HReg dst, ULong value)
4825{
4826 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4827
4828 insn->tag = S390_INSN_LOAD_IMMEDIATE;
4829 insn->size = size;
4830 insn->variant.load_immediate.dst = dst;
4831 insn->variant.load_immediate.value = value;
4832
4833 return insn;
4834}
4835
4836
4837s390_insn *
4838s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
4839{
4840 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4841
4842 insn->tag = S390_INSN_ALU;
4843 insn->size = size;
4844 insn->variant.alu.tag = tag;
4845 insn->variant.alu.dst = dst;
4846 insn->variant.alu.op2 = op2;
4847
4848 return insn;
4849}
4850
4851
4852s390_insn *
4853s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
4854 Bool signed_multiply)
4855{
4856 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4857
4858 vassert(! hregIsVirtual(dst_hi));
4859 vassert(! hregIsVirtual(dst_lo));
4860
florianc4aa7ed2012-12-22 15:01:04 +00004861 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
sewardj2019a972011-03-07 16:04:07 +00004862 insn->size = size;
4863 insn->variant.mul.dst_hi = dst_hi;
4864 insn->variant.mul.dst_lo = dst_lo;
4865 insn->variant.mul.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00004866
4867 return insn;
4868}
4869
4870
4871s390_insn *
4872s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
4873 Bool signed_divide)
4874{
4875 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4876
4877 vassert(size == 4 || size == 8);
4878 vassert(! hregIsVirtual(op1_hi));
4879 vassert(! hregIsVirtual(op1_lo));
4880
florianc4aa7ed2012-12-22 15:01:04 +00004881 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
sewardj2019a972011-03-07 16:04:07 +00004882 insn->size = size;
4883 insn->variant.div.op1_hi = op1_hi;
4884 insn->variant.div.op1_lo = op1_lo;
4885 insn->variant.div.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00004886
4887 return insn;
4888}
4889
4890
4891s390_insn *
4892s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
4893{
4894 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4895
4896 vassert(size == 8);
4897 vassert(! hregIsVirtual(op1));
4898 vassert(! hregIsVirtual(rem));
4899
4900 insn->tag = S390_INSN_DIVS;
4901 insn->size = size;
4902 insn->variant.divs.rem = rem; /* remainder */
4903 insn->variant.divs.op1 = op1; /* also quotient */
4904 insn->variant.divs.op2 = op2;
4905
4906 return insn;
4907}
4908
4909
4910s390_insn *
sewardj611b06e2011-03-24 08:57:29 +00004911s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
sewardj2019a972011-03-07 16:04:07 +00004912{
4913 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4914
4915 vassert(size == 8);
sewardj611b06e2011-03-24 08:57:29 +00004916 vassert(! hregIsVirtual(num_bits));
4917 vassert(! hregIsVirtual(clobber));
sewardj2019a972011-03-07 16:04:07 +00004918
sewardj611b06e2011-03-24 08:57:29 +00004919 insn->tag = S390_INSN_CLZ;
sewardj2019a972011-03-07 16:04:07 +00004920 insn->size = size;
sewardj611b06e2011-03-24 08:57:29 +00004921 insn->variant.clz.num_bits = num_bits;
4922 insn->variant.clz.clobber = clobber;
4923 insn->variant.clz.src = src;
sewardj2019a972011-03-07 16:04:07 +00004924
4925 return insn;
4926}
4927
4928
4929s390_insn *
4930s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
4931{
4932 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4933
4934 insn->tag = S390_INSN_UNOP;
4935 insn->size = size;
4936 insn->variant.unop.tag = tag;
4937 insn->variant.unop.dst = dst;
4938 insn->variant.unop.src = opnd;
4939
4940 return insn;
4941}
4942
4943
4944s390_insn *
4945s390_insn_test(UChar size, s390_opnd_RMI src)
4946{
4947 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4948
4949 vassert(size == 4 || size == 8);
4950
4951 insn->tag = S390_INSN_TEST;
4952 insn->size = size;
4953 insn->variant.test.src = src;
4954
4955 return insn;
4956}
4957
4958
4959s390_insn *
4960s390_insn_cc2bool(HReg dst, s390_cc_t cond)
4961{
4962 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4963
4964 insn->tag = S390_INSN_CC2BOOL;
4965 insn->size = 0; /* does not matter */
4966 insn->variant.cc2bool.cond = cond;
4967 insn->variant.cc2bool.dst = dst;
4968
4969 return insn;
4970}
4971
4972
4973s390_insn *
4974s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
4975{
4976 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4977
4978 vassert(size == 4 || size == 8);
4979 vassert(op2->x == 0);
4980
4981 insn->tag = S390_INSN_CAS;
4982 insn->size = size;
4983 insn->variant.cas.op1 = op1;
4984 insn->variant.cas.op2 = op2;
4985 insn->variant.cas.op3 = op3;
4986 insn->variant.cas.old_mem = old_mem;
4987
4988 return insn;
4989}
4990
4991
4992s390_insn *
florian448cbba2012-06-06 02:26:01 +00004993s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
4994 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
4995 HReg scratch)
4996{
4997 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00004998 s390_cdas *cdas = LibVEX_Alloc(sizeof(s390_cdas));
florian448cbba2012-06-06 02:26:01 +00004999
5000 vassert(size == 4 || size == 8);
5001 vassert(op2->x == 0);
5002 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
5003
5004 insn->tag = S390_INSN_CDAS;
5005 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005006 insn->variant.cdas.details = cdas;
5007
5008 cdas->op1_high = op1_high;
5009 cdas->op1_low = op1_low;
5010 cdas->op2 = op2;
5011 cdas->op3_high = op3_high;
5012 cdas->op3_low = op3_low;
5013 cdas->old_mem_high = old_mem_high;
5014 cdas->old_mem_low = old_mem_low;
5015 cdas->scratch = scratch;
florian448cbba2012-06-06 02:26:01 +00005016
5017 return insn;
5018}
5019
5020
5021s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005022s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
5023 Bool signed_comparison)
5024{
5025 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5026
5027 vassert(size == 4 || size == 8);
5028
5029 insn->tag = S390_INSN_COMPARE;
5030 insn->size = size;
5031 insn->variant.compare.src1 = src1;
5032 insn->variant.compare.src2 = src2;
5033 insn->variant.compare.signed_comparison = signed_comparison;
5034
5035 return insn;
5036}
5037
5038
5039s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005040s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
florian1ff47562012-10-21 02:09:51 +00005041 const HChar *name, HReg dst)
sewardj2019a972011-03-07 16:04:07 +00005042{
5043 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5044
5045 insn->tag = S390_INSN_HELPER_CALL;
5046 insn->size = 0; /* does not matter */
5047 insn->variant.helper_call.cond = cond;
5048 insn->variant.helper_call.target = target;
5049 insn->variant.helper_call.num_args = num_args;
5050 insn->variant.helper_call.name = name;
florian01ed6e72012-05-27 16:52:43 +00005051 insn->variant.helper_call.dst = dst;
sewardj2019a972011-03-07 16:04:07 +00005052
5053 return insn;
5054}
5055
5056
5057s390_insn *
5058s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
florian2c74d242012-09-12 19:38:42 +00005059 HReg op3)
sewardj2019a972011-03-07 16:04:07 +00005060{
5061 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5062
floriancc491a62012-09-10 23:44:37 +00005063 vassert(size == 4 || size == 8);
5064
sewardj2019a972011-03-07 16:04:07 +00005065 insn->tag = S390_INSN_BFP_TRIOP;
5066 insn->size = size;
5067 insn->variant.bfp_triop.tag = tag;
5068 insn->variant.bfp_triop.dst = dst;
5069 insn->variant.bfp_triop.op2 = op2;
5070 insn->variant.bfp_triop.op3 = op3;
sewardj2019a972011-03-07 16:04:07 +00005071
5072 return insn;
5073}
5074
5075
5076s390_insn *
florian2c74d242012-09-12 19:38:42 +00005077s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
sewardj2019a972011-03-07 16:04:07 +00005078{
5079 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5080
floriancc491a62012-09-10 23:44:37 +00005081 vassert(size == 4 || size == 8);
5082
sewardj2019a972011-03-07 16:04:07 +00005083 insn->tag = S390_INSN_BFP_BINOP;
5084 insn->size = size;
5085 insn->variant.bfp_binop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005086 insn->variant.bfp_binop.dst_hi = dst;
5087 insn->variant.bfp_binop.op2_hi = op2;
5088 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
5089 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005090
5091 return insn;
5092}
5093
5094
5095s390_insn *
florian2c74d242012-09-12 19:38:42 +00005096s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
sewardj2019a972011-03-07 16:04:07 +00005097{
5098 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5099
floriancc491a62012-09-10 23:44:37 +00005100 vassert(size == 4 || size == 8);
5101
sewardj2019a972011-03-07 16:04:07 +00005102 insn->tag = S390_INSN_BFP_UNOP;
5103 insn->size = size;
5104 insn->variant.bfp_unop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005105 insn->variant.bfp_unop.dst_hi = dst;
5106 insn->variant.bfp_unop.op_hi = op;
5107 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
5108 insn->variant.bfp_unop.op_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005109
5110 return insn;
5111}
5112
5113
5114s390_insn *
5115s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
5116{
5117 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5118
5119 vassert(size == 4 || size == 8);
5120
5121 insn->tag = S390_INSN_BFP_COMPARE;
5122 insn->size = size;
5123 insn->variant.bfp_compare.dst = dst;
floriancc491a62012-09-10 23:44:37 +00005124 insn->variant.bfp_compare.op1_hi = op1;
5125 insn->variant.bfp_compare.op2_hi = op2;
5126 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
5127 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005128
5129 return insn;
5130}
5131
5132
5133s390_insn *
florian6dc90242012-12-21 21:43:00 +00005134s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
florian125e20d2012-10-07 15:42:37 +00005135 s390_bfp_round_t rounding_mode)
florian9fcff4c2012-09-10 03:09:04 +00005136{
5137 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5138
floriancc491a62012-09-10 23:44:37 +00005139 vassert(size == 4 || size == 8);
5140
florian9fcff4c2012-09-10 03:09:04 +00005141 insn->tag = S390_INSN_BFP_CONVERT;
5142 insn->size = size;
5143 insn->variant.bfp_convert.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005144 insn->variant.bfp_convert.dst_hi = dst;
5145 insn->variant.bfp_convert.op_hi = op;
5146 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
5147 insn->variant.bfp_convert.op_lo = INVALID_HREG;
florian9fcff4c2012-09-10 03:09:04 +00005148 insn->variant.bfp_convert.rounding_mode = rounding_mode;
5149
5150 return insn;
5151}
5152
5153
floriane38f6412012-12-21 17:32:12 +00005154/* Check validity of a register pair for 128-bit FP. Valid register
floriancc491a62012-09-10 23:44:37 +00005155 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
5156 and (13, 15). */
5157static Bool
floriane38f6412012-12-21 17:32:12 +00005158is_valid_fp128_regpair(HReg hi, HReg lo)
floriancc491a62012-09-10 23:44:37 +00005159{
5160 UInt hi_regno = hregNumber(hi);
5161 UInt lo_regno = hregNumber(lo);
5162
5163 if (lo_regno != hi_regno + 2) return False;
5164 if ((hi_regno & 0x2) != 0) return False;
5165
5166 return True;
5167}
5168
florian9fcff4c2012-09-10 03:09:04 +00005169s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005170s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005171 HReg dst_lo, HReg op2_hi, HReg op2_lo)
sewardj2019a972011-03-07 16:04:07 +00005172{
5173 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5174
floriancc491a62012-09-10 23:44:37 +00005175 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005176 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5177 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005178
5179 insn->tag = S390_INSN_BFP_BINOP;
sewardj2019a972011-03-07 16:04:07 +00005180 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005181 insn->variant.bfp_binop.tag = tag;
5182 insn->variant.bfp_binop.dst_hi = dst_hi;
5183 insn->variant.bfp_binop.dst_lo = dst_lo;
5184 insn->variant.bfp_binop.op2_hi = op2_hi;
5185 insn->variant.bfp_binop.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005186
5187 return insn;
5188}
5189
5190
5191s390_insn *
sewardja970c402011-04-28 18:38:42 +00005192s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005193 HReg dst_lo, HReg op_hi, HReg op_lo)
sewardj2019a972011-03-07 16:04:07 +00005194{
5195 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5196
floriancc491a62012-09-10 23:44:37 +00005197 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005198 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5199 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005200
5201 insn->tag = S390_INSN_BFP_UNOP;
sewardj2019a972011-03-07 16:04:07 +00005202 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005203 insn->variant.bfp_unop.tag = tag;
5204 insn->variant.bfp_unop.dst_hi = dst_hi;
5205 insn->variant.bfp_unop.dst_lo = dst_lo;
5206 insn->variant.bfp_unop.op_hi = op_hi;
5207 insn->variant.bfp_unop.op_lo = op_lo;
sewardj2019a972011-03-07 16:04:07 +00005208
5209 return insn;
5210}
5211
5212
5213s390_insn *
5214s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
5215 HReg op2_hi, HReg op2_lo)
5216{
5217 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5218
floriancc491a62012-09-10 23:44:37 +00005219 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005220 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
5221 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005222
5223 insn->tag = S390_INSN_BFP_COMPARE;
sewardj2019a972011-03-07 16:04:07 +00005224 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005225 insn->variant.bfp_compare.dst = dst;
5226 insn->variant.bfp_compare.op1_hi = op1_hi;
5227 insn->variant.bfp_compare.op1_lo = op1_lo;
5228 insn->variant.bfp_compare.op2_hi = op2_hi;
5229 insn->variant.bfp_compare.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005230
5231 return insn;
5232}
5233
5234
florian9fcff4c2012-09-10 03:09:04 +00005235static s390_insn *
florian6dc90242012-12-21 21:43:00 +00005236s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005237 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005238 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005239{
5240 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5241
floriancc491a62012-09-10 23:44:37 +00005242 if (size == 16) {
5243 /* From smaller size to 16 bytes */
floriane38f6412012-12-21 17:32:12 +00005244 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
floriancc491a62012-09-10 23:44:37 +00005245 vassert(op_lo == INVALID_HREG);
5246 } else {
5247 /* From 16 bytes to smaller size */
floriane38f6412012-12-21 17:32:12 +00005248 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005249 vassert(dst_lo == INVALID_HREG);
5250 }
5251
5252 insn->tag = S390_INSN_BFP_CONVERT;
sewardj2019a972011-03-07 16:04:07 +00005253 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005254 insn->variant.bfp_convert.tag = tag;
5255 insn->variant.bfp_convert.dst_hi = dst_hi;
5256 insn->variant.bfp_convert.dst_lo = dst_lo;
5257 insn->variant.bfp_convert.op_hi = op_hi;
5258 insn->variant.bfp_convert.op_lo = op_lo;
5259 insn->variant.bfp_convert.rounding_mode = rounding_mode;
sewardj2019a972011-03-07 16:04:07 +00005260
5261 return insn;
5262}
5263
5264
5265s390_insn *
florian6dc90242012-12-21 21:43:00 +00005266s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005267 HReg dst_lo, HReg op)
5268{
5269 /* Conversion to bfp128 never requires a rounding mode. Provide default
5270 rounding mode. It will not be used when emitting insns. */
florian125e20d2012-10-07 15:42:37 +00005271 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
florian9fcff4c2012-09-10 03:09:04 +00005272
5273 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
5274 INVALID_HREG, rounding_mode);
5275}
5276
5277
5278s390_insn *
florian6dc90242012-12-21 21:43:00 +00005279s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst,
sewardj2019a972011-03-07 16:04:07 +00005280 HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005281 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005282{
florian9fcff4c2012-09-10 03:09:04 +00005283 return s390_insn_bfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
5284 rounding_mode);
sewardj2019a972011-03-07 16:04:07 +00005285}
5286
5287
sewardja52e37e2011-04-28 18:48:06 +00005288s390_insn *
florian12390202012-11-10 22:34:14 +00005289s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
5290 HReg op3, s390_dfp_round_t rounding_mode)
5291{
5292 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005293 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop));
florian12390202012-11-10 22:34:14 +00005294
5295 vassert(size == 8);
5296
5297 insn->tag = S390_INSN_DFP_BINOP;
5298 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005299 insn->variant.dfp_binop.details = dfp_binop;
5300
5301 dfp_binop->tag = tag;
5302 dfp_binop->dst_hi = dst;
5303 dfp_binop->op2_hi = op2;
5304 dfp_binop->op3_hi = op3;
5305 dfp_binop->dst_lo = INVALID_HREG;
5306 dfp_binop->op2_lo = INVALID_HREG;
5307 dfp_binop->op3_lo = INVALID_HREG;
5308 dfp_binop->rounding_mode = rounding_mode;
florian12390202012-11-10 22:34:14 +00005309
5310 return insn;
5311}
5312
5313
5314s390_insn *
florian20c6bca2012-12-26 17:47:19 +00005315s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
5316 HReg op1, HReg op2)
floriane38f6412012-12-21 17:32:12 +00005317{
5318 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5319
5320 vassert(size == 8);
5321
5322 insn->tag = S390_INSN_DFP_COMPARE;
5323 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00005324 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00005325 insn->variant.dfp_compare.dst = dst;
5326 insn->variant.dfp_compare.op1_hi = op1;
5327 insn->variant.dfp_compare.op2_hi = op2;
5328 insn->variant.dfp_compare.op1_lo = INVALID_HREG;
5329 insn->variant.dfp_compare.op2_lo = INVALID_HREG;
5330
5331 return insn;
5332}
5333
5334
5335s390_insn *
5336s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
5337 s390_dfp_round_t rounding_mode)
5338{
5339 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5340
florian06dfe212012-12-22 02:09:40 +00005341 vassert(size == 4 || size == 8);
floriane38f6412012-12-21 17:32:12 +00005342
5343 insn->tag = S390_INSN_DFP_CONVERT;
5344 insn->size = size;
5345 insn->variant.dfp_convert.tag = tag;
5346 insn->variant.dfp_convert.dst_hi = dst;
5347 insn->variant.dfp_convert.op_hi = op;
5348 insn->variant.dfp_convert.dst_lo = INVALID_HREG;
5349 insn->variant.dfp_convert.op_lo = INVALID_HREG;
5350 insn->variant.dfp_convert.rounding_mode = rounding_mode;
5351
5352 return insn;
5353}
5354
5355
5356s390_insn *
5357s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
5358 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
5359 HReg op3_lo, s390_dfp_round_t rounding_mode)
5360{
5361 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005362 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop));
floriane38f6412012-12-21 17:32:12 +00005363
5364 vassert(size == 16);
5365 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5366 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
5367 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
5368
floriane38f6412012-12-21 17:32:12 +00005369 insn->tag = S390_INSN_DFP_BINOP;
5370 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005371 insn->variant.dfp_binop.details = dfp_binop;
5372
5373 dfp_binop->tag = tag;
5374 dfp_binop->dst_hi = dst_hi;
5375 dfp_binop->dst_lo = dst_lo;
5376 dfp_binop->op2_hi = op2_hi;
5377 dfp_binop->op2_lo = op2_lo;
5378 dfp_binop->op3_hi = op3_hi;
5379 dfp_binop->op3_lo = op3_lo;
5380 dfp_binop->rounding_mode = rounding_mode;
floriane38f6412012-12-21 17:32:12 +00005381
5382 return insn;
5383}
5384
5385
5386s390_insn *
florian20c6bca2012-12-26 17:47:19 +00005387s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
5388 HReg op1_lo, HReg op2_hi, HReg op2_lo)
floriane38f6412012-12-21 17:32:12 +00005389{
5390 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5391
5392 vassert(size == 16);
5393 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
5394 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
5395
5396 insn->tag = S390_INSN_DFP_COMPARE;
5397 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00005398 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00005399 insn->variant.dfp_compare.dst = dst;
5400 insn->variant.dfp_compare.op1_hi = op1_hi;
5401 insn->variant.dfp_compare.op1_lo = op1_lo;
5402 insn->variant.dfp_compare.op2_hi = op2_hi;
5403 insn->variant.dfp_compare.op2_lo = op2_lo;
5404
5405 return insn;
5406}
5407
5408
5409static s390_insn *
5410s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
5411 HReg dst_lo, HReg op_hi, HReg op_lo,
5412 s390_dfp_round_t rounding_mode)
5413{
5414 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5415
5416 if (size == 16) {
5417 /* From smaller size to 16 bytes */
5418 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5419 vassert(op_lo == INVALID_HREG);
5420 } else {
5421 /* From 16 bytes to smaller size */
5422 vassert(is_valid_fp128_regpair(op_hi, op_lo));
5423 vassert(dst_lo == INVALID_HREG);
5424 }
5425
5426 insn->tag = S390_INSN_DFP_CONVERT;
5427 insn->size = size;
5428 insn->variant.dfp_convert.tag = tag;
5429 insn->variant.dfp_convert.dst_hi = dst_hi;
5430 insn->variant.dfp_convert.dst_lo = dst_lo;
5431 insn->variant.dfp_convert.op_hi = op_hi;
5432 insn->variant.dfp_convert.op_lo = op_lo;
5433 insn->variant.dfp_convert.rounding_mode = rounding_mode;
5434
5435 return insn;
5436}
5437
5438
5439s390_insn *
5440s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
5441 HReg dst_lo, HReg op)
5442{
5443 /* Conversion to dfp128 never requires a rounding mode. Provide default
5444 rounding mode. It will not be used when emitting insns. */
5445 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
5446
5447 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
5448 INVALID_HREG, rounding_mode);
5449}
5450
5451
5452s390_insn *
5453s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst,
5454 HReg op_hi, HReg op_lo,
5455 s390_dfp_round_t rounding_mode)
5456{
5457 return s390_insn_dfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
5458 rounding_mode);
5459}
5460
5461
5462s390_insn *
sewardja52e37e2011-04-28 18:48:06 +00005463s390_insn_mfence(void)
5464{
5465 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5466
5467 insn->tag = S390_INSN_MFENCE;
5468 insn->size = 0; /* not needed */
5469
5470 return insn;
5471}
5472
5473
florianad43b3a2012-02-20 15:01:14 +00005474s390_insn *
florian09bbba82012-12-11 04:09:43 +00005475s390_insn_mzero(UChar size, s390_amode *dst)
florianad43b3a2012-02-20 15:01:14 +00005476{
5477 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5478
florian09bbba82012-12-11 04:09:43 +00005479 /* This insn will be mapped to an XC so we can only allow base register
5480 plus 12-bit displacement */
5481 vassert(dst->tag == S390_AMODE_B12);
5482
5483 insn->tag = S390_INSN_MZERO;
florianad43b3a2012-02-20 15:01:14 +00005484 insn->size = size;
florian09bbba82012-12-11 04:09:43 +00005485 insn->variant.mzero.dst = dst;
florianad43b3a2012-02-20 15:01:14 +00005486
5487 return insn;
5488}
5489
5490
5491s390_insn *
florianf85fe3e2012-12-22 02:28:25 +00005492s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
florianad43b3a2012-02-20 15:01:14 +00005493{
5494 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5495
florianf85fe3e2012-12-22 02:28:25 +00005496 vassert(size == 4 || size == 8);
5497
5498 /* This insn will be mapped to an ASI or AGSI so we can only allow base
5499 register plus 12-bit / 20-bit displacement. */
5500 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
5501
5502 insn->tag = S390_INSN_MADD;
florianad43b3a2012-02-20 15:01:14 +00005503 insn->size = size;
florianf85fe3e2012-12-22 02:28:25 +00005504 insn->variant.madd.dst = dst;
5505 insn->variant.madd.delta = delta;
5506 insn->variant.madd.value = value;
florianad43b3a2012-02-20 15:01:14 +00005507
5508 return insn;
5509}
5510
5511
florian8844a632012-04-13 04:04:06 +00005512s390_insn *
florian125e20d2012-10-07 15:42:37 +00005513s390_insn_set_fpc_bfprm(UChar size, HReg mode)
florian2c74d242012-09-12 19:38:42 +00005514{
5515 vassert(size == 4);
5516
5517 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5518
florian125e20d2012-10-07 15:42:37 +00005519 insn->tag = S390_INSN_SET_FPC_BFPRM;
florian2c74d242012-09-12 19:38:42 +00005520 insn->size = size;
florian125e20d2012-10-07 15:42:37 +00005521 insn->variant.set_fpc_bfprm.mode = mode;
florian2c74d242012-09-12 19:38:42 +00005522
5523 return insn;
5524}
5525
5526
5527s390_insn *
florianc8e4f562012-10-27 16:19:31 +00005528s390_insn_set_fpc_dfprm(UChar size, HReg mode)
5529{
5530 vassert(size == 4);
5531
5532 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5533
5534 insn->tag = S390_INSN_SET_FPC_DFPRM;
5535 insn->size = size;
5536 insn->variant.set_fpc_dfprm.mode = mode;
5537
5538 return insn;
5539}
5540
5541
5542s390_insn *
florian8844a632012-04-13 04:04:06 +00005543s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
5544 Bool to_fast_entry)
5545{
5546 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5547
5548 insn->tag = S390_INSN_XDIRECT;
5549 insn->size = 0; /* does not matter */
5550
5551 insn->variant.xdirect.cond = cond;
5552 insn->variant.xdirect.dst = dst;
5553 insn->variant.xdirect.guest_IA = guest_IA;
5554 insn->variant.xdirect.to_fast_entry = to_fast_entry;
5555
5556 return insn;
5557}
5558
5559
5560s390_insn *
5561s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
5562{
5563 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5564
florian7346c7a2012-04-13 21:14:24 +00005565 insn->tag = S390_INSN_XINDIR;
florian8844a632012-04-13 04:04:06 +00005566 insn->size = 0; /* does not matter */
5567
florian7346c7a2012-04-13 21:14:24 +00005568 insn->variant.xindir.cond = cond;
5569 insn->variant.xindir.dst = dst;
5570 insn->variant.xindir.guest_IA = guest_IA;
florian8844a632012-04-13 04:04:06 +00005571
5572 return insn;
5573}
5574
5575
5576s390_insn *
5577s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
5578 IRJumpKind kind)
5579{
5580 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5581
5582 insn->tag = S390_INSN_XASSISTED;
5583 insn->size = 0; /* does not matter */
5584
5585 insn->variant.xassisted.cond = cond;
5586 insn->variant.xassisted.dst = dst;
5587 insn->variant.xassisted.guest_IA = guest_IA;
5588 insn->variant.xassisted.kind = kind;
5589
5590 return insn;
5591}
5592
5593
5594s390_insn *
5595s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
5596{
5597 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5598
florianbf516d12012-04-21 15:53:13 +00005599 vassert(counter->tag == S390_AMODE_B12);
5600 vassert(fail_addr->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00005601
5602 insn->tag = S390_INSN_EVCHECK;
5603 insn->size = 0; /* does not matter */
5604
5605 insn->variant.evcheck.counter = counter;
5606 insn->variant.evcheck.fail_addr = fail_addr;
5607
5608 return insn;
5609}
5610
5611
5612s390_insn *
5613s390_insn_profinc(void)
5614{
5615 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5616
5617 insn->tag = S390_INSN_PROFINC;
5618 insn->size = 0; /* does not matter */
5619
5620 return insn;
5621}
5622
5623
sewardj2019a972011-03-07 16:04:07 +00005624/*---------------------------------------------------------------*/
5625/*--- Debug print ---*/
5626/*---------------------------------------------------------------*/
5627
5628static const HChar *
5629s390_cc_as_string(s390_cc_t cc)
5630{
5631 switch (cc) {
5632 case S390_CC_NEVER: return "never";
5633 case S390_CC_OVFL: return "overflow";
5634 case S390_CC_H: return "greater than"; /* A > B ; high */
5635 case S390_CC_NLE: return "not low or equal";
5636 case S390_CC_L: return "less than"; /* A < B ; low */
5637 case S390_CC_NHE: return "not high or equal";
5638 case S390_CC_LH: return "low or high";
5639 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
5640 case S390_CC_E: return "equal"; /* A == B ; zero */
5641 case S390_CC_NLH: return "not low or high";
5642 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
5643 case S390_CC_NL: return "not low"; /* not low */
5644 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
5645 case S390_CC_NH: return "not high";
5646 case S390_CC_NO: return "not overflow";
5647 case S390_CC_ALWAYS: return "always";
5648 default:
5649 vpanic("s390_cc_as_string");
5650 }
5651}
5652
5653
florian8844a632012-04-13 04:04:06 +00005654static const HChar *
5655s390_jump_kind_as_string(IRJumpKind kind)
5656{
5657 switch (kind) {
5658 case Ijk_Boring: return "Boring";
5659 case Ijk_Call: return "Call";
5660 case Ijk_Ret: return "Return";
5661 case Ijk_ClientReq: return "ClientReq";
5662 case Ijk_Yield: return "Yield";
5663 case Ijk_EmWarn: return "EmWarn";
5664 case Ijk_EmFail: return "EmFail";
5665 case Ijk_NoDecode: return "NoDecode";
5666 case Ijk_MapFail: return "MapFail";
5667 case Ijk_TInval: return "Invalidate";
5668 case Ijk_NoRedir: return "NoRedir";
5669 case Ijk_SigTRAP: return "SigTRAP";
5670 case Ijk_SigSEGV: return "SigSEGV";
5671 case Ijk_SigBUS: return "SigBUS";
5672 case Ijk_Sys_syscall: return "Sys_syscall";
5673 default:
5674 vpanic("s390_jump_kind_as_string");
5675 }
5676}
5677
5678
sewardj2019a972011-03-07 16:04:07 +00005679/* Helper function for writing out a V insn */
5680static void
florian55085f82012-11-21 00:36:55 +00005681s390_sprintf(HChar *buf, const HChar *fmt, ...)
sewardj2019a972011-03-07 16:04:07 +00005682{
5683 HChar *p;
5684 ULong value;
5685 va_list args;
5686 va_start(args, fmt);
5687
5688 p = buf;
5689 for ( ; *fmt; ++fmt) {
5690 Int c = *fmt;
5691
5692 if (c != '%') {
5693 *p++ = c;
5694 continue;
5695 }
5696
5697 c = *++fmt; /* next char */
5698 switch (c) {
5699 case '%':
5700 *p++ = c; /* %% */
5701 continue;
5702
5703 case 's': /* %s */
5704 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
5705 continue;
5706
5707 case 'M': /* %M = mnemonic */
5708 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
5709 continue;
5710
5711 case 'R': /* %R = register */
5712 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
5713 continue;
5714
5715 case 'A': /* %A = amode */
5716 p += vex_sprintf(p, "%s",
5717 s390_amode_as_string(va_arg(args, s390_amode *)));
5718 continue;
5719
florianad43b3a2012-02-20 15:01:14 +00005720 case 'G': /* %G = guest state @ offset */
5721 p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt));
5722 continue;
5723
sewardj2019a972011-03-07 16:04:07 +00005724 case 'C': /* %C = condition code */
5725 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
5726 continue;
5727
florian8844a632012-04-13 04:04:06 +00005728 case 'J': /* &J = jump kind */
5729 p += vex_sprintf(p, "%s",
5730 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
5731 continue;
5732
sewardj2019a972011-03-07 16:04:07 +00005733 case 'L': { /* %L = argument list in helper call*/
5734 UInt i, num_args;
5735
5736 num_args = va_arg(args, UInt);
5737
5738 for (i = 0; i < num_args; ++i) {
5739 if (i != 0) p += vex_sprintf(p, ", ");
5740 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
5741 }
5742 continue;
5743 }
5744
5745 case 'O': { /* %O = RMI operand */
5746 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
5747
5748 switch (op->tag) {
5749 case S390_OPND_REG:
5750 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
5751 continue;
5752
5753 case S390_OPND_AMODE:
5754 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
5755 continue;
5756
5757 case S390_OPND_IMMEDIATE:
5758 value = op->variant.imm;
5759 goto print_value;
5760
5761 default:
5762 goto fail;
5763 }
5764 }
5765
5766 case 'I': /* %I = immediate value */
5767 value = va_arg(args, ULong);
5768 goto print_value;
5769
5770 print_value:
5771 if ((Long)value < 0)
5772 p += vex_sprintf(p, "%lld", (Long)value);
5773 else if (value < 100)
5774 p += vex_sprintf(p, "%llu", value);
5775 else
5776 p += vex_sprintf(p, "0x%llx", value);
5777 continue;
5778
5779 default:
5780 goto fail;
5781 }
5782 }
5783 *p = '\0';
5784 va_end(args);
5785
5786 return;
5787
5788 fail: vpanic("s390_printf");
5789}
5790
5791
5792/* Decompile the given insn into a static buffer and return it */
5793const HChar *
5794s390_insn_as_string(const s390_insn *insn)
5795{
5796 static HChar buf[300];
5797 const HChar *op;
5798 HChar *p;
5799
5800 buf[0] = '\0';
5801
5802 switch (insn->tag) {
5803 case S390_INSN_LOAD:
5804 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
5805 insn->variant.load.src);
5806 break;
5807
5808 case S390_INSN_STORE:
5809 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
5810 insn->variant.store.dst);
5811 break;
5812
5813 case S390_INSN_MOVE:
5814 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
5815 insn->variant.move.src);
5816 break;
5817
5818 case S390_INSN_COND_MOVE:
5819 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
5820 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
5821 &insn->variant.cond_move.src);
5822 break;
5823
5824 case S390_INSN_LOAD_IMMEDIATE:
5825 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
5826 insn->variant.load_immediate.value);
5827 break;
5828
5829 case S390_INSN_ALU:
5830 switch (insn->variant.alu.tag) {
5831 case S390_ALU_ADD: op = "v-add"; break;
5832 case S390_ALU_SUB: op = "v-sub"; break;
5833 case S390_ALU_MUL: op = "v-mul"; break;
5834 case S390_ALU_AND: op = "v-and"; break;
5835 case S390_ALU_OR: op = "v-or"; break;
5836 case S390_ALU_XOR: op = "v-xor"; break;
5837 case S390_ALU_LSH: op = "v-lsh"; break;
5838 case S390_ALU_RSH: op = "v-rsh"; break;
5839 case S390_ALU_RSHA: op = "v-rsha"; break;
5840 default: goto fail;
5841 }
florian043af212012-06-06 02:44:53 +00005842 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
sewardj2019a972011-03-07 16:04:07 +00005843 &insn->variant.alu.op2);
5844 break;
5845
florianc4aa7ed2012-12-22 15:01:04 +00005846 case S390_INSN_SMUL:
5847 case S390_INSN_UMUL:
5848 if (insn->tag == S390_INSN_SMUL) {
sewardj2019a972011-03-07 16:04:07 +00005849 op = "v-muls";
5850 } else {
5851 op = "v-mulu";
5852 }
5853 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
5854 &insn->variant.mul.op2);
5855 break;
5856
florianc4aa7ed2012-12-22 15:01:04 +00005857 case S390_INSN_SDIV:
5858 case S390_INSN_UDIV:
5859 if (insn->tag == S390_INSN_SDIV) {
sewardj2019a972011-03-07 16:04:07 +00005860 op = "v-divs";
5861 } else {
5862 op = "v-divu";
5863 }
5864 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
5865 &insn->variant.div.op2);
5866 break;
5867
5868 case S390_INSN_DIVS:
5869 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
5870 &insn->variant.divs.op2);
5871 break;
5872
sewardj611b06e2011-03-24 08:57:29 +00005873 case S390_INSN_CLZ:
5874 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
5875 &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +00005876 break;
5877
5878 case S390_INSN_UNOP:
5879 switch (insn->variant.unop.tag) {
5880 case S390_ZERO_EXTEND_8:
5881 case S390_ZERO_EXTEND_16:
5882 case S390_ZERO_EXTEND_32:
5883 op = "v-zerox";
5884 break;
5885
5886 case S390_SIGN_EXTEND_8:
5887 case S390_SIGN_EXTEND_16:
5888 case S390_SIGN_EXTEND_32:
5889 op = "v-signx";
5890 break;
5891
5892 case S390_NEGATE:
5893 op = "v-neg";
5894 break;
5895
5896 default:
5897 goto fail;
5898 }
5899 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
5900 &insn->variant.unop.src);
5901 break;
5902
5903 case S390_INSN_TEST:
5904 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
5905 break;
5906
5907 case S390_INSN_CC2BOOL:
5908 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
5909 insn->variant.cc2bool.cond);
5910 break;
5911
5912 case S390_INSN_CAS:
5913 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
5914 insn->variant.cas.op2, insn->variant.cas.op3,
5915 insn->variant.cas.old_mem);
5916 break;
5917
florianc4aa7ed2012-12-22 15:01:04 +00005918 case S390_INSN_CDAS: {
5919 s390_cdas *cdas = insn->variant.cdas.details;
5920
florian448cbba2012-06-06 02:26:01 +00005921 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
florianc4aa7ed2012-12-22 15:01:04 +00005922 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
5923 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
florian448cbba2012-06-06 02:26:01 +00005924 break;
florianc4aa7ed2012-12-22 15:01:04 +00005925 }
florian448cbba2012-06-06 02:26:01 +00005926
sewardj2019a972011-03-07 16:04:07 +00005927 case S390_INSN_COMPARE:
5928 if (insn->variant.compare.signed_comparison) {
5929 op = "v-cmps";
5930 } else {
5931 op = "v-cmpu";
5932 }
5933 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
5934 &insn->variant.compare.src2);
5935 break;
5936
sewardj2019a972011-03-07 16:04:07 +00005937 case S390_INSN_HELPER_CALL: {
florian01ed6e72012-05-27 16:52:43 +00005938 if (insn->variant.helper_call.dst != INVALID_HREG) {
5939 s390_sprintf(buf, "%M if (%C) %R = %s{%I}(%L)", "v-call",
5940 insn->variant.helper_call.cond,
5941 insn->variant.helper_call.dst,
5942 insn->variant.helper_call.name,
5943 insn->variant.helper_call.target,
5944 insn->variant.helper_call.num_args);
5945 } else {
5946 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
5947 insn->variant.helper_call.cond,
5948 insn->variant.helper_call.name,
5949 insn->variant.helper_call.target,
5950 insn->variant.helper_call.num_args);
5951 }
florian8844a632012-04-13 04:04:06 +00005952 return buf; /* avoid printing "size = ..." which is meaningless */
sewardj2019a972011-03-07 16:04:07 +00005953 }
5954
5955 case S390_INSN_BFP_TRIOP:
5956 switch (insn->variant.bfp_triop.tag) {
5957 case S390_BFP_MADD: op = "v-fmadd"; break;
5958 case S390_BFP_MSUB: op = "v-fmsub"; break;
5959 default: goto fail;
5960 }
florian043af212012-06-06 02:44:53 +00005961 s390_sprintf(buf, "%M %R,%R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00005962 insn->variant.bfp_triop.dst /* op1 same as dst */,
5963 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
5964 break;
5965
5966 case S390_INSN_BFP_BINOP:
5967 switch (insn->variant.bfp_binop.tag) {
5968 case S390_BFP_ADD: op = "v-fadd"; break;
5969 case S390_BFP_SUB: op = "v-fsub"; break;
5970 case S390_BFP_MUL: op = "v-fmul"; break;
5971 case S390_BFP_DIV: op = "v-fdiv"; break;
5972 default: goto fail;
5973 }
florian043af212012-06-06 02:44:53 +00005974 s390_sprintf(buf, "%M %R,%R", op,
floriancc491a62012-09-10 23:44:37 +00005975 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
5976 insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00005977 break;
5978
5979 case S390_INSN_BFP_COMPARE:
5980 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
floriancc491a62012-09-10 23:44:37 +00005981 insn->variant.bfp_compare.op1_hi,
5982 insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00005983 break;
5984
5985 case S390_INSN_BFP_UNOP:
5986 switch (insn->variant.bfp_unop.tag) {
5987 case S390_BFP_ABS: op = "v-fabs"; break;
5988 case S390_BFP_NABS: op = "v-fnabs"; break;
5989 case S390_BFP_NEG: op = "v-fneg"; break;
5990 case S390_BFP_SQRT: op = "v-fsqrt"; break;
florian9fcff4c2012-09-10 03:09:04 +00005991 default: goto fail;
5992 }
floriancc491a62012-09-10 23:44:37 +00005993 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
5994 insn->variant.bfp_unop.op_hi);
florian9fcff4c2012-09-10 03:09:04 +00005995 break;
5996
5997 case S390_INSN_BFP_CONVERT:
5998 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00005999 case S390_BFP_I32_TO_F32:
6000 case S390_BFP_I32_TO_F64:
6001 case S390_BFP_I32_TO_F128:
6002 case S390_BFP_I64_TO_F32:
6003 case S390_BFP_I64_TO_F64:
6004 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006005 case S390_BFP_U32_TO_F32:
6006 case S390_BFP_U32_TO_F64:
6007 case S390_BFP_U32_TO_F128:
6008 case S390_BFP_U64_TO_F32:
6009 case S390_BFP_U64_TO_F64:
6010 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
sewardj2019a972011-03-07 16:04:07 +00006011 case S390_BFP_F32_TO_I32:
6012 case S390_BFP_F32_TO_I64:
6013 case S390_BFP_F64_TO_I32:
6014 case S390_BFP_F64_TO_I64:
6015 case S390_BFP_F128_TO_I32:
6016 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006017 case S390_BFP_F32_TO_U32:
6018 case S390_BFP_F32_TO_U64:
6019 case S390_BFP_F64_TO_U32:
6020 case S390_BFP_F64_TO_U64:
6021 case S390_BFP_F128_TO_U32:
6022 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
sewardj2019a972011-03-07 16:04:07 +00006023 case S390_BFP_F32_TO_F64:
6024 case S390_BFP_F32_TO_F128:
6025 case S390_BFP_F64_TO_F32:
6026 case S390_BFP_F64_TO_F128:
6027 case S390_BFP_F128_TO_F32:
6028 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
6029 default: goto fail;
6030 }
floriancc491a62012-09-10 23:44:37 +00006031 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
6032 insn->variant.bfp_convert.op_hi);
sewardj2019a972011-03-07 16:04:07 +00006033 break;
6034
florianc4aa7ed2012-12-22 15:01:04 +00006035 case S390_INSN_DFP_BINOP: {
6036 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
6037
6038 switch (dfp_binop->tag) {
florian12390202012-11-10 22:34:14 +00006039 case S390_DFP_ADD: op = "v-dadd"; break;
6040 case S390_DFP_SUB: op = "v-dsub"; break;
6041 case S390_DFP_MUL: op = "v-dmul"; break;
6042 case S390_DFP_DIV: op = "v-ddiv"; break;
6043 default: goto fail;
6044 }
florianc4aa7ed2012-12-22 15:01:04 +00006045 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
6046 dfp_binop->op2_hi, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +00006047 break;
florianc4aa7ed2012-12-22 15:01:04 +00006048 }
florian12390202012-11-10 22:34:14 +00006049
floriane38f6412012-12-21 17:32:12 +00006050 case S390_INSN_DFP_COMPARE:
florian20c6bca2012-12-26 17:47:19 +00006051 switch (insn->variant.dfp_compare.tag) {
6052 case S390_DFP_COMPARE: op = "v-dcmp"; break;
6053 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
6054 default: goto fail;
6055 }
6056 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
floriane38f6412012-12-21 17:32:12 +00006057 insn->variant.dfp_compare.op1_hi,
6058 insn->variant.dfp_compare.op2_hi);
6059 break;
6060
6061 case S390_INSN_DFP_CONVERT:
6062 switch (insn->variant.dfp_convert.tag) {
6063 case S390_DFP_D32_TO_D64:
6064 case S390_DFP_D64_TO_D32:
6065 case S390_DFP_D64_TO_D128:
6066 case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
6067 default: goto fail;
6068 }
6069 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
6070 insn->variant.dfp_convert.op_hi);
6071 break;
6072
sewardja52e37e2011-04-28 18:48:06 +00006073 case S390_INSN_MFENCE:
6074 s390_sprintf(buf, "%M", "v-mfence");
6075 return buf; /* avoid printing "size = ..." which is meaningless */
6076
florian09bbba82012-12-11 04:09:43 +00006077 case S390_INSN_MZERO:
6078 s390_sprintf(buf, "%M %A", "v-mzero", insn->variant.mzero.dst);
florianad43b3a2012-02-20 15:01:14 +00006079 break;
6080
florianf85fe3e2012-12-22 02:28:25 +00006081 case S390_INSN_MADD:
6082 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd",
6083 insn->variant.madd.dst,
6084 (Long)(Char)insn->variant.madd.delta,
6085 insn->variant.madd.value);
florianad43b3a2012-02-20 15:01:14 +00006086 break;
6087
florian125e20d2012-10-07 15:42:37 +00006088 case S390_INSN_SET_FPC_BFPRM:
6089 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
6090 insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00006091 break;
6092
florianc8e4f562012-10-27 16:19:31 +00006093 case S390_INSN_SET_FPC_DFPRM:
6094 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
6095 insn->variant.set_fpc_dfprm.mode);
6096 break;
6097
florian8844a632012-04-13 04:04:06 +00006098 case S390_INSN_EVCHECK:
6099 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
6100 insn->variant.evcheck.counter,
6101 insn->variant.evcheck.fail_addr);
6102 return buf; /* avoid printing "size = ..." which is meaningless */
6103
6104 case S390_INSN_PROFINC:
6105 s390_sprintf(buf, "%M", "v-profinc");
6106 return buf; /* avoid printing "size = ..." which is meaningless */
6107
6108 case S390_INSN_XDIRECT:
6109 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
6110 insn->variant.xdirect.cond,
6111 insn->variant.xdirect.guest_IA,
6112 insn->variant.xdirect.dst,
6113 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
6114 return buf; /* avoid printing "size = ..." which is meaningless */
6115
6116 case S390_INSN_XINDIR:
6117 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
6118 insn->variant.xindir.cond,
6119 insn->variant.xindir.guest_IA,
6120 insn->variant.xindir.dst);
6121 return buf; /* avoid printing "size = ..." which is meaningless */
6122
6123 case S390_INSN_XASSISTED:
6124 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
6125 insn->variant.xassisted.cond,
6126 insn->variant.xassisted.kind,
6127 insn->variant.xassisted.guest_IA,
6128 insn->variant.xassisted.dst);
6129 return buf; /* avoid printing "size = ..." which is meaningless */
6130
sewardj2019a972011-03-07 16:04:07 +00006131 default: goto fail;
6132 }
6133
6134 /* Write out how many bytes are involved in the operation */
6135
6136 {
6137 UInt len, i;
6138
6139 for (p = buf; *p; ++p)
6140 continue;
6141
6142 len = p - buf;
6143
6144 if (len < 32) {
6145 for (i = len; i < 32; ++i)
6146 p += vex_sprintf(p, " ");
6147 } else {
6148 p += vex_sprintf(p, "\t");
6149 }
6150 }
6151
6152 /* Special cases first */
6153 switch (insn->tag) {
6154 case S390_INSN_UNOP:
6155 switch (insn->variant.unop.tag) {
6156 case S390_SIGN_EXTEND_8:
6157 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
6158 case S390_SIGN_EXTEND_16:
6159 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
6160 case S390_SIGN_EXTEND_32:
6161 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
6162 default:
6163 goto common;
6164 }
6165
floriancc491a62012-09-10 23:44:37 +00006166 case S390_INSN_BFP_CONVERT:
6167 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00006168 case S390_BFP_I32_TO_F32:
6169 case S390_BFP_I32_TO_F64:
6170 case S390_BFP_I32_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00006171 case S390_BFP_U32_TO_F32:
6172 case S390_BFP_U32_TO_F64:
6173 case S390_BFP_U32_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00006174 case S390_BFP_F32_TO_I32:
6175 case S390_BFP_F32_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006176 case S390_BFP_F32_TO_U32:
6177 case S390_BFP_F32_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006178 case S390_BFP_F32_TO_F64:
6179 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
6180 case S390_BFP_I64_TO_F32:
6181 case S390_BFP_I64_TO_F64:
6182 case S390_BFP_I64_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00006183 case S390_BFP_U64_TO_F32:
6184 case S390_BFP_U64_TO_F64:
6185 case S390_BFP_U64_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00006186 case S390_BFP_F64_TO_I32:
6187 case S390_BFP_F64_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006188 case S390_BFP_F64_TO_U32:
6189 case S390_BFP_F64_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006190 case S390_BFP_F64_TO_F32:
6191 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
6192 case S390_BFP_F128_TO_I32:
6193 case S390_BFP_F128_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006194 case S390_BFP_F128_TO_U32:
6195 case S390_BFP_F128_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006196 case S390_BFP_F128_TO_F32:
6197 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
6198 default:
6199 goto common;
6200 }
6201
floriane38f6412012-12-21 17:32:12 +00006202 case S390_INSN_DFP_CONVERT:
6203 switch (insn->variant.dfp_convert.tag) {
6204 case S390_DFP_D32_TO_D64: p += vex_sprintf(p, "4 -> "); goto common;
6205 case S390_DFP_D64_TO_D32:
6206 case S390_DFP_D64_TO_D128:p += vex_sprintf(p, "8 -> "); goto common;
6207 case S390_DFP_D128_TO_D64:p += vex_sprintf(p, "16 -> "); goto common;
6208 default:
6209 goto common;
6210 }
6211
sewardj2019a972011-03-07 16:04:07 +00006212 default:
6213 goto common;
6214 }
6215
6216 /* Common case */
6217 common:
6218 vex_sprintf(p, "%u bytes", (UInt)insn->size);
6219
6220 return buf;
6221
6222 fail: vpanic("s390_insn_as_string");
6223}
6224
6225
6226
6227/* Load NUM bytes from memory into register REG using addressing mode AM. */
6228static UChar *
6229s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
6230{
6231 UInt b = hregNumber(am->b);
6232 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
6233 UInt d = am->d;
6234
6235 switch (am->tag) {
6236 case S390_AMODE_B12:
6237 case S390_AMODE_BX12:
6238 switch (num) {
6239 case 1: return s390_emit_IC(p, reg, x, b, d);
6240 case 2: return s390_emit_LH(p, reg, x, b, d);
6241 case 4: return s390_emit_L(p, reg, x, b, d);
6242 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
6243 default: goto fail;
6244 }
6245 break;
6246
6247 case S390_AMODE_B20:
6248 case S390_AMODE_BX20:
6249 switch (num) {
6250 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
6251 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
6252 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
6253 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
6254 default: goto fail;
6255 }
6256 break;
6257
6258 default: goto fail;
6259 }
6260
6261 fail:
6262 vpanic("s390_emit_load_mem");
6263}
6264
6265
6266/* Load condition code into register REG */
6267static UChar *
6268s390_emit_load_cc(UChar *p, UChar reg)
6269{
6270 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
6271 p = s390_emit_IPM(p, reg, reg);
6272 /* Shift 28 bits to the right --> [0,1,2,3] */
sewardjf74c86f2011-04-05 14:04:53 +00006273 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
sewardj2019a972011-03-07 16:04:07 +00006274}
6275
6276
6277/*---------------------------------------------------------------*/
6278/*--- Code generation ---*/
6279/*---------------------------------------------------------------*/
6280
6281/* Do not load more bytes than requested. */
6282static UChar *
6283s390_insn_load_emit(UChar *buf, const s390_insn *insn)
6284{
6285 UInt r, x, b, d;
6286 const s390_amode *src;
6287
6288 src = insn->variant.load.src;
6289
6290 r = hregNumber(insn->variant.load.dst);
6291
6292 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
6293 b = hregNumber(src->b);
6294 x = hregNumber(src->x); /* 0 for B12 and B20 */
6295 d = src->d;
6296
6297 switch (insn->size) {
6298
6299 case 4:
6300 switch (src->tag) {
6301 case S390_AMODE_B12:
6302 case S390_AMODE_BX12:
6303 return s390_emit_LE(buf, r, x, b, d);
6304
6305 case S390_AMODE_B20:
6306 case S390_AMODE_BX20:
6307 return s390_emit_LEY(buf, r, x, b, DISP20(d));
6308 }
6309 break;
6310
6311 case 8:
6312 switch (src->tag) {
6313 case S390_AMODE_B12:
6314 case S390_AMODE_BX12:
6315 return s390_emit_LD(buf, r, x, b, d);
6316
6317 case S390_AMODE_B20:
6318 case S390_AMODE_BX20:
6319 return s390_emit_LDY(buf, r, x, b, DISP20(d));
6320 }
6321 break;
6322 }
6323 vpanic("s390_insn_load_emit");
6324 }
6325
6326 /* Integer stuff */
6327 return s390_emit_load_mem(buf, insn->size, r, src);
6328}
6329
6330
6331static UChar *
6332s390_insn_store_emit(UChar *buf, const s390_insn *insn)
6333{
6334 UInt r, x, b, d;
6335 const s390_amode *dst;
6336
6337 dst = insn->variant.store.dst;
6338
6339 r = hregNumber(insn->variant.store.src);
6340 b = hregNumber(dst->b);
6341 x = hregNumber(dst->x); /* 0 for B12 and B20 */
6342 d = dst->d;
6343
6344 if (hregClass(insn->variant.store.src) == HRcFlt64) {
6345 switch (insn->size) {
6346
6347 case 4:
6348 switch (dst->tag) {
6349 case S390_AMODE_B12:
6350 case S390_AMODE_BX12:
6351 return s390_emit_STE(buf, r, x, b, d);
6352
6353 case S390_AMODE_B20:
6354 case S390_AMODE_BX20:
6355 return s390_emit_STEY(buf, r, x, b, DISP20(d));
6356 }
6357 break;
6358
6359 case 8:
6360 switch (dst->tag) {
6361 case S390_AMODE_B12:
6362 case S390_AMODE_BX12:
6363 return s390_emit_STD(buf, r, x, b, d);
6364
6365 case S390_AMODE_B20:
6366 case S390_AMODE_BX20:
6367 return s390_emit_STDY(buf, r, x, b, DISP20(d));
6368 }
6369 break;
6370 }
6371 vpanic("s390_insn_store_emit");
6372 }
6373
6374 /* Integer stuff */
6375 switch (insn->size) {
6376 case 1:
6377 switch (dst->tag) {
6378 case S390_AMODE_B12:
6379 case S390_AMODE_BX12:
6380 return s390_emit_STC(buf, r, x, b, d);
6381
6382 case S390_AMODE_B20:
6383 case S390_AMODE_BX20:
6384 return s390_emit_STCY(buf, r, x, b, DISP20(d));
6385 }
6386 break;
6387
6388 case 2:
6389 switch (dst->tag) {
6390 case S390_AMODE_B12:
6391 case S390_AMODE_BX12:
6392 return s390_emit_STH(buf, r, x, b, d);
6393
6394 case S390_AMODE_B20:
6395 case S390_AMODE_BX20:
6396 return s390_emit_STHY(buf, r, x, b, DISP20(d));
6397 }
6398 break;
6399
6400 case 4:
6401 switch (dst->tag) {
6402 case S390_AMODE_B12:
6403 case S390_AMODE_BX12:
6404 return s390_emit_ST(buf, r, x, b, d);
6405
6406 case S390_AMODE_B20:
6407 case S390_AMODE_BX20:
6408 return s390_emit_STY(buf, r, x, b, DISP20(d));
6409 }
6410 break;
6411
6412 case 8:
6413 return s390_emit_STG(buf, r, x, b, DISP20(d));
6414
6415 default:
6416 break;
6417 }
6418
6419 vpanic("s390_insn_store_emit");
6420}
6421
6422
6423static UChar *
6424s390_insn_move_emit(UChar *buf, const s390_insn *insn)
6425{
6426 UInt dst, src;
6427 HRegClass dst_class, src_class;
6428
6429 dst = hregNumber(insn->variant.move.dst);
6430 src = hregNumber(insn->variant.move.src);
6431
6432 dst_class = hregClass(insn->variant.move.dst);
6433 src_class = hregClass(insn->variant.move.src);
6434
6435 if (dst_class == src_class) {
6436 if (dst_class == HRcInt64)
6437 return s390_emit_LGR(buf, dst, src);
6438 if (dst_class == HRcFlt64)
6439 return s390_emit_LDR(buf, dst, src);
6440 } else {
floriana782a172011-12-18 15:51:54 +00006441 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
6442 if (insn->size == 4) {
6443 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
6444 return s390_emit_LDGRw(buf, dst, R0);
6445 } else {
6446 return s390_emit_LDGRw(buf, dst, src);
6447 }
6448 }
6449 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
6450 if (insn->size == 4) {
6451 buf = s390_emit_LGDRw(buf, dst, src);
6452 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
6453 } else {
6454 return s390_emit_LGDRw(buf, dst, src);
6455 }
6456 }
sewardj2019a972011-03-07 16:04:07 +00006457 /* A move between floating point registers and general purpose
6458 registers of different size should never occur and indicates
6459 an error elsewhere. */
6460 }
6461
6462 vpanic("s390_insn_move_emit");
6463}
6464
6465
6466static UChar *
6467s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
6468{
6469 UInt r;
6470 ULong value = insn->variant.load_immediate.value;
6471
6472 r = hregNumber(insn->variant.load_immediate.dst);
6473
6474 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
6475 vassert(value == 0);
6476 switch (insn->size) {
6477 case 4: return s390_emit_LZER(buf, r, value);
6478 case 8: return s390_emit_LZDR(buf, r, value);
6479 }
6480 vpanic("s390_insn_load_immediate_emit");
6481 }
6482
6483 switch (insn->size) {
6484 case 1:
6485 case 2:
6486 /* Load the immediate values as a 4 byte value. That does not hurt as
6487 those extra bytes will not be looked at. Fall through .... */
6488 case 4:
6489 return s390_emit_load_32imm(buf, r, value);
6490
6491 case 8:
6492 return s390_emit_load_64imm(buf, r, value);
6493 }
6494
6495 vpanic("s390_insn_load_immediate_emit");
6496}
6497
6498
6499/* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
6500 So we simply perform a 4-byte operation. Doing so uses possibly undefined
6501 bits and produces an undefined result in those extra bit positions. But
6502 upstream does not look at those positions, so this is OK. */
6503static UChar *
6504s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
6505{
6506 s390_opnd_RMI op2;
6507 UInt dst;
6508
6509 dst = hregNumber(insn->variant.alu.dst);
6510 op2 = insn->variant.alu.op2;
6511
6512 /* Second operand is in a register */
6513 if (op2.tag == S390_OPND_REG) {
6514 UInt r2 = hregNumber(op2.variant.reg);
6515
6516 switch (insn->size) {
6517 case 1:
6518 case 2:
6519 case 4:
6520 switch (insn->variant.alu.tag) {
6521 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
6522 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
6523 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
6524 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
6525 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
6526 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
sewardj3c49aaa2011-04-05 14:00:37 +00006527 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
6528 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
6529 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
sewardj2019a972011-03-07 16:04:07 +00006530 }
6531 goto fail;
6532
6533 case 8:
6534 switch (insn->variant.alu.tag) {
6535 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
6536 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
6537 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
6538 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
6539 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
6540 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
6541 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
6542 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
6543 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
6544 }
6545 goto fail;
6546 }
6547 goto fail;
6548 }
6549
6550 /* 2nd operand is in memory */
6551 if (op2.tag == S390_OPND_AMODE) {
6552 UInt b, x, d;
6553 const s390_amode *src = op2.variant.am;
6554
6555 b = hregNumber(src->b);
6556 x = hregNumber(src->x); /* 0 for B12 and B20 */
6557 d = src->d;
6558
6559 /* Shift operands are special here as there are no opcodes that
sewardje0dd77e2011-04-27 12:07:01 +00006560 allow a memory operand. So we first load the 2nd operand into
6561 some register. R0 is used to save restore the contents of the
6562 chosen register.. */
sewardj652b56a2011-04-13 15:38:17 +00006563
sewardj2019a972011-03-07 16:04:07 +00006564 if (insn->variant.alu.tag == S390_ALU_LSH ||
6565 insn->variant.alu.tag == S390_ALU_RSH ||
6566 insn->variant.alu.tag == S390_ALU_RSHA) {
sewardje0dd77e2011-04-27 12:07:01 +00006567 UInt b2;
sewardj2019a972011-03-07 16:04:07 +00006568
sewardje0dd77e2011-04-27 12:07:01 +00006569 /* Choose a register (other than DST or R0) into which to stick the
6570 shift amount. The following works because r15 is reserved and
6571 thusly dst != 15. */
6572 vassert(dst != 15); /* extra paranoia */
6573 b2 = (dst + 1) % 16;
6574
6575 buf = s390_emit_LGR(buf, R0, b2); /* save */
6576
6577 /* Loading SRC to B2 does not modify R0. */
6578 buf = s390_emit_load_mem(buf, insn->size, b2, src);
sewardj2019a972011-03-07 16:04:07 +00006579
6580 if (insn->size == 8) {
sewardje0dd77e2011-04-27 12:07:01 +00006581 switch (insn->variant.alu.tag) {
6582 case S390_ALU_LSH:
6583 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
6584 break;
6585 case S390_ALU_RSH:
6586 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
6587 break;
6588 case S390_ALU_RSHA:
6589 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
6590 break;
6591 default: /* unreachable */
6592 goto fail;
6593 }
sewardj2019a972011-03-07 16:04:07 +00006594 } else {
sewardje0dd77e2011-04-27 12:07:01 +00006595 switch (insn->variant.alu.tag) {
6596 case S390_ALU_LSH:
6597 buf = s390_emit_SLL(buf, dst, b2, 0);
6598 break;
6599 case S390_ALU_RSH:
6600 buf = s390_emit_SRL(buf, dst, b2, 0);
6601 break;
6602 case S390_ALU_RSHA:
6603 buf = s390_emit_SRA(buf, dst, b2, 0);
6604 break;
6605 default: /* unreachable */
6606 goto fail;
6607 }
sewardj2019a972011-03-07 16:04:07 +00006608 }
sewardje0dd77e2011-04-27 12:07:01 +00006609 return s390_emit_LGR(buf, b2, R0); /* restore */
sewardj2019a972011-03-07 16:04:07 +00006610 }
6611
6612 switch (insn->size) {
6613 case 1:
6614 /* Move the byte from memory into scratch register r0 */
6615 buf = s390_emit_load_mem(buf, 1, R0, src);
6616
6617 switch (insn->variant.alu.tag) {
6618 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
6619 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
6620 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
6621 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
6622 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
6623 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
6624 case S390_ALU_LSH:
6625 case S390_ALU_RSH:
6626 case S390_ALU_RSHA: ; /* avoid GCC warning */
6627 }
6628 goto fail;
6629
6630 case 2:
6631 switch (src->tag) {
6632 case S390_AMODE_B12:
6633 case S390_AMODE_BX12:
6634 switch (insn->variant.alu.tag) {
6635 case S390_ALU_ADD:
6636 return s390_emit_AH(buf, dst, x, b, d);
6637
6638 case S390_ALU_SUB:
6639 return s390_emit_SH(buf, dst, x, b, d);
6640
6641 case S390_ALU_MUL:
6642 return s390_emit_MH(buf, dst, x, b, d);
6643
6644 /* For bitwise operations: Move two bytes from memory into scratch
6645 register r0; then perform operation */
6646 case S390_ALU_AND:
6647 buf = s390_emit_LH(buf, R0, x, b, d);
6648 return s390_emit_NR(buf, dst, R0);
6649
6650 case S390_ALU_OR:
6651 buf = s390_emit_LH(buf, R0, x, b, d);
6652 return s390_emit_OR(buf, dst, R0);
6653
6654 case S390_ALU_XOR:
6655 buf = s390_emit_LH(buf, R0, x, b, d);
6656 return s390_emit_XR(buf, dst, R0);
6657
6658 case S390_ALU_LSH:
6659 case S390_ALU_RSH:
6660 case S390_ALU_RSHA: ; /* avoid GCC warning */
6661 }
6662 goto fail;
6663
6664 case S390_AMODE_B20:
6665 case S390_AMODE_BX20:
6666 switch (insn->variant.alu.tag) {
6667 case S390_ALU_ADD:
6668 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
6669
6670 case S390_ALU_SUB:
6671 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
6672
6673 case S390_ALU_MUL:
sewardjeae8db52011-03-24 09:01:50 +00006674 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006675
6676 /* For bitwise operations: Move two bytes from memory into scratch
6677 register r0; then perform operation */
6678 case S390_ALU_AND:
6679 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6680 return s390_emit_NR(buf, dst, R0);
6681
6682 case S390_ALU_OR:
6683 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6684 return s390_emit_OR(buf, dst, R0);
6685
6686 case S390_ALU_XOR:
6687 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6688 return s390_emit_XR(buf, dst, R0);
6689
6690 case S390_ALU_LSH:
6691 case S390_ALU_RSH:
6692 case S390_ALU_RSHA: ; /* avoid GCC warning */
6693 }
6694 goto fail;
6695 }
6696 goto fail;
6697
6698 case 4:
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: return s390_emit_A(buf, dst, x, b, d);
6704 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
6705 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
6706 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
6707 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
6708 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
6709 case S390_ALU_LSH:
6710 case S390_ALU_RSH:
6711 case S390_ALU_RSHA: ; /* avoid GCC warning */
6712 }
6713 goto fail;
6714
6715 case S390_AMODE_B20:
6716 case S390_AMODE_BX20:
6717 switch (insn->variant.alu.tag) {
6718 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
6719 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
6720 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
6721 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
6722 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
6723 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
6724 case S390_ALU_LSH:
6725 case S390_ALU_RSH:
6726 case S390_ALU_RSHA: ; /* avoid GCC warning */
6727 }
6728 goto fail;
6729 }
6730 goto fail;
6731
6732 case 8:
6733 switch (insn->variant.alu.tag) {
6734 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
6735 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
6736 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
6737 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
6738 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
6739 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
6740 case S390_ALU_LSH:
6741 case S390_ALU_RSH:
6742 case S390_ALU_RSHA: ; /* avoid GCC warning */
6743 }
6744 goto fail;
6745 }
6746 goto fail;
6747 }
6748
6749 /* 2nd operand is an immediate value */
6750 if (op2.tag == S390_OPND_IMMEDIATE) {
6751 ULong value;
6752
6753 /* No masking of the value is required as it is not sign extended */
6754 value = op2.variant.imm;
6755
6756 switch (insn->size) {
6757 case 1:
6758 case 2:
6759 /* There is no 1-byte opcode. Do the computation in
6760 2 bytes. The extra byte will be ignored. */
6761 switch (insn->variant.alu.tag) {
6762 case S390_ALU_ADD:
6763 return s390_emit_AHI(buf, dst, value);
6764
6765 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00006766 return s390_emit_SLFIw(buf, dst, value);
sewardj2019a972011-03-07 16:04:07 +00006767
6768 case S390_ALU_MUL:
6769 return s390_emit_MHI(buf, dst, value);
6770
6771 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
6772 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
6773 case S390_ALU_XOR:
6774 /* There is no XILL instruction. Load the immediate value into
6775 R0 and combine with the destination register. */
6776 buf = s390_emit_LHI(buf, R0, value);
6777 return s390_emit_XR(buf, dst, R0);
6778
6779 case S390_ALU_LSH:
sewardj3c49aaa2011-04-05 14:00:37 +00006780 return s390_emit_SLL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006781
6782 case S390_ALU_RSH:
sewardj3c49aaa2011-04-05 14:00:37 +00006783 return s390_emit_SRL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006784
6785 case S390_ALU_RSHA:
sewardj3c49aaa2011-04-05 14:00:37 +00006786 return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006787 }
6788 goto fail;
6789
6790 case 4:
6791 switch (insn->variant.alu.tag) {
6792 case S390_ALU_ADD:
6793 if (uint_fits_signed_16bit(value)) {
6794 return s390_emit_AHI(buf, dst, value);
6795 }
6796 return s390_emit_AFIw(buf, dst, value);
6797
6798 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
6799 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
6800 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
6801 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
6802 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
sewardj3c49aaa2011-04-05 14:00:37 +00006803 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
6804 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
6805 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006806 }
6807 goto fail;
6808
6809 case 8:
6810 switch (insn->variant.alu.tag) {
6811 case S390_ALU_ADD:
6812 if (ulong_fits_signed_16bit(value)) {
6813 return s390_emit_AGHI(buf, dst, value);
6814 }
6815 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
6816 return s390_emit_AGFI(buf, dst, value);
6817 }
6818 /* Load constant into R0 then add */
6819 buf = s390_emit_load_64imm(buf, R0, value);
6820 return s390_emit_AGR(buf, dst, R0);
6821
6822 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00006823 if (ulong_fits_unsigned_32bit(value)) {
6824 return s390_emit_SLGFIw(buf, dst, value);
6825 }
sewardj2019a972011-03-07 16:04:07 +00006826 /* Load value into R0; then subtract from destination reg */
6827 buf = s390_emit_load_64imm(buf, R0, value);
6828 return s390_emit_SGR(buf, dst, R0);
6829
6830 case S390_ALU_MUL:
6831 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
6832 return s390_emit_MSGFI(buf, dst, value);
6833 }
6834 /* Load constant into R0 then add */
6835 buf = s390_emit_load_64imm(buf, R0, value);
6836 return s390_emit_MSGR(buf, dst, R0);
6837
6838 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
6839 case S390_ALU_AND:
6840 if (s390_host_has_eimm) {
6841 buf = s390_emit_NIHF(buf, dst, value >> 32);
6842 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
6843 }
6844 /* Load value into R0; then combine with destination reg */
6845 buf = s390_emit_load_64imm(buf, R0, value);
6846 return s390_emit_NGR(buf, dst, R0);
6847
6848 case S390_ALU_OR:
6849 if (s390_host_has_eimm) {
6850 buf = s390_emit_OIHF(buf, dst, value >> 32);
6851 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
6852 }
6853 /* Load value into R0; then combine with destination reg */
6854 buf = s390_emit_load_64imm(buf, R0, value);
6855 return s390_emit_OGR(buf, dst, R0);
6856
6857 case S390_ALU_XOR:
6858 if (s390_host_has_eimm) {
6859 buf = s390_emit_XIHF(buf, dst, value >> 32);
6860 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
6861 }
6862 /* Load value into R0; then combine with destination reg */
6863 buf = s390_emit_load_64imm(buf, R0, value);
6864 return s390_emit_XGR(buf, dst, R0);
6865
sewardj652b56a2011-04-13 15:38:17 +00006866 /* No special considerations for long displacement here. Only the six
6867 least significant bits of VALUE will be taken; all other bits are
6868 ignored. So the DH2 bits are irrelevant and do not influence the
6869 shift operation, independent of whether long-displacement is available
6870 or not. */
sewardj2019a972011-03-07 16:04:07 +00006871 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
6872 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
6873 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
6874 }
6875 goto fail;
6876 }
6877 goto fail;
6878 }
6879
6880 fail:
6881 vpanic("s390_insn_alu_emit");
6882}
6883
6884
6885static UChar *
6886s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
6887 Bool sign_extend)
6888{
sewardj06122e72011-03-28 12:14:48 +00006889 s390_opnd_RMI opnd = insn->variant.unop.src;
sewardj2019a972011-03-07 16:04:07 +00006890
6891 switch (opnd.tag) {
6892 case S390_OPND_REG: {
6893 UChar r1 = hregNumber(insn->variant.unop.dst);
6894 UChar r2 = hregNumber(opnd.variant.reg);
6895
6896 switch (from_size) {
6897 case 1:
6898 /* Widening to a half-word is implemented like widening to a word
6899 because the upper half-word will not be looked at. */
6900 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
6901 if (sign_extend)
6902 return s390_emit_LBRw(buf, r1, r2);
6903 else
6904 return s390_emit_LLCRw(buf, r1, r2);
6905 }
6906 if (insn->size == 8) { /* 8 --> 64 */
6907 if (sign_extend)
6908 return s390_emit_LGBRw(buf, r1, r2);
6909 else
6910 return s390_emit_LLGCRw(buf, r1, r2);
6911 }
6912 goto fail;
6913
6914 case 2:
6915 if (insn->size == 4) { /* 16 --> 32 */
6916 if (sign_extend)
6917 return s390_emit_LHRw(buf, r1, r2);
6918 else
6919 return s390_emit_LLHRw(buf, r1, r2);
6920 }
6921 if (insn->size == 8) { /* 16 --> 64 */
6922 if (sign_extend)
6923 return s390_emit_LGHRw(buf, r1, r2);
6924 else
6925 return s390_emit_LLGHRw(buf, r1, r2);
6926 }
6927 goto fail;
6928
6929 case 4:
6930 if (insn->size == 8) { /* 32 --> 64 */
6931 if (sign_extend)
6932 return s390_emit_LGFR(buf, r1, r2);
6933 else
6934 return s390_emit_LLGFR(buf, r1, r2);
6935 }
6936 goto fail;
6937
6938 default: /* unexpected "from" size */
6939 goto fail;
6940 }
6941 }
6942
6943 case S390_OPND_AMODE: {
6944 UChar r1 = hregNumber(insn->variant.unop.dst);
6945 const s390_amode *src = opnd.variant.am;
6946 UChar b = hregNumber(src->b);
6947 UChar x = hregNumber(src->x);
6948 Int d = src->d;
6949
6950 switch (from_size) {
6951 case 1:
6952 if (insn->size == 4 || insn->size == 2) {
6953 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00006954 return s390_emit_LBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006955 else
6956 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
6957 }
6958 if (insn->size == 8) {
6959 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00006960 return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006961 else
sewardj2019a972011-03-07 16:04:07 +00006962 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
6963 }
6964 goto fail;
6965
6966 case 2:
6967 if (insn->size == 4) { /* 16 --> 32 */
6968 if (sign_extend == 0)
6969 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
6970
6971 switch (src->tag) {
6972 case S390_AMODE_B12:
6973 case S390_AMODE_BX12:
6974 return s390_emit_LH(buf, r1, x, b, d);
6975
6976 case S390_AMODE_B20:
6977 case S390_AMODE_BX20:
6978 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
6979 }
6980 goto fail;
6981 }
6982 if (insn->size == 8) { /* 16 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00006983 if (sign_extend)
6984 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
6985 else
6986 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
6987 }
6988 goto fail;
6989
6990 case 4:
6991 if (insn->size == 8) { /* 32 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00006992 if (sign_extend)
6993 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
6994 else
6995 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
6996 }
6997 goto fail;
6998
6999 default: /* unexpected "from" size */
7000 goto fail;
7001 }
7002 }
7003
7004 case S390_OPND_IMMEDIATE: {
7005 UChar r1 = hregNumber(insn->variant.unop.dst);
7006 ULong value = opnd.variant.imm;
7007
7008 switch (from_size) {
7009 case 1:
7010 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7011 if (sign_extend) {
7012 /* host can do the sign extension to 16-bit; LHI does the rest */
7013 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
7014 } else {
7015 return s390_emit_LHI(buf, r1, value);
7016 }
7017 }
7018 if (insn->size == 8) { /* 8 --> 64 */
7019 if (sign_extend) {
7020 /* host can do the sign extension to 16-bit; LGHI does the rest */
7021 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
7022 } else {
7023 return s390_emit_LGHI(buf, r1, value);
7024 }
7025 }
7026 goto fail;
7027
7028 case 2:
7029 if (insn->size == 4) { /* 16 --> 32 */
7030 return s390_emit_LHI(buf, r1, value);
7031 }
7032 if (insn->size == 8) { /* 16 --> 64 */
7033 if (sign_extend)
7034 return s390_emit_LGHI(buf, r1, value);
7035 else
7036 return s390_emit_LLILL(buf, r1, value);
7037 }
7038 goto fail;
7039
7040 case 4:
7041 if (insn->size == 8) { /* 32 --> 64 */
7042 if (sign_extend)
7043 return s390_emit_LGFIw(buf, r1, value);
7044 else
7045 return s390_emit_LLILFw(buf, r1, value);
7046 }
7047 goto fail;
7048
7049 default: /* unexpected "from" size */
7050 goto fail;
7051 }
7052 }
7053 }
7054
7055 fail:
7056 vpanic("s390_widen_emit");
7057}
7058
7059
7060static UChar *
7061s390_negate_emit(UChar *buf, const s390_insn *insn)
7062{
7063 s390_opnd_RMI opnd;
7064
7065 opnd = insn->variant.unop.src;
7066
7067 switch (opnd.tag) {
7068 case S390_OPND_REG: {
7069 UChar r1 = hregNumber(insn->variant.unop.dst);
7070 UChar r2 = hregNumber(opnd.variant.reg);
7071
7072 switch (insn->size) {
7073 case 1:
7074 case 2:
7075 case 4:
7076 return s390_emit_LCR(buf, r1, r2);
7077
7078 case 8:
7079 return s390_emit_LCGR(buf, r1, r2);
7080
7081 default:
7082 goto fail;
7083 }
7084 }
7085
7086 case S390_OPND_AMODE: {
7087 UChar r1 = hregNumber(insn->variant.unop.dst);
7088
7089 /* Load bytes into scratch register R0, then negate */
7090 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
7091
7092 switch (insn->size) {
7093 case 1:
7094 case 2:
7095 case 4:
7096 return s390_emit_LCR(buf, r1, R0);
7097
7098 case 8:
7099 return s390_emit_LCGR(buf, r1, R0);
7100
7101 default:
7102 goto fail;
7103 }
7104 }
7105
7106 case S390_OPND_IMMEDIATE: {
7107 UChar r1 = hregNumber(insn->variant.unop.dst);
7108 ULong value = opnd.variant.imm;
7109
7110 value = ~value + 1; /* two's complement */
7111
7112 switch (insn->size) {
7113 case 1:
7114 case 2:
7115 /* Load the immediate values as a 4 byte value. That does not hurt as
7116 those extra bytes will not be looked at. Fall through .... */
7117 case 4:
7118 return s390_emit_load_32imm(buf, r1, value);
7119
7120 case 8:
7121 return s390_emit_load_64imm(buf, r1, value);
7122
7123 default:
7124 goto fail;
7125 }
7126 }
7127 }
7128
7129 fail:
7130 vpanic("s390_negate_emit");
7131}
7132
7133
7134static UChar *
7135s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
7136{
7137 switch (insn->variant.unop.tag) {
7138 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
7139 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
7140 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
7141
7142 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
7143 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
7144 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
7145
7146 case S390_NEGATE: return s390_negate_emit(buf, insn);
7147 }
7148
7149 vpanic("s390_insn_unop_emit");
7150}
7151
7152
7153/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
7154 comparisons will have been converted to 4-byte comparisons in
7155 s390_isel_cc and should not occur here. */
7156static UChar *
7157s390_insn_test_emit(UChar *buf, const s390_insn *insn)
7158{
7159 s390_opnd_RMI opnd;
7160
7161 opnd = insn->variant.test.src;
7162
7163 switch (opnd.tag) {
7164 case S390_OPND_REG: {
7165 UInt reg = hregNumber(opnd.variant.reg);
7166
7167 switch (insn->size) {
7168 case 4:
7169 return s390_emit_LTR(buf, reg, reg);
7170
7171 case 8:
7172 return s390_emit_LTGR(buf, reg, reg);
7173
7174 default:
7175 goto fail;
7176 }
7177 }
7178
7179 case S390_OPND_AMODE: {
7180 const s390_amode *am = opnd.variant.am;
7181 UChar b = hregNumber(am->b);
7182 UChar x = hregNumber(am->x);
7183 Int d = am->d;
7184
7185 switch (insn->size) {
7186 case 4:
7187 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
7188
7189 case 8:
7190 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
7191
7192 default:
7193 goto fail;
7194 }
7195 }
7196
7197 case S390_OPND_IMMEDIATE: {
7198 ULong value = opnd.variant.imm;
7199
7200 switch (insn->size) {
7201 case 4:
7202 buf = s390_emit_load_32imm(buf, R0, value);
7203 return s390_emit_LTR(buf, R0, R0);
7204
7205 case 8:
7206 buf = s390_emit_load_64imm(buf, R0, value);
7207 return s390_emit_LTGR(buf, R0, R0);
7208
7209 default:
7210 goto fail;
7211 }
7212 }
7213
7214 default:
7215 goto fail;
7216 }
7217
7218 fail:
7219 vpanic("s390_insn_test_emit");
7220}
7221
7222
7223static UChar *
7224s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
7225{
7226 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
7227 s390_cc_t cond = insn->variant.cc2bool.cond;
7228
7229 /* Make the destination register be 1 or 0, depending on whether
7230 the relevant condition holds. A 64-bit value is computed. */
7231 if (cond == S390_CC_ALWAYS)
7232 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
7233
7234 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
7235 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
7236 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
7237 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
7238 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
7239
7240 return buf;
7241}
7242
7243
7244/* Only 4-byte and 8-byte operands are handled. */
7245static UChar *
7246s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
7247{
7248 UChar r1, r3, b, old;
7249 Int d;
7250 s390_amode *am;
7251
7252 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
7253 r3 = hregNumber(insn->variant.cas.op3);
7254 old= hregNumber(insn->variant.cas.old_mem);
7255 am = insn->variant.cas.op2;
7256 b = hregNumber(am->b);
7257 d = am->d;
7258
7259 switch (insn->size) {
7260 case 4:
7261 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
7262 buf = s390_emit_LR(buf, R0, r1);
7263 if (am->tag == S390_AMODE_B12)
7264 buf = s390_emit_CS(buf, R0, r3, b, d);
7265 else
7266 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
7267 /* Now copy R0 which has the old memory value to OLD */
7268 return s390_emit_LR(buf, old, R0);
7269
7270 case 8:
7271 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
7272 buf = s390_emit_LGR(buf, R0, r1);
7273 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
7274 /* Now copy R0 which has the old memory value to OLD */
7275 return s390_emit_LGR(buf, old, R0);
7276
7277 default:
7278 goto fail;
7279 }
7280
7281 fail:
7282 vpanic("s390_insn_cas_emit");
7283}
7284
7285
florian448cbba2012-06-06 02:26:01 +00007286/* Only 4-byte and 8-byte operands are handled. */
7287static UChar *
7288s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
7289{
sewardja90622a2012-06-19 13:29:00 +00007290 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
florian448cbba2012-06-06 02:26:01 +00007291 Int d;
7292 s390_amode *am;
florianc4aa7ed2012-12-22 15:01:04 +00007293 s390_cdas *cdas = insn->variant.cdas.details;
florian448cbba2012-06-06 02:26:01 +00007294
florianc4aa7ed2012-12-22 15:01:04 +00007295 r1 = hregNumber(cdas->op1_high); /* expected value */
7296 r1p1 = hregNumber(cdas->op1_low); /* expected value */
7297 r3 = hregNumber(cdas->op3_high);
7298 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
7299 old_high = hregNumber(cdas->old_mem_high);
7300 old_low = hregNumber(cdas->old_mem_low);
7301 scratch = hregNumber(cdas->scratch);
7302 am = cdas->op2;
florian448cbba2012-06-06 02:26:01 +00007303 b = hregNumber(am->b);
7304 d = am->d;
7305
7306 vassert(scratch == 1);
7307
7308 switch (insn->size) {
7309 case 4:
7310 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
7311 and let CDS/CDSY clobber it */
7312 buf = s390_emit_LR(buf, R0, r1);
7313 buf = s390_emit_LR(buf, scratch, r1p1);
7314
7315 if (am->tag == S390_AMODE_B12)
7316 buf = s390_emit_CDS(buf, R0, r3, b, d);
7317 else
7318 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
7319
7320 /* Now copy R0,scratch which has the old memory value to OLD */
7321 buf = s390_emit_LR(buf, old_high, R0);
7322 buf = s390_emit_LR(buf, old_low, scratch);
7323 return buf;
7324
7325 case 8:
7326 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
7327 and let CDSG clobber it */
7328 buf = s390_emit_LGR(buf, R0, r1);
7329 buf = s390_emit_LGR(buf, scratch, r1p1);
7330
7331 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
7332
7333 /* Now copy R0,scratch which has the old memory value to OLD */
7334 buf = s390_emit_LGR(buf, old_high, R0);
7335 buf = s390_emit_LGR(buf, old_low, scratch);
7336 return buf;
7337
7338 default:
7339 goto fail;
7340 }
7341
7342 fail:
florianbb5aa782012-12-01 21:29:07 +00007343 vpanic("s390_insn_cdas_emit");
florian448cbba2012-06-06 02:26:01 +00007344}
7345
7346
sewardj2019a972011-03-07 16:04:07 +00007347/* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
7348 comparisons will have been converted to 4-byte comparisons in
7349 s390_isel_cc and should not occur here. */
7350static UChar *
7351s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
7352{
7353 s390_opnd_RMI op2;
7354 HReg op1;
7355 Bool signed_comparison;
7356
7357 op1 = insn->variant.compare.src1;
7358 op2 = insn->variant.compare.src2;
7359 signed_comparison = insn->variant.compare.signed_comparison;
7360
7361 switch (op2.tag) {
7362 case S390_OPND_REG: {
7363 UInt r1 = hregNumber(op1);
7364 UInt r2 = hregNumber(op2.variant.reg);
7365
7366 switch (insn->size) {
7367 case 4:
7368 if (signed_comparison)
7369 return s390_emit_CR(buf, r1, r2);
7370 else
7371 return s390_emit_CLR(buf, r1, r2);
7372
7373 case 8:
7374 if (signed_comparison)
7375 return s390_emit_CGR(buf, r1, r2);
7376 else
7377 return s390_emit_CLGR(buf, r1, r2);
7378
7379 default:
7380 goto fail;
7381 }
7382 }
7383
7384 case S390_OPND_AMODE: {
7385 UChar r1 = hregNumber(op1);
7386 const s390_amode *am = op2.variant.am;
7387 UChar b = hregNumber(am->b);
7388 UChar x = hregNumber(am->x);
7389 Int d = am->d;
7390
7391 switch (insn->size) {
7392 case 4:
7393 switch (am->tag) {
7394 case S390_AMODE_B12:
7395 case S390_AMODE_BX12:
7396 if (signed_comparison)
7397 return s390_emit_C(buf, r1, x, b, d);
7398 else
7399 return s390_emit_CL(buf, r1, x, b, d);
7400
7401 case S390_AMODE_B20:
7402 case S390_AMODE_BX20:
7403 if (signed_comparison)
7404 return s390_emit_CY(buf, r1, x, b, DISP20(d));
7405 else
7406 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
7407 }
7408 goto fail;
7409
7410 case 8:
7411 if (signed_comparison)
7412 return s390_emit_CG(buf, r1, x, b, DISP20(d));
7413 else
7414 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
7415
7416 default:
7417 goto fail;
7418 }
7419 }
7420
7421 case S390_OPND_IMMEDIATE: {
7422 UChar r1 = hregNumber(op1);
7423 ULong value = op2.variant.imm;
7424
7425 switch (insn->size) {
7426 case 4:
7427 if (signed_comparison)
7428 return s390_emit_CFIw(buf, r1, value);
7429 else
7430 return s390_emit_CLFIw(buf, r1, value);
7431
7432 case 8:
florian07d34552012-05-26 01:59:21 +00007433 if (s390_host_has_eimm) {
7434 if (signed_comparison) {
7435 if (ulong_fits_signed_32bit(value))
7436 return s390_emit_CGFI(buf, r1, value);
7437 } else {
7438 if (ulong_fits_unsigned_32bit(value))
7439 return s390_emit_CLGFI(buf, r1, value);
7440 }
7441 }
sewardj2019a972011-03-07 16:04:07 +00007442 buf = s390_emit_load_64imm(buf, R0, value);
7443 if (signed_comparison)
7444 return s390_emit_CGR(buf, r1, R0);
7445 else
7446 return s390_emit_CLGR(buf, r1, R0);
7447
7448 default:
7449 goto fail;
7450 }
7451 }
7452
7453 default:
7454 goto fail;
7455 }
7456
7457 fail:
7458 vpanic("s390_insn_compare_emit");
7459}
7460
7461
7462static UChar *
7463s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
7464{
7465 s390_opnd_RMI op2;
7466 UChar r1;
7467 Bool signed_multiply;
7468
7469 /* The register number identifying the register pair */
7470 r1 = hregNumber(insn->variant.mul.dst_hi);
7471
7472 op2 = insn->variant.mul.op2;
florianc4aa7ed2012-12-22 15:01:04 +00007473 signed_multiply = insn->tag == S390_INSN_SMUL;
sewardj2019a972011-03-07 16:04:07 +00007474
7475 switch (op2.tag) {
7476 case S390_OPND_REG: {
7477 UInt r2 = hregNumber(op2.variant.reg);
7478
7479 switch (insn->size) {
7480 case 1:
7481 case 2:
7482 case 4:
7483 if (signed_multiply)
7484 return s390_emit_MR(buf, r1, r2);
7485 else
7486 return s390_emit_MLR(buf, r1, r2);
7487
7488 case 8:
7489 if (signed_multiply)
7490 vpanic("s390_insn_mul_emit");
7491 else
7492 return s390_emit_MLGR(buf, r1, r2);
7493
7494 default:
7495 goto fail;
7496 }
7497 }
7498
7499 case S390_OPND_AMODE: {
7500 const s390_amode *am = op2.variant.am;
7501 UChar b = hregNumber(am->b);
7502 UChar x = hregNumber(am->x);
7503 Int d = am->d;
7504
7505 switch (insn->size) {
7506 case 1:
7507 case 2:
7508 /* Load bytes into scratch register R0, then multiply */
7509 buf = s390_emit_load_mem(buf, insn->size, R0, am);
7510 if (signed_multiply)
7511 return s390_emit_MR(buf, r1, R0);
7512 else
7513 return s390_emit_MLR(buf, r1, R0);
7514
7515 case 4:
7516 switch (am->tag) {
7517 case S390_AMODE_B12:
7518 case S390_AMODE_BX12:
7519 if (signed_multiply)
7520 return s390_emit_M(buf, r1, x, b, d);
7521 else
7522 return s390_emit_ML(buf, r1, x, b, DISP20(d));
7523
7524 case S390_AMODE_B20:
7525 case S390_AMODE_BX20:
7526 if (signed_multiply)
7527 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
7528 else
sewardjb13a92a2011-04-13 14:44:29 +00007529 return s390_emit_ML(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007530 }
7531 goto fail;
7532
7533 case 8:
7534 if (signed_multiply)
7535 vpanic("s390_insn_mul_emit");
7536 else
7537 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
7538
7539 default:
7540 goto fail;
7541 }
7542 }
7543
7544 case S390_OPND_IMMEDIATE: {
7545 ULong value = op2.variant.imm;
7546
7547 switch (insn->size) {
7548 case 1:
7549 case 2:
7550 case 4:
7551 buf = s390_emit_load_32imm(buf, R0, value);
7552 if (signed_multiply)
7553 return s390_emit_MR(buf, r1, R0);
7554 else
7555 return s390_emit_MLR(buf, r1, R0);
7556
7557 case 8:
7558 buf = s390_emit_load_64imm(buf, R0, value);
7559 if (signed_multiply)
7560 vpanic("s390_insn_mul_emit");
7561 else
7562 return s390_emit_MLGR(buf, r1, R0);
7563
7564 default:
7565 goto fail;
7566 }
7567 }
7568
7569 default:
7570 goto fail;
7571 }
7572
7573 fail:
7574 vpanic("s390_insn_mul_emit");
7575}
7576
7577
7578static UChar *
7579s390_insn_div_emit(UChar *buf, const s390_insn *insn)
7580{
7581 s390_opnd_RMI op2;
7582 UChar r1;
7583 Bool signed_divide;
7584
7585 r1 = hregNumber(insn->variant.div.op1_hi);
7586 op2 = insn->variant.div.op2;
florianc4aa7ed2012-12-22 15:01:04 +00007587 signed_divide = insn->tag == S390_INSN_SDIV;
sewardj2019a972011-03-07 16:04:07 +00007588
7589 switch (op2.tag) {
7590 case S390_OPND_REG: {
7591 UInt r2 = hregNumber(op2.variant.reg);
7592
7593 switch (insn->size) {
7594 case 4:
7595 if (signed_divide)
7596 return s390_emit_DR(buf, r1, r2);
7597 else
7598 return s390_emit_DLR(buf, r1, r2);
7599
7600 case 8:
7601 if (signed_divide)
7602 vpanic("s390_insn_div_emit");
7603 else
7604 return s390_emit_DLGR(buf, r1, r2);
7605
7606 default:
7607 goto fail;
7608 }
7609 }
7610
7611 case S390_OPND_AMODE: {
7612 const s390_amode *am = op2.variant.am;
7613 UChar b = hregNumber(am->b);
7614 UChar x = hregNumber(am->x);
7615 Int d = am->d;
7616
7617 switch (insn->size) {
7618 case 4:
7619 switch (am->tag) {
7620 case S390_AMODE_B12:
7621 case S390_AMODE_BX12:
7622 if (signed_divide)
7623 return s390_emit_D(buf, r1, x, b, d);
7624 else
7625 return s390_emit_DL(buf, r1, x, b, DISP20(d));
7626
7627 case S390_AMODE_B20:
7628 case S390_AMODE_BX20:
sewardjb13a92a2011-04-13 14:44:29 +00007629 if (signed_divide) {
7630 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007631 return s390_emit_DR(buf, r1, R0);
sewardjb13a92a2011-04-13 14:44:29 +00007632 } else
7633 return s390_emit_DL(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007634 }
7635 goto fail;
7636
7637 case 8:
7638 if (signed_divide)
7639 vpanic("s390_insn_div_emit");
7640 else
7641 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
7642
7643 default:
7644 goto fail;
7645 }
7646 }
7647
7648 case S390_OPND_IMMEDIATE: {
7649 ULong value = op2.variant.imm;
7650
7651 switch (insn->size) {
7652 case 4:
7653 buf = s390_emit_load_32imm(buf, R0, value);
7654 if (signed_divide)
7655 return s390_emit_DR(buf, r1, R0);
7656 else
7657 return s390_emit_DLR(buf, r1, R0);
7658
7659 case 8:
7660 buf = s390_emit_load_64imm(buf, R0, value);
7661 if (signed_divide)
7662 vpanic("s390_insn_div_emit");
7663 else
7664 return s390_emit_DLGR(buf, r1, R0);
7665
7666 default:
7667 goto fail;
7668 }
7669 }
7670
7671 default:
7672 goto fail;
7673 }
7674
7675 fail:
7676 vpanic("s390_insn_div_emit");
7677}
7678
7679
7680static UChar *
7681s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
7682{
7683 s390_opnd_RMI op2;
7684 UChar r1;
7685
7686 r1 = hregNumber(insn->variant.divs.rem);
7687 op2 = insn->variant.divs.op2;
7688
7689 switch (op2.tag) {
7690 case S390_OPND_REG: {
7691 UInt r2 = hregNumber(op2.variant.reg);
7692
7693 return s390_emit_DSGR(buf, r1, r2);
7694 }
7695
7696 case S390_OPND_AMODE: {
7697 const s390_amode *am = op2.variant.am;
7698 UChar b = hregNumber(am->b);
7699 UChar x = hregNumber(am->x);
7700 Int d = am->d;
7701
7702 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
7703 }
7704
7705 case S390_OPND_IMMEDIATE: {
7706 ULong value = op2.variant.imm;
7707
7708 buf = s390_emit_load_64imm(buf, R0, value);
7709 return s390_emit_DSGR(buf, r1, R0);
7710 }
7711
7712 default:
7713 goto fail;
7714 }
7715
7716 fail:
7717 vpanic("s390_insn_divs_emit");
7718}
7719
7720
7721static UChar *
sewardj611b06e2011-03-24 08:57:29 +00007722s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
sewardj2019a972011-03-07 16:04:07 +00007723{
7724 s390_opnd_RMI src;
sewardj611b06e2011-03-24 08:57:29 +00007725 UChar r1, r1p1, r2, *p;
sewardj2019a972011-03-07 16:04:07 +00007726
sewardj611b06e2011-03-24 08:57:29 +00007727 r1 = hregNumber(insn->variant.clz.num_bits);
7728 r1p1 = hregNumber(insn->variant.clz.clobber);
sewardj2019a972011-03-07 16:04:07 +00007729
7730 vassert((r1 & 0x1) == 0);
7731 vassert(r1p1 == r1 + 1);
7732
sewardj611b06e2011-03-24 08:57:29 +00007733 p = buf;
7734 src = insn->variant.clz.src;
sewardj2019a972011-03-07 16:04:07 +00007735
sewardj611b06e2011-03-24 08:57:29 +00007736 /* Get operand and move it to r2 */
sewardj2019a972011-03-07 16:04:07 +00007737 switch (src.tag) {
sewardj611b06e2011-03-24 08:57:29 +00007738 case S390_OPND_REG:
7739 r2 = hregNumber(src.variant.reg);
7740 break;
sewardj2019a972011-03-07 16:04:07 +00007741
7742 case S390_OPND_AMODE: {
7743 const s390_amode *am = src.variant.am;
7744 UChar b = hregNumber(am->b);
7745 UChar x = hregNumber(am->x);
7746 Int d = am->d;
7747
sewardj611b06e2011-03-24 08:57:29 +00007748 p = s390_emit_LG(p, R0, x, b, DISP20(d));
7749 r2 = R0;
7750 break;
sewardj2019a972011-03-07 16:04:07 +00007751 }
7752
7753 case S390_OPND_IMMEDIATE: {
7754 ULong value = src.variant.imm;
7755
sewardj611b06e2011-03-24 08:57:29 +00007756 p = s390_emit_load_64imm(p, R0, value);
7757 r2 = R0;
7758 break;
sewardj2019a972011-03-07 16:04:07 +00007759 }
7760
7761 default:
7762 goto fail;
7763 }
7764
sewardj611b06e2011-03-24 08:57:29 +00007765 /* Use FLOGR if you can */
7766 if (s390_host_has_eimm) {
7767 return s390_emit_FLOGR(p, r1, r2);
7768 }
7769
7770 /*
7771 r0 = r2;
7772 r1 = 64;
7773 while (r0 != 0) {
7774 r1 -= 1;
7775 r0 >>= 1;
7776 }
7777 */
7778 p = s390_emit_LTGR(p, R0, r2);
7779 p = s390_emit_LLILL(p, r1, 64);
7780
7781 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
7782 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
7783 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
7784 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
7785 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
7786 (UShort)(-(4 + 6 + 4) / 2));
7787 return p;
7788
sewardj2019a972011-03-07 16:04:07 +00007789 fail:
sewardj611b06e2011-03-24 08:57:29 +00007790 vpanic("s390_insn_clz_emit");
sewardj2019a972011-03-07 16:04:07 +00007791}
7792
7793
7794static UChar *
sewardj2019a972011-03-07 16:04:07 +00007795s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
7796{
7797 s390_cc_t cond;
7798 ULong target;
7799 UChar *ptmp = buf;
7800
7801 cond = insn->variant.helper_call.cond;
7802 target = insn->variant.helper_call.target;
7803
7804 if (cond != S390_CC_ALWAYS) {
7805 /* So we have something like this
7806 if (cond) call X;
7807 Y: ...
7808 We convert this into
7809 if (! cond) goto Y; // BRC opcode; 4 bytes
7810 call X;
7811 Y:
7812 */
7813 /* 4 bytes (a BRC insn) to be filled in here */
7814 buf += 4;
7815 }
7816
7817 /* Load the target address into a register, that
7818 (a) is not used for passing parameters to the helper and
7819 (b) can be clobbered by the callee
florianc9e90e52012-05-27 17:20:47 +00007820 (c) is not special to the BASR insn
7821 r1 is the only choice.
sewardj2019a972011-03-07 16:04:07 +00007822 Also, need to arrange for the return address be put into the
7823 link-register */
7824 buf = s390_emit_load_64imm(buf, 1, target);
7825
7826 /* Stash away the client's FPC register because the helper might change it. */
7827 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
7828
7829 /* Before we can call the helper, we need to save the link register,
7830 because the BASR will overwrite it. We cannot use a register for that.
7831 (a) Volatile registers will be modified by the helper.
7832 (b) For saved registers the client code assumes that they have not
7833 changed after the function returns. So we cannot use it to store
7834 the link register.
7835 In the dispatcher, before calling the client code, we have arranged for
7836 a location on the stack for this purpose. See dispatch-s390x-linux.S. */
7837 buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR
7838 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
7839 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
florian01ed6e72012-05-27 16:52:43 +00007840
7841 /* Move the return value to the destination register */
7842 if (insn->variant.helper_call.dst != INVALID_HREG) {
7843 buf = s390_emit_LGR(buf, hregNumber(insn->variant.helper_call.dst),
7844 S390_REGNO_RETURN_VALUE);
7845 }
7846
sewardj2019a972011-03-07 16:04:07 +00007847 buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR
7848 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
7849 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
7850 S390_OFFSET_SAVED_FPC_C);
7851
7852 if (cond != S390_CC_ALWAYS) {
7853 Int delta = buf - ptmp;
7854
7855 delta >>= 1; /* immediate constant is #half-words */
7856 vassert(delta > 0 && delta < (1 << 16));
7857 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7858 }
7859
7860 return buf;
7861}
7862
7863
7864static UChar *
7865s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
7866{
7867 HReg dst;
7868 s390_opnd_RMI src;
7869 s390_cc_t cond;
7870 UChar *p, *ptmp = 0; /* avoid compiler warnings */
7871
7872 cond = insn->variant.cond_move.cond;
7873 dst = insn->variant.cond_move.dst;
7874 src = insn->variant.cond_move.src;
7875
florian3a3d7f12012-12-03 13:32:05 +00007876 if (cond == S390_CC_NEVER) return buf;
7877
sewardj2019a972011-03-07 16:04:07 +00007878 p = buf;
7879
florianaec8e052012-12-09 17:26:32 +00007880 if (s390_host_has_lsc) {
florian3a3d7f12012-12-03 13:32:05 +00007881 /* LOCx is not the preferred way to implement an unconditional load. */
7882 if (cond != S390_CC_ALWAYS) goto use_branch_insn;
7883
7884 switch (src.tag) {
7885 case S390_OPND_REG:
7886 return s390_emit_LOCGR(p, cond, hregNumber(dst),
7887 hregNumber(src.variant.reg));
7888
7889 case S390_OPND_AMODE: {
7890 const s390_amode *am = src.variant.am;
7891
7892 /* We cannot use LOCx for loads less than 4 bytes. In that case
7893 load into R0 and then use LOCGR. Do the same if the amode uses
7894 an index register. */
7895 if (insn->size < 4 ||
7896 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
7897 p = s390_emit_load_mem(p, insn->size, R0, am);
7898 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
7899 return p;
7900 }
7901
7902 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
7903 vassert(insn->size == 4 || insn->size == 8);
7904
7905 UInt b = hregNumber(am->b);
7906 UInt d = am->d;
7907
7908 if (insn->size == 4) {
7909 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
7910 }
7911 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
7912 }
7913
7914 case S390_OPND_IMMEDIATE: {
7915 ULong value = src.variant.imm;
7916
7917 /* Load value into R0, then use LOCGR */
7918 if (insn->size <= 4) {
7919 p = s390_emit_load_32imm(p, R0, value);
7920 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
7921 }
7922
7923 vassert(insn->size == 8);
7924 p = s390_emit_load_64imm(p, R0, value);
7925 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
7926 }
7927 }
7928 }
7929
7930use_branch_insn:
sewardj2019a972011-03-07 16:04:07 +00007931 /* Branch (if cond fails) over move instrs */
7932 if (cond != S390_CC_ALWAYS) {
7933 /* Don't know how many bytes to jump over yet.
7934 Make space for a BRC instruction (4 bytes) and fill in later. */
7935 ptmp = p; /* to be filled in here */
7936 p += 4;
7937 }
7938
7939 // cond true: move src => dst
7940
7941 switch (src.tag) {
7942 case S390_OPND_REG:
7943 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
7944 break;
7945
7946 case S390_OPND_AMODE:
7947 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
7948 break;
7949
7950 case S390_OPND_IMMEDIATE: {
7951 ULong value = src.variant.imm;
7952 UInt r = hregNumber(dst);
7953
7954 switch (insn->size) {
7955 case 1:
7956 case 2:
7957 /* Load the immediate values as a 4 byte value. That does not hurt as
7958 those extra bytes will not be looked at. Fall through .... */
7959 case 4:
7960 p = s390_emit_load_32imm(p, r, value);
7961 break;
7962
7963 case 8:
7964 p = s390_emit_load_64imm(p, r, value);
7965 break;
7966 }
7967 break;
7968 }
7969
7970 default:
7971 goto fail;
7972 }
7973
7974 if (cond != S390_CC_ALWAYS) {
7975 Int delta = p - ptmp;
7976
7977 delta >>= 1; /* immediate constant is #half-words */
7978 vassert(delta > 0 && delta < (1 << 16));
7979 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7980 }
7981
7982 return p;
7983
7984 fail:
7985 vpanic("s390_insn_cond_move_emit");
7986}
7987
7988
sewardj2019a972011-03-07 16:04:07 +00007989static UChar *
7990s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
7991{
7992 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
7993 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
7994 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +00007995
7996 switch (insn->size) {
7997 case 4:
7998 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00007999 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
8000 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008001 default: goto fail;
8002 }
8003 break;
8004
8005 case 8:
8006 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008007 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
8008 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008009 default: goto fail;
8010 }
8011 break;
8012
8013 default: goto fail;
8014 }
8015
sewardj2019a972011-03-07 16:04:07 +00008016 fail:
8017 vpanic("s390_insn_bfp_triop_emit");
8018}
8019
8020
8021static UChar *
8022s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
8023{
floriancc491a62012-09-10 23:44:37 +00008024 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
8025 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00008026
8027 switch (insn->size) {
8028 case 4:
8029 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008030 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
8031 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
8032 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
8033 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008034 default: goto fail;
8035 }
8036 break;
8037
8038 case 8:
8039 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008040 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
8041 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
8042 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
8043 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008044 default: goto fail;
8045 }
8046 break;
8047
floriancc491a62012-09-10 23:44:37 +00008048 case 16:
8049 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008050 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
8051 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
8052 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
8053 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008054 default: goto fail;
8055 }
8056 break;
8057
sewardj2019a972011-03-07 16:04:07 +00008058 default: goto fail;
8059 }
8060
sewardj2019a972011-03-07 16:04:07 +00008061 fail:
8062 vpanic("s390_insn_bfp_binop_emit");
8063}
8064
8065
8066static UChar *
8067s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
8068{
floriancc491a62012-09-10 23:44:37 +00008069 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
8070 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
sewardj2019a972011-03-07 16:04:07 +00008071
8072 switch (insn->variant.bfp_unop.tag) {
8073 case S390_BFP_ABS:
8074 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008075 case 4: return s390_emit_LPEBR(buf, r1, r2);
8076 case 8: return s390_emit_LPDBR(buf, r1, r2);
8077 case 16: return s390_emit_LPXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008078 default: goto fail;
8079 }
8080 break;
8081
8082 case S390_BFP_NABS:
8083 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008084 case 4: return s390_emit_LNEBR(buf, r1, r2);
8085 case 8: return s390_emit_LNDBR(buf, r1, r2);
8086 case 16: return s390_emit_LNXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008087 default: goto fail;
8088 }
8089 break;
8090
8091 case S390_BFP_NEG:
8092 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008093 case 4: return s390_emit_LCEBR(buf, r1, r2);
8094 case 8: return s390_emit_LCDBR(buf, r1, r2);
8095 case 16: return s390_emit_LCXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008096 default: goto fail;
8097 }
8098 break;
8099
8100 case S390_BFP_SQRT:
8101 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008102 case 4: return s390_emit_SQEBR(buf, r1, r2);
8103 case 8: return s390_emit_SQDBR(buf, r1, r2);
8104 case 16: return s390_emit_SQXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008105 default: goto fail;
8106 }
8107 break;
8108
florian9fcff4c2012-09-10 03:09:04 +00008109 default: goto fail;
8110 }
8111
florian9fcff4c2012-09-10 03:09:04 +00008112 fail:
8113 vpanic("s390_insn_bfp_unop_emit");
8114}
8115
8116
8117static UChar *
8118s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
8119{
floriancc491a62012-09-10 23:44:37 +00008120 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
8121 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
florian125e20d2012-10-07 15:42:37 +00008122 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
florian2c74d242012-09-12 19:38:42 +00008123 /* The IEEE-inexact-exception control is not modelled. So the
8124 m4 field is 0 (which is what GCC does, too) */
8125 const UInt m4 = 0;
florian9fcff4c2012-09-10 03:09:04 +00008126
florian9fcff4c2012-09-10 03:09:04 +00008127 switch (insn->variant.bfp_convert.tag) {
floriancc491a62012-09-10 23:44:37 +00008128 /* Convert to fixed */
florian9fcff4c2012-09-10 03:09:04 +00008129 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
8130 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008131 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008132 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
8133 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008134 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008135
floriancc491a62012-09-10 23:44:37 +00008136 /* Convert to logical */
florian2c74d242012-09-12 19:38:42 +00008137 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
8138 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
8139 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
8140 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
8141 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
8142 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008143
florian2c74d242012-09-12 19:38:42 +00008144 /* Convert from fixed */
8145 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
8146 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
8147 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
8148 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
8149 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
8150 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
8151
8152 /* Convert from logical */
8153 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
8154 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
8155 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
8156 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
8157 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
8158 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
8159
8160 /* Load lengthened */
8161 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008162 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
8163 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008164
florian2c74d242012-09-12 19:38:42 +00008165 /* Load rounded */
8166 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
8167 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
8168 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008169
sewardj2019a972011-03-07 16:04:07 +00008170 default: goto fail;
8171 }
8172
sewardj2019a972011-03-07 16:04:07 +00008173 fail:
florian9fcff4c2012-09-10 03:09:04 +00008174 vpanic("s390_insn_bfp_convert_emit");
sewardj2019a972011-03-07 16:04:07 +00008175}
8176
8177
8178static UChar *
8179s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
8180{
8181 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +00008182 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
8183 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00008184
8185 switch (insn->size) {
floriancc491a62012-09-10 23:44:37 +00008186 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
8187 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
8188 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
sewardj2019a972011-03-07 16:04:07 +00008189 default: goto fail;
8190 }
8191
8192 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
8193
8194 fail:
8195 vpanic("s390_insn_bfp_compare_emit");
8196}
8197
8198
8199static UChar *
florian12390202012-11-10 22:34:14 +00008200s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
8201{
florianc4aa7ed2012-12-22 15:01:04 +00008202 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
8203
8204 UInt r1 = hregNumber(dfp_binop->dst_hi);
8205 UInt r2 = hregNumber(dfp_binop->op2_hi);
8206 UInt r3 = hregNumber(dfp_binop->op3_hi);
8207 UInt m4 = hregNumber(dfp_binop->rounding_mode);
florian12390202012-11-10 22:34:14 +00008208
8209 switch (insn->size) {
8210 case 8:
florianc4aa7ed2012-12-22 15:01:04 +00008211 switch (dfp_binop->tag) {
florian12390202012-11-10 22:34:14 +00008212 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2); break;
8213 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2); break;
8214 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2); break;
8215 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2); break;
8216 default: goto fail;
8217 }
8218 break;
floriane38f6412012-12-21 17:32:12 +00008219
8220 case 16:
florianc4aa7ed2012-12-22 15:01:04 +00008221 switch (dfp_binop->tag) {
floriane38f6412012-12-21 17:32:12 +00008222 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2);
8223 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2);
8224 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2);
8225 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2);
8226 default: goto fail;
8227 }
8228 break;
8229
florian12390202012-11-10 22:34:14 +00008230 default: goto fail;
8231 }
8232
8233 fail:
8234 vpanic("s390_insn_dfp_binop_emit");
8235}
8236
8237
8238static UChar *
floriane38f6412012-12-21 17:32:12 +00008239s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
8240{
8241 UInt dst = hregNumber(insn->variant.dfp_compare.dst);
8242 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi);
8243 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi);
8244
8245 switch (insn->size) {
florian20c6bca2012-12-26 17:47:19 +00008246 case 8:
8247 switch(insn->variant.dfp_compare.tag) {
8248 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break;
8249 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
8250 default: goto fail;
8251 }
8252 break;
8253
8254 case 16:
8255 switch(insn->variant.dfp_compare.tag) {
8256 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break;
8257 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
8258 default: goto fail;
8259 }
8260 break;
8261
floriane38f6412012-12-21 17:32:12 +00008262 default: goto fail;
8263 }
8264
8265 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
8266
8267 fail:
8268 vpanic("s390_insn_dfp_compare_emit");
8269}
8270
8271
8272static UChar *
8273s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
8274{
8275 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
8276 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi);
8277 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
8278 /* The IEEE-inexact-exception control is not modelled. So the
8279 m4 field is 0 (which is what GCC does, too) */
8280 const UInt m4 = 0;
8281
8282 switch (insn->variant.dfp_convert.tag) {
8283
8284 /* Load lengthened */
8285 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2);
8286 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2);
8287
8288 /* Load rounded */
8289 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2);
8290 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2);
8291
8292 default: goto fail;
8293 }
8294
8295 fail:
8296 vpanic("s390_insn_dfp_convert_emit");
8297}
8298
8299
8300static UChar *
sewardja52e37e2011-04-28 18:48:06 +00008301s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
8302{
8303 return s390_emit_BCR(buf, 0xF, 0x0);
8304}
8305
8306
florianad43b3a2012-02-20 15:01:14 +00008307static UChar *
florian09bbba82012-12-11 04:09:43 +00008308s390_insn_mzero_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00008309{
florian09bbba82012-12-11 04:09:43 +00008310 s390_amode *am = insn->variant.mzero.dst;
8311
8312 return s390_emit_XC(buf, insn->size - 1, am->b, am->d, am->b, am->d);
florianad43b3a2012-02-20 15:01:14 +00008313}
8314
8315
8316static UChar *
florianf85fe3e2012-12-22 02:28:25 +00008317s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00008318{
florianf85fe3e2012-12-22 02:28:25 +00008319 s390_amode *am = insn->variant.madd.dst;
8320
8321 if (insn->size == 4) {
8322 return s390_emit_ASI(buf, insn->variant.madd.delta, am->b,
8323 DISP20(am->d));
8324 }
8325
8326 return s390_emit_AGSI(buf, insn->variant.madd.delta, am->b, DISP20(am->d));
florianad43b3a2012-02-20 15:01:14 +00008327}
8328
8329
florian2c74d242012-09-12 19:38:42 +00008330static UChar *
florian125e20d2012-10-07 15:42:37 +00008331s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
florian2c74d242012-09-12 19:38:42 +00008332{
florian125e20d2012-10-07 15:42:37 +00008333 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00008334
8335 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
8336 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
8337 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
8338
8339 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
8340 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
florian6d8e26e2012-09-12 19:52:16 +00008341 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
florian2c74d242012-09-12 19:38:42 +00008342
8343 return buf;
8344}
8345
8346
florianc8e4f562012-10-27 16:19:31 +00008347static UChar *
8348s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
8349{
8350 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
8351
8352 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
8353 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
8354 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
8355
8356 /* DFP rounding mode is set at bit position 25:27 in FPC register */
8357 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
8358 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
8359 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
8360 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
8361
8362 return buf;
8363}
8364
8365
florian8844a632012-04-13 04:04:06 +00008366/* Define convenience functions needed for translation chaining.
8367 Any changes need to be applied to the functions in concert. */
8368
florian1c857042012-04-15 04:11:07 +00008369static __inline__ Bool
8370s390_insn_is_BRCL(const UChar *p, UChar condition)
8371{
8372 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
8373}
8374
8375static __inline__ Bool
8376s390_insn_is_BR(const UChar *p, UChar reg)
8377{
8378 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
8379}
8380
florianebaf8d92012-04-22 17:38:46 +00008381
8382/* The length of the BASR insn */
8383#define S390_BASR_LEN 2
8384
florian1c857042012-04-15 04:11:07 +00008385
florian8844a632012-04-13 04:04:06 +00008386/* Load the 64-bit VALUE into REG. Note that this function must NOT
8387 optimise the generated code by looking at the value. I.e. using
floriane09e8bb2012-05-07 03:28:18 +00008388 LGHI if value == 0 would be very wrong. */
florian8844a632012-04-13 04:04:06 +00008389static UChar *
8390s390_tchain_load64(UChar *buf, UChar regno, ULong value)
8391{
florian1c857042012-04-15 04:11:07 +00008392 UChar *begin = buf;
8393
florian1c2b4db2012-04-22 17:46:31 +00008394 if (s390_host_has_eimm) {
8395 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
8396 buf = s390_emit_IIHF(buf, regno, value >> 32);
8397 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
8398 } else {
8399 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
8400 value >>= 16;
8401 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
8402 value >>= 16;
8403 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
8404 value >>= 16;
8405 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
8406 }
florian8844a632012-04-13 04:04:06 +00008407
florian1c857042012-04-15 04:11:07 +00008408 vassert(buf - begin == s390_tchain_load64_len());
8409
florian8844a632012-04-13 04:04:06 +00008410 return buf;
8411}
8412
8413/* Return number of bytes generated by s390_tchain_load64 */
8414static UInt
8415s390_tchain_load64_len(void)
8416{
florian1c2b4db2012-04-22 17:46:31 +00008417 if (s390_host_has_eimm) {
8418 return 6 + 6; /* IIHF + IILF */
8419 }
florianebaf8d92012-04-22 17:38:46 +00008420 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
florian8844a632012-04-13 04:04:06 +00008421}
8422
8423/* Verify that CODE is the code sequence generated by s390_tchain_load64
8424 to load VALUE into REGNO. Return pointer to the byte following the
8425 insn sequence. */
8426static const UChar *
8427s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
8428{
8429 UInt regmask = regno << 4;
8430 UInt hw;
8431
florian1c2b4db2012-04-22 17:46:31 +00008432 if (s390_host_has_eimm) {
8433 /* Check for IIHF */
8434 vassert(code[0] == 0xC0);
8435 vassert(code[1] == (0x08 | regmask));
8436 vassert(*(const UInt *)&code[2] == (value >> 32));
8437 /* Check for IILF */
8438 vassert(code[6] == 0xC0);
8439 vassert(code[7] == (0x09 | regmask));
8440 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
8441 } else {
8442 /* Check for IILL */
8443 hw = value & 0xFFFF;
8444 vassert(code[0] == 0xA5);
8445 vassert(code[1] == (0x03 | regmask));
8446 vassert(code[2] == (hw >> 8));
8447 vassert(code[3] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00008448
florian1c2b4db2012-04-22 17:46:31 +00008449 /* Check for IILH */
8450 hw = (value >> 16) & 0xFFFF;
8451 vassert(code[4] == 0xA5);
8452 vassert(code[5] == (0x02 | regmask));
8453 vassert(code[6] == (hw >> 8));
8454 vassert(code[7] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00008455
florian1c2b4db2012-04-22 17:46:31 +00008456 /* Check for IIHL */
8457 hw = (value >> 32) & 0xFFFF;
8458 vassert(code[8] == 0xA5);
8459 vassert(code[9] == (0x01 | regmask));
8460 vassert(code[10] == (hw >> 8));
8461 vassert(code[11] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00008462
florian1c2b4db2012-04-22 17:46:31 +00008463 /* Check for IIHH */
8464 hw = (value >> 48) & 0xFFFF;
8465 vassert(code[12] == 0xA5);
8466 vassert(code[13] == (0x00 | regmask));
8467 vassert(code[14] == (hw >> 8));
8468 vassert(code[15] == (hw & 0xFF));
8469 }
florian8844a632012-04-13 04:04:06 +00008470
florian1c857042012-04-15 04:11:07 +00008471 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00008472}
8473
8474/* CODE points to the code sequence as generated by s390_tchain_load64.
florian5ea257b2012-09-29 17:05:46 +00008475 Change the loaded value to IMM64. Return pointer to the byte following
florian8844a632012-04-13 04:04:06 +00008476 the patched code sequence. */
8477static UChar *
8478s390_tchain_patch_load64(UChar *code, ULong imm64)
8479{
florian1c2b4db2012-04-22 17:46:31 +00008480 if (s390_host_has_eimm) {
8481 /* Patch IIHF */
8482 *(UInt *)&code[2] = imm64 >> 32;
8483 /* Patch IILF */
8484 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
8485 } else {
8486 code[3] = imm64 & 0xFF; imm64 >>= 8;
8487 code[2] = imm64 & 0xFF; imm64 >>= 8;
8488 code[7] = imm64 & 0xFF; imm64 >>= 8;
8489 code[6] = imm64 & 0xFF; imm64 >>= 8;
8490 code[11] = imm64 & 0xFF; imm64 >>= 8;
8491 code[10] = imm64 & 0xFF; imm64 >>= 8;
8492 code[15] = imm64 & 0xFF; imm64 >>= 8;
8493 code[14] = imm64 & 0xFF; imm64 >>= 8;
8494 }
florian8844a632012-04-13 04:04:06 +00008495
florian1c857042012-04-15 04:11:07 +00008496 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00008497}
8498
8499
8500/* NB: what goes on here has to be very closely coordinated with the
8501 chainXDirect_S390 and unchainXDirect_S390 below. */
8502static UChar *
8503s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
8504 void *disp_cp_chain_me_to_slowEP,
8505 void *disp_cp_chain_me_to_fastEP)
8506{
8507 /* We're generating chain-me requests here, so we need to be
8508 sure this is actually allowed -- no-redir translations can't
8509 use chain-me's. Hence: */
8510 vassert(disp_cp_chain_me_to_slowEP != NULL);
8511 vassert(disp_cp_chain_me_to_fastEP != NULL);
8512
8513 /* Use ptmp for backpatching conditional jumps. */
8514 UChar *ptmp = buf;
8515
8516 /* First off, if this is conditional, create a conditional
8517 jump over the rest of it. */
8518 s390_cc_t cond = insn->variant.xdirect.cond;
8519
8520 if (cond != S390_CC_ALWAYS) {
8521 /* So we have something like this
8522 if (cond) do_xdirect;
8523 Y: ...
8524 We convert this into
8525 if (! cond) goto Y; // BRC opcode; 4 bytes
8526 do_xdirect;
8527 Y:
8528 */
8529 /* 4 bytes (a BRC insn) to be filled in here */
8530 buf += 4;
8531 }
8532
8533 /* Update the guest IA. */
8534 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
8535
8536 const s390_amode *amode = insn->variant.xdirect.guest_IA;
florianbf516d12012-04-21 15:53:13 +00008537 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00008538 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008539 UInt d = amode->d;
8540
florianbf516d12012-04-21 15:53:13 +00008541 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00008542
florian8844a632012-04-13 04:04:06 +00008543 /* Load the chosen entry point into the scratch reg */
8544 void *disp_cp_chain_me;
8545
8546 disp_cp_chain_me =
8547 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
8548 : disp_cp_chain_me_to_slowEP;
florianebaf8d92012-04-22 17:38:46 +00008549 /* Get the address of the beginning of the load64 code sequence into %r1.
8550 Do not change the register! This is part of the protocol with the
8551 dispatcher. */
8552 buf = s390_emit_BASR(buf, 1, R0);
florian8844a632012-04-13 04:04:06 +00008553
florianebaf8d92012-04-22 17:38:46 +00008554 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
florian8844a632012-04-13 04:04:06 +00008555 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
8556 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
8557
florianebaf8d92012-04-22 17:38:46 +00008558 /* goto *tchain_scratch */
8559 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00008560
8561 /* --- END of PATCHABLE BYTES --- */
8562
8563 /* Fix up the conditional jump, if there was one. */
8564 if (cond != S390_CC_ALWAYS) {
8565 Int delta = buf - ptmp;
8566
8567 delta >>= 1; /* immediate constant is #half-words */
8568 vassert(delta > 0 && delta < (1 << 16));
8569 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8570 }
8571
8572 return buf;
8573}
8574
8575/* Return the number of patchable bytes from an xdirect insn. */
8576static UInt
8577s390_xdirect_patchable_len(void)
8578{
florianebaf8d92012-04-22 17:38:46 +00008579 return s390_tchain_load64_len() + S390_BASR_LEN;
florian8844a632012-04-13 04:04:06 +00008580}
8581
8582
8583static UChar *
8584s390_insn_xindir_emit(UChar *buf, const s390_insn *insn, void *disp_cp_xindir)
8585{
8586 /* We're generating transfers that could lead indirectly to a
8587 chain-me, so we need to be sure this is actually allowed --
8588 no-redir translations are not allowed to reach normal
8589 translations without going through the scheduler. That means
8590 no XDirects or XIndirs out from no-redir translations.
8591 Hence: */
8592 vassert(disp_cp_xindir != NULL);
8593
8594 /* Use ptmp for backpatching conditional jumps. */
8595 UChar *ptmp = buf;
8596
8597 /* First off, if this is conditional, create a conditional
8598 jump over the rest of it. */
8599 s390_cc_t cond = insn->variant.xdirect.cond;
8600
8601 if (cond != S390_CC_ALWAYS) {
8602 /* So we have something like this
8603 if (cond) do_xdirect;
8604 Y: ...
8605 We convert this into
8606 if (! cond) goto Y; // BRC opcode; 4 bytes
8607 do_xdirect;
8608 Y:
8609 */
8610 /* 4 bytes (a BRC insn) to be filled in here */
8611 buf += 4;
8612 }
8613
8614 /* Update the guest IA with the address in xdirect.dst. */
florian7346c7a2012-04-13 21:14:24 +00008615 const s390_amode *amode = insn->variant.xindir.guest_IA;
florian8844a632012-04-13 04:04:06 +00008616
florianbf516d12012-04-21 15:53:13 +00008617 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00008618 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008619 UInt d = amode->d;
florian7346c7a2012-04-13 21:14:24 +00008620 UInt regno = hregNumber(insn->variant.xindir.dst);
florian8844a632012-04-13 04:04:06 +00008621
florianbf516d12012-04-21 15:53:13 +00008622 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00008623
8624 /* load tchain_scratch, #disp_indir */
8625 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
8626 Ptr_to_ULong(disp_cp_xindir));
florianebaf8d92012-04-22 17:38:46 +00008627 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00008628 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
8629
8630 /* Fix up the conditional jump, if there was one. */
8631 if (cond != S390_CC_ALWAYS) {
8632 Int delta = buf - ptmp;
8633
8634 delta >>= 1; /* immediate constant is #half-words */
8635 vassert(delta > 0 && delta < (1 << 16));
8636 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8637 }
8638
8639 return buf;
8640}
8641
8642static UChar *
8643s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
8644 void *disp_cp_xassisted)
8645{
8646 /* Use ptmp for backpatching conditional jumps. */
8647 UChar *ptmp = buf;
8648
8649 /* First off, if this is conditional, create a conditional
8650 jump over the rest of it. */
8651 s390_cc_t cond = insn->variant.xdirect.cond;
8652
8653 if (cond != S390_CC_ALWAYS) {
8654 /* So we have something like this
8655 if (cond) do_xdirect;
8656 Y: ...
8657 We convert this into
8658 if (! cond) goto Y; // BRC opcode; 4 bytes
8659 do_xdirect;
8660 Y:
8661 */
8662 /* 4 bytes (a BRC insn) to be filled in here */
8663 buf += 4;
8664 }
8665
8666 /* Update the guest IA with the address in xassisted.dst. */
8667 const s390_amode *amode = insn->variant.xassisted.guest_IA;
8668
florianbf516d12012-04-21 15:53:13 +00008669 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00008670 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008671 UInt d = amode->d;
8672 UInt regno = hregNumber(insn->variant.xassisted.dst);
8673
florianbf516d12012-04-21 15:53:13 +00008674 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00008675
8676 UInt trcval = 0;
8677
8678 switch (insn->variant.xassisted.kind) {
8679 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
8680 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
florian8844a632012-04-13 04:04:06 +00008681 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
8682 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
florian4e0083e2012-08-26 03:41:56 +00008683 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
florian8844a632012-04-13 04:04:06 +00008684 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
8685 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
8686 case Ijk_TInval: trcval = VEX_TRC_JMP_TINVAL; break;
8687 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
8688 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
8689 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
8690 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
8691 /* We don't expect to see the following being assisted. */
8692 case Ijk_Ret:
8693 case Ijk_Call:
8694 /* fallthrough */
8695 default:
8696 ppIRJumpKind(insn->variant.xassisted.kind);
8697 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
8698 }
8699
8700 vassert(trcval != 0);
8701
8702 /* guest_state_pointer = trcval */
8703 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
8704
8705 /* load tchain_scratch, #disp_assisted */
8706 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
8707 Ptr_to_ULong(disp_cp_xassisted));
8708
florianebaf8d92012-04-22 17:38:46 +00008709 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00008710 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
8711
8712 /* Fix up the conditional jump, if there was one. */
8713 if (cond != S390_CC_ALWAYS) {
8714 Int delta = buf - ptmp;
8715
8716 delta >>= 1; /* immediate constant is #half-words */
8717 vassert(delta > 0 && delta < (1 << 16));
8718 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8719 }
8720
8721 return buf;
8722}
8723
8724
8725/* Pseudo code:
8726
8727 guest_state[host_EvC_COUNTER] -= 1;
8728 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
8729 goto guest_state[host_EvC_FAILADDR];
8730 nofail: ;
8731
8732 The dispatch counter is a 32-bit value. */
8733static UChar *
8734s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn)
8735{
8736 s390_amode *amode;
florianbf516d12012-04-21 15:53:13 +00008737 UInt b, d;
florian8844a632012-04-13 04:04:06 +00008738 UChar *code_begin, *code_end;
8739
8740 code_begin = buf;
8741
8742 amode = insn->variant.evcheck.counter;
florianbf516d12012-04-21 15:53:13 +00008743 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00008744 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008745 d = amode->d;
8746
8747 /* Decrement the dispatch counter in the guest state */
florian0e047d62012-04-21 16:06:04 +00008748 if (s390_host_has_gie) {
8749 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
8750 } else {
8751 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
8752 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
8753 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
8754 }
florian8844a632012-04-13 04:04:06 +00008755
8756 /* Jump over the next insn if >= 0 */
8757 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
8758
8759 /* Computed goto to fail_address */
8760 amode = insn->variant.evcheck.fail_addr;
8761 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00008762 d = amode->d;
florianbf516d12012-04-21 15:53:13 +00008763 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
florian8844a632012-04-13 04:04:06 +00008764 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
8765
8766 code_end = buf;
8767
8768 /* Make sure the size of the generated code is identical to the size
8769 returned by evCheckSzB_S390 */
8770 vassert(evCheckSzB_S390() == code_end - code_begin);
8771
8772 return buf;
8773}
8774
8775
8776static UChar *
8777s390_insn_profinc_emit(UChar *buf,
8778 const s390_insn *insn __attribute__((unused)))
8779{
8780 /* Generate a code template to increment a memory location whose
8781 address will be known later as an immediate value. This code
8782 template will be patched once the memory location is known.
8783 For now we do this with address == 0. */
8784 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
florian0e047d62012-04-21 16:06:04 +00008785 if (s390_host_has_gie) {
8786 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8787 } else {
8788 buf = s390_emit_LGHI(buf, R0, 1);
8789 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8790 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8791 }
florian8844a632012-04-13 04:04:06 +00008792
8793 return buf;
8794}
8795
8796
sewardj2019a972011-03-07 16:04:07 +00008797Int
florian8844a632012-04-13 04:04:06 +00008798emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, s390_insn *insn,
8799 Bool mode64, void *disp_cp_chain_me_to_slowEP,
8800 void *disp_cp_chain_me_to_fastEP, void *disp_cp_xindir,
8801 void *disp_cp_xassisted)
sewardj2019a972011-03-07 16:04:07 +00008802{
8803 UChar *end;
8804
florianc4aa7ed2012-12-22 15:01:04 +00008805 /* Used to be 48 bytes. Make sure it stays low */
8806 vassert(sizeof(s390_insn) == 32);
8807
sewardj2019a972011-03-07 16:04:07 +00008808 switch (insn->tag) {
8809 case S390_INSN_LOAD:
8810 end = s390_insn_load_emit(buf, insn);
8811 break;
8812
8813 case S390_INSN_STORE:
8814 end = s390_insn_store_emit(buf, insn);
8815 break;
8816
8817 case S390_INSN_MOVE:
8818 end = s390_insn_move_emit(buf, insn);
8819 break;
8820
8821 case S390_INSN_COND_MOVE:
8822 end = s390_insn_cond_move_emit(buf, insn);
8823 break;
8824
8825 case S390_INSN_LOAD_IMMEDIATE:
8826 end = s390_insn_load_immediate_emit(buf, insn);
8827 break;
8828
8829 case S390_INSN_ALU:
8830 end = s390_insn_alu_emit(buf, insn);
8831 break;
8832
florianc4aa7ed2012-12-22 15:01:04 +00008833 case S390_INSN_SMUL:
8834 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +00008835 end = s390_insn_mul_emit(buf, insn);
8836 break;
8837
florianc4aa7ed2012-12-22 15:01:04 +00008838 case S390_INSN_SDIV:
8839 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +00008840 end = s390_insn_div_emit(buf, insn);
8841 break;
8842
8843 case S390_INSN_DIVS:
8844 end = s390_insn_divs_emit(buf, insn);
8845 break;
8846
sewardj611b06e2011-03-24 08:57:29 +00008847 case S390_INSN_CLZ:
8848 end = s390_insn_clz_emit(buf, insn);
sewardj2019a972011-03-07 16:04:07 +00008849 break;
8850
8851 case S390_INSN_UNOP:
8852 end = s390_insn_unop_emit(buf, insn);
8853 break;
8854
8855 case S390_INSN_TEST:
8856 end = s390_insn_test_emit(buf, insn);
8857 break;
8858
8859 case S390_INSN_CC2BOOL:
8860 end = s390_insn_cc2bool_emit(buf, insn);
8861 break;
8862
8863 case S390_INSN_CAS:
8864 end = s390_insn_cas_emit(buf, insn);
8865 break;
8866
florian448cbba2012-06-06 02:26:01 +00008867 case S390_INSN_CDAS:
8868 end = s390_insn_cdas_emit(buf, insn);
8869 break;
8870
sewardj2019a972011-03-07 16:04:07 +00008871 case S390_INSN_COMPARE:
8872 end = s390_insn_compare_emit(buf, insn);
8873 break;
8874
sewardj2019a972011-03-07 16:04:07 +00008875 case S390_INSN_HELPER_CALL:
8876 end = s390_insn_helper_call_emit(buf, insn);
8877 break;
8878
8879 case S390_INSN_BFP_TRIOP:
8880 end = s390_insn_bfp_triop_emit(buf, insn);
8881 break;
8882
8883 case S390_INSN_BFP_BINOP:
8884 end = s390_insn_bfp_binop_emit(buf, insn);
8885 break;
8886
8887 case S390_INSN_BFP_UNOP:
8888 end = s390_insn_bfp_unop_emit(buf, insn);
8889 break;
8890
8891 case S390_INSN_BFP_COMPARE:
8892 end = s390_insn_bfp_compare_emit(buf, insn);
8893 break;
8894
florian9fcff4c2012-09-10 03:09:04 +00008895 case S390_INSN_BFP_CONVERT:
8896 end = s390_insn_bfp_convert_emit(buf, insn);
8897 break;
8898
florian12390202012-11-10 22:34:14 +00008899 case S390_INSN_DFP_BINOP:
8900 end = s390_insn_dfp_binop_emit(buf, insn);
8901 break;
8902
floriane38f6412012-12-21 17:32:12 +00008903 case S390_INSN_DFP_COMPARE:
8904 end = s390_insn_dfp_compare_emit(buf, insn);
8905 break;
8906
8907 case S390_INSN_DFP_CONVERT:
8908 end = s390_insn_dfp_convert_emit(buf, insn);
8909 break;
8910
sewardja52e37e2011-04-28 18:48:06 +00008911 case S390_INSN_MFENCE:
8912 end = s390_insn_mfence_emit(buf, insn);
8913 break;
8914
florian09bbba82012-12-11 04:09:43 +00008915 case S390_INSN_MZERO:
8916 end = s390_insn_mzero_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +00008917 break;
8918
florianf85fe3e2012-12-22 02:28:25 +00008919 case S390_INSN_MADD:
8920 end = s390_insn_madd_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +00008921 break;
8922
florian125e20d2012-10-07 15:42:37 +00008923 case S390_INSN_SET_FPC_BFPRM:
8924 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
florian2c74d242012-09-12 19:38:42 +00008925 break;
8926
florianc8e4f562012-10-27 16:19:31 +00008927 case S390_INSN_SET_FPC_DFPRM:
8928 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
8929 break;
8930
florian8844a632012-04-13 04:04:06 +00008931 case S390_INSN_PROFINC:
8932 end = s390_insn_profinc_emit(buf, insn);
8933 /* Tell the caller .. */
8934 vassert(*is_profinc == False);
8935 *is_profinc = True;
8936 break;
8937
8938 case S390_INSN_EVCHECK:
8939 end = s390_insn_evcheck_emit(buf, insn);
8940 break;
8941
8942 case S390_INSN_XDIRECT:
8943 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
8944 disp_cp_chain_me_to_fastEP);
8945 break;
8946
8947 case S390_INSN_XINDIR:
8948 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
8949 break;
8950
8951 case S390_INSN_XASSISTED:
8952 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
8953 break;
8954
sewardj2019a972011-03-07 16:04:07 +00008955 default:
florian616458b2012-03-25 16:17:18 +00008956 vpanic("emit_S390Instr");
sewardj2019a972011-03-07 16:04:07 +00008957 }
8958
8959 vassert(end - buf <= nbuf);
8960
8961 return end - buf;
8962}
8963
8964
florian8844a632012-04-13 04:04:06 +00008965/* Return the number of bytes emitted for an S390_INSN_EVCHECK.
8966 See s390_insn_evcheck_emit */
8967Int
8968evCheckSzB_S390(void)
8969{
florian0e047d62012-04-21 16:06:04 +00008970 return s390_host_has_gie ? 18 : 24;
florian8844a632012-04-13 04:04:06 +00008971}
8972
8973
8974/* Patch the counter address into CODE_TO_PATCH as previously
8975 generated by s390_insn_profinc_emit. */
8976VexInvalRange
8977patchProfInc_S390(void *code_to_patch, ULong *location_of_counter)
8978{
8979 vassert(sizeof(ULong *) == 8);
8980
8981 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
8982
florian5ea257b2012-09-29 17:05:46 +00008983 UChar *p = s390_tchain_patch_load64(code_to_patch,
8984 Ptr_to_ULong(location_of_counter));
florian8844a632012-04-13 04:04:06 +00008985
florian5ea257b2012-09-29 17:05:46 +00008986 UInt len = p - (UChar *)code_to_patch;
8987 VexInvalRange vir = { (HWord)code_to_patch, len };
florian8844a632012-04-13 04:04:06 +00008988 return vir;
8989}
8990
8991
8992/* NB: what goes on here has to be very closely coordinated with the
8993 s390_insn_xdirect_emit code above. */
8994VexInvalRange
8995chainXDirect_S390(void *place_to_chain,
8996 void *disp_cp_chain_me_EXPECTED,
8997 void *place_to_jump_to)
8998{
florianebaf8d92012-04-22 17:38:46 +00008999 /* What we're expecting to see @ PLACE_TO_CHAIN is:
florian8844a632012-04-13 04:04:06 +00009000
florianebaf8d92012-04-22 17:38:46 +00009001 load tchain_scratch, #disp_cp_chain_me_EXPECTED
9002 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009003 */
9004 const UChar *next;
9005 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
9006 Ptr_to_ULong(disp_cp_chain_me_EXPECTED));
florianebaf8d92012-04-22 17:38:46 +00009007 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +00009008
9009 /* And what we want to change it to is either:
9010 (general case):
9011
florianebaf8d92012-04-22 17:38:46 +00009012 load tchain_scratch, #place_to_jump_to
9013 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009014
9015 ---OR---
9016
9017 in the case where the displacement is small enough
9018
9019 BRCL delta where delta is in half-words
9020 invalid opcodes
9021
9022 In both cases the replacement has the same length as the original.
9023 To remain sane & verifiable,
9024 (1) limit the displacement for the short form to
9025 (say) +/- one billion, so as to avoid wraparound
9026 off-by-ones
9027 (2) even if the short form is applicable, once every (say)
9028 1024 times use the long form anyway, so as to maintain
9029 verifiability
9030 */
9031
9032 /* This is the delta we need to put into a BRCL insn. Note, that the
9033 offset in BRCL is in half-words. Hence division by 2. */
9034 Long delta = (Long)((UChar *)place_to_jump_to - (UChar *)place_to_chain) / 2;
9035 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
9036
9037 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
9038 if (shortOK) {
9039 shortCTR++; // thread safety bleh
9040 if (0 == (shortCTR & 0x3FF)) {
9041 shortOK = False;
9042 if (0)
9043 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
9044 "using long jmp\n", shortCTR);
9045 }
9046 }
9047
9048 /* And make the modifications. */
9049 UChar *p = (UChar *)place_to_chain;
9050 if (shortOK) {
9051 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
9052
florian48cb9612012-04-20 02:50:28 +00009053 /* Make sure that BRCL fits into the patchable part of an xdirect
florian1c857042012-04-15 04:11:07 +00009054 code sequence */
florian48cb9612012-04-20 02:50:28 +00009055 vassert(6 <= s390_xdirect_patchable_len());
florian1c857042012-04-15 04:11:07 +00009056
florian8844a632012-04-13 04:04:06 +00009057 /* Fill remaining bytes with 0x00 (invalid opcode) */
9058 Int i;
9059 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
9060 p[i] = 0x00;
9061 } else {
florian1c857042012-04-15 04:11:07 +00009062 /*
florianebaf8d92012-04-22 17:38:46 +00009063 load tchain_scratch, #place_to_jump_to
9064 goto *tchain_scratch
florian1c857042012-04-15 04:11:07 +00009065 */
9066 ULong addr = Ptr_to_ULong(place_to_jump_to);
9067 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +00009068 /* There is not need to emit a BCR here, as it is already there. */
florian8844a632012-04-13 04:04:06 +00009069 }
9070
florian5ea257b2012-09-29 17:05:46 +00009071 UInt len = p - (UChar *)place_to_chain;
9072 VexInvalRange vir = { (HWord)place_to_chain, len };
florian8844a632012-04-13 04:04:06 +00009073 return vir;
9074}
9075
9076
9077/* NB: what goes on here has to be very closely coordinated with the
9078 s390_insn_xdirect_emit code above. */
9079VexInvalRange
9080unchainXDirect_S390(void *place_to_unchain,
9081 void *place_to_jump_to_EXPECTED,
9082 void *disp_cp_chain_me)
9083{
9084 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
9085
florianebaf8d92012-04-22 17:38:46 +00009086 load tchain_scratch, #place_to_jump_to_EXPECTED
9087 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009088
9089 ---OR---
9090 in the case where the displacement falls within 32 bits
9091
9092 BRCL delta
9093 invalid opcodes
9094 */
9095 UChar *p = place_to_unchain;
florian1c857042012-04-15 04:11:07 +00009096
florianebaf8d92012-04-22 17:38:46 +00009097 Bool uses_short_form = False;
9098
florian1c857042012-04-15 04:11:07 +00009099 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
florian8844a632012-04-13 04:04:06 +00009100 /* Looks like the short form */
9101 Int num_hw = *(Int *)&p[2];
9102 Int delta = 2 *num_hw;
9103
9104 vassert(p + delta == place_to_jump_to_EXPECTED);
9105
florian8844a632012-04-13 04:04:06 +00009106 Int i;
9107 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
florian1c857042012-04-15 04:11:07 +00009108 vassert(p[6+i] == 0x00);
florianebaf8d92012-04-22 17:38:46 +00009109 uses_short_form = True;
florian8844a632012-04-13 04:04:06 +00009110 } else {
9111 /* Should be the long form */
9112 const UChar *next;
9113
9114 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
9115 Ptr_to_ULong(place_to_jump_to_EXPECTED));
9116 /* Check for BR *tchain_scratch */
florian1c857042012-04-15 04:11:07 +00009117 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +00009118 }
9119
9120 /* And what we want to change it to is:
9121
9122 load tchain_scratch, #disp_cp_chain_me
florianebaf8d92012-04-22 17:38:46 +00009123 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009124 */
florianebaf8d92012-04-22 17:38:46 +00009125
9126 /* Get the address of the beginning of the load64 code sequence into %r1.
9127 Do not change the register! This is part of the protocol with the
9128 dispatcher.
9129 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
9130 load64 insn sequence. That sequence is prefixed with a BASR to get its
9131 address (see s390_insn_xdirect_emit). */
9132 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
9133
florian8844a632012-04-13 04:04:06 +00009134 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
9135 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +00009136
9137 /* Emit the BCR in case the short form was used. In case of the long
9138 form, the BCR is already there. */
9139 if (uses_short_form)
9140 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00009141
florian5ea257b2012-09-29 17:05:46 +00009142 UInt len = p - (UChar *)place_to_unchain;
9143 VexInvalRange vir = { (HWord)place_to_unchain, len };
florian8844a632012-04-13 04:04:06 +00009144 return vir;
9145}
9146
sewardj2019a972011-03-07 16:04:07 +00009147/*---------------------------------------------------------------*/
9148/*--- end host_s390_defs.c ---*/
9149/*---------------------------------------------------------------*/