blob: d89179b27df2a6a2a1dc571ff3759bdb80fcb67e [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
11 Copyright IBM Corp. 2010-2011
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31/* Contributed by Florian Krohm */
32
33#include "libvex_basictypes.h"
34#include "libvex.h"
35#include "libvex_trc_values.h"
sewardj2019a972011-03-07 16:04:07 +000036#include "libvex_s390x_common.h"
37
38#include "main_util.h"
39#include "main_globals.h"
40#include "host_generic_regs.h"
41#include "host_s390_defs.h"
42#include "host_s390_disasm.h"
florian428dfdd2012-03-27 03:09:49 +000043#include "guest_s390_defs.h" /* S390X_GUEST_OFFSET */
sewardj2019a972011-03-07 16:04:07 +000044#include <stdarg.h>
45
46/* KLUDGE: We need to know the hwcaps of the host when generating
47 code. But that info is not passed to emit_S390Instr. Only mode64 is
48 being passed. So, ideally, we want this passed as an argument, too.
49 Until then, we use a global variable. This variable is set as a side
50 effect of iselSB_S390. This is safe because instructions are selected
51 before they are emitted. */
florianf26994a2012-04-21 03:34:54 +000052UInt s390_host_hwcaps;
sewardj2019a972011-03-07 16:04:07 +000053
florianb4df7682011-07-05 02:09:01 +000054
55/*------------------------------------------------------------*/
56/*--- Forward declarations ---*/
57/*------------------------------------------------------------*/
58
59static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
60static void s390_insn_map_regs(HRegRemap *, s390_insn *);
61static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
florian1c857042012-04-15 04:11:07 +000062static UInt s390_tchain_load64_len(void);
florianb4df7682011-07-05 02:09:01 +000063
64
sewardj2019a972011-03-07 16:04:07 +000065/*------------------------------------------------------------*/
66/*--- Registers ---*/
67/*------------------------------------------------------------*/
68
69/* Decompile the given register into a static buffer and return it */
70const HChar *
71s390_hreg_as_string(HReg reg)
72{
73 static HChar buf[10];
74
75 static const HChar ireg_names[16][5] = {
76 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
77 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
78 };
79
80 static const HChar freg_names[16][5] = {
81 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
82 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
83 };
84
85 UInt r; /* hregNumber() returns an UInt */
86
87 r = hregNumber(reg);
88
89 /* Be generic for all virtual regs. */
90 if (hregIsVirtual(reg)) {
91 buf[0] = '\0';
92 switch (hregClass(reg)) {
93 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
94 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
95 default: goto fail;
96 }
97 return buf;
98 }
99
100 /* But specific for real regs. */
101 vassert(r < 16);
102
103 switch (hregClass(reg)) {
104 case HRcInt64: return ireg_names[r];
105 case HRcFlt64: return freg_names[r];
106 default: goto fail;
107 }
108
109 fail: vpanic("s390_hreg_as_string");
110}
111
112
113/* Tell the register allocator which registers can be allocated. */
florianb4df7682011-07-05 02:09:01 +0000114static void
sewardj2019a972011-03-07 16:04:07 +0000115s390_hreg_get_allocable(Int *nregs, HReg **arr)
116{
117 UInt i;
118
119 /* Total number of allocable registers (all classes) */
120 *nregs = 16 /* GPRs */
121 - 1 /* r0 */
florian8844a632012-04-13 04:04:06 +0000122 - 1 /* r12 scratch register for translation chaining support */
sewardj2019a972011-03-07 16:04:07 +0000123 - 1 /* r13 guest state pointer */
124 - 1 /* r14 link register */
125 - 1 /* r15 stack pointer */
126 + 16 /* FPRs */
127 ;
128
129 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
130
131 i = 0;
132
133 /* GPR0 is not available because it is interpreted as 0, when used
134 as a base or index register. */
135 (*arr)[i++] = mkHReg(1, HRcInt64, False);
136 (*arr)[i++] = mkHReg(2, HRcInt64, False);
137 (*arr)[i++] = mkHReg(3, HRcInt64, False);
138 (*arr)[i++] = mkHReg(4, HRcInt64, False);
139 (*arr)[i++] = mkHReg(5, HRcInt64, False);
140 (*arr)[i++] = mkHReg(6, HRcInt64, False);
141 (*arr)[i++] = mkHReg(7, HRcInt64, False);
142 (*arr)[i++] = mkHReg(8, HRcInt64, False);
143 (*arr)[i++] = mkHReg(9, HRcInt64, False);
144 /* GPR10 and GPR11 are used for instructions that use register pairs.
145 Otherwise, they are available to the allocator */
146 (*arr)[i++] = mkHReg(10, HRcInt64, False);
147 (*arr)[i++] = mkHReg(11, HRcInt64, False);
florian8844a632012-04-13 04:04:06 +0000148 /* GPR12 is not available because it us used as a scratch register
149 in translation chaining. */
sewardj2019a972011-03-07 16:04:07 +0000150 /* GPR13 is not available because it is used as guest state pointer */
151 /* GPR14 is not available because it is used as link register */
152 /* GPR15 is not available because it is used as stack pointer */
153
154 /* Add the available real (non-virtual) FPRs */
155 (*arr)[i++] = mkHReg(0, HRcFlt64, False);
156 (*arr)[i++] = mkHReg(1, HRcFlt64, False);
157 (*arr)[i++] = mkHReg(2, HRcFlt64, False);
158 (*arr)[i++] = mkHReg(3, HRcFlt64, False);
159 (*arr)[i++] = mkHReg(4, HRcFlt64, False);
160 (*arr)[i++] = mkHReg(5, HRcFlt64, False);
161 (*arr)[i++] = mkHReg(6, HRcFlt64, False);
162 (*arr)[i++] = mkHReg(7, HRcFlt64, False);
163 (*arr)[i++] = mkHReg(8, HRcFlt64, False);
164 (*arr)[i++] = mkHReg(9, HRcFlt64, False);
165 (*arr)[i++] = mkHReg(10, HRcFlt64, False);
166 (*arr)[i++] = mkHReg(11, HRcFlt64, False);
167 (*arr)[i++] = mkHReg(12, HRcFlt64, False);
168 (*arr)[i++] = mkHReg(13, HRcFlt64, False);
169 (*arr)[i++] = mkHReg(14, HRcFlt64, False);
170 (*arr)[i++] = mkHReg(15, HRcFlt64, False);
171 /* FPR12 - FPR15 are also used as register pairs for 128-bit
172 floating point operations */
173}
174
175
176/* Return the real register that holds the guest state pointer */
177HReg
178s390_hreg_guest_state_pointer(void)
179{
180 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
181}
182
florian8844a632012-04-13 04:04:06 +0000183
sewardj2019a972011-03-07 16:04:07 +0000184/* Is VALUE within the domain of a 20-bit signed integer. */
185static __inline__ Bool
186fits_signed_20bit(Int value)
187{
188 return ((value << 12) >> 12) == value;
189}
190
191
192/* Is VALUE within the domain of a 12-bit unsigned integer. */
193static __inline__ Bool
194fits_unsigned_12bit(Int value)
195{
196 return (value & 0xFFF) == value;
197}
198
199/*------------------------------------------------------------*/
200/*--- Addressing modes (amodes) ---*/
201/*------------------------------------------------------------*/
202
203/* Construct a b12 amode. */
204s390_amode *
205s390_amode_b12(Int d, HReg b)
206{
207 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
208
209 vassert(fits_unsigned_12bit(d));
210
211 am->tag = S390_AMODE_B12;
212 am->d = d;
213 am->b = b;
214 am->x = 0; /* hregNumber(0) == 0 */
215
216 return am;
217}
218
219
220/* Construct a b20 amode. */
221s390_amode *
222s390_amode_b20(Int d, HReg b)
223{
224 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
225
226 vassert(fits_signed_20bit(d));
227
228 am->tag = S390_AMODE_B20;
229 am->d = d;
230 am->b = b;
231 am->x = 0; /* hregNumber(0) == 0 */
232
233 return am;
234}
235
236
237/* Construct a bx12 amode. */
238s390_amode *
239s390_amode_bx12(Int d, HReg b, HReg x)
240{
241 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
242
243 vassert(fits_unsigned_12bit(d));
244 vassert(b != 0);
245 vassert(x != 0);
246
247 am->tag = S390_AMODE_BX12;
248 am->d = d;
249 am->b = b;
250 am->x = x;
251
252 return am;
253}
254
255
256/* Construct a bx20 amode. */
257s390_amode *
258s390_amode_bx20(Int d, HReg b, HReg x)
259{
260 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
261
262 vassert(fits_signed_20bit(d));
263 vassert(b != 0);
264 vassert(x != 0);
265
266 am->tag = S390_AMODE_BX20;
267 am->d = d;
268 am->b = b;
269 am->x = x;
270
271 return am;
272}
273
274
275/* Construct an AMODE for accessing the guest state at OFFSET */
276s390_amode *
277s390_amode_for_guest_state(Int offset)
278{
279 if (fits_unsigned_12bit(offset))
280 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
sewardj2019a972011-03-07 16:04:07 +0000281
282 vpanic("invalid guest state offset");
283}
284
285
286/* Decompile the given amode into a static buffer and return it. */
287const HChar *
288s390_amode_as_string(const s390_amode *am)
289{
290 static HChar buf[30];
291 HChar *p;
292
293 buf[0] = '\0';
294 p = buf;
295
296 switch (am->tag) {
297 case S390_AMODE_B12:
298 case S390_AMODE_B20:
299 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
300 break;
301
302 case S390_AMODE_BX12:
303 case S390_AMODE_BX20:
304 /* s390_hreg_as_string returns pointer to local buffer. Need to
305 split this into two printfs */
306 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
307 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
308 break;
309
310 default:
311 vpanic("s390_amode_as_string");
312 }
313
314 return buf;
315}
316
317
318/* Helper function for s390_amode_is_sane */
319static __inline__ Bool
320is_virtual_gpr(HReg reg)
321{
322 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
323}
324
325
326/* Sanity check for an amode */
327Bool
328s390_amode_is_sane(const s390_amode *am)
329{
330 switch (am->tag) {
331 case S390_AMODE_B12:
332 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
333
334 case S390_AMODE_B20:
335 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
336
337 case S390_AMODE_BX12:
338 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
339 fits_unsigned_12bit(am->d);
340
341 case S390_AMODE_BX20:
342 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
343 fits_signed_20bit(am->d);
344
345 default:
346 vpanic("s390_amode_is_sane");
347 }
348}
349
350
351/* Record the register use of an amode */
florianb4df7682011-07-05 02:09:01 +0000352static void
sewardj2019a972011-03-07 16:04:07 +0000353s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
354{
355 switch (am->tag) {
356 case S390_AMODE_B12:
357 case S390_AMODE_B20:
358 addHRegUse(u, HRmRead, am->b);
359 return;
360
361 case S390_AMODE_BX12:
362 case S390_AMODE_BX20:
363 addHRegUse(u, HRmRead, am->b);
364 addHRegUse(u, HRmRead, am->x);
365 return;
366
367 default:
368 vpanic("s390_amode_get_reg_usage");
369 }
370}
371
372
florianb4df7682011-07-05 02:09:01 +0000373static void
sewardj2019a972011-03-07 16:04:07 +0000374s390_amode_map_regs(HRegRemap *m, s390_amode *am)
375{
376 switch (am->tag) {
377 case S390_AMODE_B12:
378 case S390_AMODE_B20:
379 am->b = lookupHRegRemap(m, am->b);
380 return;
381
382 case S390_AMODE_BX12:
383 case S390_AMODE_BX20:
384 am->b = lookupHRegRemap(m, am->b);
385 am->x = lookupHRegRemap(m, am->x);
386 return;
387
388 default:
389 vpanic("s390_amode_map_regs");
390 }
391}
392
393
sewardj2019a972011-03-07 16:04:07 +0000394void
florianb4df7682011-07-05 02:09:01 +0000395ppS390AMode(s390_amode *am)
sewardj2019a972011-03-07 16:04:07 +0000396{
397 vex_printf("%s", s390_amode_as_string(am));
398}
399
400void
florianb4df7682011-07-05 02:09:01 +0000401ppS390Instr(s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000402{
403 vex_printf("%s", s390_insn_as_string(insn));
404}
405
406void
407ppHRegS390(HReg reg)
408{
409 vex_printf("%s", s390_hreg_as_string(reg));
410}
411
412/*------------------------------------------------------------*/
413/*--- Helpers for register allocation ---*/
414/*------------------------------------------------------------*/
415
416/* Called once per translation. */
417void
418getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
419{
420 s390_hreg_get_allocable(nregs, arr);
421}
422
423
424/* Tell the register allocator how the given instruction uses the registers
425 it refers to. */
426void
florianb4df7682011-07-05 02:09:01 +0000427getRegUsage_S390Instr(HRegUsage *u, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000428{
429 s390_insn_get_reg_usage(u, insn);
430}
431
432
433/* Map the registers of the given instruction */
434void
florianb4df7682011-07-05 02:09:01 +0000435mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000436{
437 s390_insn_map_regs(m, insn);
438}
439
440
441/* Figure out if the given insn represents a reg-reg move, and if so
442 assign the source and destination to *src and *dst. If in doubt say No.
443 Used by the register allocator to do move coalescing. */
444Bool
florianb4df7682011-07-05 02:09:01 +0000445isMove_S390Instr(s390_insn *insn, HReg *src, HReg *dst)
sewardj2019a972011-03-07 16:04:07 +0000446{
447 return s390_insn_is_reg_reg_move(insn, src, dst);
448}
449
450
451/* Generate s390 spill/reload instructions under the direction of the
452 register allocator. Note it's critical these don't write the
453 condition codes. This is like an Ist_Put */
454void
455genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
456{
457 s390_amode *am;
458
459 vassert(offsetB >= 0);
460 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
461 vassert(!hregIsVirtual(rreg));
462
463 *i1 = *i2 = NULL;
464
465 am = s390_amode_for_guest_state(offsetB);
466
467 switch (hregClass(rreg)) {
468 case HRcInt64:
469 case HRcFlt64:
470 *i1 = s390_insn_store(8, am, rreg);
471 return;
472
473 default:
474 ppHRegClass(hregClass(rreg));
475 vpanic("genSpill_S390: unimplemented regclass");
476 }
477}
478
479
480/* This is like an Iex_Get */
481void
482genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
483{
484 s390_amode *am;
485
486 vassert(offsetB >= 0);
487 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
488 vassert(!hregIsVirtual(rreg));
489
490 *i1 = *i2 = NULL;
491
492 am = s390_amode_for_guest_state(offsetB);
493
494 switch (hregClass(rreg)) {
495 case HRcInt64:
496 case HRcFlt64:
497 *i1 = s390_insn_load(8, rreg, am);
498 return;
499
500 default:
501 ppHRegClass(hregClass(rreg));
502 vpanic("genReload_S390: unimplemented regclass");
503 }
504}
505
506/* Helper function for s390_insn_get_reg_usage */
507static void
508s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
509{
510 switch (op.tag) {
511 case S390_OPND_REG:
512 addHRegUse(u, HRmRead, op.variant.reg);
513 break;
514
515 case S390_OPND_AMODE:
516 s390_amode_get_reg_usage(u, op.variant.am);
517 break;
518
519 case S390_OPND_IMMEDIATE:
520 break;
521
522 default:
523 vpanic("s390_opnd_RMI_get_reg_usage");
524 }
525}
526
527
528/* Tell the register allocator how the given insn uses the registers */
florianb4df7682011-07-05 02:09:01 +0000529static void
sewardj2019a972011-03-07 16:04:07 +0000530s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
531{
532 initHRegUsage(u);
533
534 switch (insn->tag) {
535 case S390_INSN_LOAD:
536 addHRegUse(u, HRmWrite, insn->variant.load.dst);
537 s390_amode_get_reg_usage(u, insn->variant.load.src);
538 break;
539
540 case S390_INSN_LOAD_IMMEDIATE:
541 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
542 break;
543
544 case S390_INSN_STORE:
545 addHRegUse(u, HRmRead, insn->variant.store.src);
546 s390_amode_get_reg_usage(u, insn->variant.store.dst);
547 break;
548
549 case S390_INSN_MOVE:
550 addHRegUse(u, HRmRead, insn->variant.move.src);
551 addHRegUse(u, HRmWrite, insn->variant.move.dst);
552 break;
553
554 case S390_INSN_COND_MOVE:
555 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
556 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
557 break;
558
559 case S390_INSN_ALU:
560 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
561 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
562 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
563 break;
564
565 case S390_INSN_MUL:
566 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
567 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
568 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
569 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
570 break;
571
572 case S390_INSN_DIV:
573 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
574 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
575 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
576 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
577 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
578 break;
579
580 case S390_INSN_DIVS:
581 addHRegUse(u, HRmRead, insn->variant.divs.op1);
582 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
583 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
584 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
585 break;
586
sewardj611b06e2011-03-24 08:57:29 +0000587 case S390_INSN_CLZ:
588 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
589 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
590 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000591 break;
592
593 case S390_INSN_UNOP:
594 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
595 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
596 break;
597
598 case S390_INSN_TEST:
599 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
600 break;
601
602 case S390_INSN_CC2BOOL:
603 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
604 break;
605
606 case S390_INSN_CAS:
607 addHRegUse(u, HRmRead, insn->variant.cas.op1);
608 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
609 addHRegUse(u, HRmRead, insn->variant.cas.op3);
610 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
611 break;
612
florian448cbba2012-06-06 02:26:01 +0000613 case S390_INSN_CDAS:
614 addHRegUse(u, HRmRead, insn->variant.cdas.op1_high);
615 addHRegUse(u, HRmRead, insn->variant.cdas.op1_low);
616 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
617 addHRegUse(u, HRmRead, insn->variant.cdas.op3_high);
618 addHRegUse(u, HRmRead, insn->variant.cdas.op3_low);
619 addHRegUse(u, HRmWrite, insn->variant.cdas.old_mem_high);
620 addHRegUse(u, HRmWrite, insn->variant.cdas.old_mem_low);
621 addHRegUse(u, HRmWrite, insn->variant.cdas.scratch);
622 break;
623
sewardj2019a972011-03-07 16:04:07 +0000624 case S390_INSN_COMPARE:
625 addHRegUse(u, HRmRead, insn->variant.compare.src1);
626 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
627 break;
628
sewardj2019a972011-03-07 16:04:07 +0000629 case S390_INSN_HELPER_CALL: {
630 UInt i;
631
632 /* Assume that all volatile registers are clobbered. ABI says,
633 volatile registers are: r0 - r5. Valgrind's register allocator
634 does not know about r0, so we can leave that out */
635 for (i = 1; i <= 5; ++i) {
636 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
637 }
florian01ed6e72012-05-27 16:52:43 +0000638 if (insn->variant.helper_call.dst != INVALID_HREG)
639 addHRegUse(u, HRmWrite, insn->variant.helper_call.dst);
sewardj2019a972011-03-07 16:04:07 +0000640
641 /* Ditto for floating point registers. f0 - f7 are volatile */
642 for (i = 0; i <= 7; ++i) {
643 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
644 }
645
646 /* The registers that are used for passing arguments will be read.
647 Not all of them may, but in general we need to assume that. */
648 for (i = 0; i < insn->variant.helper_call.num_args; ++i) {
649 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
650 HRcInt64, False));
651 }
652
653 /* s390_insn_helper_call_emit also reads / writes the link register
654 and stack pointer. But those registers are not visible to the
655 register allocator. So we don't need to do anything for them. */
656 break;
657 }
658
659 case S390_INSN_BFP_TRIOP:
660 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
661 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
662 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
663 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
664 break;
665
666 case S390_INSN_BFP_BINOP:
667 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst);
668 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst); /* left */
669 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2); /* right */
670 break;
671
672 case S390_INSN_BFP_UNOP:
673 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst);
674 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op); /* operand */
675 break;
676
677 case S390_INSN_BFP_COMPARE:
678 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
679 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1); /* left */
680 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2); /* right */
681 break;
682
683 case S390_INSN_BFP128_BINOP:
684 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_hi);
685 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_lo);
686 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_hi); /* left */
687 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_lo); /* left */
688 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_hi); /* right */
689 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_lo); /* right */
690 break;
691
692 case S390_INSN_BFP128_COMPARE:
693 addHRegUse(u, HRmWrite, insn->variant.bfp128_compare.dst);
694 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_hi); /* left */
695 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_lo); /* left */
696 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_hi); /* right */
697 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_lo); /* right */
698 break;
699
700 case S390_INSN_BFP128_UNOP:
701 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
702 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
703 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
704 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo);
705 break;
706
707 case S390_INSN_BFP128_CONVERT_TO:
708 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
709 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
710 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
711 break;
712
713 case S390_INSN_BFP128_CONVERT_FROM:
714 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
715 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
716 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo);
717 break;
718
sewardja52e37e2011-04-28 18:48:06 +0000719 case S390_INSN_MFENCE:
florianad43b3a2012-02-20 15:01:14 +0000720 case S390_INSN_GZERO:
721 case S390_INSN_GADD:
sewardja52e37e2011-04-28 18:48:06 +0000722 break;
723
florian8844a632012-04-13 04:04:06 +0000724 case S390_INSN_EVCHECK:
725 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
726 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
727 break;
728
729 case S390_INSN_PROFINC:
730 /* Does not use any register visible to the register allocator */
731 break;
732
733 case S390_INSN_XDIRECT:
734 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
735 break;
736
737 case S390_INSN_XINDIR:
738 addHRegUse(u, HRmRead, insn->variant.xindir.dst);
739 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
740 break;
741
742 case S390_INSN_XASSISTED:
743 addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
744 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
745 break;
746
sewardj2019a972011-03-07 16:04:07 +0000747 default:
748 vpanic("s390_insn_get_reg_usage");
749 }
750}
751
752
753/* Helper function for s390_insn_map_regs */
754static void
755s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
756{
757 switch (op->tag) {
758 case S390_OPND_REG:
759 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
760 break;
761
762 case S390_OPND_IMMEDIATE:
763 break;
764
765 case S390_OPND_AMODE:
766 s390_amode_map_regs(m, op->variant.am);
767 break;
768
769 default:
770 vpanic("s390_opnd_RMI_map_regs");
771 }
772}
773
774
florianb4df7682011-07-05 02:09:01 +0000775static void
sewardj2019a972011-03-07 16:04:07 +0000776s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
777{
778 switch (insn->tag) {
779 case S390_INSN_LOAD:
780 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
781 s390_amode_map_regs(m, insn->variant.load.src);
782 break;
783
784 case S390_INSN_STORE:
785 s390_amode_map_regs(m, insn->variant.store.dst);
786 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
787 break;
788
789 case S390_INSN_MOVE:
790 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
791 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
792 break;
793
794 case S390_INSN_COND_MOVE:
795 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
796 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
797 break;
798
799 case S390_INSN_LOAD_IMMEDIATE:
800 insn->variant.load_immediate.dst =
801 lookupHRegRemap(m, insn->variant.load_immediate.dst);
802 break;
803
804 case S390_INSN_ALU:
805 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
806 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
807 break;
808
809 case S390_INSN_MUL:
810 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
811 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
812 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
813 break;
814
815 case S390_INSN_DIV:
816 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
817 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
818 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
819 break;
820
821 case S390_INSN_DIVS:
822 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
823 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
824 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
825 break;
826
sewardj611b06e2011-03-24 08:57:29 +0000827 case S390_INSN_CLZ:
828 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
829 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
830 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000831 break;
832
833 case S390_INSN_UNOP:
834 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
835 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
836 break;
837
838 case S390_INSN_TEST:
839 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
840 break;
841
842 case S390_INSN_CC2BOOL:
843 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
844 break;
845
846 case S390_INSN_CAS:
847 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
848 s390_amode_map_regs(m, insn->variant.cas.op2);
849 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
850 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
851 break;
852
florian448cbba2012-06-06 02:26:01 +0000853 case S390_INSN_CDAS:
854 insn->variant.cdas.op1_high = lookupHRegRemap(m, insn->variant.cdas.op1_high);
855 insn->variant.cdas.op1_low = lookupHRegRemap(m, insn->variant.cdas.op1_low);
856 s390_amode_map_regs(m, insn->variant.cdas.op2);
857 insn->variant.cdas.op3_high = lookupHRegRemap(m, insn->variant.cdas.op3_high);
858 insn->variant.cdas.op3_low = lookupHRegRemap(m, insn->variant.cdas.op3_low);
859 insn->variant.cdas.old_mem_high = lookupHRegRemap(m, insn->variant.cdas.old_mem_high);
860 insn->variant.cdas.old_mem_low = lookupHRegRemap(m, insn->variant.cdas.old_mem_low);
861 insn->variant.cdas.scratch = lookupHRegRemap(m, insn->variant.cdas.scratch);
862 break;
863
sewardj2019a972011-03-07 16:04:07 +0000864 case S390_INSN_COMPARE:
865 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
866 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
867 break;
868
sewardj2019a972011-03-07 16:04:07 +0000869 case S390_INSN_HELPER_CALL:
870 /* s390_insn_helper_call_emit also reads / writes the link register
871 and stack pointer. But those registers are not visible to the
872 register allocator. So we don't need to do anything for them.
873 As for the arguments of the helper call -- they will be loaded into
874 non-virtual registers. Again, we don't need to do anything for those
875 here. */
florian01ed6e72012-05-27 16:52:43 +0000876 if (insn->variant.helper_call.dst != INVALID_HREG)
877 insn->variant.helper_call.dst = lookupHRegRemap(m, insn->variant.helper_call.dst);
sewardj2019a972011-03-07 16:04:07 +0000878 break;
879
880 case S390_INSN_BFP_TRIOP:
881 insn->variant.bfp_triop.dst = lookupHRegRemap(m, insn->variant.bfp_triop.dst);
882 insn->variant.bfp_triop.op2 = lookupHRegRemap(m, insn->variant.bfp_triop.op2);
883 insn->variant.bfp_triop.op3 = lookupHRegRemap(m, insn->variant.bfp_triop.op3);
884 break;
885
886 case S390_INSN_BFP_BINOP:
887 insn->variant.bfp_binop.dst = lookupHRegRemap(m, insn->variant.bfp_binop.dst);
888 insn->variant.bfp_binop.op2 = lookupHRegRemap(m, insn->variant.bfp_binop.op2);
889 break;
890
891 case S390_INSN_BFP_UNOP:
892 insn->variant.bfp_unop.dst = lookupHRegRemap(m, insn->variant.bfp_unop.dst);
893 insn->variant.bfp_unop.op = lookupHRegRemap(m, insn->variant.bfp_unop.op);
894 break;
895
896 case S390_INSN_BFP_COMPARE:
897 insn->variant.bfp_compare.dst = lookupHRegRemap(m, insn->variant.bfp_compare.dst);
898 insn->variant.bfp_compare.op1 = lookupHRegRemap(m, insn->variant.bfp_compare.op1);
899 insn->variant.bfp_compare.op2 = lookupHRegRemap(m, insn->variant.bfp_compare.op2);
900 break;
901
902 case S390_INSN_BFP128_BINOP:
903 insn->variant.bfp128_binop.dst_hi =
904 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_hi);
905 insn->variant.bfp128_binop.dst_lo =
906 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_lo);
907 insn->variant.bfp128_binop.op2_hi =
908 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_hi);
909 insn->variant.bfp128_binop.op2_lo =
910 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_lo);
911 break;
912
913 case S390_INSN_BFP128_COMPARE:
914 insn->variant.bfp128_compare.dst =
915 lookupHRegRemap(m, insn->variant.bfp128_compare.dst);
916 insn->variant.bfp128_compare.op1_hi =
917 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_hi);
918 insn->variant.bfp128_compare.op1_lo =
919 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_lo);
920 insn->variant.bfp128_compare.op2_hi =
921 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_hi);
922 insn->variant.bfp128_compare.op2_lo =
923 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_lo);
924 break;
925
926 case S390_INSN_BFP128_UNOP:
927 insn->variant.bfp128_unop.dst_hi =
928 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
929 insn->variant.bfp128_unop.dst_lo =
930 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
931 insn->variant.bfp128_unop.op_hi =
932 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
933 insn->variant.bfp128_unop.op_lo =
934 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
935 break;
936
937 case S390_INSN_BFP128_CONVERT_TO:
938 insn->variant.bfp128_unop.dst_hi =
939 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
940 insn->variant.bfp128_unop.dst_lo =
941 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
942 insn->variant.bfp128_unop.op_hi =
943 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
944 break;
945
946 case S390_INSN_BFP128_CONVERT_FROM:
947 insn->variant.bfp128_unop.dst_hi =
948 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
949 insn->variant.bfp128_unop.op_hi =
950 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
951 insn->variant.bfp128_unop.op_lo =
952 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
953 break;
954
sewardja52e37e2011-04-28 18:48:06 +0000955 case S390_INSN_MFENCE:
florianad43b3a2012-02-20 15:01:14 +0000956 case S390_INSN_GZERO:
957 case S390_INSN_GADD:
sewardja52e37e2011-04-28 18:48:06 +0000958 break;
959
florian8844a632012-04-13 04:04:06 +0000960 case S390_INSN_EVCHECK:
961 s390_amode_map_regs(m, insn->variant.evcheck.counter);
962 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
963 break;
964
965 case S390_INSN_PROFINC:
966 /* Does not use any register visible to the register allocator */
967 break;
968
969 case S390_INSN_XDIRECT:
970 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
971 break;
972
973 case S390_INSN_XINDIR:
974 s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
975 insn->variant.xindir.dst =
976 lookupHRegRemap(m, insn->variant.xindir.dst);
977 break;
978
979 case S390_INSN_XASSISTED:
980 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
981 insn->variant.xassisted.dst =
982 lookupHRegRemap(m, insn->variant.xassisted.dst);
983 break;
984
sewardj2019a972011-03-07 16:04:07 +0000985 default:
986 vpanic("s390_insn_map_regs");
987 }
988}
989
990
991/* Return True, if INSN is a move between two registers of the same class.
992 In that case assign the source and destination registers to SRC and DST,
993 respectively. */
florianb4df7682011-07-05 02:09:01 +0000994static Bool
sewardj2019a972011-03-07 16:04:07 +0000995s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
996{
997 if (insn->tag == S390_INSN_MOVE &&
998 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
999 *src = insn->variant.move.src;
1000 *dst = insn->variant.move.dst;
1001 return True;
1002 }
1003
1004 return False;
1005}
1006
1007
sewardj2019a972011-03-07 16:04:07 +00001008/*------------------------------------------------------------*/
1009/*--- Functions to emit a sequence of bytes ---*/
1010/*------------------------------------------------------------*/
1011
sewardj2019a972011-03-07 16:04:07 +00001012static __inline__ UChar *
1013emit_2bytes(UChar *p, ULong val)
1014{
1015 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1016}
1017
1018
1019static __inline__ UChar *
1020emit_4bytes(UChar *p, ULong val)
1021{
1022 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1023}
1024
1025
1026static __inline__ UChar *
1027emit_6bytes(UChar *p, ULong val)
1028{
1029 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1030}
1031
1032
1033/*------------------------------------------------------------*/
1034/*--- Functions to emit various instruction formats ---*/
1035/*------------------------------------------------------------*/
1036
sewardj2019a972011-03-07 16:04:07 +00001037static UChar *
1038emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1039{
1040 ULong the_insn = op;
1041
1042 the_insn |= ((ULong)r1) << 20;
1043 the_insn |= ((ULong)i2) << 0;
1044
1045 return emit_4bytes(p, the_insn);
1046}
1047
1048
1049static UChar *
1050emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1051{
1052 ULong the_insn = op;
1053
1054 the_insn |= ((ULong)r1) << 36;
1055 the_insn |= ((ULong)i2) << 0;
1056
1057 return emit_6bytes(p, the_insn);
1058}
1059
1060
1061static UChar *
1062emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1063{
1064 ULong the_insn = op;
1065
1066 the_insn |= ((ULong)r1) << 4;
1067 the_insn |= ((ULong)r2) << 0;
1068
1069 return emit_2bytes(p, the_insn);
1070}
1071
1072
1073static UChar *
1074emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1075{
1076 ULong the_insn = op;
1077
1078 the_insn |= ((ULong)r1) << 4;
1079 the_insn |= ((ULong)r2) << 0;
1080
1081 return emit_4bytes(p, the_insn);
1082}
1083
1084
1085static UChar *
1086emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1087{
1088 ULong the_insn = op;
1089
1090 the_insn |= ((ULong)r1) << 12;
1091 the_insn |= ((ULong)r3) << 4;
1092 the_insn |= ((ULong)r2) << 0;
1093
1094 return emit_4bytes(p, the_insn);
1095}
1096
1097
1098static UChar *
1099emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1100{
1101 ULong the_insn = op;
1102
1103 the_insn |= ((ULong)r3) << 12;
1104 the_insn |= ((ULong)r1) << 4;
1105 the_insn |= ((ULong)r2) << 0;
1106
1107 return emit_4bytes(p, the_insn);
1108}
1109
1110
1111static UChar *
1112emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1113{
1114 ULong the_insn = op;
1115
1116 the_insn |= ((ULong)r1) << 20;
1117 the_insn |= ((ULong)r3) << 16;
1118 the_insn |= ((ULong)b2) << 12;
1119 the_insn |= ((ULong)d2) << 0;
1120
1121 return emit_4bytes(p, the_insn);
1122}
1123
1124
1125static UChar *
1126emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1127{
1128 ULong the_insn = op;
1129
1130 the_insn |= ((ULong)r1) << 36;
1131 the_insn |= ((ULong)r3) << 32;
1132 the_insn |= ((ULong)b2) << 28;
1133 the_insn |= ((ULong)dl2) << 16;
1134 the_insn |= ((ULong)dh2) << 8;
1135
1136 return emit_6bytes(p, the_insn);
1137}
1138
1139
1140static UChar *
1141emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1142{
1143 ULong the_insn = op;
1144
1145 the_insn |= ((ULong)r1) << 20;
1146 the_insn |= ((ULong)x2) << 16;
1147 the_insn |= ((ULong)b2) << 12;
1148 the_insn |= ((ULong)d2) << 0;
1149
1150 return emit_4bytes(p, the_insn);
1151}
1152
1153
1154static UChar *
1155emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1156{
1157 ULong the_insn = op;
1158
1159 the_insn |= ((ULong)r1) << 36;
1160 the_insn |= ((ULong)x2) << 32;
1161 the_insn |= ((ULong)b2) << 28;
1162 the_insn |= ((ULong)dl2) << 16;
1163 the_insn |= ((ULong)dh2) << 8;
1164
1165 return emit_6bytes(p, the_insn);
1166}
1167
1168
1169static UChar *
1170emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1171{
1172 ULong the_insn = op;
1173
1174 the_insn |= ((ULong)b2) << 12;
1175 the_insn |= ((ULong)d2) << 0;
1176
1177 return emit_4bytes(p, the_insn);
1178}
1179
1180
florianad43b3a2012-02-20 15:01:14 +00001181static UChar *
1182emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1183{
1184 ULong the_insn = op;
1185
1186 the_insn |= ((ULong)i2) << 32;
1187 the_insn |= ((ULong)b1) << 28;
1188 the_insn |= ((ULong)dl1) << 16;
1189 the_insn |= ((ULong)dh1) << 8;
1190
1191 return emit_6bytes(p, the_insn);
1192}
1193
1194
1195static UChar *
1196emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1197{
1198 ULong the_insn = op;
1199
1200 the_insn |= ((ULong)l) << 32;
1201 the_insn |= ((ULong)b1) << 28;
1202 the_insn |= ((ULong)d1) << 16;
1203 the_insn |= ((ULong)b2) << 12;
1204 the_insn |= ((ULong)d2) << 0;
1205
1206 return emit_6bytes(p, the_insn);
1207}
1208
1209
sewardj2019a972011-03-07 16:04:07 +00001210/*------------------------------------------------------------*/
1211/*--- Functions to emit particular instructions ---*/
1212/*------------------------------------------------------------*/
1213
sewardj9d31dfd2011-03-15 12:36:44 +00001214static UChar *
sewardj2019a972011-03-07 16:04:07 +00001215s390_emit_AR(UChar *p, UChar r1, UChar r2)
1216{
sewardj7ee97522011-05-09 21:45:04 +00001217 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001218 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1219
1220 return emit_RR(p, 0x1a00, r1, r2);
1221}
1222
1223
sewardj9d31dfd2011-03-15 12:36:44 +00001224static UChar *
sewardj2019a972011-03-07 16:04:07 +00001225s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1226{
sewardj7ee97522011-05-09 21:45:04 +00001227 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001228 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1229
1230 return emit_RRE(p, 0xb9080000, r1, r2);
1231}
1232
1233
sewardj9d31dfd2011-03-15 12:36:44 +00001234static UChar *
sewardj2019a972011-03-07 16:04:07 +00001235s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1236{
sewardj7ee97522011-05-09 21:45:04 +00001237 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001238 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1239
1240 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1241}
1242
1243
sewardj9d31dfd2011-03-15 12:36:44 +00001244static UChar *
sewardj2019a972011-03-07 16:04:07 +00001245s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1246{
sewardj652b56a2011-04-13 15:38:17 +00001247 vassert(s390_host_has_ldisp);
1248
sewardj7ee97522011-05-09 21:45:04 +00001249 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001250 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1251
1252 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1253}
1254
1255
sewardj9d31dfd2011-03-15 12:36:44 +00001256static UChar *
sewardj2019a972011-03-07 16:04:07 +00001257s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1258{
sewardj652b56a2011-04-13 15:38:17 +00001259 vassert(s390_host_has_ldisp || dh2 == 0);
1260
sewardj7ee97522011-05-09 21:45:04 +00001261 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001262 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1263
1264 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1265}
1266
1267
sewardj9d31dfd2011-03-15 12:36:44 +00001268static UChar *
sewardj2019a972011-03-07 16:04:07 +00001269s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1270{
sewardj652b56a2011-04-13 15:38:17 +00001271 vassert(s390_host_has_eimm);
1272
sewardj7ee97522011-05-09 21:45:04 +00001273 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001274 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1275
1276 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1277}
1278
1279
sewardj9d31dfd2011-03-15 12:36:44 +00001280static UChar *
sewardj2019a972011-03-07 16:04:07 +00001281s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1282{
sewardj652b56a2011-04-13 15:38:17 +00001283 vassert(s390_host_has_eimm);
1284
sewardj7ee97522011-05-09 21:45:04 +00001285 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001286 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1287
1288 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1289}
1290
1291
sewardj9d31dfd2011-03-15 12:36:44 +00001292static UChar *
sewardj2019a972011-03-07 16:04:07 +00001293s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1294{
sewardj7ee97522011-05-09 21:45:04 +00001295 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001296 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1297
1298 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1299}
1300
1301
sewardj9d31dfd2011-03-15 12:36:44 +00001302static UChar *
sewardj2019a972011-03-07 16:04:07 +00001303s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1304{
sewardj652b56a2011-04-13 15:38:17 +00001305 vassert(s390_host_has_ldisp);
1306
sewardj7ee97522011-05-09 21:45:04 +00001307 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001308 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1309
1310 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1311}
1312
1313
sewardj9d31dfd2011-03-15 12:36:44 +00001314static UChar *
sewardj2019a972011-03-07 16:04:07 +00001315s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1316{
sewardj7ee97522011-05-09 21:45:04 +00001317 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001318 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1319
1320 return emit_RI(p, 0xa70a0000, r1, i2);
1321}
1322
1323
sewardj9d31dfd2011-03-15 12:36:44 +00001324static UChar *
sewardj2019a972011-03-07 16:04:07 +00001325s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1326{
sewardj7ee97522011-05-09 21:45:04 +00001327 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001328 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1329
1330 return emit_RI(p, 0xa70b0000, r1, i2);
1331}
1332
1333
sewardj9d31dfd2011-03-15 12:36:44 +00001334static UChar *
florianad43b3a2012-02-20 15:01:14 +00001335s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1336{
1337 vassert(s390_host_has_gie);
1338
1339 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001340 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
florianad43b3a2012-02-20 15:01:14 +00001341
1342 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
1343}
1344
1345
1346static UChar *
florian0e047d62012-04-21 16:06:04 +00001347s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1348{
1349 vassert(s390_host_has_gie);
1350
1351 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001352 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
florian0e047d62012-04-21 16:06:04 +00001353
1354 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
1355}
1356
1357
1358static UChar *
sewardj2019a972011-03-07 16:04:07 +00001359s390_emit_NR(UChar *p, UChar r1, UChar r2)
1360{
sewardj7ee97522011-05-09 21:45:04 +00001361 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001362 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1363
1364 return emit_RR(p, 0x1400, r1, r2);
1365}
1366
1367
sewardj9d31dfd2011-03-15 12:36:44 +00001368static UChar *
sewardj2019a972011-03-07 16:04:07 +00001369s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1370{
sewardj7ee97522011-05-09 21:45:04 +00001371 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001372 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1373
1374 return emit_RRE(p, 0xb9800000, r1, r2);
1375}
1376
1377
sewardj9d31dfd2011-03-15 12:36:44 +00001378static UChar *
sewardj2019a972011-03-07 16:04:07 +00001379s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1380{
sewardj7ee97522011-05-09 21:45:04 +00001381 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001382 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1383
1384 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1385}
1386
1387
sewardj9d31dfd2011-03-15 12:36:44 +00001388static UChar *
sewardj2019a972011-03-07 16:04:07 +00001389s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1390{
sewardj652b56a2011-04-13 15:38:17 +00001391 vassert(s390_host_has_ldisp);
1392
sewardj7ee97522011-05-09 21:45:04 +00001393 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001394 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1395
1396 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1397}
1398
1399
sewardj9d31dfd2011-03-15 12:36:44 +00001400static UChar *
sewardj2019a972011-03-07 16:04:07 +00001401s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1402{
sewardj652b56a2011-04-13 15:38:17 +00001403 vassert(s390_host_has_ldisp || dh2 == 0);
1404
sewardj7ee97522011-05-09 21:45:04 +00001405 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001406 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1407
1408 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1409}
1410
1411
sewardj9d31dfd2011-03-15 12:36:44 +00001412static UChar *
sewardj2019a972011-03-07 16:04:07 +00001413s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1414{
sewardj652b56a2011-04-13 15:38:17 +00001415 vassert(s390_host_has_eimm);
1416
sewardj7ee97522011-05-09 21:45:04 +00001417 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001418 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1419
1420 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1421}
1422
1423
sewardj9d31dfd2011-03-15 12:36:44 +00001424static UChar *
sewardj2019a972011-03-07 16:04:07 +00001425s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1426{
sewardj652b56a2011-04-13 15:38:17 +00001427 vassert(s390_host_has_eimm);
1428
sewardj7ee97522011-05-09 21:45:04 +00001429 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001430 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1431
1432 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1433}
1434
1435
sewardj9d31dfd2011-03-15 12:36:44 +00001436static UChar *
sewardj2019a972011-03-07 16:04:07 +00001437s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1438{
sewardj7ee97522011-05-09 21:45:04 +00001439 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001440 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1441
1442 return emit_RI(p, 0xa5070000, r1, i2);
1443}
1444
1445
sewardj9d31dfd2011-03-15 12:36:44 +00001446static UChar *
sewardj2019a972011-03-07 16:04:07 +00001447s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1448{
sewardj7ee97522011-05-09 21:45:04 +00001449 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001450 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1451
1452 return emit_RR(p, 0x0d00, r1, r2);
1453}
1454
1455
sewardj9d31dfd2011-03-15 12:36:44 +00001456static UChar *
sewardj2019a972011-03-07 16:04:07 +00001457s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1458{
sewardj7ee97522011-05-09 21:45:04 +00001459 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001460 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1461
1462 return emit_RR(p, 0x0700, r1, r2);
1463}
1464
1465
sewardj9d31dfd2011-03-15 12:36:44 +00001466static UChar *
sewardj2019a972011-03-07 16:04:07 +00001467s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1468{
sewardj7ee97522011-05-09 21:45:04 +00001469 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001470 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1471
1472 return emit_RI(p, 0xa7040000, r1, i2);
1473}
1474
1475
sewardj9d31dfd2011-03-15 12:36:44 +00001476static UChar *
florian8844a632012-04-13 04:04:06 +00001477s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
1478{
1479 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1480 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
1481
1482 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
1483}
1484
1485
1486static UChar *
sewardj2019a972011-03-07 16:04:07 +00001487s390_emit_CR(UChar *p, UChar r1, UChar r2)
1488{
sewardj7ee97522011-05-09 21:45:04 +00001489 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001490 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1491
1492 return emit_RR(p, 0x1900, r1, r2);
1493}
1494
1495
sewardj9d31dfd2011-03-15 12:36:44 +00001496static UChar *
sewardj2019a972011-03-07 16:04:07 +00001497s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1498{
sewardj7ee97522011-05-09 21:45:04 +00001499 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001500 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1501
1502 return emit_RRE(p, 0xb9200000, r1, r2);
1503}
1504
1505
sewardj9d31dfd2011-03-15 12:36:44 +00001506static UChar *
sewardj2019a972011-03-07 16:04:07 +00001507s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1508{
sewardj7ee97522011-05-09 21:45:04 +00001509 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001510 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1511
1512 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1513}
1514
1515
sewardj9d31dfd2011-03-15 12:36:44 +00001516static UChar *
sewardj2019a972011-03-07 16:04:07 +00001517s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1518{
sewardj652b56a2011-04-13 15:38:17 +00001519 vassert(s390_host_has_ldisp);
1520
sewardj7ee97522011-05-09 21:45:04 +00001521 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001522 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1523
1524 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1525}
1526
1527
sewardj9d31dfd2011-03-15 12:36:44 +00001528static UChar *
sewardj2019a972011-03-07 16:04:07 +00001529s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1530{
sewardj652b56a2011-04-13 15:38:17 +00001531 vassert(s390_host_has_ldisp || dh2 == 0);
1532
sewardj7ee97522011-05-09 21:45:04 +00001533 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001534 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1535
1536 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1537}
1538
1539
sewardj9d31dfd2011-03-15 12:36:44 +00001540static UChar *
sewardj2019a972011-03-07 16:04:07 +00001541s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1542{
sewardj652b56a2011-04-13 15:38:17 +00001543 vassert(s390_host_has_eimm);
1544
sewardj7ee97522011-05-09 21:45:04 +00001545 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001546 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1547
1548 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1549}
1550
1551
sewardj9d31dfd2011-03-15 12:36:44 +00001552static UChar *
florian07d34552012-05-26 01:59:21 +00001553s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
1554{
1555 vassert(s390_host_has_eimm);
1556
1557 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1558 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
1559
1560 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
1561}
1562
1563
1564static UChar *
sewardj2019a972011-03-07 16:04:07 +00001565s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1566{
sewardj7ee97522011-05-09 21:45:04 +00001567 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001568 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1569
1570 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1571}
1572
1573
sewardj9d31dfd2011-03-15 12:36:44 +00001574static UChar *
sewardj2019a972011-03-07 16:04:07 +00001575s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1576{
sewardj652b56a2011-04-13 15:38:17 +00001577 vassert(s390_host_has_ldisp);
1578
sewardj7ee97522011-05-09 21:45:04 +00001579 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001580 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1581
1582 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1583}
1584
1585
sewardj9d31dfd2011-03-15 12:36:44 +00001586static UChar *
sewardj2019a972011-03-07 16:04:07 +00001587s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1588{
sewardj652b56a2011-04-13 15:38:17 +00001589 vassert(s390_host_has_ldisp || dh2 == 0);
1590
sewardj7ee97522011-05-09 21:45:04 +00001591 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001592 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1593
1594 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1595}
1596
1597
sewardj9d31dfd2011-03-15 12:36:44 +00001598static UChar *
florian448cbba2012-06-06 02:26:01 +00001599s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1600{
1601 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1602 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
1603
1604 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
1605}
1606
1607
1608static UChar *
1609s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1610{
1611 vassert(s390_host_has_ldisp);
1612
1613 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1614 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
1615
1616 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
1617}
1618
1619
1620static UChar *
1621s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1622{
1623 vassert(s390_host_has_ldisp || dh2 == 0);
1624
1625 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1626 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
1627
1628 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
1629}
1630
1631
1632static UChar *
sewardj2019a972011-03-07 16:04:07 +00001633s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1634{
sewardj7ee97522011-05-09 21:45:04 +00001635 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001636 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1637
1638 return emit_RR(p, 0x1500, r1, r2);
1639}
1640
1641
sewardj9d31dfd2011-03-15 12:36:44 +00001642static UChar *
sewardj2019a972011-03-07 16:04:07 +00001643s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1644{
sewardj7ee97522011-05-09 21:45:04 +00001645 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001646 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1647
1648 return emit_RRE(p, 0xb9210000, r1, r2);
1649}
1650
1651
sewardj9d31dfd2011-03-15 12:36:44 +00001652static UChar *
sewardj2019a972011-03-07 16:04:07 +00001653s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1654{
sewardj7ee97522011-05-09 21:45:04 +00001655 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001656 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1657
1658 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1659}
1660
1661
sewardj9d31dfd2011-03-15 12:36:44 +00001662static UChar *
sewardj2019a972011-03-07 16:04:07 +00001663s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1664{
sewardj652b56a2011-04-13 15:38:17 +00001665 vassert(s390_host_has_ldisp);
1666
sewardj7ee97522011-05-09 21:45:04 +00001667 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001668 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1669
1670 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1671}
1672
1673
sewardj9d31dfd2011-03-15 12:36:44 +00001674static UChar *
sewardj2019a972011-03-07 16:04:07 +00001675s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1676{
sewardj652b56a2011-04-13 15:38:17 +00001677 vassert(s390_host_has_ldisp || dh2 == 0);
1678
sewardj7ee97522011-05-09 21:45:04 +00001679 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001680 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1681
1682 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1683}
1684
1685
sewardj9d31dfd2011-03-15 12:36:44 +00001686static UChar *
sewardj2019a972011-03-07 16:04:07 +00001687s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1688{
sewardj652b56a2011-04-13 15:38:17 +00001689 vassert(s390_host_has_eimm);
1690
sewardj7ee97522011-05-09 21:45:04 +00001691 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001692 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1693
1694 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1695}
1696
1697
sewardj9d31dfd2011-03-15 12:36:44 +00001698static UChar *
florian07d34552012-05-26 01:59:21 +00001699s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
1700{
1701 vassert(s390_host_has_eimm);
1702
1703 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1704 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
1705
1706 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
1707}
1708
1709
1710static UChar *
sewardj2019a972011-03-07 16:04:07 +00001711s390_emit_DR(UChar *p, UChar r1, UChar r2)
1712{
sewardj7ee97522011-05-09 21:45:04 +00001713 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001714 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1715
1716 return emit_RR(p, 0x1d00, r1, r2);
1717}
1718
1719
sewardj9d31dfd2011-03-15 12:36:44 +00001720static UChar *
sewardj2019a972011-03-07 16:04:07 +00001721s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1722{
sewardj7ee97522011-05-09 21:45:04 +00001723 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001724 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1725
1726 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1727}
1728
1729
sewardj9d31dfd2011-03-15 12:36:44 +00001730static UChar *
sewardj2019a972011-03-07 16:04:07 +00001731s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1732{
sewardj7ee97522011-05-09 21:45:04 +00001733 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001734 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1735
1736 return emit_RRE(p, 0xb9970000, r1, r2);
1737}
1738
1739
sewardj9d31dfd2011-03-15 12:36:44 +00001740static UChar *
sewardj2019a972011-03-07 16:04:07 +00001741s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
1742{
sewardj7ee97522011-05-09 21:45:04 +00001743 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001744 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
1745
1746 return emit_RRE(p, 0xb9870000, r1, r2);
1747}
1748
1749
sewardj9d31dfd2011-03-15 12:36:44 +00001750static UChar *
sewardj2019a972011-03-07 16:04:07 +00001751s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1752{
sewardj652b56a2011-04-13 15:38:17 +00001753 vassert(s390_host_has_ldisp || dh2 == 0);
1754
sewardj7ee97522011-05-09 21:45:04 +00001755 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001756 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
1757
1758 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
1759}
1760
1761
sewardj9d31dfd2011-03-15 12:36:44 +00001762static UChar *
sewardj2019a972011-03-07 16:04:07 +00001763s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1764{
sewardj652b56a2011-04-13 15:38:17 +00001765 vassert(s390_host_has_ldisp || dh2 == 0);
1766
sewardj7ee97522011-05-09 21:45:04 +00001767 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001768 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
1769
1770 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
1771}
1772
1773
sewardj9d31dfd2011-03-15 12:36:44 +00001774static UChar *
sewardj2019a972011-03-07 16:04:07 +00001775s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
1776{
sewardj7ee97522011-05-09 21:45:04 +00001777 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001778 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
1779
1780 return emit_RRE(p, 0xb90d0000, r1, r2);
1781}
1782
1783
sewardj9d31dfd2011-03-15 12:36:44 +00001784static UChar *
sewardj2019a972011-03-07 16:04:07 +00001785s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1786{
sewardj652b56a2011-04-13 15:38:17 +00001787 vassert(s390_host_has_ldisp || dh2 == 0);
1788
sewardj7ee97522011-05-09 21:45:04 +00001789 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001790 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
1791
1792 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
1793}
1794
1795
sewardj9d31dfd2011-03-15 12:36:44 +00001796static UChar *
sewardj2019a972011-03-07 16:04:07 +00001797s390_emit_XR(UChar *p, UChar r1, UChar r2)
1798{
sewardj7ee97522011-05-09 21:45:04 +00001799 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001800 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
1801
1802 return emit_RR(p, 0x1700, r1, r2);
1803}
1804
1805
sewardj9d31dfd2011-03-15 12:36:44 +00001806static UChar *
sewardj2019a972011-03-07 16:04:07 +00001807s390_emit_XGR(UChar *p, UChar r1, UChar r2)
1808{
sewardj7ee97522011-05-09 21:45:04 +00001809 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001810 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
1811
1812 return emit_RRE(p, 0xb9820000, r1, r2);
1813}
1814
1815
sewardj9d31dfd2011-03-15 12:36:44 +00001816static UChar *
sewardj2019a972011-03-07 16:04:07 +00001817s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1818{
sewardj7ee97522011-05-09 21:45:04 +00001819 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001820 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
1821
1822 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
1823}
1824
1825
sewardj9d31dfd2011-03-15 12:36:44 +00001826static UChar *
sewardj2019a972011-03-07 16:04:07 +00001827s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1828{
sewardj652b56a2011-04-13 15:38:17 +00001829 vassert(s390_host_has_ldisp);
1830
sewardj7ee97522011-05-09 21:45:04 +00001831 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001832 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
1833
1834 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
1835}
1836
1837
sewardj9d31dfd2011-03-15 12:36:44 +00001838static UChar *
sewardj2019a972011-03-07 16:04:07 +00001839s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1840{
sewardj652b56a2011-04-13 15:38:17 +00001841 vassert(s390_host_has_ldisp || dh2 == 0);
1842
sewardj7ee97522011-05-09 21:45:04 +00001843 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001844 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
1845
1846 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
1847}
1848
1849
sewardj9d31dfd2011-03-15 12:36:44 +00001850static UChar *
sewardj2019a972011-03-07 16:04:07 +00001851s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
1852{
sewardj652b56a2011-04-13 15:38:17 +00001853 vassert(s390_host_has_eimm);
1854
sewardj7ee97522011-05-09 21:45:04 +00001855 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001856 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
1857
1858 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
1859}
1860
1861
sewardj9d31dfd2011-03-15 12:36:44 +00001862static UChar *
sewardj2019a972011-03-07 16:04:07 +00001863s390_emit_XILF(UChar *p, UChar r1, UInt i2)
1864{
sewardj652b56a2011-04-13 15:38:17 +00001865 vassert(s390_host_has_eimm);
1866
sewardj7ee97522011-05-09 21:45:04 +00001867 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001868 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
1869
1870 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
1871}
1872
1873
sewardj9d31dfd2011-03-15 12:36:44 +00001874static UChar *
florianad43b3a2012-02-20 15:01:14 +00001875s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
1876{
1877 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1878 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
1879
1880 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
1881}
1882
1883
1884static UChar *
sewardj2019a972011-03-07 16:04:07 +00001885s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
1886{
sewardj652b56a2011-04-13 15:38:17 +00001887 vassert(s390_host_has_eimm);
1888
sewardj7ee97522011-05-09 21:45:04 +00001889 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001890 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
1891
1892 return emit_RRE(p, 0xb9830000, r1, r2);
1893}
1894
1895
sewardj9d31dfd2011-03-15 12:36:44 +00001896static UChar *
sewardj2019a972011-03-07 16:04:07 +00001897s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1898{
sewardj7ee97522011-05-09 21:45:04 +00001899 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001900 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
1901
1902 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
1903}
1904
1905
sewardj9d31dfd2011-03-15 12:36:44 +00001906static UChar *
sewardj2019a972011-03-07 16:04:07 +00001907s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1908{
sewardj652b56a2011-04-13 15:38:17 +00001909 vassert(s390_host_has_ldisp);
1910
sewardj7ee97522011-05-09 21:45:04 +00001911 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001912 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
1913
1914 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
1915}
1916
1917
sewardj9d31dfd2011-03-15 12:36:44 +00001918static UChar *
sewardj2019a972011-03-07 16:04:07 +00001919s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
1920{
sewardj652b56a2011-04-13 15:38:17 +00001921 vassert(s390_host_has_eimm);
1922
sewardj7ee97522011-05-09 21:45:04 +00001923 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001924 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
1925
1926 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
1927}
1928
1929
sewardj9d31dfd2011-03-15 12:36:44 +00001930static UChar *
sewardj2019a972011-03-07 16:04:07 +00001931s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
1932{
sewardj7ee97522011-05-09 21:45:04 +00001933 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001934 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
1935
1936 return emit_RI(p, 0xa5000000, r1, i2);
1937}
1938
1939
sewardj9d31dfd2011-03-15 12:36:44 +00001940static UChar *
sewardj2019a972011-03-07 16:04:07 +00001941s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
1942{
sewardj7ee97522011-05-09 21:45:04 +00001943 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001944 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
1945
1946 return emit_RI(p, 0xa5010000, r1, i2);
1947}
1948
1949
sewardj9d31dfd2011-03-15 12:36:44 +00001950static UChar *
sewardj2019a972011-03-07 16:04:07 +00001951s390_emit_IILF(UChar *p, UChar r1, UInt i2)
1952{
sewardj652b56a2011-04-13 15:38:17 +00001953 vassert(s390_host_has_eimm);
1954
sewardj7ee97522011-05-09 21:45:04 +00001955 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001956 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
1957
1958 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
1959}
1960
1961
sewardj9d31dfd2011-03-15 12:36:44 +00001962static UChar *
sewardj2019a972011-03-07 16:04:07 +00001963s390_emit_IILH(UChar *p, UChar r1, UShort i2)
1964{
sewardj7ee97522011-05-09 21:45:04 +00001965 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001966 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
1967
1968 return emit_RI(p, 0xa5020000, r1, i2);
1969}
1970
1971
sewardj9d31dfd2011-03-15 12:36:44 +00001972static UChar *
sewardj2019a972011-03-07 16:04:07 +00001973s390_emit_IILL(UChar *p, UChar r1, UShort i2)
1974{
sewardj7ee97522011-05-09 21:45:04 +00001975 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001976 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
1977
1978 return emit_RI(p, 0xa5030000, r1, i2);
1979}
1980
1981
sewardj9d31dfd2011-03-15 12:36:44 +00001982static UChar *
sewardj2019a972011-03-07 16:04:07 +00001983s390_emit_IPM(UChar *p, UChar r1, UChar r2)
1984{
sewardj7ee97522011-05-09 21:45:04 +00001985 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001986 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
1987
1988 return emit_RRE(p, 0xb2220000, r1, r2);
1989}
1990
1991
sewardj9d31dfd2011-03-15 12:36:44 +00001992static UChar *
sewardj2019a972011-03-07 16:04:07 +00001993s390_emit_LR(UChar *p, UChar r1, UChar r2)
1994{
sewardj7ee97522011-05-09 21:45:04 +00001995 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001996 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
1997
1998 return emit_RR(p, 0x1800, r1, r2);
1999}
2000
2001
sewardj9d31dfd2011-03-15 12:36:44 +00002002static UChar *
sewardj2019a972011-03-07 16:04:07 +00002003s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2004{
sewardj7ee97522011-05-09 21:45:04 +00002005 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002006 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2007
2008 return emit_RRE(p, 0xb9040000, r1, r2);
2009}
2010
2011
sewardj9d31dfd2011-03-15 12:36:44 +00002012static UChar *
sewardj2019a972011-03-07 16:04:07 +00002013s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2014{
sewardj7ee97522011-05-09 21:45:04 +00002015 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002016 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2017
2018 return emit_RRE(p, 0xb9140000, r1, r2);
2019}
2020
2021
sewardj9d31dfd2011-03-15 12:36:44 +00002022static UChar *
sewardj2019a972011-03-07 16:04:07 +00002023s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2024{
sewardj7ee97522011-05-09 21:45:04 +00002025 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002026 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2027
2028 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2029}
2030
2031
sewardj9d31dfd2011-03-15 12:36:44 +00002032static UChar *
sewardj2019a972011-03-07 16:04:07 +00002033s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2034{
sewardj652b56a2011-04-13 15:38:17 +00002035 vassert(s390_host_has_ldisp);
2036
sewardj7ee97522011-05-09 21:45:04 +00002037 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002038 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2039
2040 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2041}
2042
2043
sewardj9d31dfd2011-03-15 12:36:44 +00002044static UChar *
sewardj2019a972011-03-07 16:04:07 +00002045s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2046{
sewardj652b56a2011-04-13 15:38:17 +00002047 vassert(s390_host_has_ldisp || dh2 == 0);
2048
sewardj7ee97522011-05-09 21:45:04 +00002049 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002050 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2051
2052 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2053}
2054
2055
sewardj9d31dfd2011-03-15 12:36:44 +00002056static UChar *
sewardj2019a972011-03-07 16:04:07 +00002057s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2058{
sewardj652b56a2011-04-13 15:38:17 +00002059 vassert(s390_host_has_ldisp || dh2 == 0);
2060
sewardj7ee97522011-05-09 21:45:04 +00002061 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002062 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2063
2064 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2065}
2066
2067
sewardj9d31dfd2011-03-15 12:36:44 +00002068static UChar *
sewardj2019a972011-03-07 16:04:07 +00002069s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2070{
sewardj652b56a2011-04-13 15:38:17 +00002071 vassert(s390_host_has_eimm);
2072
sewardj7ee97522011-05-09 21:45:04 +00002073 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002074 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2075
2076 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2077}
2078
2079
sewardj9d31dfd2011-03-15 12:36:44 +00002080static UChar *
sewardj2019a972011-03-07 16:04:07 +00002081s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2082{
sewardj7ee97522011-05-09 21:45:04 +00002083 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002084 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2085
2086 return emit_RR(p, 0x1200, r1, r2);
2087}
2088
2089
sewardj9d31dfd2011-03-15 12:36:44 +00002090static UChar *
sewardj2019a972011-03-07 16:04:07 +00002091s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2092{
sewardj7ee97522011-05-09 21:45:04 +00002093 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002094 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2095
2096 return emit_RRE(p, 0xb9020000, r1, r2);
2097}
2098
2099
sewardj9d31dfd2011-03-15 12:36:44 +00002100static UChar *
sewardj2019a972011-03-07 16:04:07 +00002101s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2102{
sewardj652b56a2011-04-13 15:38:17 +00002103 vassert(s390_host_has_eimm);
2104
sewardj7ee97522011-05-09 21:45:04 +00002105 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002106 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2107
2108 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2109}
2110
2111
sewardj9d31dfd2011-03-15 12:36:44 +00002112static UChar *
sewardj2019a972011-03-07 16:04:07 +00002113s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2114{
sewardj652b56a2011-04-13 15:38:17 +00002115 vassert(s390_host_has_eimm);
2116
sewardj7ee97522011-05-09 21:45:04 +00002117 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002118 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2119
2120 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2121}
2122
2123
sewardj9d31dfd2011-03-15 12:36:44 +00002124static UChar *
sewardj2019a972011-03-07 16:04:07 +00002125s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2126{
sewardj652b56a2011-04-13 15:38:17 +00002127 vassert(s390_host_has_eimm);
2128
sewardj7ee97522011-05-09 21:45:04 +00002129 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002130 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2131
2132 return emit_RRE(p, 0xb9260000, r1, r2);
2133}
2134
2135
sewardj9d31dfd2011-03-15 12:36:44 +00002136static UChar *
sewardj2019a972011-03-07 16:04:07 +00002137s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2138{
sewardj652b56a2011-04-13 15:38:17 +00002139 vassert(s390_host_has_eimm);
2140
sewardj7ee97522011-05-09 21:45:04 +00002141 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002142 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2143
2144 return emit_RRE(p, 0xb9060000, r1, r2);
2145}
2146
2147
sewardj9d31dfd2011-03-15 12:36:44 +00002148static UChar *
sewardj2019a972011-03-07 16:04:07 +00002149s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2150{
sewardj652b56a2011-04-13 15:38:17 +00002151 vassert(s390_host_has_ldisp);
2152
sewardj7ee97522011-05-09 21:45:04 +00002153 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002154 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2155
2156 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2157}
2158
2159
sewardj9d31dfd2011-03-15 12:36:44 +00002160static UChar *
sewardj2019a972011-03-07 16:04:07 +00002161s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2162{
sewardj652b56a2011-04-13 15:38:17 +00002163 vassert(s390_host_has_ldisp);
2164
sewardj7ee97522011-05-09 21:45:04 +00002165 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002166 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2167
2168 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2169}
2170
2171
sewardj9d31dfd2011-03-15 12:36:44 +00002172static UChar *
sewardj2019a972011-03-07 16:04:07 +00002173s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2174{
sewardj7ee97522011-05-09 21:45:04 +00002175 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002176 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2177
2178 return emit_RR(p, 0x1300, r1, r2);
2179}
2180
2181
sewardj9d31dfd2011-03-15 12:36:44 +00002182static UChar *
sewardj2019a972011-03-07 16:04:07 +00002183s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2184{
sewardj7ee97522011-05-09 21:45:04 +00002185 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002186 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2187
2188 return emit_RRE(p, 0xb9030000, r1, r2);
2189}
2190
2191
sewardj9d31dfd2011-03-15 12:36:44 +00002192static UChar *
sewardj2019a972011-03-07 16:04:07 +00002193s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2194{
sewardj652b56a2011-04-13 15:38:17 +00002195 vassert(s390_host_has_eimm);
2196
sewardj7ee97522011-05-09 21:45:04 +00002197 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002198 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2199
2200 return emit_RRE(p, 0xb9270000, r1, r2);
2201}
2202
2203
sewardj9d31dfd2011-03-15 12:36:44 +00002204static UChar *
sewardj2019a972011-03-07 16:04:07 +00002205s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2206{
sewardj652b56a2011-04-13 15:38:17 +00002207 vassert(s390_host_has_eimm);
2208
sewardj7ee97522011-05-09 21:45:04 +00002209 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002210 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2211
2212 return emit_RRE(p, 0xb9070000, r1, r2);
2213}
2214
2215
sewardj9d31dfd2011-03-15 12:36:44 +00002216static UChar *
sewardj2019a972011-03-07 16:04:07 +00002217s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2218{
sewardj7ee97522011-05-09 21:45:04 +00002219 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002220 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2221
2222 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2223}
2224
2225
sewardj9d31dfd2011-03-15 12:36:44 +00002226static UChar *
sewardj2019a972011-03-07 16:04:07 +00002227s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2228{
sewardj652b56a2011-04-13 15:38:17 +00002229 vassert(s390_host_has_ldisp);
2230
sewardj7ee97522011-05-09 21:45:04 +00002231 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002232 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2233
2234 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2235}
2236
2237
sewardj9d31dfd2011-03-15 12:36:44 +00002238static UChar *
sewardj2019a972011-03-07 16:04:07 +00002239s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2240{
sewardj652b56a2011-04-13 15:38:17 +00002241 vassert(s390_host_has_ldisp || dh2 == 0);
2242
sewardj7ee97522011-05-09 21:45:04 +00002243 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002244 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2245
2246 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2247}
2248
2249
sewardj9d31dfd2011-03-15 12:36:44 +00002250static UChar *
sewardj2019a972011-03-07 16:04:07 +00002251s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2252{
sewardj7ee97522011-05-09 21:45:04 +00002253 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002254 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2255
2256 return emit_RI(p, 0xa7080000, r1, i2);
2257}
2258
2259
sewardj9d31dfd2011-03-15 12:36:44 +00002260static UChar *
sewardj2019a972011-03-07 16:04:07 +00002261s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2262{
sewardj7ee97522011-05-09 21:45:04 +00002263 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002264 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2265
2266 return emit_RI(p, 0xa7090000, r1, i2);
2267}
2268
2269
sewardj9d31dfd2011-03-15 12:36:44 +00002270static UChar *
sewardj2019a972011-03-07 16:04:07 +00002271s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2272{
sewardj7ee97522011-05-09 21:45:04 +00002273 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002274 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2275
2276 return emit_RRE(p, 0xb9160000, r1, r2);
2277}
2278
2279
sewardj9d31dfd2011-03-15 12:36:44 +00002280static UChar *
sewardj2019a972011-03-07 16:04:07 +00002281s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2282{
sewardj652b56a2011-04-13 15:38:17 +00002283 vassert(s390_host_has_ldisp || dh2 == 0);
2284
sewardj7ee97522011-05-09 21:45:04 +00002285 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002286 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2287
2288 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2289}
2290
2291
sewardj9d31dfd2011-03-15 12:36:44 +00002292static UChar *
sewardj2019a972011-03-07 16:04:07 +00002293s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2294{
sewardj652b56a2011-04-13 15:38:17 +00002295 vassert(s390_host_has_eimm);
2296
sewardj7ee97522011-05-09 21:45:04 +00002297 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002298 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2299
2300 return emit_RRE(p, 0xb9940000, r1, r2);
2301}
2302
2303
sewardj9d31dfd2011-03-15 12:36:44 +00002304static UChar *
sewardj2019a972011-03-07 16:04:07 +00002305s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2306{
sewardj652b56a2011-04-13 15:38:17 +00002307 vassert(s390_host_has_eimm);
2308
sewardj7ee97522011-05-09 21:45:04 +00002309 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002310 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2311
2312 return emit_RRE(p, 0xb9840000, r1, r2);
2313}
2314
2315
sewardj9d31dfd2011-03-15 12:36:44 +00002316static UChar *
sewardj2019a972011-03-07 16:04:07 +00002317s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2318{
sewardj652b56a2011-04-13 15:38:17 +00002319 vassert(s390_host_has_eimm);
2320
sewardj7ee97522011-05-09 21:45:04 +00002321 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002322 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2323
2324 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2325}
2326
2327
sewardj9d31dfd2011-03-15 12:36:44 +00002328static UChar *
sewardj2019a972011-03-07 16:04:07 +00002329s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2330{
sewardj652b56a2011-04-13 15:38:17 +00002331 vassert(s390_host_has_ldisp || dh2 == 0);
2332
sewardj7ee97522011-05-09 21:45:04 +00002333 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002334 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2335
2336 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2337}
2338
2339
sewardj9d31dfd2011-03-15 12:36:44 +00002340static UChar *
sewardj2019a972011-03-07 16:04:07 +00002341s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2342{
sewardj652b56a2011-04-13 15:38:17 +00002343 vassert(s390_host_has_eimm);
2344
sewardj7ee97522011-05-09 21:45:04 +00002345 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002346 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2347
2348 return emit_RRE(p, 0xb9950000, r1, r2);
2349}
2350
2351
sewardj9d31dfd2011-03-15 12:36:44 +00002352static UChar *
sewardj2019a972011-03-07 16:04:07 +00002353s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2354{
sewardj652b56a2011-04-13 15:38:17 +00002355 vassert(s390_host_has_eimm);
2356
sewardj7ee97522011-05-09 21:45:04 +00002357 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002358 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2359
2360 return emit_RRE(p, 0xb9850000, r1, r2);
2361}
2362
2363
sewardj9d31dfd2011-03-15 12:36:44 +00002364static UChar *
sewardj2019a972011-03-07 16:04:07 +00002365s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2366{
sewardj652b56a2011-04-13 15:38:17 +00002367 vassert(s390_host_has_eimm);
2368
sewardj7ee97522011-05-09 21:45:04 +00002369 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002370 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2371
2372 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2373}
2374
2375
sewardj9d31dfd2011-03-15 12:36:44 +00002376static UChar *
sewardj2019a972011-03-07 16:04:07 +00002377s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2378{
sewardj652b56a2011-04-13 15:38:17 +00002379 vassert(s390_host_has_ldisp || dh2 == 0);
2380
sewardj7ee97522011-05-09 21:45:04 +00002381 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002382 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2383
2384 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2385}
2386
2387
sewardj9d31dfd2011-03-15 12:36:44 +00002388static UChar *
sewardj2019a972011-03-07 16:04:07 +00002389s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2390{
sewardj652b56a2011-04-13 15:38:17 +00002391 vassert(s390_host_has_eimm);
2392
sewardj7ee97522011-05-09 21:45:04 +00002393 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002394 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2395
2396 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2397}
2398
2399
sewardj9d31dfd2011-03-15 12:36:44 +00002400static UChar *
sewardj2019a972011-03-07 16:04:07 +00002401s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2402{
sewardj7ee97522011-05-09 21:45:04 +00002403 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002404 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2405
2406 return emit_RI(p, 0xa50e0000, r1, i2);
2407}
2408
2409
sewardj9d31dfd2011-03-15 12:36:44 +00002410static UChar *
sewardj2019a972011-03-07 16:04:07 +00002411s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2412{
sewardj7ee97522011-05-09 21:45:04 +00002413 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002414 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2415
2416 return emit_RI(p, 0xa50f0000, r1, i2);
2417}
2418
2419
sewardj9d31dfd2011-03-15 12:36:44 +00002420static UChar *
sewardj2019a972011-03-07 16:04:07 +00002421s390_emit_MR(UChar *p, UChar r1, UChar r2)
2422{
sewardj7ee97522011-05-09 21:45:04 +00002423 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002424 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2425
2426 return emit_RR(p, 0x1c00, r1, r2);
2427}
2428
2429
sewardj9d31dfd2011-03-15 12:36:44 +00002430static UChar *
sewardj2019a972011-03-07 16:04:07 +00002431s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2432{
sewardj7ee97522011-05-09 21:45:04 +00002433 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002434 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2435
2436 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2437}
2438
2439
sewardj9d31dfd2011-03-15 12:36:44 +00002440static UChar *
sewardj2019a972011-03-07 16:04:07 +00002441s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2442{
sewardj652b56a2011-04-13 15:38:17 +00002443 vassert(s390_host_has_gie);
2444
sewardj7ee97522011-05-09 21:45:04 +00002445 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002446 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2447
2448 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2449}
2450
2451
sewardj9d31dfd2011-03-15 12:36:44 +00002452static UChar *
sewardj2019a972011-03-07 16:04:07 +00002453s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2454{
sewardj7ee97522011-05-09 21:45:04 +00002455 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002456 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2457
2458 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2459}
2460
2461
sewardj9d31dfd2011-03-15 12:36:44 +00002462static UChar *
sewardj2019a972011-03-07 16:04:07 +00002463s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2464{
sewardj652b56a2011-04-13 15:38:17 +00002465 vassert(s390_host_has_gie);
2466
sewardj7ee97522011-05-09 21:45:04 +00002467 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002468 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2469
2470 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2471}
2472
2473
sewardj9d31dfd2011-03-15 12:36:44 +00002474static UChar *
sewardj2019a972011-03-07 16:04:07 +00002475s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2476{
sewardj7ee97522011-05-09 21:45:04 +00002477 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002478 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2479
2480 return emit_RI(p, 0xa70c0000, r1, i2);
2481}
2482
2483
sewardj9d31dfd2011-03-15 12:36:44 +00002484static UChar *
sewardj2019a972011-03-07 16:04:07 +00002485s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2486{
sewardj7ee97522011-05-09 21:45:04 +00002487 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002488 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2489
2490 return emit_RRE(p, 0xb9960000, r1, r2);
2491}
2492
2493
sewardj9d31dfd2011-03-15 12:36:44 +00002494static UChar *
sewardj2019a972011-03-07 16:04:07 +00002495s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2496{
sewardj7ee97522011-05-09 21:45:04 +00002497 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002498 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2499
2500 return emit_RRE(p, 0xb9860000, r1, r2);
2501}
2502
2503
sewardj9d31dfd2011-03-15 12:36:44 +00002504static UChar *
sewardj2019a972011-03-07 16:04:07 +00002505s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2506{
sewardj652b56a2011-04-13 15:38:17 +00002507 vassert(s390_host_has_ldisp || dh2 == 0);
2508
sewardj7ee97522011-05-09 21:45:04 +00002509 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002510 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2511
2512 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2513}
2514
2515
sewardj9d31dfd2011-03-15 12:36:44 +00002516static UChar *
sewardj2019a972011-03-07 16:04:07 +00002517s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2518{
sewardj652b56a2011-04-13 15:38:17 +00002519 vassert(s390_host_has_ldisp || dh2 == 0);
2520
sewardj7ee97522011-05-09 21:45:04 +00002521 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002522 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2523
2524 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2525}
2526
2527
sewardj9d31dfd2011-03-15 12:36:44 +00002528static UChar *
sewardj2019a972011-03-07 16:04:07 +00002529s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2530{
sewardj7ee97522011-05-09 21:45:04 +00002531 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002532 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2533
2534 return emit_RRE(p, 0xb2520000, r1, r2);
2535}
2536
2537
sewardj9d31dfd2011-03-15 12:36:44 +00002538static UChar *
sewardj2019a972011-03-07 16:04:07 +00002539s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2540{
sewardj7ee97522011-05-09 21:45:04 +00002541 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002542 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2543
2544 return emit_RRE(p, 0xb90c0000, r1, r2);
2545}
2546
2547
sewardj9d31dfd2011-03-15 12:36:44 +00002548static UChar *
sewardj2019a972011-03-07 16:04:07 +00002549s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2550{
sewardj7ee97522011-05-09 21:45:04 +00002551 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002552 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2553
2554 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2555}
2556
2557
sewardj9d31dfd2011-03-15 12:36:44 +00002558static UChar *
sewardj2019a972011-03-07 16:04:07 +00002559s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2560{
sewardj652b56a2011-04-13 15:38:17 +00002561 vassert(s390_host_has_ldisp);
2562
sewardj7ee97522011-05-09 21:45:04 +00002563 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002564 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2565
2566 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2567}
2568
2569
sewardj9d31dfd2011-03-15 12:36:44 +00002570static UChar *
sewardj2019a972011-03-07 16:04:07 +00002571s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2572{
sewardj652b56a2011-04-13 15:38:17 +00002573 vassert(s390_host_has_ldisp || dh2 == 0);
2574
sewardj7ee97522011-05-09 21:45:04 +00002575 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002576 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2577
2578 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2579}
2580
2581
sewardj9d31dfd2011-03-15 12:36:44 +00002582static UChar *
sewardj2019a972011-03-07 16:04:07 +00002583s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2584{
sewardj652b56a2011-04-13 15:38:17 +00002585 vassert(s390_host_has_gie);
2586
sewardj7ee97522011-05-09 21:45:04 +00002587 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002588 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2589
2590 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2591}
2592
2593
sewardj9d31dfd2011-03-15 12:36:44 +00002594static UChar *
sewardj2019a972011-03-07 16:04:07 +00002595s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2596{
sewardj652b56a2011-04-13 15:38:17 +00002597 vassert(s390_host_has_gie);
2598
sewardj7ee97522011-05-09 21:45:04 +00002599 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002600 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2601
2602 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2603}
2604
2605
sewardj9d31dfd2011-03-15 12:36:44 +00002606static UChar *
sewardj2019a972011-03-07 16:04:07 +00002607s390_emit_OR(UChar *p, UChar r1, UChar r2)
2608{
sewardj7ee97522011-05-09 21:45:04 +00002609 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002610 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2611
2612 return emit_RR(p, 0x1600, r1, r2);
2613}
2614
2615
sewardj9d31dfd2011-03-15 12:36:44 +00002616static UChar *
sewardj2019a972011-03-07 16:04:07 +00002617s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2618{
sewardj7ee97522011-05-09 21:45:04 +00002619 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002620 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2621
2622 return emit_RRE(p, 0xb9810000, r1, r2);
2623}
2624
2625
sewardj9d31dfd2011-03-15 12:36:44 +00002626static UChar *
sewardj2019a972011-03-07 16:04:07 +00002627s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2628{
sewardj7ee97522011-05-09 21:45:04 +00002629 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002630 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2631
2632 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2633}
2634
2635
sewardj9d31dfd2011-03-15 12:36:44 +00002636static UChar *
sewardj2019a972011-03-07 16:04:07 +00002637s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2638{
sewardj652b56a2011-04-13 15:38:17 +00002639 vassert(s390_host_has_ldisp);
2640
sewardj7ee97522011-05-09 21:45:04 +00002641 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002642 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2643
2644 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2645}
2646
2647
sewardj9d31dfd2011-03-15 12:36:44 +00002648static UChar *
sewardj2019a972011-03-07 16:04:07 +00002649s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2650{
sewardj652b56a2011-04-13 15:38:17 +00002651 vassert(s390_host_has_ldisp || dh2 == 0);
2652
sewardj7ee97522011-05-09 21:45:04 +00002653 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002654 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2655
2656 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2657}
2658
2659
sewardj9d31dfd2011-03-15 12:36:44 +00002660static UChar *
sewardj2019a972011-03-07 16:04:07 +00002661s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2662{
sewardj652b56a2011-04-13 15:38:17 +00002663 vassert(s390_host_has_eimm);
2664
sewardj7ee97522011-05-09 21:45:04 +00002665 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002666 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2667
2668 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2669}
2670
2671
sewardj9d31dfd2011-03-15 12:36:44 +00002672static UChar *
sewardj2019a972011-03-07 16:04:07 +00002673s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2674{
sewardj652b56a2011-04-13 15:38:17 +00002675 vassert(s390_host_has_eimm);
2676
sewardj7ee97522011-05-09 21:45:04 +00002677 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002678 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2679
2680 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2681}
2682
2683
sewardj9d31dfd2011-03-15 12:36:44 +00002684static UChar *
sewardj2019a972011-03-07 16:04:07 +00002685s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2686{
sewardj7ee97522011-05-09 21:45:04 +00002687 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002688 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2689
2690 return emit_RI(p, 0xa50b0000, r1, i2);
2691}
2692
2693
sewardj9d31dfd2011-03-15 12:36:44 +00002694static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002695s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002696{
sewardj7ee97522011-05-09 21:45:04 +00002697 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002698 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2699
sewardj3c49aaa2011-04-05 14:00:37 +00002700 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002701}
2702
2703
sewardj9d31dfd2011-03-15 12:36:44 +00002704static UChar *
sewardj2019a972011-03-07 16:04:07 +00002705s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2706{
sewardj652b56a2011-04-13 15:38:17 +00002707 vassert(s390_host_has_ldisp || dh2 == 0);
2708
sewardj7ee97522011-05-09 21:45:04 +00002709 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002710 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2711
2712 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2713}
2714
2715
sewardj9d31dfd2011-03-15 12:36:44 +00002716static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002717s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002718{
sewardj7ee97522011-05-09 21:45:04 +00002719 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002720 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
2721
sewardj3c49aaa2011-04-05 14:00:37 +00002722 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002723}
2724
2725
sewardj9d31dfd2011-03-15 12:36:44 +00002726static UChar *
sewardj2019a972011-03-07 16:04:07 +00002727s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2728{
sewardj652b56a2011-04-13 15:38:17 +00002729 vassert(s390_host_has_ldisp || dh2 == 0);
2730
sewardj7ee97522011-05-09 21:45:04 +00002731 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002732 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2733
2734 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2735}
2736
2737
sewardj9d31dfd2011-03-15 12:36:44 +00002738static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002739s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002740{
sewardj7ee97522011-05-09 21:45:04 +00002741 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002742 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
2743
sewardj3c49aaa2011-04-05 14:00:37 +00002744 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002745}
2746
2747
sewardj9d31dfd2011-03-15 12:36:44 +00002748static UChar *
sewardj2019a972011-03-07 16:04:07 +00002749s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2750{
sewardj652b56a2011-04-13 15:38:17 +00002751 vassert(s390_host_has_ldisp || dh2 == 0);
2752
sewardj7ee97522011-05-09 21:45:04 +00002753 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002754 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
2755
2756 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
2757}
2758
2759
sewardj9d31dfd2011-03-15 12:36:44 +00002760static UChar *
sewardj2019a972011-03-07 16:04:07 +00002761s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2762{
sewardj7ee97522011-05-09 21:45:04 +00002763 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002764 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
2765
2766 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
2767}
2768
2769
sewardj9d31dfd2011-03-15 12:36:44 +00002770static UChar *
sewardj2019a972011-03-07 16:04:07 +00002771s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2772{
sewardj652b56a2011-04-13 15:38:17 +00002773 vassert(s390_host_has_ldisp);
2774
sewardj7ee97522011-05-09 21:45:04 +00002775 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002776 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
2777
2778 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
2779}
2780
2781
sewardj9d31dfd2011-03-15 12:36:44 +00002782static UChar *
sewardj2019a972011-03-07 16:04:07 +00002783s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2784{
sewardj652b56a2011-04-13 15:38:17 +00002785 vassert(s390_host_has_ldisp || dh2 == 0);
2786
sewardj7ee97522011-05-09 21:45:04 +00002787 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002788 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
2789
2790 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
2791}
2792
2793
sewardj9d31dfd2011-03-15 12:36:44 +00002794static UChar *
sewardj2019a972011-03-07 16:04:07 +00002795s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2796{
sewardj7ee97522011-05-09 21:45:04 +00002797 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002798 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
2799
2800 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
2801}
2802
2803
sewardj9d31dfd2011-03-15 12:36:44 +00002804static UChar *
sewardj2019a972011-03-07 16:04:07 +00002805s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2806{
sewardj652b56a2011-04-13 15:38:17 +00002807 vassert(s390_host_has_ldisp);
2808
sewardj7ee97522011-05-09 21:45:04 +00002809 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002810 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
2811
2812 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
2813}
2814
2815
sewardj9d31dfd2011-03-15 12:36:44 +00002816static UChar *
sewardj2019a972011-03-07 16:04:07 +00002817s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2818{
sewardj7ee97522011-05-09 21:45:04 +00002819 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002820 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
2821
2822 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
2823}
2824
2825
sewardj9d31dfd2011-03-15 12:36:44 +00002826static UChar *
sewardj2019a972011-03-07 16:04:07 +00002827s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2828{
sewardj652b56a2011-04-13 15:38:17 +00002829 vassert(s390_host_has_ldisp);
2830
sewardj7ee97522011-05-09 21:45:04 +00002831 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002832 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
2833
2834 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
2835}
2836
2837
sewardj9d31dfd2011-03-15 12:36:44 +00002838static UChar *
sewardj2019a972011-03-07 16:04:07 +00002839s390_emit_SR(UChar *p, UChar r1, UChar r2)
2840{
sewardj7ee97522011-05-09 21:45:04 +00002841 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002842 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
2843
2844 return emit_RR(p, 0x1b00, r1, r2);
2845}
2846
2847
sewardj9d31dfd2011-03-15 12:36:44 +00002848static UChar *
sewardj2019a972011-03-07 16:04:07 +00002849s390_emit_SGR(UChar *p, UChar r1, UChar r2)
2850{
sewardj7ee97522011-05-09 21:45:04 +00002851 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002852 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
2853
2854 return emit_RRE(p, 0xb9090000, r1, r2);
2855}
2856
2857
sewardj9d31dfd2011-03-15 12:36:44 +00002858static UChar *
sewardj2019a972011-03-07 16:04:07 +00002859s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2860{
sewardj7ee97522011-05-09 21:45:04 +00002861 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002862 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
2863
2864 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
2865}
2866
2867
sewardj9d31dfd2011-03-15 12:36:44 +00002868static UChar *
sewardj2019a972011-03-07 16:04:07 +00002869s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2870{
sewardj652b56a2011-04-13 15:38:17 +00002871 vassert(s390_host_has_ldisp);
2872
sewardj7ee97522011-05-09 21:45:04 +00002873 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002874 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
2875
2876 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
2877}
2878
2879
sewardj9d31dfd2011-03-15 12:36:44 +00002880static UChar *
sewardj2019a972011-03-07 16:04:07 +00002881s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2882{
sewardj652b56a2011-04-13 15:38:17 +00002883 vassert(s390_host_has_ldisp || dh2 == 0);
2884
sewardj7ee97522011-05-09 21:45:04 +00002885 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002886 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
2887
2888 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
2889}
2890
2891
sewardj9d31dfd2011-03-15 12:36:44 +00002892static UChar *
sewardj2019a972011-03-07 16:04:07 +00002893s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2894{
sewardj7ee97522011-05-09 21:45:04 +00002895 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002896 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
2897
2898 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
2899}
2900
2901
sewardj9d31dfd2011-03-15 12:36:44 +00002902static UChar *
sewardj2019a972011-03-07 16:04:07 +00002903s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2904{
sewardj652b56a2011-04-13 15:38:17 +00002905 vassert(s390_host_has_ldisp);
2906
sewardj7ee97522011-05-09 21:45:04 +00002907 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002908 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
2909
2910 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
2911}
2912
2913
sewardj9d31dfd2011-03-15 12:36:44 +00002914static UChar *
sewardj2019a972011-03-07 16:04:07 +00002915s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
2916{
sewardj652b56a2011-04-13 15:38:17 +00002917 vassert(s390_host_has_eimm);
2918
sewardj7ee97522011-05-09 21:45:04 +00002919 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002920 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
2921
2922 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
2923}
2924
2925
sewardj9d31dfd2011-03-15 12:36:44 +00002926static UChar *
sewardjb13a92a2011-04-13 14:44:29 +00002927s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
2928{
sewardj7ee97522011-05-09 21:45:04 +00002929 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardjb13a92a2011-04-13 14:44:29 +00002930 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
2931
2932 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
2933}
2934
2935
2936static UChar *
sewardj2019a972011-03-07 16:04:07 +00002937s390_emit_LDR(UChar *p, UChar r1, UChar r2)
2938{
sewardj7ee97522011-05-09 21:45:04 +00002939 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002940 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
2941
2942 return emit_RR(p, 0x2800, r1, r2);
2943}
2944
2945
sewardj9d31dfd2011-03-15 12:36:44 +00002946static UChar *
sewardj2019a972011-03-07 16:04:07 +00002947s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2948{
sewardj7ee97522011-05-09 21:45:04 +00002949 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002950 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
2951
2952 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
2953}
2954
2955
sewardj9d31dfd2011-03-15 12:36:44 +00002956static UChar *
sewardj2019a972011-03-07 16:04:07 +00002957s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2958{
sewardj7ee97522011-05-09 21:45:04 +00002959 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002960 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
2961
2962 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
2963}
2964
2965
sewardj9d31dfd2011-03-15 12:36:44 +00002966static UChar *
sewardj2019a972011-03-07 16:04:07 +00002967s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2968{
sewardj652b56a2011-04-13 15:38:17 +00002969 vassert(s390_host_has_ldisp);
2970
sewardj7ee97522011-05-09 21:45:04 +00002971 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002972 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
2973
2974 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
2975}
2976
2977
sewardj9d31dfd2011-03-15 12:36:44 +00002978static UChar *
sewardj2019a972011-03-07 16:04:07 +00002979s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2980{
sewardj652b56a2011-04-13 15:38:17 +00002981 vassert(s390_host_has_ldisp);
2982
sewardj7ee97522011-05-09 21:45:04 +00002983 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002984 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
2985
2986 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
2987}
2988
2989
sewardj9d31dfd2011-03-15 12:36:44 +00002990static UChar *
sewardj2019a972011-03-07 16:04:07 +00002991s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
2992{
sewardj7ee97522011-05-09 21:45:04 +00002993 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002994 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
2995
2996 return emit_S(p, 0xb29d0000, b2, d2);
2997}
2998
2999
sewardj9d31dfd2011-03-15 12:36:44 +00003000static UChar *
sewardj2019a972011-03-07 16:04:07 +00003001s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3002{
sewardjd07b8562011-04-27 11:58:22 +00003003 vassert(s390_host_has_fgx);
3004
sewardj7ee97522011-05-09 21:45:04 +00003005 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003006 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
3007
3008 return emit_RRE(p, 0xb3c10000, r1, r2);
3009}
3010
3011
sewardj9d31dfd2011-03-15 12:36:44 +00003012static UChar *
sewardj2019a972011-03-07 16:04:07 +00003013s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3014{
sewardjd07b8562011-04-27 11:58:22 +00003015 vassert(s390_host_has_fgx);
3016
sewardj7ee97522011-05-09 21:45:04 +00003017 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003018 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3019
3020 return emit_RRE(p, 0xb3cd0000, r1, r2);
3021}
3022
3023
sewardj9d31dfd2011-03-15 12:36:44 +00003024static UChar *
sewardj2019a972011-03-07 16:04:07 +00003025s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3026{
sewardj7ee97522011-05-09 21:45:04 +00003027 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003028 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3029
3030 return emit_RRE(p, 0xb3740000, r1, r2);
3031}
3032
3033
sewardj9d31dfd2011-03-15 12:36:44 +00003034static UChar *
sewardj2019a972011-03-07 16:04:07 +00003035s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3036{
sewardj7ee97522011-05-09 21:45:04 +00003037 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003038 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3039
3040 return emit_RRE(p, 0xb3750000, r1, r2);
3041}
3042
3043
sewardj9d31dfd2011-03-15 12:36:44 +00003044static UChar *
sewardj2019a972011-03-07 16:04:07 +00003045s390_emit_SFPC(UChar *p, UChar r1, UChar r2)
3046{
sewardj7ee97522011-05-09 21:45:04 +00003047 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003048 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3049
3050 return emit_RRE(p, 0xb3840000, r1, r2);
3051}
3052
3053
sewardj9d31dfd2011-03-15 12:36:44 +00003054static UChar *
sewardj2019a972011-03-07 16:04:07 +00003055s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3056{
sewardj7ee97522011-05-09 21:45:04 +00003057 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003058 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3059
3060 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3061}
3062
3063
sewardj9d31dfd2011-03-15 12:36:44 +00003064static UChar *
sewardj2019a972011-03-07 16:04:07 +00003065s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3066{
sewardj7ee97522011-05-09 21:45:04 +00003067 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003068 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3069
3070 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3071}
3072
3073
sewardj9d31dfd2011-03-15 12:36:44 +00003074static UChar *
sewardj2019a972011-03-07 16:04:07 +00003075s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3076{
sewardj652b56a2011-04-13 15:38:17 +00003077 vassert(s390_host_has_ldisp);
3078
sewardj7ee97522011-05-09 21:45:04 +00003079 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003080 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3081
3082 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3083}
3084
3085
sewardj9d31dfd2011-03-15 12:36:44 +00003086static UChar *
sewardj2019a972011-03-07 16:04:07 +00003087s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3088{
sewardj652b56a2011-04-13 15:38:17 +00003089 vassert(s390_host_has_ldisp);
3090
sewardj7ee97522011-05-09 21:45:04 +00003091 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003092 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3093
3094 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3095}
3096
3097
sewardj9d31dfd2011-03-15 12:36:44 +00003098static UChar *
sewardj2019a972011-03-07 16:04:07 +00003099s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3100{
sewardj7ee97522011-05-09 21:45:04 +00003101 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003102 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3103
3104 return emit_S(p, 0xb29c0000, b2, d2);
3105}
3106
3107
sewardj9d31dfd2011-03-15 12:36:44 +00003108static UChar *
sewardj2019a972011-03-07 16:04:07 +00003109s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3110{
sewardj7ee97522011-05-09 21:45:04 +00003111 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003112 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3113
3114 return emit_RRE(p, 0xb30a0000, r1, r2);
3115}
3116
3117
sewardj9d31dfd2011-03-15 12:36:44 +00003118static UChar *
sewardj2019a972011-03-07 16:04:07 +00003119s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3120{
sewardj7ee97522011-05-09 21:45:04 +00003121 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003122 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3123
3124 return emit_RRE(p, 0xb31a0000, r1, r2);
3125}
3126
3127
sewardj9d31dfd2011-03-15 12:36:44 +00003128static UChar *
sewardj2019a972011-03-07 16:04:07 +00003129s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3130{
sewardj7ee97522011-05-09 21:45:04 +00003131 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003132 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3133
3134 return emit_RRE(p, 0xb34a0000, r1, r2);
3135}
3136
3137
sewardj9d31dfd2011-03-15 12:36:44 +00003138static UChar *
sewardj2019a972011-03-07 16:04:07 +00003139s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3140{
sewardj7ee97522011-05-09 21:45:04 +00003141 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003142 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3143
3144 return emit_RRE(p, 0xb3090000, r1, r2);
3145}
3146
3147
sewardj9d31dfd2011-03-15 12:36:44 +00003148static UChar *
sewardj2019a972011-03-07 16:04:07 +00003149s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3150{
sewardj7ee97522011-05-09 21:45:04 +00003151 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003152 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3153
3154 return emit_RRE(p, 0xb3190000, r1, r2);
3155}
3156
3157
sewardj9d31dfd2011-03-15 12:36:44 +00003158static UChar *
sewardj2019a972011-03-07 16:04:07 +00003159s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3160{
sewardj7ee97522011-05-09 21:45:04 +00003161 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003162 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3163
3164 return emit_RRE(p, 0xb3490000, r1, r2);
3165}
3166
3167
sewardj9d31dfd2011-03-15 12:36:44 +00003168static UChar *
sewardj2019a972011-03-07 16:04:07 +00003169s390_emit_CEFBR(UChar *p, UChar r1, UChar r2)
3170{
sewardj7ee97522011-05-09 21:45:04 +00003171 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003172 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3173
3174 return emit_RRE(p, 0xb3940000, r1, r2);
3175}
3176
3177
sewardj9d31dfd2011-03-15 12:36:44 +00003178static UChar *
sewardj2019a972011-03-07 16:04:07 +00003179s390_emit_CDFBR(UChar *p, UChar r1, UChar r2)
3180{
sewardj7ee97522011-05-09 21:45:04 +00003181 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003182 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3183
3184 return emit_RRE(p, 0xb3950000, r1, r2);
3185}
3186
3187
sewardj9d31dfd2011-03-15 12:36:44 +00003188static UChar *
sewardj2019a972011-03-07 16:04:07 +00003189s390_emit_CXFBR(UChar *p, UChar r1, UChar r2)
3190{
sewardj7ee97522011-05-09 21:45:04 +00003191 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003192 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3193
3194 return emit_RRE(p, 0xb3960000, r1, r2);
3195}
3196
3197
sewardj9d31dfd2011-03-15 12:36:44 +00003198static UChar *
sewardj2019a972011-03-07 16:04:07 +00003199s390_emit_CEGBR(UChar *p, UChar r1, UChar r2)
3200{
sewardj7ee97522011-05-09 21:45:04 +00003201 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003202 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3203
3204 return emit_RRE(p, 0xb3a40000, r1, r2);
3205}
3206
3207
sewardj9d31dfd2011-03-15 12:36:44 +00003208static UChar *
sewardj2019a972011-03-07 16:04:07 +00003209s390_emit_CDGBR(UChar *p, UChar r1, UChar r2)
3210{
sewardj7ee97522011-05-09 21:45:04 +00003211 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003212 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3213
3214 return emit_RRE(p, 0xb3a50000, r1, r2);
3215}
3216
3217
sewardj9d31dfd2011-03-15 12:36:44 +00003218static UChar *
sewardj2019a972011-03-07 16:04:07 +00003219s390_emit_CXGBR(UChar *p, UChar r1, UChar r2)
3220{
sewardj7ee97522011-05-09 21:45:04 +00003221 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003222 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3223
3224 return emit_RRE(p, 0xb3a60000, r1, r2);
3225}
3226
3227
sewardj9d31dfd2011-03-15 12:36:44 +00003228static UChar *
sewardj2019a972011-03-07 16:04:07 +00003229s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3230{
sewardj7ee97522011-05-09 21:45:04 +00003231 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003232 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3233
3234 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3235}
3236
3237
sewardj9d31dfd2011-03-15 12:36:44 +00003238static UChar *
sewardj2019a972011-03-07 16:04:07 +00003239s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3240{
sewardj7ee97522011-05-09 21:45:04 +00003241 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003242 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3243
3244 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3245}
3246
3247
sewardj9d31dfd2011-03-15 12:36:44 +00003248static UChar *
sewardj2019a972011-03-07 16:04:07 +00003249s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3250{
sewardj7ee97522011-05-09 21:45:04 +00003251 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003252 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3253
3254 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3255}
3256
3257
sewardj9d31dfd2011-03-15 12:36:44 +00003258static UChar *
sewardj2019a972011-03-07 16:04:07 +00003259s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3260{
sewardj7ee97522011-05-09 21:45:04 +00003261 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003262 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3263
3264 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3265}
3266
3267
sewardj9d31dfd2011-03-15 12:36:44 +00003268static UChar *
sewardj2019a972011-03-07 16:04:07 +00003269s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3270{
sewardj7ee97522011-05-09 21:45:04 +00003271 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003272 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3273
3274 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3275}
3276
3277
sewardj9d31dfd2011-03-15 12:36:44 +00003278static UChar *
sewardj2019a972011-03-07 16:04:07 +00003279s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3280{
sewardj7ee97522011-05-09 21:45:04 +00003281 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003282 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3283
3284 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3285}
3286
3287
sewardj9d31dfd2011-03-15 12:36:44 +00003288static UChar *
sewardj2019a972011-03-07 16:04:07 +00003289s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3290{
sewardj7ee97522011-05-09 21:45:04 +00003291 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003292 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3293
3294 return emit_RRE(p, 0xb30d0000, r1, r2);
3295}
3296
3297
sewardj9d31dfd2011-03-15 12:36:44 +00003298static UChar *
sewardj2019a972011-03-07 16:04:07 +00003299s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3300{
sewardj7ee97522011-05-09 21:45:04 +00003301 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003302 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3303
3304 return emit_RRE(p, 0xb31d0000, r1, r2);
3305}
3306
3307
sewardj9d31dfd2011-03-15 12:36:44 +00003308static UChar *
sewardj2019a972011-03-07 16:04:07 +00003309s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3310{
sewardj7ee97522011-05-09 21:45:04 +00003311 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003312 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3313
3314 return emit_RRE(p, 0xb34d0000, r1, r2);
3315}
3316
3317
sewardj9d31dfd2011-03-15 12:36:44 +00003318static UChar *
sewardj2019a972011-03-07 16:04:07 +00003319s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3320{
sewardj7ee97522011-05-09 21:45:04 +00003321 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003322 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3323
3324 return emit_RRE(p, 0xb3030000, r1, r2);
3325}
3326
3327
sewardj9d31dfd2011-03-15 12:36:44 +00003328static UChar *
sewardj2019a972011-03-07 16:04:07 +00003329s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3330{
sewardj7ee97522011-05-09 21:45:04 +00003331 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003332 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3333
3334 return emit_RRE(p, 0xb3130000, r1, r2);
3335}
3336
3337
sewardj9d31dfd2011-03-15 12:36:44 +00003338static UChar *
sewardj2019a972011-03-07 16:04:07 +00003339s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3340{
sewardj7ee97522011-05-09 21:45:04 +00003341 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003342 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3343
3344 return emit_RRE(p, 0xb3430000, r1, r2);
3345}
3346
3347
sewardj9d31dfd2011-03-15 12:36:44 +00003348static UChar *
sewardj2019a972011-03-07 16:04:07 +00003349s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3350{
sewardj7ee97522011-05-09 21:45:04 +00003351 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003352 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3353
3354 return emit_RRE(p, 0xb3040000, r1, r2);
3355}
3356
3357
sewardj9d31dfd2011-03-15 12:36:44 +00003358static UChar *
sewardj2019a972011-03-07 16:04:07 +00003359s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3360{
sewardj7ee97522011-05-09 21:45:04 +00003361 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003362 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3363
3364 return emit_RRE(p, 0xb3050000, r1, r2);
3365}
3366
3367
sewardj9d31dfd2011-03-15 12:36:44 +00003368static UChar *
sewardj2019a972011-03-07 16:04:07 +00003369s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3370{
sewardj7ee97522011-05-09 21:45:04 +00003371 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003372 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3373
3374 return emit_RRE(p, 0xb3060000, r1, r2);
3375}
3376
3377
sewardj9d31dfd2011-03-15 12:36:44 +00003378static UChar *
sewardj2019a972011-03-07 16:04:07 +00003379s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3380{
sewardj7ee97522011-05-09 21:45:04 +00003381 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003382 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3383
3384 return emit_RRE(p, 0xb3010000, r1, r2);
3385}
3386
3387
sewardj9d31dfd2011-03-15 12:36:44 +00003388static UChar *
sewardj2019a972011-03-07 16:04:07 +00003389s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3390{
sewardj7ee97522011-05-09 21:45:04 +00003391 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003392 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3393
3394 return emit_RRE(p, 0xb3110000, r1, r2);
3395}
3396
3397
sewardj9d31dfd2011-03-15 12:36:44 +00003398static UChar *
sewardj2019a972011-03-07 16:04:07 +00003399s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3400{
sewardj7ee97522011-05-09 21:45:04 +00003401 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003402 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3403
3404 return emit_RRE(p, 0xb3410000, r1, r2);
3405}
3406
3407
sewardj9d31dfd2011-03-15 12:36:44 +00003408static UChar *
sewardj2019a972011-03-07 16:04:07 +00003409s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3410{
sewardj7ee97522011-05-09 21:45:04 +00003411 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003412 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3413
3414 return emit_RRE(p, 0xb3000000, r1, r2);
3415}
3416
3417
sewardj9d31dfd2011-03-15 12:36:44 +00003418static UChar *
sewardj2019a972011-03-07 16:04:07 +00003419s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3420{
sewardj7ee97522011-05-09 21:45:04 +00003421 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003422 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3423
3424 return emit_RRE(p, 0xb3100000, r1, r2);
3425}
3426
3427
sewardj9d31dfd2011-03-15 12:36:44 +00003428static UChar *
sewardj2019a972011-03-07 16:04:07 +00003429s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3430{
sewardj7ee97522011-05-09 21:45:04 +00003431 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003432 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3433
3434 return emit_RRE(p, 0xb3400000, r1, r2);
3435}
3436
3437
sewardj9d31dfd2011-03-15 12:36:44 +00003438static UChar *
sewardj2019a972011-03-07 16:04:07 +00003439s390_emit_LEDBR(UChar *p, UChar r1, UChar r2)
3440{
sewardj7ee97522011-05-09 21:45:04 +00003441 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003442 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3443
3444 return emit_RRE(p, 0xb3440000, r1, r2);
3445}
3446
3447
sewardj9d31dfd2011-03-15 12:36:44 +00003448static UChar *
sewardj2019a972011-03-07 16:04:07 +00003449s390_emit_LDXBR(UChar *p, UChar r1, UChar r2)
3450{
sewardj7ee97522011-05-09 21:45:04 +00003451 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003452 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3453
3454 return emit_RRE(p, 0xb3450000, r1, r2);
3455}
3456
3457
sewardj9d31dfd2011-03-15 12:36:44 +00003458static UChar *
sewardj2019a972011-03-07 16:04:07 +00003459s390_emit_LEXBR(UChar *p, UChar r1, UChar r2)
3460{
sewardj7ee97522011-05-09 21:45:04 +00003461 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003462 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3463
3464 return emit_RRE(p, 0xb3460000, r1, r2);
3465}
3466
3467
sewardj9d31dfd2011-03-15 12:36:44 +00003468static UChar *
sewardj2019a972011-03-07 16:04:07 +00003469s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3470{
sewardj7ee97522011-05-09 21:45:04 +00003471 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003472 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3473
3474 return emit_RRE(p, 0xb3170000, r1, r2);
3475}
3476
3477
sewardj9d31dfd2011-03-15 12:36:44 +00003478static UChar *
sewardj2019a972011-03-07 16:04:07 +00003479s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3480{
sewardj7ee97522011-05-09 21:45:04 +00003481 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003482 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3483
3484 return emit_RRE(p, 0xb31c0000, r1, r2);
3485}
3486
3487
sewardj9d31dfd2011-03-15 12:36:44 +00003488static UChar *
sewardj2019a972011-03-07 16:04:07 +00003489s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3490{
sewardj7ee97522011-05-09 21:45:04 +00003491 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003492 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3493
3494 return emit_RRE(p, 0xb34c0000, r1, r2);
3495}
3496
3497
sewardj9d31dfd2011-03-15 12:36:44 +00003498static UChar *
sewardj2019a972011-03-07 16:04:07 +00003499s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3500{
sewardj7ee97522011-05-09 21:45:04 +00003501 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003502 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3503
3504 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3505}
3506
3507
sewardj9d31dfd2011-03-15 12:36:44 +00003508static UChar *
sewardj2019a972011-03-07 16:04:07 +00003509s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3510{
sewardj7ee97522011-05-09 21:45:04 +00003511 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003512 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3513
3514 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3515}
3516
3517
sewardj9d31dfd2011-03-15 12:36:44 +00003518static UChar *
sewardj2019a972011-03-07 16:04:07 +00003519s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3520{
sewardj7ee97522011-05-09 21:45:04 +00003521 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003522 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3523
3524 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3525}
3526
3527
sewardj9d31dfd2011-03-15 12:36:44 +00003528static UChar *
sewardj2019a972011-03-07 16:04:07 +00003529s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3530{
sewardj7ee97522011-05-09 21:45:04 +00003531 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003532 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3533
3534 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
3535}
3536
3537
sewardj9d31dfd2011-03-15 12:36:44 +00003538static UChar *
sewardj2019a972011-03-07 16:04:07 +00003539s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
3540{
sewardj7ee97522011-05-09 21:45:04 +00003541 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003542 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
3543
3544 return emit_RRE(p, 0xb3140000, r1, r2);
3545}
3546
3547
sewardj9d31dfd2011-03-15 12:36:44 +00003548static UChar *
sewardj2019a972011-03-07 16:04:07 +00003549s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
3550{
sewardj7ee97522011-05-09 21:45:04 +00003551 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003552 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
3553
3554 return emit_RRE(p, 0xb3150000, r1, r2);
3555}
3556
3557
sewardj9d31dfd2011-03-15 12:36:44 +00003558static UChar *
sewardj2019a972011-03-07 16:04:07 +00003559s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
3560{
sewardj7ee97522011-05-09 21:45:04 +00003561 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003562 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
3563
3564 return emit_RRE(p, 0xb3160000, r1, r2);
3565}
3566
3567
sewardj9d31dfd2011-03-15 12:36:44 +00003568static UChar *
sewardj2019a972011-03-07 16:04:07 +00003569s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
3570{
sewardj7ee97522011-05-09 21:45:04 +00003571 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003572 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
3573
3574 return emit_RRE(p, 0xb30b0000, r1, r2);
3575}
3576
3577
sewardj9d31dfd2011-03-15 12:36:44 +00003578static UChar *
sewardj2019a972011-03-07 16:04:07 +00003579s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
3580{
sewardj7ee97522011-05-09 21:45:04 +00003581 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003582 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
3583
3584 return emit_RRE(p, 0xb31b0000, r1, r2);
3585}
3586
3587
sewardj9d31dfd2011-03-15 12:36:44 +00003588static UChar *
sewardj2019a972011-03-07 16:04:07 +00003589s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
3590{
sewardj7ee97522011-05-09 21:45:04 +00003591 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003592 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
3593
3594 return emit_RRE(p, 0xb34b0000, r1, r2);
3595}
3596
sewardj2019a972011-03-07 16:04:07 +00003597
3598/* Provide a symbolic name for register "R0" */
3599#define R0 0
3600
3601/* Split up a 20-bit displacement into its high and low piece
3602 suitable for passing as function arguments */
sewardjcd2b0252011-05-09 20:35:41 +00003603#define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
sewardj2019a972011-03-07 16:04:07 +00003604
3605/*---------------------------------------------------------------*/
3606/*--- Helper functions ---*/
3607/*---------------------------------------------------------------*/
3608
3609static __inline__ Bool
3610uint_fits_signed_16bit(UInt val)
3611{
3612 int v = val & 0xFFFFu;
3613
3614 /* sign extend */
3615 v = (v << 16) >> 16;
3616
3617 return val == (UInt)v;
3618}
3619
3620
3621static __inline__ Bool
3622ulong_fits_signed_16bit(ULong val)
3623{
3624 Long v = val & 0xFFFFu;
3625
3626 /* sign extend */
3627 v = (v << 48) >> 48;
3628
3629 return val == (ULong)v;
3630}
3631
3632
3633static __inline__ Bool
3634ulong_fits_signed_32bit(ULong val)
3635{
3636 Long v = val & 0xFFFFFFFFu;
3637
3638 /* sign extend */
3639 v = (v << 32) >> 32;
3640
3641 return val == (ULong)v;
3642}
3643
3644
3645static __inline__ Bool
3646ulong_fits_unsigned_32bit(ULong val)
3647{
3648 return (val & 0xFFFFFFFFu) == val;
3649}
3650
3651
3652/* Load a 64-bit immediate VAL into register REG. */
3653static UChar *
3654s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
3655{
3656 if (ulong_fits_signed_16bit(val)) {
3657 return s390_emit_LGHI(p, reg, val);
3658 }
3659
3660 if (s390_host_has_eimm) {
3661 if (ulong_fits_unsigned_32bit(val)) {
3662 return s390_emit_LLILF(p, reg, val);
3663 }
3664 if (ulong_fits_signed_32bit(val)) {
3665 /* LGFI's sign extension will recreate the correct 64-bit value */
3666 return s390_emit_LGFI(p, reg, val);
3667 }
3668 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
3669 p = s390_emit_IIHF(p, reg, val >> 32);
3670 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
3671 }
3672
3673 /* Fall back */
3674 if (ulong_fits_unsigned_32bit(val)) {
3675 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
3676 val[0:31] = 0 */
3677 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
3678 return p;
3679 }
3680
3681 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
3682 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
3683 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3684 p = s390_emit_IILL(p, reg, val & 0xFFFF);
3685
3686 return p;
3687}
3688
3689/* Load a 32-bit immediate VAL into register REG. */
3690static UChar *
3691s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
3692{
3693 if (uint_fits_signed_16bit(val)) {
3694 /* LHI's sign extension will recreate the correct 32-bit value */
3695 return s390_emit_LHI(p, reg, val);
3696 }
3697 if (s390_host_has_eimm) {
3698 return s390_emit_IILF(p, reg, val);
3699 }
3700 /* val[0:15] --> (val >> 16) & 0xFFFF
3701 val[16:31] --> val & 0xFFFF */
3702 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3703 return s390_emit_IILL(p, reg, val & 0xFFFF);
3704}
3705
3706/*------------------------------------------------------------*/
3707/*--- Wrapper functions ---*/
3708/*------------------------------------------------------------*/
3709
sewardjeae8db52011-03-24 09:01:50 +00003710/* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
sewardj2019a972011-03-07 16:04:07 +00003711static UChar *
3712s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3713{
3714 if (s390_host_has_gie) {
3715 return s390_emit_MFY(p, r1, x, b, dl, dh);
3716 }
3717
3718 /* Load from memory into R0, then MULTIPLY with R1 */
3719 p = s390_emit_LY(p, R0, x, b, dl, dh);
3720 return s390_emit_MR(p, r1, R0);
3721}
3722
sewardjeae8db52011-03-24 09:01:50 +00003723/* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
3724static UChar *
3725s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3726{
3727 if (s390_host_has_gie) {
3728 return s390_emit_MHY(p, r1, x, b, dl, dh);
3729 }
3730
3731 /* Load from memory into R0, then MULTIPLY with R1 */
3732 p = s390_emit_LHY(p, R0, x, b, dl, dh);
3733 return s390_emit_MSR(p, r1, R0);
3734}
3735
sewardj2019a972011-03-07 16:04:07 +00003736/* r1[32:63] = r1[32:63] * i2 */
3737static UChar *
3738s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
3739{
3740 if (s390_host_has_gie) {
3741 return s390_emit_MSFI(p, r1, i2);
3742 }
3743
3744 /* Load I2 into R0; then MULTIPLY R0 with R1 */
3745 p = s390_emit_load_32imm(p, R0, i2);
3746 return s390_emit_MSR(p, r1, R0);
3747}
3748
3749
3750/* r1[32:63] = r1[32:63] & i2 */
3751static UChar *
3752s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
3753{
3754 if (s390_host_has_eimm) {
3755 return s390_emit_NILF(p, r1, i2);
3756 }
3757
3758 /* Load I2 into R0; then AND R0 with R1 */
3759 p = s390_emit_load_32imm(p, R0, i2);
3760 return s390_emit_NR(p, r1, R0);
3761}
3762
3763
3764/* r1[32:63] = r1[32:63] | i2 */
3765static UChar *
3766s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
3767{
3768 if (s390_host_has_eimm) {
3769 return s390_emit_OILF(p, r1, i2);
3770 }
3771
3772 /* Load I2 into R0; then AND R0 with R1 */
3773 p = s390_emit_load_32imm(p, R0, i2);
3774 return s390_emit_OR(p, r1, R0);
3775}
3776
3777
3778/* r1[32:63] = r1[32:63] ^ i2 */
3779static UChar *
3780s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
3781{
3782 if (s390_host_has_eimm) {
3783 return s390_emit_XILF(p, r1, i2);
3784 }
3785
3786 /* Load I2 into R0; then AND R0 with R1 */
3787 p = s390_emit_load_32imm(p, R0, i2);
3788 return s390_emit_XR(p, r1, R0);
3789}
3790
3791
sewardj652b56a2011-04-13 15:38:17 +00003792/* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
3793static UChar *
3794s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3795{
3796 vassert(s390_host_has_ldisp || dh2 == 0);
3797
3798 if (s390_host_has_ldisp) {
3799 return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
3800 }
3801
3802 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
3803 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
3804 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
3805}
3806
3807
sewardj2019a972011-03-07 16:04:07 +00003808/* r1[32:63] = sign_extend(r2[56:63]) */
3809static UChar *
3810s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
3811{
3812 if (s390_host_has_eimm) {
3813 return s390_emit_LBR(p, r1, r2);
3814 }
3815
3816 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00003817 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
3818 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
sewardj2019a972011-03-07 16:04:07 +00003819}
3820
3821
sewardj652b56a2011-04-13 15:38:17 +00003822/* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
3823static UChar *
3824s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3825{
3826 vassert(s390_host_has_ldisp || dh2 == 0);
3827
3828 if (s390_host_has_ldisp) {
3829 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
3830 }
3831
3832 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
3833 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
3834 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3835}
3836
3837
sewardj2019a972011-03-07 16:04:07 +00003838/* r1[0:63] = sign_extend(r2[56:63]) */
3839static UChar *
3840s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
3841{
3842 if (s390_host_has_eimm) {
3843 return s390_emit_LGBR(p, r1, r2);
3844 }
3845
3846 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3847 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
3848 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3849}
3850
3851
3852/* r1[32:63] = sign_extend(r2[48:63]) */
3853static UChar *
3854s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
3855{
3856 if (s390_host_has_eimm) {
3857 return s390_emit_LHR(p, r1, r2);
3858 }
3859
3860 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00003861 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
3862 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
sewardj2019a972011-03-07 16:04:07 +00003863}
3864
3865
3866/* r1[0:63] = sign_extend(r2[48:63]) */
3867static UChar *
3868s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
3869{
3870 if (s390_host_has_eimm) {
3871 return s390_emit_LGHR(p, r1, r2);
3872 }
3873
3874 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3875 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
3876 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
3877}
3878
3879
3880/* r1[0:63] = sign_extend(i2) */
3881static UChar *
3882s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
3883{
3884 if (s390_host_has_eimm) {
3885 return s390_emit_LGFI(p, r1, i2);
3886 }
3887
3888 p = s390_emit_load_32imm(p, R0, i2);
3889 return s390_emit_LGFR(p, r1, R0);
3890}
3891
3892
3893/* r1[32:63] = zero_extend($r2[56:63]) */
3894static UChar *
3895s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
3896{
3897 if (s390_host_has_eimm) {
3898 return s390_emit_LLCR(p, r1, r2);
3899 }
3900
3901 p = s390_emit_LR(p, r1, r2);
3902 p = s390_emit_LHI(p, R0, 0xFF);
3903 return s390_emit_NR(p, r1, R0);
3904}
3905
3906
3907/* r1[0:63] = zero_extend($r2[56:63]) */
3908static UChar *
3909s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
3910{
3911 if (s390_host_has_eimm) {
3912 return s390_emit_LLGCR(p, r1, r2);
3913 }
3914
3915 p = s390_emit_LR(p, r1, r2);
3916 p = s390_emit_LLILL(p, R0, 0xFF);
3917 return s390_emit_NGR(p, r1, R0);
3918}
3919
3920
3921/* r1[32:63] = zero_extend(r2[48:63]) */
3922static UChar *
3923s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
3924{
3925 if (s390_host_has_eimm) {
3926 return s390_emit_LLHR(p, r1, r2);
3927 }
3928
3929 p = s390_emit_LR(p, r1, r2);
3930 p = s390_emit_LLILL(p, R0, 0xFFFF);
3931 return s390_emit_NR(p, r1, R0);
3932}
3933
3934
3935/* r1[0:63] = zero_extend(r2[48:63]) */
3936static UChar *
3937s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
3938{
3939 if (s390_host_has_eimm) {
3940 return s390_emit_LLGHR(p, r1, r2);
3941 }
3942
3943 p = s390_emit_LR(p, r1, r2);
3944 p = s390_emit_LLILL(p, R0, 0xFFFF);
3945 return s390_emit_NGR(p, r1, R0);
3946}
3947
3948
3949/* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
3950static UChar *
3951s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3952{
3953 if (s390_host_has_eimm) {
3954 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
3955 }
3956
3957 if (dh == 0) {
3958 p = s390_emit_IC(p, r1, x2, b2, dl);
3959 } else {
3960 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
3961 }
3962 p = s390_emit_LLILL(p, R0, 0xFF);
3963 return s390_emit_NR(p, r1, R0);
3964}
3965
3966
3967/* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
3968static UChar *
3969s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3970{
3971 if (s390_host_has_eimm) {
3972 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
3973 }
3974
3975 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
3976 p = s390_emit_LLILL(p, R0, 0xFFFF);
3977 return s390_emit_NR(p, r1, R0);
3978}
3979
3980
3981/* r1[0:63] = zero_extend(i2) */
3982static UChar *
3983s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
3984{
3985 if (s390_host_has_eimm) {
3986 return s390_emit_LLILF(p, r1, i2);
3987 }
3988
3989 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
3990 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
3991}
3992
3993
3994/* r1[32:63] = r1[32:63] + i2 */
3995static UChar *
3996s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
3997{
3998 if (s390_host_has_eimm) {
3999 return s390_emit_AFI(p, r1, i2);
4000 }
4001 /* Load 32 bit immediate to R0 then add */
4002 p = s390_emit_load_32imm(p, R0, i2);
4003 return s390_emit_AR(p, r1, R0);
4004}
4005
4006
4007/* r1[32:63] = r1[32:63] - i2 */
4008static UChar *
4009s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
4010{
4011 if (s390_host_has_eimm) {
4012 return s390_emit_SLFI(p, r1, i2);
4013 }
4014
4015 /* Load 32 bit immediate to R0 then subtract */
4016 p = s390_emit_load_32imm(p, R0, i2);
4017 return s390_emit_SR(p, r1, R0);
4018}
4019
4020
sewardjb13a92a2011-04-13 14:44:29 +00004021/* r1[0:63] = r1[0:63] - zero_extend(i2) */
4022static UChar *
4023s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
4024{
4025 if (s390_host_has_eimm) {
4026 return s390_emit_SLGFI(p, r1, i2);
4027 }
4028
4029 /* Load zero-extended 32 bit immediate to R0 then subtract */
4030 p = s390_emit_load_64imm(p, R0, i2);
4031 return s390_emit_SGR(p, r1, R0);
4032}
4033
4034
sewardj2019a972011-03-07 16:04:07 +00004035static UChar *
4036s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4037{
4038 if (s390_host_has_eimm) {
4039 return s390_emit_LT(p, r1, x2, b2, dl, dh);
4040 }
4041 /* Load 32 bit from memory to R0 then compare */
4042 if (dh == 0) {
4043 p = s390_emit_L(p, R0, x2, b2, dl);
4044 } else {
4045 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
4046 }
4047 return s390_emit_LTR(p, r1, R0);
4048}
4049
4050
4051static UChar *
4052s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4053{
4054 if (s390_host_has_eimm) {
4055 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
4056 }
4057 /* Load 64 bit from memory to R0 then compare */
4058 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
4059 return s390_emit_LTGR(p, r1, R0);
4060}
4061
4062
4063static UChar *
4064s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
4065{
4066 if (s390_host_has_eimm) {
4067 return s390_emit_CFI(p, r1, i2);
4068 }
4069 /* Load 32 bit immediate to R0 then compare */
4070 p = s390_emit_load_32imm(p, R0, i2);
4071 return s390_emit_CR(p, r1, R0);
4072}
4073
4074
4075static UChar *
4076s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
4077{
4078 if (s390_host_has_eimm) {
4079 return s390_emit_CLFI(p, r1, i2);
4080 }
4081 /* Load 32 bit immediate to R0 then compare */
4082 p = s390_emit_load_32imm(p, R0, i2);
4083 return s390_emit_CLR(p, r1, R0);
4084}
4085
sewardjd07b8562011-04-27 11:58:22 +00004086
4087static UChar *
4088s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
4089{
4090 if (s390_host_has_fgx) {
4091 return s390_emit_LGDR(p, r1, r2);
4092 }
4093
4094 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
4095 smaller addresses and is 8-byte aligned. Then load the GPR from that
4096 memory location/ */
4097 if (s390_host_has_ldisp) {
4098 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4099 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4100 }
4101
4102 /* No long displacement. Need to adjust SP explicitly as to avoid negative
4103 displacements. */
4104 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4105 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
4106 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4107 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4108}
4109
4110
4111static UChar *
4112s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
4113{
4114 if (s390_host_has_fgx) {
4115 return s390_emit_LDGR(p, r1, r2);
4116 }
4117
4118 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
4119 smaller addresses and is 8-byte aligned. Then load the FPR from that
4120 memory location/ */
4121 if (s390_host_has_ldisp) {
4122 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4123 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4124 }
4125
4126 /* No long displacement. Need to adjust SP explicitly as to avoid negative
4127 displacements. */
4128 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4129 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4130 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
4131 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4132}
4133
4134
sewardj2019a972011-03-07 16:04:07 +00004135/*---------------------------------------------------------------*/
4136/*--- Constructors for the various s390_insn kinds ---*/
4137/*---------------------------------------------------------------*/
4138
4139s390_insn *
4140s390_insn_load(UChar size, HReg dst, s390_amode *src)
4141{
4142 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4143
4144 insn->tag = S390_INSN_LOAD;
4145 insn->size = size;
4146 insn->variant.load.src = src;
4147 insn->variant.load.dst = dst;
4148
4149 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4150
4151 return insn;
4152}
4153
4154
4155s390_insn *
4156s390_insn_store(UChar size, s390_amode *dst, HReg src)
4157{
4158 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4159
4160 insn->tag = S390_INSN_STORE;
4161 insn->size = size;
4162 insn->variant.store.src = src;
4163 insn->variant.store.dst = dst;
4164
4165 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4166
4167 return insn;
4168}
4169
4170
4171s390_insn *
4172s390_insn_move(UChar size, HReg dst, HReg src)
4173{
4174 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4175
4176 insn->tag = S390_INSN_MOVE;
4177 insn->size = size;
4178 insn->variant.move.src = src;
4179 insn->variant.move.dst = dst;
4180
4181 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4182
4183 return insn;
4184}
4185
4186
4187s390_insn *
4188s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
4189{
4190 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4191
4192 insn->tag = S390_INSN_COND_MOVE;
4193 insn->size = size;
4194 insn->variant.cond_move.cond = cond;
4195 insn->variant.cond_move.src = src;
4196 insn->variant.cond_move.dst = dst;
4197
4198 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4199
4200 return insn;
4201}
4202
4203
4204s390_insn *
4205s390_insn_load_immediate(UChar size, HReg dst, ULong value)
4206{
4207 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4208
4209 insn->tag = S390_INSN_LOAD_IMMEDIATE;
4210 insn->size = size;
4211 insn->variant.load_immediate.dst = dst;
4212 insn->variant.load_immediate.value = value;
4213
4214 return insn;
4215}
4216
4217
4218s390_insn *
4219s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
4220{
4221 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4222
4223 insn->tag = S390_INSN_ALU;
4224 insn->size = size;
4225 insn->variant.alu.tag = tag;
4226 insn->variant.alu.dst = dst;
4227 insn->variant.alu.op2 = op2;
4228
4229 return insn;
4230}
4231
4232
4233s390_insn *
4234s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
4235 Bool signed_multiply)
4236{
4237 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4238
4239 vassert(! hregIsVirtual(dst_hi));
4240 vassert(! hregIsVirtual(dst_lo));
4241
4242 insn->tag = S390_INSN_MUL;
4243 insn->size = size;
4244 insn->variant.mul.dst_hi = dst_hi;
4245 insn->variant.mul.dst_lo = dst_lo;
4246 insn->variant.mul.op2 = op2;
4247 insn->variant.mul.signed_multiply = signed_multiply;
4248
4249 return insn;
4250}
4251
4252
4253s390_insn *
4254s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
4255 Bool signed_divide)
4256{
4257 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4258
4259 vassert(size == 4 || size == 8);
4260 vassert(! hregIsVirtual(op1_hi));
4261 vassert(! hregIsVirtual(op1_lo));
4262
4263 insn->tag = S390_INSN_DIV;
4264 insn->size = size;
4265 insn->variant.div.op1_hi = op1_hi;
4266 insn->variant.div.op1_lo = op1_lo;
4267 insn->variant.div.op2 = op2;
4268 insn->variant.div.signed_divide = signed_divide;
4269
4270 return insn;
4271}
4272
4273
4274s390_insn *
4275s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
4276{
4277 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4278
4279 vassert(size == 8);
4280 vassert(! hregIsVirtual(op1));
4281 vassert(! hregIsVirtual(rem));
4282
4283 insn->tag = S390_INSN_DIVS;
4284 insn->size = size;
4285 insn->variant.divs.rem = rem; /* remainder */
4286 insn->variant.divs.op1 = op1; /* also quotient */
4287 insn->variant.divs.op2 = op2;
4288
4289 return insn;
4290}
4291
4292
4293s390_insn *
sewardj611b06e2011-03-24 08:57:29 +00004294s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
sewardj2019a972011-03-07 16:04:07 +00004295{
4296 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4297
4298 vassert(size == 8);
sewardj611b06e2011-03-24 08:57:29 +00004299 vassert(! hregIsVirtual(num_bits));
4300 vassert(! hregIsVirtual(clobber));
sewardj2019a972011-03-07 16:04:07 +00004301
sewardj611b06e2011-03-24 08:57:29 +00004302 insn->tag = S390_INSN_CLZ;
sewardj2019a972011-03-07 16:04:07 +00004303 insn->size = size;
sewardj611b06e2011-03-24 08:57:29 +00004304 insn->variant.clz.num_bits = num_bits;
4305 insn->variant.clz.clobber = clobber;
4306 insn->variant.clz.src = src;
sewardj2019a972011-03-07 16:04:07 +00004307
4308 return insn;
4309}
4310
4311
4312s390_insn *
4313s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
4314{
4315 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4316
4317 insn->tag = S390_INSN_UNOP;
4318 insn->size = size;
4319 insn->variant.unop.tag = tag;
4320 insn->variant.unop.dst = dst;
4321 insn->variant.unop.src = opnd;
4322
4323 return insn;
4324}
4325
4326
4327s390_insn *
4328s390_insn_test(UChar size, s390_opnd_RMI src)
4329{
4330 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4331
4332 vassert(size == 4 || size == 8);
4333
4334 insn->tag = S390_INSN_TEST;
4335 insn->size = size;
4336 insn->variant.test.src = src;
4337
4338 return insn;
4339}
4340
4341
4342s390_insn *
4343s390_insn_cc2bool(HReg dst, s390_cc_t cond)
4344{
4345 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4346
4347 insn->tag = S390_INSN_CC2BOOL;
4348 insn->size = 0; /* does not matter */
4349 insn->variant.cc2bool.cond = cond;
4350 insn->variant.cc2bool.dst = dst;
4351
4352 return insn;
4353}
4354
4355
4356s390_insn *
4357s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
4358{
4359 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4360
4361 vassert(size == 4 || size == 8);
4362 vassert(op2->x == 0);
4363
4364 insn->tag = S390_INSN_CAS;
4365 insn->size = size;
4366 insn->variant.cas.op1 = op1;
4367 insn->variant.cas.op2 = op2;
4368 insn->variant.cas.op3 = op3;
4369 insn->variant.cas.old_mem = old_mem;
4370
4371 return insn;
4372}
4373
4374
4375s390_insn *
florian448cbba2012-06-06 02:26:01 +00004376s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
4377 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
4378 HReg scratch)
4379{
4380 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4381
4382 vassert(size == 4 || size == 8);
4383 vassert(op2->x == 0);
4384 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
4385
4386 insn->tag = S390_INSN_CDAS;
4387 insn->size = size;
4388 insn->variant.cdas.op1_high = op1_high;
4389 insn->variant.cdas.op1_low = op1_low;
4390 insn->variant.cdas.op2 = op2;
4391 insn->variant.cdas.op3_high = op3_high;
4392 insn->variant.cdas.op3_low = op3_low;
4393 insn->variant.cdas.old_mem_high = old_mem_high;
4394 insn->variant.cdas.old_mem_low = old_mem_low;
4395 insn->variant.cdas.scratch = scratch;
4396
4397 return insn;
4398}
4399
4400
4401s390_insn *
sewardj2019a972011-03-07 16:04:07 +00004402s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
4403 Bool signed_comparison)
4404{
4405 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4406
4407 vassert(size == 4 || size == 8);
4408
4409 insn->tag = S390_INSN_COMPARE;
4410 insn->size = size;
4411 insn->variant.compare.src1 = src1;
4412 insn->variant.compare.src2 = src2;
4413 insn->variant.compare.signed_comparison = signed_comparison;
4414
4415 return insn;
4416}
4417
4418
4419s390_insn *
sewardj2019a972011-03-07 16:04:07 +00004420s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
florian01ed6e72012-05-27 16:52:43 +00004421 HChar *name, HReg dst)
sewardj2019a972011-03-07 16:04:07 +00004422{
4423 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4424
4425 insn->tag = S390_INSN_HELPER_CALL;
4426 insn->size = 0; /* does not matter */
4427 insn->variant.helper_call.cond = cond;
4428 insn->variant.helper_call.target = target;
4429 insn->variant.helper_call.num_args = num_args;
4430 insn->variant.helper_call.name = name;
florian01ed6e72012-05-27 16:52:43 +00004431 insn->variant.helper_call.dst = dst;
sewardj2019a972011-03-07 16:04:07 +00004432
4433 return insn;
4434}
4435
4436
4437s390_insn *
4438s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
4439 HReg op3, s390_round_t rounding_mode)
4440{
4441 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4442
4443 insn->tag = S390_INSN_BFP_TRIOP;
4444 insn->size = size;
4445 insn->variant.bfp_triop.tag = tag;
4446 insn->variant.bfp_triop.dst = dst;
4447 insn->variant.bfp_triop.op2 = op2;
4448 insn->variant.bfp_triop.op3 = op3;
4449 insn->variant.bfp_triop.rounding_mode = rounding_mode;
4450
4451 return insn;
4452}
4453
4454
4455s390_insn *
4456s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2,
4457 s390_round_t rounding_mode)
4458{
4459 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4460
4461 insn->tag = S390_INSN_BFP_BINOP;
4462 insn->size = size;
4463 insn->variant.bfp_binop.tag = tag;
4464 insn->variant.bfp_binop.dst = dst;
4465 insn->variant.bfp_binop.op2 = op2;
4466 insn->variant.bfp_binop.rounding_mode = rounding_mode;
4467
4468 return insn;
4469}
4470
4471
4472s390_insn *
4473s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op,
4474 s390_round_t rounding_mode)
4475{
4476 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4477
4478 insn->tag = S390_INSN_BFP_UNOP;
4479 insn->size = size;
4480 insn->variant.bfp_unop.tag = tag;
4481 insn->variant.bfp_unop.dst = dst;
4482 insn->variant.bfp_unop.op = op;
4483 insn->variant.bfp_unop.rounding_mode = rounding_mode;
4484
4485 return insn;
4486}
4487
4488
4489s390_insn *
4490s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
4491{
4492 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4493
4494 vassert(size == 4 || size == 8);
4495
4496 insn->tag = S390_INSN_BFP_COMPARE;
4497 insn->size = size;
4498 insn->variant.bfp_compare.dst = dst;
4499 insn->variant.bfp_compare.op1 = op1;
4500 insn->variant.bfp_compare.op2 = op2;
4501
4502 return insn;
4503}
4504
4505
4506s390_insn *
4507s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
4508 HReg dst_lo, HReg op2_hi, HReg op2_lo,
4509 s390_round_t rounding_mode)
4510{
4511 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4512
4513 insn->tag = S390_INSN_BFP128_BINOP;
4514 insn->size = size;
4515 insn->variant.bfp128_binop.tag = tag;
4516 insn->variant.bfp128_binop.dst_hi = dst_hi;
4517 insn->variant.bfp128_binop.dst_lo = dst_lo;
4518 insn->variant.bfp128_binop.op2_hi = op2_hi;
4519 insn->variant.bfp128_binop.op2_lo = op2_lo;
4520 insn->variant.bfp128_binop.rounding_mode = rounding_mode;
4521
4522 return insn;
4523}
4524
4525
4526s390_insn *
sewardja970c402011-04-28 18:38:42 +00004527s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
sewardj2019a972011-03-07 16:04:07 +00004528 HReg dst_lo, HReg op_hi, HReg op_lo,
4529 s390_round_t rounding_mode)
4530{
4531 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4532
4533 insn->tag = S390_INSN_BFP128_UNOP;
4534 insn->size = size;
4535 insn->variant.bfp128_unop.tag = tag;
4536 insn->variant.bfp128_unop.dst_hi = dst_hi;
4537 insn->variant.bfp128_unop.dst_lo = dst_lo;
4538 insn->variant.bfp128_unop.op_hi = op_hi;
4539 insn->variant.bfp128_unop.op_lo = op_lo;
4540 insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4541
4542 return insn;
4543}
4544
4545
4546s390_insn *
4547s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
4548 HReg op2_hi, HReg op2_lo)
4549{
4550 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4551
4552 insn->tag = S390_INSN_BFP128_COMPARE;
4553 insn->size = size;
4554 insn->variant.bfp128_compare.dst = dst;
4555 insn->variant.bfp128_compare.op1_hi = op1_hi;
4556 insn->variant.bfp128_compare.op1_lo = op1_lo;
4557 insn->variant.bfp128_compare.op2_hi = op2_hi;
4558 insn->variant.bfp128_compare.op2_lo = op2_lo;
4559
4560 return insn;
4561}
4562
4563
4564s390_insn *
4565s390_insn_bfp128_convert_to(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
4566 HReg dst_lo, HReg op)
4567{
4568 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4569
4570 insn->tag = S390_INSN_BFP128_CONVERT_TO;
4571 insn->size = size;
4572 insn->variant.bfp128_unop.tag = tag;
4573 insn->variant.bfp128_unop.dst_hi = dst_hi;
4574 insn->variant.bfp128_unop.dst_lo = dst_lo;
4575 insn->variant.bfp128_unop.op_hi = op;
4576 insn->variant.bfp128_unop.op_lo = INVALID_HREG; /* unused */
4577 insn->variant.bfp128_unop.rounding_mode = S390_ROUND_NEAREST_EVEN; /* unused */
4578
4579 return insn;
4580}
4581
4582
4583s390_insn *
4584s390_insn_bfp128_convert_from(UChar size, s390_bfp_unop_t tag, HReg dst,
4585 HReg op_hi, HReg op_lo,
4586 s390_round_t rounding_mode)
4587{
4588 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4589
4590 insn->tag = S390_INSN_BFP128_CONVERT_FROM;
4591 insn->size = size;
4592 insn->variant.bfp128_unop.tag = tag;
4593 insn->variant.bfp128_unop.dst_hi = dst;
4594 insn->variant.bfp128_unop.dst_lo = INVALID_HREG; /* unused */
4595 insn->variant.bfp128_unop.op_hi = op_hi;
4596 insn->variant.bfp128_unop.op_lo = op_lo;
4597 insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4598
4599 return insn;
4600}
4601
4602
sewardja52e37e2011-04-28 18:48:06 +00004603s390_insn *
4604s390_insn_mfence(void)
4605{
4606 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4607
4608 insn->tag = S390_INSN_MFENCE;
4609 insn->size = 0; /* not needed */
4610
4611 return insn;
4612}
4613
4614
florianad43b3a2012-02-20 15:01:14 +00004615s390_insn *
4616s390_insn_gzero(UChar size, UInt offset)
4617{
4618 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4619
4620 insn->tag = S390_INSN_GZERO;
4621 insn->size = size;
4622 insn->variant.gzero.offset = offset;
4623
4624 return insn;
4625}
4626
4627
4628s390_insn *
4629s390_insn_gadd(UChar size, UInt offset, UChar delta, ULong value)
4630{
4631 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4632
4633 insn->tag = S390_INSN_GADD;
4634 insn->size = size;
4635 insn->variant.gadd.offset = offset;
4636 insn->variant.gadd.delta = delta;
4637 insn->variant.gadd.value = value;
4638
4639 return insn;
4640}
4641
4642
florian8844a632012-04-13 04:04:06 +00004643s390_insn *
4644s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
4645 Bool to_fast_entry)
4646{
4647 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4648
4649 insn->tag = S390_INSN_XDIRECT;
4650 insn->size = 0; /* does not matter */
4651
4652 insn->variant.xdirect.cond = cond;
4653 insn->variant.xdirect.dst = dst;
4654 insn->variant.xdirect.guest_IA = guest_IA;
4655 insn->variant.xdirect.to_fast_entry = to_fast_entry;
4656
4657 return insn;
4658}
4659
4660
4661s390_insn *
4662s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
4663{
4664 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4665
florian7346c7a2012-04-13 21:14:24 +00004666 insn->tag = S390_INSN_XINDIR;
florian8844a632012-04-13 04:04:06 +00004667 insn->size = 0; /* does not matter */
4668
florian7346c7a2012-04-13 21:14:24 +00004669 insn->variant.xindir.cond = cond;
4670 insn->variant.xindir.dst = dst;
4671 insn->variant.xindir.guest_IA = guest_IA;
florian8844a632012-04-13 04:04:06 +00004672
4673 return insn;
4674}
4675
4676
4677s390_insn *
4678s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
4679 IRJumpKind kind)
4680{
4681 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4682
4683 insn->tag = S390_INSN_XASSISTED;
4684 insn->size = 0; /* does not matter */
4685
4686 insn->variant.xassisted.cond = cond;
4687 insn->variant.xassisted.dst = dst;
4688 insn->variant.xassisted.guest_IA = guest_IA;
4689 insn->variant.xassisted.kind = kind;
4690
4691 return insn;
4692}
4693
4694
4695s390_insn *
4696s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
4697{
4698 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4699
florianbf516d12012-04-21 15:53:13 +00004700 vassert(counter->tag == S390_AMODE_B12);
4701 vassert(fail_addr->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00004702
4703 insn->tag = S390_INSN_EVCHECK;
4704 insn->size = 0; /* does not matter */
4705
4706 insn->variant.evcheck.counter = counter;
4707 insn->variant.evcheck.fail_addr = fail_addr;
4708
4709 return insn;
4710}
4711
4712
4713s390_insn *
4714s390_insn_profinc(void)
4715{
4716 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4717
4718 insn->tag = S390_INSN_PROFINC;
4719 insn->size = 0; /* does not matter */
4720
4721 return insn;
4722}
4723
4724
sewardj2019a972011-03-07 16:04:07 +00004725/*---------------------------------------------------------------*/
4726/*--- Debug print ---*/
4727/*---------------------------------------------------------------*/
4728
4729static const HChar *
4730s390_cc_as_string(s390_cc_t cc)
4731{
4732 switch (cc) {
4733 case S390_CC_NEVER: return "never";
4734 case S390_CC_OVFL: return "overflow";
4735 case S390_CC_H: return "greater than"; /* A > B ; high */
4736 case S390_CC_NLE: return "not low or equal";
4737 case S390_CC_L: return "less than"; /* A < B ; low */
4738 case S390_CC_NHE: return "not high or equal";
4739 case S390_CC_LH: return "low or high";
4740 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
4741 case S390_CC_E: return "equal"; /* A == B ; zero */
4742 case S390_CC_NLH: return "not low or high";
4743 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
4744 case S390_CC_NL: return "not low"; /* not low */
4745 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
4746 case S390_CC_NH: return "not high";
4747 case S390_CC_NO: return "not overflow";
4748 case S390_CC_ALWAYS: return "always";
4749 default:
4750 vpanic("s390_cc_as_string");
4751 }
4752}
4753
4754
florian8844a632012-04-13 04:04:06 +00004755static const HChar *
4756s390_jump_kind_as_string(IRJumpKind kind)
4757{
4758 switch (kind) {
4759 case Ijk_Boring: return "Boring";
4760 case Ijk_Call: return "Call";
4761 case Ijk_Ret: return "Return";
4762 case Ijk_ClientReq: return "ClientReq";
4763 case Ijk_Yield: return "Yield";
4764 case Ijk_EmWarn: return "EmWarn";
4765 case Ijk_EmFail: return "EmFail";
4766 case Ijk_NoDecode: return "NoDecode";
4767 case Ijk_MapFail: return "MapFail";
4768 case Ijk_TInval: return "Invalidate";
4769 case Ijk_NoRedir: return "NoRedir";
4770 case Ijk_SigTRAP: return "SigTRAP";
4771 case Ijk_SigSEGV: return "SigSEGV";
4772 case Ijk_SigBUS: return "SigBUS";
4773 case Ijk_Sys_syscall: return "Sys_syscall";
4774 default:
4775 vpanic("s390_jump_kind_as_string");
4776 }
4777}
4778
4779
sewardj2019a972011-03-07 16:04:07 +00004780/* Helper function for writing out a V insn */
4781static void
4782s390_sprintf(HChar *buf, HChar *fmt, ...)
4783{
4784 HChar *p;
4785 ULong value;
4786 va_list args;
4787 va_start(args, fmt);
4788
4789 p = buf;
4790 for ( ; *fmt; ++fmt) {
4791 Int c = *fmt;
4792
4793 if (c != '%') {
4794 *p++ = c;
4795 continue;
4796 }
4797
4798 c = *++fmt; /* next char */
4799 switch (c) {
4800 case '%':
4801 *p++ = c; /* %% */
4802 continue;
4803
4804 case 's': /* %s */
4805 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
4806 continue;
4807
4808 case 'M': /* %M = mnemonic */
4809 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
4810 continue;
4811
4812 case 'R': /* %R = register */
4813 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
4814 continue;
4815
4816 case 'A': /* %A = amode */
4817 p += vex_sprintf(p, "%s",
4818 s390_amode_as_string(va_arg(args, s390_amode *)));
4819 continue;
4820
florianad43b3a2012-02-20 15:01:14 +00004821 case 'G': /* %G = guest state @ offset */
4822 p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt));
4823 continue;
4824
sewardj2019a972011-03-07 16:04:07 +00004825 case 'C': /* %C = condition code */
4826 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
4827 continue;
4828
florian8844a632012-04-13 04:04:06 +00004829 case 'J': /* &J = jump kind */
4830 p += vex_sprintf(p, "%s",
4831 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
4832 continue;
4833
sewardj2019a972011-03-07 16:04:07 +00004834 case 'L': { /* %L = argument list in helper call*/
4835 UInt i, num_args;
4836
4837 num_args = va_arg(args, UInt);
4838
4839 for (i = 0; i < num_args; ++i) {
4840 if (i != 0) p += vex_sprintf(p, ", ");
4841 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
4842 }
4843 continue;
4844 }
4845
4846 case 'O': { /* %O = RMI operand */
4847 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
4848
4849 switch (op->tag) {
4850 case S390_OPND_REG:
4851 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
4852 continue;
4853
4854 case S390_OPND_AMODE:
4855 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
4856 continue;
4857
4858 case S390_OPND_IMMEDIATE:
4859 value = op->variant.imm;
4860 goto print_value;
4861
4862 default:
4863 goto fail;
4864 }
4865 }
4866
4867 case 'I': /* %I = immediate value */
4868 value = va_arg(args, ULong);
4869 goto print_value;
4870
4871 print_value:
4872 if ((Long)value < 0)
4873 p += vex_sprintf(p, "%lld", (Long)value);
4874 else if (value < 100)
4875 p += vex_sprintf(p, "%llu", value);
4876 else
4877 p += vex_sprintf(p, "0x%llx", value);
4878 continue;
4879
4880 default:
4881 goto fail;
4882 }
4883 }
4884 *p = '\0';
4885 va_end(args);
4886
4887 return;
4888
4889 fail: vpanic("s390_printf");
4890}
4891
4892
4893/* Decompile the given insn into a static buffer and return it */
4894const HChar *
4895s390_insn_as_string(const s390_insn *insn)
4896{
4897 static HChar buf[300];
4898 const HChar *op;
4899 HChar *p;
4900
4901 buf[0] = '\0';
4902
4903 switch (insn->tag) {
4904 case S390_INSN_LOAD:
4905 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
4906 insn->variant.load.src);
4907 break;
4908
4909 case S390_INSN_STORE:
4910 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
4911 insn->variant.store.dst);
4912 break;
4913
4914 case S390_INSN_MOVE:
4915 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
4916 insn->variant.move.src);
4917 break;
4918
4919 case S390_INSN_COND_MOVE:
4920 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
4921 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
4922 &insn->variant.cond_move.src);
4923 break;
4924
4925 case S390_INSN_LOAD_IMMEDIATE:
4926 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
4927 insn->variant.load_immediate.value);
4928 break;
4929
4930 case S390_INSN_ALU:
4931 switch (insn->variant.alu.tag) {
4932 case S390_ALU_ADD: op = "v-add"; break;
4933 case S390_ALU_SUB: op = "v-sub"; break;
4934 case S390_ALU_MUL: op = "v-mul"; break;
4935 case S390_ALU_AND: op = "v-and"; break;
4936 case S390_ALU_OR: op = "v-or"; break;
4937 case S390_ALU_XOR: op = "v-xor"; break;
4938 case S390_ALU_LSH: op = "v-lsh"; break;
4939 case S390_ALU_RSH: op = "v-rsh"; break;
4940 case S390_ALU_RSHA: op = "v-rsha"; break;
4941 default: goto fail;
4942 }
florian043af212012-06-06 02:44:53 +00004943 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
sewardj2019a972011-03-07 16:04:07 +00004944 &insn->variant.alu.op2);
4945 break;
4946
4947 case S390_INSN_MUL:
4948 if (insn->variant.mul.signed_multiply) {
4949 op = "v-muls";
4950 } else {
4951 op = "v-mulu";
4952 }
4953 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
4954 &insn->variant.mul.op2);
4955 break;
4956
4957 case S390_INSN_DIV:
4958 if (insn->variant.div.signed_divide) {
4959 op = "v-divs";
4960 } else {
4961 op = "v-divu";
4962 }
4963 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
4964 &insn->variant.div.op2);
4965 break;
4966
4967 case S390_INSN_DIVS:
4968 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
4969 &insn->variant.divs.op2);
4970 break;
4971
sewardj611b06e2011-03-24 08:57:29 +00004972 case S390_INSN_CLZ:
4973 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
4974 &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +00004975 break;
4976
4977 case S390_INSN_UNOP:
4978 switch (insn->variant.unop.tag) {
4979 case S390_ZERO_EXTEND_8:
4980 case S390_ZERO_EXTEND_16:
4981 case S390_ZERO_EXTEND_32:
4982 op = "v-zerox";
4983 break;
4984
4985 case S390_SIGN_EXTEND_8:
4986 case S390_SIGN_EXTEND_16:
4987 case S390_SIGN_EXTEND_32:
4988 op = "v-signx";
4989 break;
4990
4991 case S390_NEGATE:
4992 op = "v-neg";
4993 break;
4994
4995 default:
4996 goto fail;
4997 }
4998 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
4999 &insn->variant.unop.src);
5000 break;
5001
5002 case S390_INSN_TEST:
5003 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
5004 break;
5005
5006 case S390_INSN_CC2BOOL:
5007 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
5008 insn->variant.cc2bool.cond);
5009 break;
5010
5011 case S390_INSN_CAS:
5012 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
5013 insn->variant.cas.op2, insn->variant.cas.op3,
5014 insn->variant.cas.old_mem);
5015 break;
5016
florian448cbba2012-06-06 02:26:01 +00005017 case S390_INSN_CDAS:
5018 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
5019 insn->variant.cdas.op1_high, insn->variant.cdas.op1_low,
5020 insn->variant.cdas.op2, insn->variant.cdas.op3_high,
5021 insn->variant.cdas.op3_low, insn->variant.cdas.old_mem_high,
5022 insn->variant.cdas.old_mem_low);
5023 break;
5024
sewardj2019a972011-03-07 16:04:07 +00005025 case S390_INSN_COMPARE:
5026 if (insn->variant.compare.signed_comparison) {
5027 op = "v-cmps";
5028 } else {
5029 op = "v-cmpu";
5030 }
5031 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
5032 &insn->variant.compare.src2);
5033 break;
5034
sewardj2019a972011-03-07 16:04:07 +00005035 case S390_INSN_HELPER_CALL: {
florian01ed6e72012-05-27 16:52:43 +00005036 if (insn->variant.helper_call.dst != INVALID_HREG) {
5037 s390_sprintf(buf, "%M if (%C) %R = %s{%I}(%L)", "v-call",
5038 insn->variant.helper_call.cond,
5039 insn->variant.helper_call.dst,
5040 insn->variant.helper_call.name,
5041 insn->variant.helper_call.target,
5042 insn->variant.helper_call.num_args);
5043 } else {
5044 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
5045 insn->variant.helper_call.cond,
5046 insn->variant.helper_call.name,
5047 insn->variant.helper_call.target,
5048 insn->variant.helper_call.num_args);
5049 }
florian8844a632012-04-13 04:04:06 +00005050 return buf; /* avoid printing "size = ..." which is meaningless */
sewardj2019a972011-03-07 16:04:07 +00005051 }
5052
5053 case S390_INSN_BFP_TRIOP:
5054 switch (insn->variant.bfp_triop.tag) {
5055 case S390_BFP_MADD: op = "v-fmadd"; break;
5056 case S390_BFP_MSUB: op = "v-fmsub"; break;
5057 default: goto fail;
5058 }
florian043af212012-06-06 02:44:53 +00005059 s390_sprintf(buf, "%M %R,%R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00005060 insn->variant.bfp_triop.dst /* op1 same as dst */,
5061 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
5062 break;
5063
5064 case S390_INSN_BFP_BINOP:
5065 switch (insn->variant.bfp_binop.tag) {
5066 case S390_BFP_ADD: op = "v-fadd"; break;
5067 case S390_BFP_SUB: op = "v-fsub"; break;
5068 case S390_BFP_MUL: op = "v-fmul"; break;
5069 case S390_BFP_DIV: op = "v-fdiv"; break;
5070 default: goto fail;
5071 }
florian043af212012-06-06 02:44:53 +00005072 s390_sprintf(buf, "%M %R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00005073 insn->variant.bfp_binop.dst /* op1 same as dst */,
5074 insn->variant.bfp_binop.op2);
5075 break;
5076
5077 case S390_INSN_BFP_COMPARE:
5078 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
5079 insn->variant.bfp_compare.op1, insn->variant.bfp_compare.op2);
5080 break;
5081
5082 case S390_INSN_BFP_UNOP:
5083 switch (insn->variant.bfp_unop.tag) {
5084 case S390_BFP_ABS: op = "v-fabs"; break;
5085 case S390_BFP_NABS: op = "v-fnabs"; break;
5086 case S390_BFP_NEG: op = "v-fneg"; break;
5087 case S390_BFP_SQRT: op = "v-fsqrt"; break;
5088 case S390_BFP_I32_TO_F32:
5089 case S390_BFP_I32_TO_F64:
5090 case S390_BFP_I32_TO_F128:
5091 case S390_BFP_I64_TO_F32:
5092 case S390_BFP_I64_TO_F64:
5093 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
5094 case S390_BFP_F32_TO_I32:
5095 case S390_BFP_F32_TO_I64:
5096 case S390_BFP_F64_TO_I32:
5097 case S390_BFP_F64_TO_I64:
5098 case S390_BFP_F128_TO_I32:
5099 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
5100 case S390_BFP_F32_TO_F64:
5101 case S390_BFP_F32_TO_F128:
5102 case S390_BFP_F64_TO_F32:
5103 case S390_BFP_F64_TO_F128:
5104 case S390_BFP_F128_TO_F32:
5105 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
5106 default: goto fail;
5107 }
5108 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst,
5109 insn->variant.bfp_unop.op);
5110 break;
5111
5112 case S390_INSN_BFP128_BINOP:
5113 switch (insn->variant.bfp128_binop.tag) {
5114 case S390_BFP_ADD: op = "v-fadd"; break;
5115 case S390_BFP_SUB: op = "v-fsub"; break;
5116 case S390_BFP_MUL: op = "v-fmul"; break;
5117 case S390_BFP_DIV: op = "v-fdiv"; break;
5118 default: goto fail;
5119 }
5120 /* Only write the register that identifies the register pair */
florian043af212012-06-06 02:44:53 +00005121 s390_sprintf(buf, "%M %R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00005122 insn->variant.bfp128_binop.dst_hi /* op1 same as dst */,
5123 insn->variant.bfp128_binop.op2_hi);
5124 break;
5125
5126 case S390_INSN_BFP128_COMPARE:
5127 /* Only write the register that identifies the register pair */
5128 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp128_compare.dst,
5129 insn->variant.bfp128_compare.op1_hi,
5130 insn->variant.bfp128_compare.op2_hi);
5131 break;
5132
5133 case S390_INSN_BFP128_UNOP:
5134 case S390_INSN_BFP128_CONVERT_TO:
5135 case S390_INSN_BFP128_CONVERT_FROM:
5136 switch (insn->variant.bfp128_unop.tag) {
5137 case S390_BFP_ABS: op = "v-fabs"; break;
5138 case S390_BFP_NABS: op = "v-fnabs"; break;
5139 case S390_BFP_NEG: op = "v-fneg"; break;
5140 case S390_BFP_SQRT: op = "v-fsqrt"; break;
5141 case S390_BFP_I32_TO_F128:
5142 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
5143 case S390_BFP_F128_TO_I32:
5144 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
5145 case S390_BFP_F32_TO_F128:
5146 case S390_BFP_F64_TO_F128:
5147 case S390_BFP_F128_TO_F32:
5148 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
5149 default: goto fail;
5150 }
5151 /* Only write the register that identifies the register pair */
5152 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp128_unop.dst_hi,
5153 insn->variant.bfp128_unop.op_hi);
5154 break;
5155
sewardja52e37e2011-04-28 18:48:06 +00005156 case S390_INSN_MFENCE:
5157 s390_sprintf(buf, "%M", "v-mfence");
5158 return buf; /* avoid printing "size = ..." which is meaningless */
5159
florianad43b3a2012-02-20 15:01:14 +00005160 case S390_INSN_GZERO:
5161 s390_sprintf(buf, "%M %G", "v-gzero", insn->variant.gzero.offset);
5162 break;
5163
5164 case S390_INSN_GADD:
5165 s390_sprintf(buf, "%M %G += %I (= %I)", "v-gadd",
5166 insn->variant.gadd.offset,
5167 (Long)(Char)insn->variant.gadd.delta,
5168 insn->variant.gadd.value);
5169 break;
5170
florian8844a632012-04-13 04:04:06 +00005171 case S390_INSN_EVCHECK:
5172 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
5173 insn->variant.evcheck.counter,
5174 insn->variant.evcheck.fail_addr);
5175 return buf; /* avoid printing "size = ..." which is meaningless */
5176
5177 case S390_INSN_PROFINC:
5178 s390_sprintf(buf, "%M", "v-profinc");
5179 return buf; /* avoid printing "size = ..." which is meaningless */
5180
5181 case S390_INSN_XDIRECT:
5182 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
5183 insn->variant.xdirect.cond,
5184 insn->variant.xdirect.guest_IA,
5185 insn->variant.xdirect.dst,
5186 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
5187 return buf; /* avoid printing "size = ..." which is meaningless */
5188
5189 case S390_INSN_XINDIR:
5190 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
5191 insn->variant.xindir.cond,
5192 insn->variant.xindir.guest_IA,
5193 insn->variant.xindir.dst);
5194 return buf; /* avoid printing "size = ..." which is meaningless */
5195
5196 case S390_INSN_XASSISTED:
5197 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
5198 insn->variant.xassisted.cond,
5199 insn->variant.xassisted.kind,
5200 insn->variant.xassisted.guest_IA,
5201 insn->variant.xassisted.dst);
5202 return buf; /* avoid printing "size = ..." which is meaningless */
5203
sewardj2019a972011-03-07 16:04:07 +00005204 default: goto fail;
5205 }
5206
5207 /* Write out how many bytes are involved in the operation */
5208
5209 {
5210 UInt len, i;
5211
5212 for (p = buf; *p; ++p)
5213 continue;
5214
5215 len = p - buf;
5216
5217 if (len < 32) {
5218 for (i = len; i < 32; ++i)
5219 p += vex_sprintf(p, " ");
5220 } else {
5221 p += vex_sprintf(p, "\t");
5222 }
5223 }
5224
5225 /* Special cases first */
5226 switch (insn->tag) {
5227 case S390_INSN_UNOP:
5228 switch (insn->variant.unop.tag) {
5229 case S390_SIGN_EXTEND_8:
5230 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
5231 case S390_SIGN_EXTEND_16:
5232 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
5233 case S390_SIGN_EXTEND_32:
5234 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
5235 default:
5236 goto common;
5237 }
5238
5239 case S390_INSN_BFP_UNOP:
5240 switch (insn->variant.bfp_unop.tag) {
5241 case S390_BFP_I32_TO_F32:
5242 case S390_BFP_I32_TO_F64:
5243 case S390_BFP_I32_TO_F128:
5244 case S390_BFP_F32_TO_I32:
5245 case S390_BFP_F32_TO_I64:
5246 case S390_BFP_F32_TO_F64:
5247 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
5248 case S390_BFP_I64_TO_F32:
5249 case S390_BFP_I64_TO_F64:
5250 case S390_BFP_I64_TO_F128:
5251 case S390_BFP_F64_TO_I32:
5252 case S390_BFP_F64_TO_I64:
5253 case S390_BFP_F64_TO_F32:
5254 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
5255 case S390_BFP_F128_TO_I32:
5256 case S390_BFP_F128_TO_I64:
5257 case S390_BFP_F128_TO_F32:
5258 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
5259 default:
5260 goto common;
5261 }
5262
5263 case S390_INSN_BFP128_UNOP:
5264 case S390_INSN_BFP128_CONVERT_TO:
5265 case S390_INSN_BFP128_CONVERT_FROM:
5266 switch (insn->variant.bfp128_unop.tag) {
5267 case S390_BFP_I32_TO_F128:
5268 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
5269 case S390_BFP_I64_TO_F128:
5270 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
5271 case S390_BFP_F128_TO_I32:
5272 case S390_BFP_F128_TO_I64:
5273 case S390_BFP_F128_TO_F32:
5274 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
5275 default:
5276 goto common;
5277 }
5278
5279 default:
5280 goto common;
5281 }
5282
5283 /* Common case */
5284 common:
5285 vex_sprintf(p, "%u bytes", (UInt)insn->size);
5286
5287 return buf;
5288
5289 fail: vpanic("s390_insn_as_string");
5290}
5291
5292
5293
5294/* Load NUM bytes from memory into register REG using addressing mode AM. */
5295static UChar *
5296s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
5297{
5298 UInt b = hregNumber(am->b);
5299 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
5300 UInt d = am->d;
5301
5302 switch (am->tag) {
5303 case S390_AMODE_B12:
5304 case S390_AMODE_BX12:
5305 switch (num) {
5306 case 1: return s390_emit_IC(p, reg, x, b, d);
5307 case 2: return s390_emit_LH(p, reg, x, b, d);
5308 case 4: return s390_emit_L(p, reg, x, b, d);
5309 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
5310 default: goto fail;
5311 }
5312 break;
5313
5314 case S390_AMODE_B20:
5315 case S390_AMODE_BX20:
5316 switch (num) {
5317 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
5318 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
5319 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
5320 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
5321 default: goto fail;
5322 }
5323 break;
5324
5325 default: goto fail;
5326 }
5327
5328 fail:
5329 vpanic("s390_emit_load_mem");
5330}
5331
5332
5333/* Load condition code into register REG */
5334static UChar *
5335s390_emit_load_cc(UChar *p, UChar reg)
5336{
5337 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
5338 p = s390_emit_IPM(p, reg, reg);
5339 /* Shift 28 bits to the right --> [0,1,2,3] */
sewardjf74c86f2011-04-05 14:04:53 +00005340 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
sewardj2019a972011-03-07 16:04:07 +00005341}
5342
5343
5344/*---------------------------------------------------------------*/
5345/*--- Code generation ---*/
5346/*---------------------------------------------------------------*/
5347
5348/* Do not load more bytes than requested. */
5349static UChar *
5350s390_insn_load_emit(UChar *buf, const s390_insn *insn)
5351{
5352 UInt r, x, b, d;
5353 const s390_amode *src;
5354
5355 src = insn->variant.load.src;
5356
5357 r = hregNumber(insn->variant.load.dst);
5358
5359 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
5360 b = hregNumber(src->b);
5361 x = hregNumber(src->x); /* 0 for B12 and B20 */
5362 d = src->d;
5363
5364 switch (insn->size) {
5365
5366 case 4:
5367 switch (src->tag) {
5368 case S390_AMODE_B12:
5369 case S390_AMODE_BX12:
5370 return s390_emit_LE(buf, r, x, b, d);
5371
5372 case S390_AMODE_B20:
5373 case S390_AMODE_BX20:
5374 return s390_emit_LEY(buf, r, x, b, DISP20(d));
5375 }
5376 break;
5377
5378 case 8:
5379 switch (src->tag) {
5380 case S390_AMODE_B12:
5381 case S390_AMODE_BX12:
5382 return s390_emit_LD(buf, r, x, b, d);
5383
5384 case S390_AMODE_B20:
5385 case S390_AMODE_BX20:
5386 return s390_emit_LDY(buf, r, x, b, DISP20(d));
5387 }
5388 break;
5389 }
5390 vpanic("s390_insn_load_emit");
5391 }
5392
5393 /* Integer stuff */
5394 return s390_emit_load_mem(buf, insn->size, r, src);
5395}
5396
5397
5398static UChar *
5399s390_insn_store_emit(UChar *buf, const s390_insn *insn)
5400{
5401 UInt r, x, b, d;
5402 const s390_amode *dst;
5403
5404 dst = insn->variant.store.dst;
5405
5406 r = hregNumber(insn->variant.store.src);
5407 b = hregNumber(dst->b);
5408 x = hregNumber(dst->x); /* 0 for B12 and B20 */
5409 d = dst->d;
5410
5411 if (hregClass(insn->variant.store.src) == HRcFlt64) {
5412 switch (insn->size) {
5413
5414 case 4:
5415 switch (dst->tag) {
5416 case S390_AMODE_B12:
5417 case S390_AMODE_BX12:
5418 return s390_emit_STE(buf, r, x, b, d);
5419
5420 case S390_AMODE_B20:
5421 case S390_AMODE_BX20:
5422 return s390_emit_STEY(buf, r, x, b, DISP20(d));
5423 }
5424 break;
5425
5426 case 8:
5427 switch (dst->tag) {
5428 case S390_AMODE_B12:
5429 case S390_AMODE_BX12:
5430 return s390_emit_STD(buf, r, x, b, d);
5431
5432 case S390_AMODE_B20:
5433 case S390_AMODE_BX20:
5434 return s390_emit_STDY(buf, r, x, b, DISP20(d));
5435 }
5436 break;
5437 }
5438 vpanic("s390_insn_store_emit");
5439 }
5440
5441 /* Integer stuff */
5442 switch (insn->size) {
5443 case 1:
5444 switch (dst->tag) {
5445 case S390_AMODE_B12:
5446 case S390_AMODE_BX12:
5447 return s390_emit_STC(buf, r, x, b, d);
5448
5449 case S390_AMODE_B20:
5450 case S390_AMODE_BX20:
5451 return s390_emit_STCY(buf, r, x, b, DISP20(d));
5452 }
5453 break;
5454
5455 case 2:
5456 switch (dst->tag) {
5457 case S390_AMODE_B12:
5458 case S390_AMODE_BX12:
5459 return s390_emit_STH(buf, r, x, b, d);
5460
5461 case S390_AMODE_B20:
5462 case S390_AMODE_BX20:
5463 return s390_emit_STHY(buf, r, x, b, DISP20(d));
5464 }
5465 break;
5466
5467 case 4:
5468 switch (dst->tag) {
5469 case S390_AMODE_B12:
5470 case S390_AMODE_BX12:
5471 return s390_emit_ST(buf, r, x, b, d);
5472
5473 case S390_AMODE_B20:
5474 case S390_AMODE_BX20:
5475 return s390_emit_STY(buf, r, x, b, DISP20(d));
5476 }
5477 break;
5478
5479 case 8:
5480 return s390_emit_STG(buf, r, x, b, DISP20(d));
5481
5482 default:
5483 break;
5484 }
5485
5486 vpanic("s390_insn_store_emit");
5487}
5488
5489
5490static UChar *
5491s390_insn_move_emit(UChar *buf, const s390_insn *insn)
5492{
5493 UInt dst, src;
5494 HRegClass dst_class, src_class;
5495
5496 dst = hregNumber(insn->variant.move.dst);
5497 src = hregNumber(insn->variant.move.src);
5498
5499 dst_class = hregClass(insn->variant.move.dst);
5500 src_class = hregClass(insn->variant.move.src);
5501
5502 if (dst_class == src_class) {
5503 if (dst_class == HRcInt64)
5504 return s390_emit_LGR(buf, dst, src);
5505 if (dst_class == HRcFlt64)
5506 return s390_emit_LDR(buf, dst, src);
5507 } else {
floriana782a172011-12-18 15:51:54 +00005508 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
5509 if (insn->size == 4) {
5510 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
5511 return s390_emit_LDGRw(buf, dst, R0);
5512 } else {
5513 return s390_emit_LDGRw(buf, dst, src);
5514 }
5515 }
5516 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
5517 if (insn->size == 4) {
5518 buf = s390_emit_LGDRw(buf, dst, src);
5519 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
5520 } else {
5521 return s390_emit_LGDRw(buf, dst, src);
5522 }
5523 }
sewardj2019a972011-03-07 16:04:07 +00005524 /* A move between floating point registers and general purpose
5525 registers of different size should never occur and indicates
5526 an error elsewhere. */
5527 }
5528
5529 vpanic("s390_insn_move_emit");
5530}
5531
5532
5533static UChar *
5534s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
5535{
5536 UInt r;
5537 ULong value = insn->variant.load_immediate.value;
5538
5539 r = hregNumber(insn->variant.load_immediate.dst);
5540
5541 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
5542 vassert(value == 0);
5543 switch (insn->size) {
5544 case 4: return s390_emit_LZER(buf, r, value);
5545 case 8: return s390_emit_LZDR(buf, r, value);
5546 }
5547 vpanic("s390_insn_load_immediate_emit");
5548 }
5549
5550 switch (insn->size) {
5551 case 1:
5552 case 2:
5553 /* Load the immediate values as a 4 byte value. That does not hurt as
5554 those extra bytes will not be looked at. Fall through .... */
5555 case 4:
5556 return s390_emit_load_32imm(buf, r, value);
5557
5558 case 8:
5559 return s390_emit_load_64imm(buf, r, value);
5560 }
5561
5562 vpanic("s390_insn_load_immediate_emit");
5563}
5564
5565
5566/* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
5567 So we simply perform a 4-byte operation. Doing so uses possibly undefined
5568 bits and produces an undefined result in those extra bit positions. But
5569 upstream does not look at those positions, so this is OK. */
5570static UChar *
5571s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
5572{
5573 s390_opnd_RMI op2;
5574 UInt dst;
5575
5576 dst = hregNumber(insn->variant.alu.dst);
5577 op2 = insn->variant.alu.op2;
5578
5579 /* Second operand is in a register */
5580 if (op2.tag == S390_OPND_REG) {
5581 UInt r2 = hregNumber(op2.variant.reg);
5582
5583 switch (insn->size) {
5584 case 1:
5585 case 2:
5586 case 4:
5587 switch (insn->variant.alu.tag) {
5588 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
5589 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
5590 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
5591 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
5592 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
5593 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
sewardj3c49aaa2011-04-05 14:00:37 +00005594 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
5595 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
5596 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
sewardj2019a972011-03-07 16:04:07 +00005597 }
5598 goto fail;
5599
5600 case 8:
5601 switch (insn->variant.alu.tag) {
5602 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
5603 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
5604 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
5605 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
5606 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
5607 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
5608 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
5609 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
5610 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
5611 }
5612 goto fail;
5613 }
5614 goto fail;
5615 }
5616
5617 /* 2nd operand is in memory */
5618 if (op2.tag == S390_OPND_AMODE) {
5619 UInt b, x, d;
5620 const s390_amode *src = op2.variant.am;
5621
5622 b = hregNumber(src->b);
5623 x = hregNumber(src->x); /* 0 for B12 and B20 */
5624 d = src->d;
5625
5626 /* Shift operands are special here as there are no opcodes that
sewardje0dd77e2011-04-27 12:07:01 +00005627 allow a memory operand. So we first load the 2nd operand into
5628 some register. R0 is used to save restore the contents of the
5629 chosen register.. */
sewardj652b56a2011-04-13 15:38:17 +00005630
sewardj2019a972011-03-07 16:04:07 +00005631 if (insn->variant.alu.tag == S390_ALU_LSH ||
5632 insn->variant.alu.tag == S390_ALU_RSH ||
5633 insn->variant.alu.tag == S390_ALU_RSHA) {
sewardje0dd77e2011-04-27 12:07:01 +00005634 UInt b2;
sewardj2019a972011-03-07 16:04:07 +00005635
sewardje0dd77e2011-04-27 12:07:01 +00005636 /* Choose a register (other than DST or R0) into which to stick the
5637 shift amount. The following works because r15 is reserved and
5638 thusly dst != 15. */
5639 vassert(dst != 15); /* extra paranoia */
5640 b2 = (dst + 1) % 16;
5641
5642 buf = s390_emit_LGR(buf, R0, b2); /* save */
5643
5644 /* Loading SRC to B2 does not modify R0. */
5645 buf = s390_emit_load_mem(buf, insn->size, b2, src);
sewardj2019a972011-03-07 16:04:07 +00005646
5647 if (insn->size == 8) {
sewardje0dd77e2011-04-27 12:07:01 +00005648 switch (insn->variant.alu.tag) {
5649 case S390_ALU_LSH:
5650 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
5651 break;
5652 case S390_ALU_RSH:
5653 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
5654 break;
5655 case S390_ALU_RSHA:
5656 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
5657 break;
5658 default: /* unreachable */
5659 goto fail;
5660 }
sewardj2019a972011-03-07 16:04:07 +00005661 } else {
sewardje0dd77e2011-04-27 12:07:01 +00005662 switch (insn->variant.alu.tag) {
5663 case S390_ALU_LSH:
5664 buf = s390_emit_SLL(buf, dst, b2, 0);
5665 break;
5666 case S390_ALU_RSH:
5667 buf = s390_emit_SRL(buf, dst, b2, 0);
5668 break;
5669 case S390_ALU_RSHA:
5670 buf = s390_emit_SRA(buf, dst, b2, 0);
5671 break;
5672 default: /* unreachable */
5673 goto fail;
5674 }
sewardj2019a972011-03-07 16:04:07 +00005675 }
sewardje0dd77e2011-04-27 12:07:01 +00005676 return s390_emit_LGR(buf, b2, R0); /* restore */
sewardj2019a972011-03-07 16:04:07 +00005677 }
5678
5679 switch (insn->size) {
5680 case 1:
5681 /* Move the byte from memory into scratch register r0 */
5682 buf = s390_emit_load_mem(buf, 1, R0, src);
5683
5684 switch (insn->variant.alu.tag) {
5685 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
5686 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
5687 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
5688 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
5689 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
5690 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
5691 case S390_ALU_LSH:
5692 case S390_ALU_RSH:
5693 case S390_ALU_RSHA: ; /* avoid GCC warning */
5694 }
5695 goto fail;
5696
5697 case 2:
5698 switch (src->tag) {
5699 case S390_AMODE_B12:
5700 case S390_AMODE_BX12:
5701 switch (insn->variant.alu.tag) {
5702 case S390_ALU_ADD:
5703 return s390_emit_AH(buf, dst, x, b, d);
5704
5705 case S390_ALU_SUB:
5706 return s390_emit_SH(buf, dst, x, b, d);
5707
5708 case S390_ALU_MUL:
5709 return s390_emit_MH(buf, dst, x, b, d);
5710
5711 /* For bitwise operations: Move two bytes from memory into scratch
5712 register r0; then perform operation */
5713 case S390_ALU_AND:
5714 buf = s390_emit_LH(buf, R0, x, b, d);
5715 return s390_emit_NR(buf, dst, R0);
5716
5717 case S390_ALU_OR:
5718 buf = s390_emit_LH(buf, R0, x, b, d);
5719 return s390_emit_OR(buf, dst, R0);
5720
5721 case S390_ALU_XOR:
5722 buf = s390_emit_LH(buf, R0, x, b, d);
5723 return s390_emit_XR(buf, dst, R0);
5724
5725 case S390_ALU_LSH:
5726 case S390_ALU_RSH:
5727 case S390_ALU_RSHA: ; /* avoid GCC warning */
5728 }
5729 goto fail;
5730
5731 case S390_AMODE_B20:
5732 case S390_AMODE_BX20:
5733 switch (insn->variant.alu.tag) {
5734 case S390_ALU_ADD:
5735 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
5736
5737 case S390_ALU_SUB:
5738 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
5739
5740 case S390_ALU_MUL:
sewardjeae8db52011-03-24 09:01:50 +00005741 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00005742
5743 /* For bitwise operations: Move two bytes from memory into scratch
5744 register r0; then perform operation */
5745 case S390_ALU_AND:
5746 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5747 return s390_emit_NR(buf, dst, R0);
5748
5749 case S390_ALU_OR:
5750 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5751 return s390_emit_OR(buf, dst, R0);
5752
5753 case S390_ALU_XOR:
5754 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5755 return s390_emit_XR(buf, dst, R0);
5756
5757 case S390_ALU_LSH:
5758 case S390_ALU_RSH:
5759 case S390_ALU_RSHA: ; /* avoid GCC warning */
5760 }
5761 goto fail;
5762 }
5763 goto fail;
5764
5765 case 4:
5766 switch (src->tag) {
5767 case S390_AMODE_B12:
5768 case S390_AMODE_BX12:
5769 switch (insn->variant.alu.tag) {
5770 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
5771 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
5772 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
5773 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
5774 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
5775 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
5776 case S390_ALU_LSH:
5777 case S390_ALU_RSH:
5778 case S390_ALU_RSHA: ; /* avoid GCC warning */
5779 }
5780 goto fail;
5781
5782 case S390_AMODE_B20:
5783 case S390_AMODE_BX20:
5784 switch (insn->variant.alu.tag) {
5785 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
5786 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
5787 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
5788 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
5789 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
5790 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
5791 case S390_ALU_LSH:
5792 case S390_ALU_RSH:
5793 case S390_ALU_RSHA: ; /* avoid GCC warning */
5794 }
5795 goto fail;
5796 }
5797 goto fail;
5798
5799 case 8:
5800 switch (insn->variant.alu.tag) {
5801 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
5802 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
5803 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
5804 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
5805 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
5806 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
5807 case S390_ALU_LSH:
5808 case S390_ALU_RSH:
5809 case S390_ALU_RSHA: ; /* avoid GCC warning */
5810 }
5811 goto fail;
5812 }
5813 goto fail;
5814 }
5815
5816 /* 2nd operand is an immediate value */
5817 if (op2.tag == S390_OPND_IMMEDIATE) {
5818 ULong value;
5819
5820 /* No masking of the value is required as it is not sign extended */
5821 value = op2.variant.imm;
5822
5823 switch (insn->size) {
5824 case 1:
5825 case 2:
5826 /* There is no 1-byte opcode. Do the computation in
5827 2 bytes. The extra byte will be ignored. */
5828 switch (insn->variant.alu.tag) {
5829 case S390_ALU_ADD:
5830 return s390_emit_AHI(buf, dst, value);
5831
5832 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00005833 return s390_emit_SLFIw(buf, dst, value);
sewardj2019a972011-03-07 16:04:07 +00005834
5835 case S390_ALU_MUL:
5836 return s390_emit_MHI(buf, dst, value);
5837
5838 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
5839 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
5840 case S390_ALU_XOR:
5841 /* There is no XILL instruction. Load the immediate value into
5842 R0 and combine with the destination register. */
5843 buf = s390_emit_LHI(buf, R0, value);
5844 return s390_emit_XR(buf, dst, R0);
5845
5846 case S390_ALU_LSH:
sewardj3c49aaa2011-04-05 14:00:37 +00005847 return s390_emit_SLL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00005848
5849 case S390_ALU_RSH:
sewardj3c49aaa2011-04-05 14:00:37 +00005850 return s390_emit_SRL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00005851
5852 case S390_ALU_RSHA:
sewardj3c49aaa2011-04-05 14:00:37 +00005853 return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00005854 }
5855 goto fail;
5856
5857 case 4:
5858 switch (insn->variant.alu.tag) {
5859 case S390_ALU_ADD:
5860 if (uint_fits_signed_16bit(value)) {
5861 return s390_emit_AHI(buf, dst, value);
5862 }
5863 return s390_emit_AFIw(buf, dst, value);
5864
5865 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
5866 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
5867 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
5868 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
5869 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
sewardj3c49aaa2011-04-05 14:00:37 +00005870 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
5871 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
5872 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00005873 }
5874 goto fail;
5875
5876 case 8:
5877 switch (insn->variant.alu.tag) {
5878 case S390_ALU_ADD:
5879 if (ulong_fits_signed_16bit(value)) {
5880 return s390_emit_AGHI(buf, dst, value);
5881 }
5882 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
5883 return s390_emit_AGFI(buf, dst, value);
5884 }
5885 /* Load constant into R0 then add */
5886 buf = s390_emit_load_64imm(buf, R0, value);
5887 return s390_emit_AGR(buf, dst, R0);
5888
5889 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00005890 if (ulong_fits_unsigned_32bit(value)) {
5891 return s390_emit_SLGFIw(buf, dst, value);
5892 }
sewardj2019a972011-03-07 16:04:07 +00005893 /* Load value into R0; then subtract from destination reg */
5894 buf = s390_emit_load_64imm(buf, R0, value);
5895 return s390_emit_SGR(buf, dst, R0);
5896
5897 case S390_ALU_MUL:
5898 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
5899 return s390_emit_MSGFI(buf, dst, value);
5900 }
5901 /* Load constant into R0 then add */
5902 buf = s390_emit_load_64imm(buf, R0, value);
5903 return s390_emit_MSGR(buf, dst, R0);
5904
5905 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
5906 case S390_ALU_AND:
5907 if (s390_host_has_eimm) {
5908 buf = s390_emit_NIHF(buf, dst, value >> 32);
5909 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
5910 }
5911 /* Load value into R0; then combine with destination reg */
5912 buf = s390_emit_load_64imm(buf, R0, value);
5913 return s390_emit_NGR(buf, dst, R0);
5914
5915 case S390_ALU_OR:
5916 if (s390_host_has_eimm) {
5917 buf = s390_emit_OIHF(buf, dst, value >> 32);
5918 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
5919 }
5920 /* Load value into R0; then combine with destination reg */
5921 buf = s390_emit_load_64imm(buf, R0, value);
5922 return s390_emit_OGR(buf, dst, R0);
5923
5924 case S390_ALU_XOR:
5925 if (s390_host_has_eimm) {
5926 buf = s390_emit_XIHF(buf, dst, value >> 32);
5927 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
5928 }
5929 /* Load value into R0; then combine with destination reg */
5930 buf = s390_emit_load_64imm(buf, R0, value);
5931 return s390_emit_XGR(buf, dst, R0);
5932
sewardj652b56a2011-04-13 15:38:17 +00005933 /* No special considerations for long displacement here. Only the six
5934 least significant bits of VALUE will be taken; all other bits are
5935 ignored. So the DH2 bits are irrelevant and do not influence the
5936 shift operation, independent of whether long-displacement is available
5937 or not. */
sewardj2019a972011-03-07 16:04:07 +00005938 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
5939 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
5940 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
5941 }
5942 goto fail;
5943 }
5944 goto fail;
5945 }
5946
5947 fail:
5948 vpanic("s390_insn_alu_emit");
5949}
5950
5951
5952static UChar *
5953s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
5954 Bool sign_extend)
5955{
sewardj06122e72011-03-28 12:14:48 +00005956 s390_opnd_RMI opnd = insn->variant.unop.src;
sewardj2019a972011-03-07 16:04:07 +00005957
5958 switch (opnd.tag) {
5959 case S390_OPND_REG: {
5960 UChar r1 = hregNumber(insn->variant.unop.dst);
5961 UChar r2 = hregNumber(opnd.variant.reg);
5962
5963 switch (from_size) {
5964 case 1:
5965 /* Widening to a half-word is implemented like widening to a word
5966 because the upper half-word will not be looked at. */
5967 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
5968 if (sign_extend)
5969 return s390_emit_LBRw(buf, r1, r2);
5970 else
5971 return s390_emit_LLCRw(buf, r1, r2);
5972 }
5973 if (insn->size == 8) { /* 8 --> 64 */
5974 if (sign_extend)
5975 return s390_emit_LGBRw(buf, r1, r2);
5976 else
5977 return s390_emit_LLGCRw(buf, r1, r2);
5978 }
5979 goto fail;
5980
5981 case 2:
5982 if (insn->size == 4) { /* 16 --> 32 */
5983 if (sign_extend)
5984 return s390_emit_LHRw(buf, r1, r2);
5985 else
5986 return s390_emit_LLHRw(buf, r1, r2);
5987 }
5988 if (insn->size == 8) { /* 16 --> 64 */
5989 if (sign_extend)
5990 return s390_emit_LGHRw(buf, r1, r2);
5991 else
5992 return s390_emit_LLGHRw(buf, r1, r2);
5993 }
5994 goto fail;
5995
5996 case 4:
5997 if (insn->size == 8) { /* 32 --> 64 */
5998 if (sign_extend)
5999 return s390_emit_LGFR(buf, r1, r2);
6000 else
6001 return s390_emit_LLGFR(buf, r1, r2);
6002 }
6003 goto fail;
6004
6005 default: /* unexpected "from" size */
6006 goto fail;
6007 }
6008 }
6009
6010 case S390_OPND_AMODE: {
6011 UChar r1 = hregNumber(insn->variant.unop.dst);
6012 const s390_amode *src = opnd.variant.am;
6013 UChar b = hregNumber(src->b);
6014 UChar x = hregNumber(src->x);
6015 Int d = src->d;
6016
6017 switch (from_size) {
6018 case 1:
6019 if (insn->size == 4 || insn->size == 2) {
6020 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00006021 return s390_emit_LBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006022 else
6023 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
6024 }
6025 if (insn->size == 8) {
6026 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00006027 return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006028 else
sewardj2019a972011-03-07 16:04:07 +00006029 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
6030 }
6031 goto fail;
6032
6033 case 2:
6034 if (insn->size == 4) { /* 16 --> 32 */
6035 if (sign_extend == 0)
6036 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
6037
6038 switch (src->tag) {
6039 case S390_AMODE_B12:
6040 case S390_AMODE_BX12:
6041 return s390_emit_LH(buf, r1, x, b, d);
6042
6043 case S390_AMODE_B20:
6044 case S390_AMODE_BX20:
6045 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
6046 }
6047 goto fail;
6048 }
6049 if (insn->size == 8) { /* 16 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00006050 if (sign_extend)
6051 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
6052 else
6053 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
6054 }
6055 goto fail;
6056
6057 case 4:
6058 if (insn->size == 8) { /* 32 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00006059 if (sign_extend)
6060 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
6061 else
6062 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
6063 }
6064 goto fail;
6065
6066 default: /* unexpected "from" size */
6067 goto fail;
6068 }
6069 }
6070
6071 case S390_OPND_IMMEDIATE: {
6072 UChar r1 = hregNumber(insn->variant.unop.dst);
6073 ULong value = opnd.variant.imm;
6074
6075 switch (from_size) {
6076 case 1:
6077 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
6078 if (sign_extend) {
6079 /* host can do the sign extension to 16-bit; LHI does the rest */
6080 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
6081 } else {
6082 return s390_emit_LHI(buf, r1, value);
6083 }
6084 }
6085 if (insn->size == 8) { /* 8 --> 64 */
6086 if (sign_extend) {
6087 /* host can do the sign extension to 16-bit; LGHI does the rest */
6088 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
6089 } else {
6090 return s390_emit_LGHI(buf, r1, value);
6091 }
6092 }
6093 goto fail;
6094
6095 case 2:
6096 if (insn->size == 4) { /* 16 --> 32 */
6097 return s390_emit_LHI(buf, r1, value);
6098 }
6099 if (insn->size == 8) { /* 16 --> 64 */
6100 if (sign_extend)
6101 return s390_emit_LGHI(buf, r1, value);
6102 else
6103 return s390_emit_LLILL(buf, r1, value);
6104 }
6105 goto fail;
6106
6107 case 4:
6108 if (insn->size == 8) { /* 32 --> 64 */
6109 if (sign_extend)
6110 return s390_emit_LGFIw(buf, r1, value);
6111 else
6112 return s390_emit_LLILFw(buf, r1, value);
6113 }
6114 goto fail;
6115
6116 default: /* unexpected "from" size */
6117 goto fail;
6118 }
6119 }
6120 }
6121
6122 fail:
6123 vpanic("s390_widen_emit");
6124}
6125
6126
6127static UChar *
6128s390_negate_emit(UChar *buf, const s390_insn *insn)
6129{
6130 s390_opnd_RMI opnd;
6131
6132 opnd = insn->variant.unop.src;
6133
6134 switch (opnd.tag) {
6135 case S390_OPND_REG: {
6136 UChar r1 = hregNumber(insn->variant.unop.dst);
6137 UChar r2 = hregNumber(opnd.variant.reg);
6138
6139 switch (insn->size) {
6140 case 1:
6141 case 2:
6142 case 4:
6143 return s390_emit_LCR(buf, r1, r2);
6144
6145 case 8:
6146 return s390_emit_LCGR(buf, r1, r2);
6147
6148 default:
6149 goto fail;
6150 }
6151 }
6152
6153 case S390_OPND_AMODE: {
6154 UChar r1 = hregNumber(insn->variant.unop.dst);
6155
6156 /* Load bytes into scratch register R0, then negate */
6157 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
6158
6159 switch (insn->size) {
6160 case 1:
6161 case 2:
6162 case 4:
6163 return s390_emit_LCR(buf, r1, R0);
6164
6165 case 8:
6166 return s390_emit_LCGR(buf, r1, R0);
6167
6168 default:
6169 goto fail;
6170 }
6171 }
6172
6173 case S390_OPND_IMMEDIATE: {
6174 UChar r1 = hregNumber(insn->variant.unop.dst);
6175 ULong value = opnd.variant.imm;
6176
6177 value = ~value + 1; /* two's complement */
6178
6179 switch (insn->size) {
6180 case 1:
6181 case 2:
6182 /* Load the immediate values as a 4 byte value. That does not hurt as
6183 those extra bytes will not be looked at. Fall through .... */
6184 case 4:
6185 return s390_emit_load_32imm(buf, r1, value);
6186
6187 case 8:
6188 return s390_emit_load_64imm(buf, r1, value);
6189
6190 default:
6191 goto fail;
6192 }
6193 }
6194 }
6195
6196 fail:
6197 vpanic("s390_negate_emit");
6198}
6199
6200
6201static UChar *
6202s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
6203{
6204 switch (insn->variant.unop.tag) {
6205 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
6206 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
6207 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
6208
6209 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
6210 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
6211 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
6212
6213 case S390_NEGATE: return s390_negate_emit(buf, insn);
6214 }
6215
6216 vpanic("s390_insn_unop_emit");
6217}
6218
6219
6220/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
6221 comparisons will have been converted to 4-byte comparisons in
6222 s390_isel_cc and should not occur here. */
6223static UChar *
6224s390_insn_test_emit(UChar *buf, const s390_insn *insn)
6225{
6226 s390_opnd_RMI opnd;
6227
6228 opnd = insn->variant.test.src;
6229
6230 switch (opnd.tag) {
6231 case S390_OPND_REG: {
6232 UInt reg = hregNumber(opnd.variant.reg);
6233
6234 switch (insn->size) {
6235 case 4:
6236 return s390_emit_LTR(buf, reg, reg);
6237
6238 case 8:
6239 return s390_emit_LTGR(buf, reg, reg);
6240
6241 default:
6242 goto fail;
6243 }
6244 }
6245
6246 case S390_OPND_AMODE: {
6247 const s390_amode *am = opnd.variant.am;
6248 UChar b = hregNumber(am->b);
6249 UChar x = hregNumber(am->x);
6250 Int d = am->d;
6251
6252 switch (insn->size) {
6253 case 4:
6254 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
6255
6256 case 8:
6257 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
6258
6259 default:
6260 goto fail;
6261 }
6262 }
6263
6264 case S390_OPND_IMMEDIATE: {
6265 ULong value = opnd.variant.imm;
6266
6267 switch (insn->size) {
6268 case 4:
6269 buf = s390_emit_load_32imm(buf, R0, value);
6270 return s390_emit_LTR(buf, R0, R0);
6271
6272 case 8:
6273 buf = s390_emit_load_64imm(buf, R0, value);
6274 return s390_emit_LTGR(buf, R0, R0);
6275
6276 default:
6277 goto fail;
6278 }
6279 }
6280
6281 default:
6282 goto fail;
6283 }
6284
6285 fail:
6286 vpanic("s390_insn_test_emit");
6287}
6288
6289
6290static UChar *
6291s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
6292{
6293 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
6294 s390_cc_t cond = insn->variant.cc2bool.cond;
6295
6296 /* Make the destination register be 1 or 0, depending on whether
6297 the relevant condition holds. A 64-bit value is computed. */
6298 if (cond == S390_CC_ALWAYS)
6299 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
6300
6301 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
6302 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
6303 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
6304 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
6305 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
6306
6307 return buf;
6308}
6309
6310
6311/* Only 4-byte and 8-byte operands are handled. */
6312static UChar *
6313s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
6314{
6315 UChar r1, r3, b, old;
6316 Int d;
6317 s390_amode *am;
6318
6319 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
6320 r3 = hregNumber(insn->variant.cas.op3);
6321 old= hregNumber(insn->variant.cas.old_mem);
6322 am = insn->variant.cas.op2;
6323 b = hregNumber(am->b);
6324 d = am->d;
6325
6326 switch (insn->size) {
6327 case 4:
6328 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
6329 buf = s390_emit_LR(buf, R0, r1);
6330 if (am->tag == S390_AMODE_B12)
6331 buf = s390_emit_CS(buf, R0, r3, b, d);
6332 else
6333 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
6334 /* Now copy R0 which has the old memory value to OLD */
6335 return s390_emit_LR(buf, old, R0);
6336
6337 case 8:
6338 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
6339 buf = s390_emit_LGR(buf, R0, r1);
6340 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
6341 /* Now copy R0 which has the old memory value to OLD */
6342 return s390_emit_LGR(buf, old, R0);
6343
6344 default:
6345 goto fail;
6346 }
6347
6348 fail:
6349 vpanic("s390_insn_cas_emit");
6350}
6351
6352
florian448cbba2012-06-06 02:26:01 +00006353/* Only 4-byte and 8-byte operands are handled. */
6354static UChar *
6355s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
6356{
sewardja90622a2012-06-19 13:29:00 +00006357 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
florian448cbba2012-06-06 02:26:01 +00006358 Int d;
6359 s390_amode *am;
6360
6361 r1 = hregNumber(insn->variant.cdas.op1_high); /* expected value */
6362 r1p1 = hregNumber(insn->variant.cdas.op1_low); /* expected value */
6363 r3 = hregNumber(insn->variant.cdas.op3_high);
sewardja90622a2012-06-19 13:29:00 +00006364 /* r3p1 = hregNumber(insn->variant.cdas.op3_low); */ /* unused */
florian448cbba2012-06-06 02:26:01 +00006365 old_high = hregNumber(insn->variant.cdas.old_mem_high);
6366 old_low = hregNumber(insn->variant.cdas.old_mem_low);
6367 scratch = hregNumber(insn->variant.cdas.scratch);
6368 am = insn->variant.cdas.op2;
6369 b = hregNumber(am->b);
6370 d = am->d;
6371
6372 vassert(scratch == 1);
6373
6374 switch (insn->size) {
6375 case 4:
6376 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
6377 and let CDS/CDSY clobber it */
6378 buf = s390_emit_LR(buf, R0, r1);
6379 buf = s390_emit_LR(buf, scratch, r1p1);
6380
6381 if (am->tag == S390_AMODE_B12)
6382 buf = s390_emit_CDS(buf, R0, r3, b, d);
6383 else
6384 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
6385
6386 /* Now copy R0,scratch which has the old memory value to OLD */
6387 buf = s390_emit_LR(buf, old_high, R0);
6388 buf = s390_emit_LR(buf, old_low, scratch);
6389 return buf;
6390
6391 case 8:
6392 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
6393 and let CDSG clobber it */
6394 buf = s390_emit_LGR(buf, R0, r1);
6395 buf = s390_emit_LGR(buf, scratch, r1p1);
6396
6397 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
6398
6399 /* Now copy R0,scratch which has the old memory value to OLD */
6400 buf = s390_emit_LGR(buf, old_high, R0);
6401 buf = s390_emit_LGR(buf, old_low, scratch);
6402 return buf;
6403
6404 default:
6405 goto fail;
6406 }
6407
6408 fail:
6409 vpanic("s390_insn_cas_emit");
6410}
6411
6412
sewardj2019a972011-03-07 16:04:07 +00006413/* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
6414 comparisons will have been converted to 4-byte comparisons in
6415 s390_isel_cc and should not occur here. */
6416static UChar *
6417s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
6418{
6419 s390_opnd_RMI op2;
6420 HReg op1;
6421 Bool signed_comparison;
6422
6423 op1 = insn->variant.compare.src1;
6424 op2 = insn->variant.compare.src2;
6425 signed_comparison = insn->variant.compare.signed_comparison;
6426
6427 switch (op2.tag) {
6428 case S390_OPND_REG: {
6429 UInt r1 = hregNumber(op1);
6430 UInt r2 = hregNumber(op2.variant.reg);
6431
6432 switch (insn->size) {
6433 case 4:
6434 if (signed_comparison)
6435 return s390_emit_CR(buf, r1, r2);
6436 else
6437 return s390_emit_CLR(buf, r1, r2);
6438
6439 case 8:
6440 if (signed_comparison)
6441 return s390_emit_CGR(buf, r1, r2);
6442 else
6443 return s390_emit_CLGR(buf, r1, r2);
6444
6445 default:
6446 goto fail;
6447 }
6448 }
6449
6450 case S390_OPND_AMODE: {
6451 UChar r1 = hregNumber(op1);
6452 const s390_amode *am = op2.variant.am;
6453 UChar b = hregNumber(am->b);
6454 UChar x = hregNumber(am->x);
6455 Int d = am->d;
6456
6457 switch (insn->size) {
6458 case 4:
6459 switch (am->tag) {
6460 case S390_AMODE_B12:
6461 case S390_AMODE_BX12:
6462 if (signed_comparison)
6463 return s390_emit_C(buf, r1, x, b, d);
6464 else
6465 return s390_emit_CL(buf, r1, x, b, d);
6466
6467 case S390_AMODE_B20:
6468 case S390_AMODE_BX20:
6469 if (signed_comparison)
6470 return s390_emit_CY(buf, r1, x, b, DISP20(d));
6471 else
6472 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
6473 }
6474 goto fail;
6475
6476 case 8:
6477 if (signed_comparison)
6478 return s390_emit_CG(buf, r1, x, b, DISP20(d));
6479 else
6480 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
6481
6482 default:
6483 goto fail;
6484 }
6485 }
6486
6487 case S390_OPND_IMMEDIATE: {
6488 UChar r1 = hregNumber(op1);
6489 ULong value = op2.variant.imm;
6490
6491 switch (insn->size) {
6492 case 4:
6493 if (signed_comparison)
6494 return s390_emit_CFIw(buf, r1, value);
6495 else
6496 return s390_emit_CLFIw(buf, r1, value);
6497
6498 case 8:
florian07d34552012-05-26 01:59:21 +00006499 if (s390_host_has_eimm) {
6500 if (signed_comparison) {
6501 if (ulong_fits_signed_32bit(value))
6502 return s390_emit_CGFI(buf, r1, value);
6503 } else {
6504 if (ulong_fits_unsigned_32bit(value))
6505 return s390_emit_CLGFI(buf, r1, value);
6506 }
6507 }
sewardj2019a972011-03-07 16:04:07 +00006508 buf = s390_emit_load_64imm(buf, R0, value);
6509 if (signed_comparison)
6510 return s390_emit_CGR(buf, r1, R0);
6511 else
6512 return s390_emit_CLGR(buf, r1, R0);
6513
6514 default:
6515 goto fail;
6516 }
6517 }
6518
6519 default:
6520 goto fail;
6521 }
6522
6523 fail:
6524 vpanic("s390_insn_compare_emit");
6525}
6526
6527
6528static UChar *
6529s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
6530{
6531 s390_opnd_RMI op2;
6532 UChar r1;
6533 Bool signed_multiply;
6534
6535 /* The register number identifying the register pair */
6536 r1 = hregNumber(insn->variant.mul.dst_hi);
6537
6538 op2 = insn->variant.mul.op2;
6539 signed_multiply = insn->variant.mul.signed_multiply;
6540
6541 switch (op2.tag) {
6542 case S390_OPND_REG: {
6543 UInt r2 = hregNumber(op2.variant.reg);
6544
6545 switch (insn->size) {
6546 case 1:
6547 case 2:
6548 case 4:
6549 if (signed_multiply)
6550 return s390_emit_MR(buf, r1, r2);
6551 else
6552 return s390_emit_MLR(buf, r1, r2);
6553
6554 case 8:
6555 if (signed_multiply)
6556 vpanic("s390_insn_mul_emit");
6557 else
6558 return s390_emit_MLGR(buf, r1, r2);
6559
6560 default:
6561 goto fail;
6562 }
6563 }
6564
6565 case S390_OPND_AMODE: {
6566 const s390_amode *am = op2.variant.am;
6567 UChar b = hregNumber(am->b);
6568 UChar x = hregNumber(am->x);
6569 Int d = am->d;
6570
6571 switch (insn->size) {
6572 case 1:
6573 case 2:
6574 /* Load bytes into scratch register R0, then multiply */
6575 buf = s390_emit_load_mem(buf, insn->size, R0, am);
6576 if (signed_multiply)
6577 return s390_emit_MR(buf, r1, R0);
6578 else
6579 return s390_emit_MLR(buf, r1, R0);
6580
6581 case 4:
6582 switch (am->tag) {
6583 case S390_AMODE_B12:
6584 case S390_AMODE_BX12:
6585 if (signed_multiply)
6586 return s390_emit_M(buf, r1, x, b, d);
6587 else
6588 return s390_emit_ML(buf, r1, x, b, DISP20(d));
6589
6590 case S390_AMODE_B20:
6591 case S390_AMODE_BX20:
6592 if (signed_multiply)
6593 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
6594 else
sewardjb13a92a2011-04-13 14:44:29 +00006595 return s390_emit_ML(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006596 }
6597 goto fail;
6598
6599 case 8:
6600 if (signed_multiply)
6601 vpanic("s390_insn_mul_emit");
6602 else
6603 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
6604
6605 default:
6606 goto fail;
6607 }
6608 }
6609
6610 case S390_OPND_IMMEDIATE: {
6611 ULong value = op2.variant.imm;
6612
6613 switch (insn->size) {
6614 case 1:
6615 case 2:
6616 case 4:
6617 buf = s390_emit_load_32imm(buf, R0, value);
6618 if (signed_multiply)
6619 return s390_emit_MR(buf, r1, R0);
6620 else
6621 return s390_emit_MLR(buf, r1, R0);
6622
6623 case 8:
6624 buf = s390_emit_load_64imm(buf, R0, value);
6625 if (signed_multiply)
6626 vpanic("s390_insn_mul_emit");
6627 else
6628 return s390_emit_MLGR(buf, r1, R0);
6629
6630 default:
6631 goto fail;
6632 }
6633 }
6634
6635 default:
6636 goto fail;
6637 }
6638
6639 fail:
6640 vpanic("s390_insn_mul_emit");
6641}
6642
6643
6644static UChar *
6645s390_insn_div_emit(UChar *buf, const s390_insn *insn)
6646{
6647 s390_opnd_RMI op2;
6648 UChar r1;
6649 Bool signed_divide;
6650
6651 r1 = hregNumber(insn->variant.div.op1_hi);
6652 op2 = insn->variant.div.op2;
6653 signed_divide = insn->variant.div.signed_divide;
6654
6655 switch (op2.tag) {
6656 case S390_OPND_REG: {
6657 UInt r2 = hregNumber(op2.variant.reg);
6658
6659 switch (insn->size) {
6660 case 4:
6661 if (signed_divide)
6662 return s390_emit_DR(buf, r1, r2);
6663 else
6664 return s390_emit_DLR(buf, r1, r2);
6665
6666 case 8:
6667 if (signed_divide)
6668 vpanic("s390_insn_div_emit");
6669 else
6670 return s390_emit_DLGR(buf, r1, r2);
6671
6672 default:
6673 goto fail;
6674 }
6675 }
6676
6677 case S390_OPND_AMODE: {
6678 const s390_amode *am = op2.variant.am;
6679 UChar b = hregNumber(am->b);
6680 UChar x = hregNumber(am->x);
6681 Int d = am->d;
6682
6683 switch (insn->size) {
6684 case 4:
6685 switch (am->tag) {
6686 case S390_AMODE_B12:
6687 case S390_AMODE_BX12:
6688 if (signed_divide)
6689 return s390_emit_D(buf, r1, x, b, d);
6690 else
6691 return s390_emit_DL(buf, r1, x, b, DISP20(d));
6692
6693 case S390_AMODE_B20:
6694 case S390_AMODE_BX20:
sewardjb13a92a2011-04-13 14:44:29 +00006695 if (signed_divide) {
6696 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006697 return s390_emit_DR(buf, r1, R0);
sewardjb13a92a2011-04-13 14:44:29 +00006698 } else
6699 return s390_emit_DL(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006700 }
6701 goto fail;
6702
6703 case 8:
6704 if (signed_divide)
6705 vpanic("s390_insn_div_emit");
6706 else
6707 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
6708
6709 default:
6710 goto fail;
6711 }
6712 }
6713
6714 case S390_OPND_IMMEDIATE: {
6715 ULong value = op2.variant.imm;
6716
6717 switch (insn->size) {
6718 case 4:
6719 buf = s390_emit_load_32imm(buf, R0, value);
6720 if (signed_divide)
6721 return s390_emit_DR(buf, r1, R0);
6722 else
6723 return s390_emit_DLR(buf, r1, R0);
6724
6725 case 8:
6726 buf = s390_emit_load_64imm(buf, R0, value);
6727 if (signed_divide)
6728 vpanic("s390_insn_div_emit");
6729 else
6730 return s390_emit_DLGR(buf, r1, R0);
6731
6732 default:
6733 goto fail;
6734 }
6735 }
6736
6737 default:
6738 goto fail;
6739 }
6740
6741 fail:
6742 vpanic("s390_insn_div_emit");
6743}
6744
6745
6746static UChar *
6747s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
6748{
6749 s390_opnd_RMI op2;
6750 UChar r1;
6751
6752 r1 = hregNumber(insn->variant.divs.rem);
6753 op2 = insn->variant.divs.op2;
6754
6755 switch (op2.tag) {
6756 case S390_OPND_REG: {
6757 UInt r2 = hregNumber(op2.variant.reg);
6758
6759 return s390_emit_DSGR(buf, r1, r2);
6760 }
6761
6762 case S390_OPND_AMODE: {
6763 const s390_amode *am = op2.variant.am;
6764 UChar b = hregNumber(am->b);
6765 UChar x = hregNumber(am->x);
6766 Int d = am->d;
6767
6768 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
6769 }
6770
6771 case S390_OPND_IMMEDIATE: {
6772 ULong value = op2.variant.imm;
6773
6774 buf = s390_emit_load_64imm(buf, R0, value);
6775 return s390_emit_DSGR(buf, r1, R0);
6776 }
6777
6778 default:
6779 goto fail;
6780 }
6781
6782 fail:
6783 vpanic("s390_insn_divs_emit");
6784}
6785
6786
6787static UChar *
sewardj611b06e2011-03-24 08:57:29 +00006788s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
sewardj2019a972011-03-07 16:04:07 +00006789{
6790 s390_opnd_RMI src;
sewardj611b06e2011-03-24 08:57:29 +00006791 UChar r1, r1p1, r2, *p;
sewardj2019a972011-03-07 16:04:07 +00006792
sewardj611b06e2011-03-24 08:57:29 +00006793 r1 = hregNumber(insn->variant.clz.num_bits);
6794 r1p1 = hregNumber(insn->variant.clz.clobber);
sewardj2019a972011-03-07 16:04:07 +00006795
6796 vassert((r1 & 0x1) == 0);
6797 vassert(r1p1 == r1 + 1);
6798
sewardj611b06e2011-03-24 08:57:29 +00006799 p = buf;
6800 src = insn->variant.clz.src;
sewardj2019a972011-03-07 16:04:07 +00006801
sewardj611b06e2011-03-24 08:57:29 +00006802 /* Get operand and move it to r2 */
sewardj2019a972011-03-07 16:04:07 +00006803 switch (src.tag) {
sewardj611b06e2011-03-24 08:57:29 +00006804 case S390_OPND_REG:
6805 r2 = hregNumber(src.variant.reg);
6806 break;
sewardj2019a972011-03-07 16:04:07 +00006807
6808 case S390_OPND_AMODE: {
6809 const s390_amode *am = src.variant.am;
6810 UChar b = hregNumber(am->b);
6811 UChar x = hregNumber(am->x);
6812 Int d = am->d;
6813
sewardj611b06e2011-03-24 08:57:29 +00006814 p = s390_emit_LG(p, R0, x, b, DISP20(d));
6815 r2 = R0;
6816 break;
sewardj2019a972011-03-07 16:04:07 +00006817 }
6818
6819 case S390_OPND_IMMEDIATE: {
6820 ULong value = src.variant.imm;
6821
sewardj611b06e2011-03-24 08:57:29 +00006822 p = s390_emit_load_64imm(p, R0, value);
6823 r2 = R0;
6824 break;
sewardj2019a972011-03-07 16:04:07 +00006825 }
6826
6827 default:
6828 goto fail;
6829 }
6830
sewardj611b06e2011-03-24 08:57:29 +00006831 /* Use FLOGR if you can */
6832 if (s390_host_has_eimm) {
6833 return s390_emit_FLOGR(p, r1, r2);
6834 }
6835
6836 /*
6837 r0 = r2;
6838 r1 = 64;
6839 while (r0 != 0) {
6840 r1 -= 1;
6841 r0 >>= 1;
6842 }
6843 */
6844 p = s390_emit_LTGR(p, R0, r2);
6845 p = s390_emit_LLILL(p, r1, 64);
6846
6847 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
6848 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
6849 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
6850 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
6851 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
6852 (UShort)(-(4 + 6 + 4) / 2));
6853 return p;
6854
sewardj2019a972011-03-07 16:04:07 +00006855 fail:
sewardj611b06e2011-03-24 08:57:29 +00006856 vpanic("s390_insn_clz_emit");
sewardj2019a972011-03-07 16:04:07 +00006857}
6858
6859
6860static UChar *
sewardj2019a972011-03-07 16:04:07 +00006861s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
6862{
6863 s390_cc_t cond;
6864 ULong target;
6865 UChar *ptmp = buf;
6866
6867 cond = insn->variant.helper_call.cond;
6868 target = insn->variant.helper_call.target;
6869
6870 if (cond != S390_CC_ALWAYS) {
6871 /* So we have something like this
6872 if (cond) call X;
6873 Y: ...
6874 We convert this into
6875 if (! cond) goto Y; // BRC opcode; 4 bytes
6876 call X;
6877 Y:
6878 */
6879 /* 4 bytes (a BRC insn) to be filled in here */
6880 buf += 4;
6881 }
6882
6883 /* Load the target address into a register, that
6884 (a) is not used for passing parameters to the helper and
6885 (b) can be clobbered by the callee
florianc9e90e52012-05-27 17:20:47 +00006886 (c) is not special to the BASR insn
6887 r1 is the only choice.
sewardj2019a972011-03-07 16:04:07 +00006888 Also, need to arrange for the return address be put into the
6889 link-register */
6890 buf = s390_emit_load_64imm(buf, 1, target);
6891
6892 /* Stash away the client's FPC register because the helper might change it. */
6893 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
6894
6895 /* Before we can call the helper, we need to save the link register,
6896 because the BASR will overwrite it. We cannot use a register for that.
6897 (a) Volatile registers will be modified by the helper.
6898 (b) For saved registers the client code assumes that they have not
6899 changed after the function returns. So we cannot use it to store
6900 the link register.
6901 In the dispatcher, before calling the client code, we have arranged for
6902 a location on the stack for this purpose. See dispatch-s390x-linux.S. */
6903 buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR
6904 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6905 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
florian01ed6e72012-05-27 16:52:43 +00006906
6907 /* Move the return value to the destination register */
6908 if (insn->variant.helper_call.dst != INVALID_HREG) {
6909 buf = s390_emit_LGR(buf, hregNumber(insn->variant.helper_call.dst),
6910 S390_REGNO_RETURN_VALUE);
6911 }
6912
sewardj2019a972011-03-07 16:04:07 +00006913 buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR
6914 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6915 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
6916 S390_OFFSET_SAVED_FPC_C);
6917
6918 if (cond != S390_CC_ALWAYS) {
6919 Int delta = buf - ptmp;
6920
6921 delta >>= 1; /* immediate constant is #half-words */
6922 vassert(delta > 0 && delta < (1 << 16));
6923 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6924 }
6925
6926 return buf;
6927}
6928
6929
6930static UChar *
6931s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
6932{
6933 HReg dst;
6934 s390_opnd_RMI src;
6935 s390_cc_t cond;
6936 UChar *p, *ptmp = 0; /* avoid compiler warnings */
6937
6938 cond = insn->variant.cond_move.cond;
6939 dst = insn->variant.cond_move.dst;
6940 src = insn->variant.cond_move.src;
6941
6942 p = buf;
6943
6944 /* Branch (if cond fails) over move instrs */
6945 if (cond != S390_CC_ALWAYS) {
6946 /* Don't know how many bytes to jump over yet.
6947 Make space for a BRC instruction (4 bytes) and fill in later. */
6948 ptmp = p; /* to be filled in here */
6949 p += 4;
6950 }
6951
6952 // cond true: move src => dst
6953
6954 switch (src.tag) {
6955 case S390_OPND_REG:
6956 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
6957 break;
6958
6959 case S390_OPND_AMODE:
6960 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
6961 break;
6962
6963 case S390_OPND_IMMEDIATE: {
6964 ULong value = src.variant.imm;
6965 UInt r = hregNumber(dst);
6966
6967 switch (insn->size) {
6968 case 1:
6969 case 2:
6970 /* Load the immediate values as a 4 byte value. That does not hurt as
6971 those extra bytes will not be looked at. Fall through .... */
6972 case 4:
6973 p = s390_emit_load_32imm(p, r, value);
6974 break;
6975
6976 case 8:
6977 p = s390_emit_load_64imm(p, r, value);
6978 break;
6979 }
6980 break;
6981 }
6982
6983 default:
6984 goto fail;
6985 }
6986
6987 if (cond != S390_CC_ALWAYS) {
6988 Int delta = p - ptmp;
6989
6990 delta >>= 1; /* immediate constant is #half-words */
6991 vassert(delta > 0 && delta < (1 << 16));
6992 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6993 }
6994
6995 return p;
6996
6997 fail:
6998 vpanic("s390_insn_cond_move_emit");
6999}
7000
7001
7002/* Little helper function to the rounding mode in the real FPC
7003 register */
7004static UChar *
7005s390_set_fpc_rounding_mode(UChar *buf, s390_round_t rounding_mode)
7006{
7007 UChar bits;
7008
7009 /* Determine BFP rounding bits */
7010 switch (rounding_mode) {
7011 case S390_ROUND_NEAREST_EVEN: bits = 0; break;
7012 case S390_ROUND_ZERO: bits = 1; break;
7013 case S390_ROUND_POSINF: bits = 2; break;
7014 case S390_ROUND_NEGINF: bits = 3; break;
7015 default: vpanic("invalid rounding mode\n");
7016 }
7017
7018 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
7019 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
florian428dfdd2012-03-27 03:09:49 +00007020 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
sewardj2019a972011-03-07 16:04:07 +00007021
7022 buf = s390_emit_NILL(buf, R0, 0xFFFC); /* Clear out right-most 2 bits */
7023 buf = s390_emit_OILL(buf, R0, bits); /* OR in the new rounding mode */
7024 buf = s390_emit_SFPC(buf, R0, 0); /* Load FPC register from R0 */
7025
7026 return buf;
7027}
7028
7029
7030static UChar *
7031s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
7032{
7033 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
7034 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
7035 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
7036 s390_round_t rounding_mode = insn->variant.bfp_triop.rounding_mode;
7037
7038 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7039 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7040 }
7041
7042 switch (insn->size) {
7043 case 4:
7044 switch (insn->variant.bfp_triop.tag) {
7045 case S390_BFP_MADD: buf = s390_emit_MAEBR(buf, r1, r3, r2); break;
7046 case S390_BFP_MSUB: buf = s390_emit_MSEBR(buf, r1, r3, r2); break;
7047 default: goto fail;
7048 }
7049 break;
7050
7051 case 8:
7052 switch (insn->variant.bfp_triop.tag) {
7053 case S390_BFP_MADD: buf = s390_emit_MADBR(buf, r1, r3, r2); break;
7054 case S390_BFP_MSUB: buf = s390_emit_MSDBR(buf, r1, r3, r2); break;
7055 default: goto fail;
7056 }
7057 break;
7058
7059 default: goto fail;
7060 }
7061
7062 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7063 /* Restore FPC register from guest state */
7064 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
florian428dfdd2012-03-27 03:09:49 +00007065 S390X_GUEST_OFFSET(guest_fpc)); // fpc = guest_fpc
sewardj2019a972011-03-07 16:04:07 +00007066 }
7067 return buf;
7068
7069 fail:
7070 vpanic("s390_insn_bfp_triop_emit");
7071}
7072
7073
7074static UChar *
7075s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
7076{
7077 UInt r1 = hregNumber(insn->variant.bfp_binop.dst);
7078 UInt r2 = hregNumber(insn->variant.bfp_binop.op2);
7079 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7080
7081 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7082 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7083 }
7084
7085 switch (insn->size) {
7086 case 4:
7087 switch (insn->variant.bfp_binop.tag) {
7088 case S390_BFP_ADD: buf = s390_emit_AEBR(buf, r1, r2); break;
7089 case S390_BFP_SUB: buf = s390_emit_SEBR(buf, r1, r2); break;
7090 case S390_BFP_MUL: buf = s390_emit_MEEBR(buf, r1, r2); break;
7091 case S390_BFP_DIV: buf = s390_emit_DEBR(buf, r1, r2); break;
7092 default: goto fail;
7093 }
7094 break;
7095
7096 case 8:
7097 switch (insn->variant.bfp_binop.tag) {
7098 case S390_BFP_ADD: buf = s390_emit_ADBR(buf, r1, r2); break;
7099 case S390_BFP_SUB: buf = s390_emit_SDBR(buf, r1, r2); break;
7100 case S390_BFP_MUL: buf = s390_emit_MDBR(buf, r1, r2); break;
7101 case S390_BFP_DIV: buf = s390_emit_DDBR(buf, r1, r2); break;
7102 default: goto fail;
7103 }
7104 break;
7105
7106 default: goto fail;
7107 }
7108
7109 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7110 /* Restore FPC register from guest state */
7111 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
florian428dfdd2012-03-27 03:09:49 +00007112 S390X_GUEST_OFFSET(guest_fpc));
sewardj2019a972011-03-07 16:04:07 +00007113 }
7114 return buf;
7115
7116 fail:
7117 vpanic("s390_insn_bfp_binop_emit");
7118}
7119
7120
7121static UChar *
7122s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
7123{
7124 UInt r1 = hregNumber(insn->variant.bfp_unop.dst);
7125 UInt r2 = hregNumber(insn->variant.bfp_unop.op);
7126 s390_round_t rounding_mode = insn->variant.bfp_unop.rounding_mode;
7127 s390_round_t m3 = rounding_mode;
7128
7129 /* The "convert to fixed" instructions have a field for the rounding
7130 mode and no FPC modification is necessary. So we handle them
7131 upfront. */
7132 switch (insn->variant.bfp_unop.tag) {
7133 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
7134 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
7135 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
7136 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
7137 default: break;
7138 }
7139
7140 /* For all other insns if a special rounding mode is requested,
7141 we need to set the FPC first and restore it later. */
7142 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7143 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7144 }
7145
7146 switch (insn->variant.bfp_unop.tag) {
7147 case S390_BFP_ABS:
7148 switch (insn->size) {
7149 case 4: buf = s390_emit_LPEBR(buf, r1, r2); break;
7150 case 8: buf = s390_emit_LPDBR(buf, r1, r2); break;
7151 case 16: buf = s390_emit_LPXBR(buf, r1, r2); break;
7152 default: goto fail;
7153 }
7154 break;
7155
7156 case S390_BFP_NABS:
7157 switch (insn->size) {
7158 case 4: buf = s390_emit_LNEBR(buf, r1, r2); break;
7159 case 8: buf = s390_emit_LNDBR(buf, r1, r2); break;
7160 case 16: buf = s390_emit_LNXBR(buf, r1, r2); break;
7161 default: goto fail;
7162 }
7163 break;
7164
7165 case S390_BFP_NEG:
7166 switch (insn->size) {
7167 case 4: buf = s390_emit_LCEBR(buf, r1, r2); break;
7168 case 8: buf = s390_emit_LCDBR(buf, r1, r2); break;
7169 case 16: buf = s390_emit_LCXBR(buf, r1, r2); break;
7170 default: goto fail;
7171 }
7172 break;
7173
7174 case S390_BFP_SQRT:
7175 switch (insn->size) {
7176 case 4: buf = s390_emit_SQEBR(buf, r1, r2); break;
7177 case 8: buf = s390_emit_SQDBR(buf, r1, r2); break;
7178 case 16: buf = s390_emit_SQXBR(buf, r1, r2); break;
7179 default: goto fail;
7180 }
7181 break;
7182
7183 case S390_BFP_I32_TO_F32: buf = s390_emit_CEFBR(buf, r1, r2); break;
7184 case S390_BFP_I32_TO_F64: buf = s390_emit_CDFBR(buf, r1, r2); break;
7185 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1, r2); break;
7186 case S390_BFP_I64_TO_F32: buf = s390_emit_CEGBR(buf, r1, r2); break;
7187 case S390_BFP_I64_TO_F64: buf = s390_emit_CDGBR(buf, r1, r2); break;
7188 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1, r2); break;
7189
7190 case S390_BFP_F32_TO_F64: buf = s390_emit_LDEBR(buf, r1, r2); break;
7191 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1, r2); break;
7192 case S390_BFP_F64_TO_F32: buf = s390_emit_LEDBR(buf, r1, r2); break;
7193 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1, r2); break;
7194
7195 default: goto fail;
7196 }
7197
7198 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7199 /* Restore FPC register from guest state */
7200 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
florian428dfdd2012-03-27 03:09:49 +00007201 S390X_GUEST_OFFSET(guest_fpc)); // fpc = guest_fpc
sewardj2019a972011-03-07 16:04:07 +00007202 }
7203 return buf;
7204
7205 fail:
7206 vpanic("s390_insn_bfp_unop_emit");
7207}
7208
7209
7210static UChar *
7211s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
7212{
7213 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
7214 UInt r1 = hregNumber(insn->variant.bfp_compare.op1);
7215 UInt r2 = hregNumber(insn->variant.bfp_compare.op2);
7216
7217 switch (insn->size) {
7218 case 4:
7219 buf = s390_emit_CEBR(buf, r1, r2);
7220 break;
7221
7222 case 8:
7223 buf = s390_emit_CDBR(buf, r1, r2);
7224 break;
7225
7226 default: goto fail;
7227 }
7228
7229 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
7230
7231 fail:
7232 vpanic("s390_insn_bfp_compare_emit");
7233}
7234
7235
7236static UChar *
7237s390_insn_bfp128_binop_emit(UChar *buf, const s390_insn *insn)
7238{
7239 UInt r1_hi = hregNumber(insn->variant.bfp128_binop.dst_hi);
7240 UInt r1_lo = hregNumber(insn->variant.bfp128_binop.dst_lo);
7241 UInt r2_hi = hregNumber(insn->variant.bfp128_binop.op2_hi);
7242 UInt r2_lo = hregNumber(insn->variant.bfp128_binop.op2_lo);
7243 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7244
7245 /* Paranoia */
7246 vassert(insn->size == 16);
7247 vassert(r1_lo == r1_hi + 2);
7248 vassert(r2_lo == r2_hi + 2);
7249 vassert((r1_hi & 0x2) == 0);
7250 vassert((r2_hi & 0x2) == 0);
7251
7252 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7253 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7254 }
7255
7256 switch (insn->variant.bfp128_binop.tag) {
7257 case S390_BFP_ADD: buf = s390_emit_AXBR(buf, r1_hi, r2_hi); break;
7258 case S390_BFP_SUB: buf = s390_emit_SXBR(buf, r1_hi, r2_hi); break;
7259 case S390_BFP_MUL: buf = s390_emit_MXBR(buf, r1_hi, r2_hi); break;
7260 case S390_BFP_DIV: buf = s390_emit_DXBR(buf, r1_hi, r2_hi); break;
7261 default: goto fail;
7262 }
7263
7264 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7265 /* Restore FPC register from guest state */
7266 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
florian428dfdd2012-03-27 03:09:49 +00007267 S390X_GUEST_OFFSET(guest_fpc)); // fpc = guest_fpc
sewardj2019a972011-03-07 16:04:07 +00007268 }
7269 return buf;
7270
7271 fail:
7272 vpanic("s390_insn_bfp128_binop_emit");
7273}
7274
7275
7276static UChar *
7277s390_insn_bfp128_compare_emit(UChar *buf, const s390_insn *insn)
7278{
7279 UInt dst = hregNumber(insn->variant.bfp128_compare.dst);
7280 UInt r1_hi = hregNumber(insn->variant.bfp128_compare.op1_hi);
7281 UInt r1_lo = hregNumber(insn->variant.bfp128_compare.op1_lo);
7282 UInt r2_hi = hregNumber(insn->variant.bfp128_compare.op2_hi);
7283 UInt r2_lo = hregNumber(insn->variant.bfp128_compare.op2_lo);
7284
7285 /* Paranoia */
7286 vassert(insn->size == 16);
7287 vassert(r1_lo == r1_hi + 2);
7288 vassert(r2_lo == r2_hi + 2);
7289 vassert((r1_hi & 0x2) == 0);
7290 vassert((r2_hi & 0x2) == 0);
7291
7292 buf = s390_emit_CXBR(buf, r1_hi, r2_hi);
7293
7294 /* Load condition code into DST */
7295 return s390_emit_load_cc(buf, dst);
7296}
7297
7298
7299static UChar *
7300s390_insn_bfp128_unop_emit(UChar *buf, const s390_insn *insn)
7301{
7302 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
7303 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
7304 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
7305 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
7306 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7307
7308 /* Paranoia */
7309 vassert(insn->size == 16);
7310 vassert(r1_lo == r1_hi + 2);
7311 vassert(r2_lo == r2_hi + 2);
7312 vassert((r1_hi & 0x2) == 0);
7313 vassert((r2_hi & 0x2) == 0);
7314
7315 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7316 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7317 }
7318
7319 switch (insn->variant.bfp128_unop.tag) {
7320 case S390_BFP_ABS: buf = s390_emit_LPXBR(buf, r1_hi, r2_hi); break;
7321 case S390_BFP_NABS: buf = s390_emit_LNXBR(buf, r1_hi, r2_hi); break;
7322 case S390_BFP_NEG: buf = s390_emit_LCXBR(buf, r1_hi, r2_hi); break;
7323 case S390_BFP_SQRT: buf = s390_emit_SQXBR(buf, r1_hi, r2_hi); break;
7324 case S390_BFP_F128_TO_F32: buf = s390_emit_LEXBR(buf, r1_hi, r2_hi); break;
7325 case S390_BFP_F128_TO_F64: buf = s390_emit_LDXBR(buf, r1_hi, r2_hi); break;
7326 default: goto fail;
7327 }
7328
7329 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7330 /* Restore FPC register from guest state */
7331 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
florian428dfdd2012-03-27 03:09:49 +00007332 S390X_GUEST_OFFSET(guest_fpc)); // fpc = guest_fpc
sewardj2019a972011-03-07 16:04:07 +00007333 }
7334 return buf;
7335
7336 fail:
7337 vpanic("s390_insn_bfp128_unop_emit");
7338}
7339
7340
7341/* Conversion to 128-bit BFP does not require a rounding mode */
7342static UChar *
7343s390_insn_bfp128_convert_to_emit(UChar *buf, const s390_insn *insn)
7344{
7345 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
7346 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
7347 UInt r2 = hregNumber(insn->variant.bfp128_unop.op_hi);
7348
7349 /* Paranoia */
7350 vassert(insn->size == 16);
7351 vassert(r1_lo == r1_hi + 2);
7352 vassert((r1_hi & 0x2) == 0);
7353
7354 switch (insn->variant.bfp128_unop.tag) {
7355 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1_hi, r2); break;
7356 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1_hi, r2); break;
7357 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1_hi, r2); break;
7358 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1_hi, r2); break;
7359 default: goto fail;
7360 }
7361
7362 return buf;
7363
7364 fail:
7365 vpanic("s390_insn_bfp128_convert_to_emit");
7366}
7367
7368
7369static UChar *
7370s390_insn_bfp128_convert_from_emit(UChar *buf, const s390_insn *insn)
7371{
7372 UInt r1 = hregNumber(insn->variant.bfp128_unop.dst_hi);
7373 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
7374 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
7375 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7376
7377 /* Paranoia */
7378 vassert(insn->size != 16);
7379 vassert(r2_lo == r2_hi + 2);
7380 vassert((r2_hi & 0x2) == 0);
7381
7382 /* The "convert to fixed" instructions have a field for the rounding
7383 mode and no FPC modification is necessary. So we handle them
7384 upfront. */
7385 switch (insn->variant.bfp_unop.tag) {
florian7fa63542012-07-13 12:48:39 +00007386 case S390_BFP_F128_TO_I32:
7387 return s390_emit_CFXBR(buf, rounding_mode, r1, r2_hi);
7388
7389 case S390_BFP_F128_TO_I64:
7390 return s390_emit_CGXBR(buf, rounding_mode, r1, r2_hi);
7391
sewardj2019a972011-03-07 16:04:07 +00007392 default: break;
7393 }
7394
7395 vpanic("s390_insn_bfp128_convert_from_emit");
7396}
7397
7398
sewardja52e37e2011-04-28 18:48:06 +00007399static UChar *
7400s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
7401{
7402 return s390_emit_BCR(buf, 0xF, 0x0);
7403}
7404
7405
florianad43b3a2012-02-20 15:01:14 +00007406static UChar *
7407s390_insn_gzero_emit(UChar *buf, const s390_insn *insn)
7408{
7409 return s390_emit_XC(buf, insn->size - 1,
7410 S390_REGNO_GUEST_STATE_POINTER, insn->variant.gzero.offset,
7411 S390_REGNO_GUEST_STATE_POINTER, insn->variant.gzero.offset);
7412}
7413
7414
7415static UChar *
7416s390_insn_gadd_emit(UChar *buf, const s390_insn *insn)
7417{
7418 return s390_emit_AGSI(buf, insn->variant.gadd.delta,
7419 S390_REGNO_GUEST_STATE_POINTER,
7420 DISP20(insn->variant.gadd.offset));
7421}
7422
7423
florian8844a632012-04-13 04:04:06 +00007424/* Define convenience functions needed for translation chaining.
7425 Any changes need to be applied to the functions in concert. */
7426
florian1c857042012-04-15 04:11:07 +00007427static __inline__ Bool
7428s390_insn_is_BRCL(const UChar *p, UChar condition)
7429{
7430 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
7431}
7432
7433static __inline__ Bool
7434s390_insn_is_BR(const UChar *p, UChar reg)
7435{
7436 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
7437}
7438
florianebaf8d92012-04-22 17:38:46 +00007439
7440/* The length of the BASR insn */
7441#define S390_BASR_LEN 2
7442
florian1c857042012-04-15 04:11:07 +00007443
florian8844a632012-04-13 04:04:06 +00007444/* Load the 64-bit VALUE into REG. Note that this function must NOT
7445 optimise the generated code by looking at the value. I.e. using
floriane09e8bb2012-05-07 03:28:18 +00007446 LGHI if value == 0 would be very wrong. */
florian8844a632012-04-13 04:04:06 +00007447static UChar *
7448s390_tchain_load64(UChar *buf, UChar regno, ULong value)
7449{
florian1c857042012-04-15 04:11:07 +00007450 UChar *begin = buf;
7451
florian1c2b4db2012-04-22 17:46:31 +00007452 if (s390_host_has_eimm) {
7453 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
7454 buf = s390_emit_IIHF(buf, regno, value >> 32);
7455 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
7456 } else {
7457 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
7458 value >>= 16;
7459 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
7460 value >>= 16;
7461 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
7462 value >>= 16;
7463 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
7464 }
florian8844a632012-04-13 04:04:06 +00007465
florian1c857042012-04-15 04:11:07 +00007466 vassert(buf - begin == s390_tchain_load64_len());
7467
florian8844a632012-04-13 04:04:06 +00007468 return buf;
7469}
7470
7471/* Return number of bytes generated by s390_tchain_load64 */
7472static UInt
7473s390_tchain_load64_len(void)
7474{
florian1c2b4db2012-04-22 17:46:31 +00007475 if (s390_host_has_eimm) {
7476 return 6 + 6; /* IIHF + IILF */
7477 }
florianebaf8d92012-04-22 17:38:46 +00007478 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
florian8844a632012-04-13 04:04:06 +00007479}
7480
7481/* Verify that CODE is the code sequence generated by s390_tchain_load64
7482 to load VALUE into REGNO. Return pointer to the byte following the
7483 insn sequence. */
7484static const UChar *
7485s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
7486{
7487 UInt regmask = regno << 4;
7488 UInt hw;
7489
florian1c2b4db2012-04-22 17:46:31 +00007490 if (s390_host_has_eimm) {
7491 /* Check for IIHF */
7492 vassert(code[0] == 0xC0);
7493 vassert(code[1] == (0x08 | regmask));
7494 vassert(*(const UInt *)&code[2] == (value >> 32));
7495 /* Check for IILF */
7496 vassert(code[6] == 0xC0);
7497 vassert(code[7] == (0x09 | regmask));
7498 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
7499 } else {
7500 /* Check for IILL */
7501 hw = value & 0xFFFF;
7502 vassert(code[0] == 0xA5);
7503 vassert(code[1] == (0x03 | regmask));
7504 vassert(code[2] == (hw >> 8));
7505 vassert(code[3] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00007506
florian1c2b4db2012-04-22 17:46:31 +00007507 /* Check for IILH */
7508 hw = (value >> 16) & 0xFFFF;
7509 vassert(code[4] == 0xA5);
7510 vassert(code[5] == (0x02 | regmask));
7511 vassert(code[6] == (hw >> 8));
7512 vassert(code[7] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00007513
florian1c2b4db2012-04-22 17:46:31 +00007514 /* Check for IIHL */
7515 hw = (value >> 32) & 0xFFFF;
7516 vassert(code[8] == 0xA5);
7517 vassert(code[9] == (0x01 | regmask));
7518 vassert(code[10] == (hw >> 8));
7519 vassert(code[11] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00007520
florian1c2b4db2012-04-22 17:46:31 +00007521 /* Check for IIHH */
7522 hw = (value >> 48) & 0xFFFF;
7523 vassert(code[12] == 0xA5);
7524 vassert(code[13] == (0x00 | regmask));
7525 vassert(code[14] == (hw >> 8));
7526 vassert(code[15] == (hw & 0xFF));
7527 }
florian8844a632012-04-13 04:04:06 +00007528
florian1c857042012-04-15 04:11:07 +00007529 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00007530}
7531
7532/* CODE points to the code sequence as generated by s390_tchain_load64.
7533 Change the loaded value to VALUE. Return pointer to the byte following
7534 the patched code sequence. */
7535static UChar *
7536s390_tchain_patch_load64(UChar *code, ULong imm64)
7537{
florian1c2b4db2012-04-22 17:46:31 +00007538 if (s390_host_has_eimm) {
7539 /* Patch IIHF */
7540 *(UInt *)&code[2] = imm64 >> 32;
7541 /* Patch IILF */
7542 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
7543 } else {
7544 code[3] = imm64 & 0xFF; imm64 >>= 8;
7545 code[2] = imm64 & 0xFF; imm64 >>= 8;
7546 code[7] = imm64 & 0xFF; imm64 >>= 8;
7547 code[6] = imm64 & 0xFF; imm64 >>= 8;
7548 code[11] = imm64 & 0xFF; imm64 >>= 8;
7549 code[10] = imm64 & 0xFF; imm64 >>= 8;
7550 code[15] = imm64 & 0xFF; imm64 >>= 8;
7551 code[14] = imm64 & 0xFF; imm64 >>= 8;
7552 }
florian8844a632012-04-13 04:04:06 +00007553
florian1c857042012-04-15 04:11:07 +00007554 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00007555}
7556
7557
7558/* NB: what goes on here has to be very closely coordinated with the
7559 chainXDirect_S390 and unchainXDirect_S390 below. */
7560static UChar *
7561s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
7562 void *disp_cp_chain_me_to_slowEP,
7563 void *disp_cp_chain_me_to_fastEP)
7564{
7565 /* We're generating chain-me requests here, so we need to be
7566 sure this is actually allowed -- no-redir translations can't
7567 use chain-me's. Hence: */
7568 vassert(disp_cp_chain_me_to_slowEP != NULL);
7569 vassert(disp_cp_chain_me_to_fastEP != NULL);
7570
7571 /* Use ptmp for backpatching conditional jumps. */
7572 UChar *ptmp = buf;
7573
7574 /* First off, if this is conditional, create a conditional
7575 jump over the rest of it. */
7576 s390_cc_t cond = insn->variant.xdirect.cond;
7577
7578 if (cond != S390_CC_ALWAYS) {
7579 /* So we have something like this
7580 if (cond) do_xdirect;
7581 Y: ...
7582 We convert this into
7583 if (! cond) goto Y; // BRC opcode; 4 bytes
7584 do_xdirect;
7585 Y:
7586 */
7587 /* 4 bytes (a BRC insn) to be filled in here */
7588 buf += 4;
7589 }
7590
7591 /* Update the guest IA. */
7592 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
7593
7594 const s390_amode *amode = insn->variant.xdirect.guest_IA;
florianbf516d12012-04-21 15:53:13 +00007595 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00007596 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007597 UInt d = amode->d;
7598
florianbf516d12012-04-21 15:53:13 +00007599 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00007600
florian8844a632012-04-13 04:04:06 +00007601 /* Load the chosen entry point into the scratch reg */
7602 void *disp_cp_chain_me;
7603
7604 disp_cp_chain_me =
7605 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
7606 : disp_cp_chain_me_to_slowEP;
florianebaf8d92012-04-22 17:38:46 +00007607 /* Get the address of the beginning of the load64 code sequence into %r1.
7608 Do not change the register! This is part of the protocol with the
7609 dispatcher. */
7610 buf = s390_emit_BASR(buf, 1, R0);
florian8844a632012-04-13 04:04:06 +00007611
florianebaf8d92012-04-22 17:38:46 +00007612 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
florian8844a632012-04-13 04:04:06 +00007613 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
7614 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
7615
florianebaf8d92012-04-22 17:38:46 +00007616 /* goto *tchain_scratch */
7617 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00007618
7619 /* --- END of PATCHABLE BYTES --- */
7620
7621 /* Fix up the conditional jump, if there was one. */
7622 if (cond != S390_CC_ALWAYS) {
7623 Int delta = buf - ptmp;
7624
7625 delta >>= 1; /* immediate constant is #half-words */
7626 vassert(delta > 0 && delta < (1 << 16));
7627 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7628 }
7629
7630 return buf;
7631}
7632
7633/* Return the number of patchable bytes from an xdirect insn. */
7634static UInt
7635s390_xdirect_patchable_len(void)
7636{
florianebaf8d92012-04-22 17:38:46 +00007637 return s390_tchain_load64_len() + S390_BASR_LEN;
florian8844a632012-04-13 04:04:06 +00007638}
7639
7640
7641static UChar *
7642s390_insn_xindir_emit(UChar *buf, const s390_insn *insn, void *disp_cp_xindir)
7643{
7644 /* We're generating transfers that could lead indirectly to a
7645 chain-me, so we need to be sure this is actually allowed --
7646 no-redir translations are not allowed to reach normal
7647 translations without going through the scheduler. That means
7648 no XDirects or XIndirs out from no-redir translations.
7649 Hence: */
7650 vassert(disp_cp_xindir != NULL);
7651
7652 /* Use ptmp for backpatching conditional jumps. */
7653 UChar *ptmp = buf;
7654
7655 /* First off, if this is conditional, create a conditional
7656 jump over the rest of it. */
7657 s390_cc_t cond = insn->variant.xdirect.cond;
7658
7659 if (cond != S390_CC_ALWAYS) {
7660 /* So we have something like this
7661 if (cond) do_xdirect;
7662 Y: ...
7663 We convert this into
7664 if (! cond) goto Y; // BRC opcode; 4 bytes
7665 do_xdirect;
7666 Y:
7667 */
7668 /* 4 bytes (a BRC insn) to be filled in here */
7669 buf += 4;
7670 }
7671
7672 /* Update the guest IA with the address in xdirect.dst. */
florian7346c7a2012-04-13 21:14:24 +00007673 const s390_amode *amode = insn->variant.xindir.guest_IA;
florian8844a632012-04-13 04:04:06 +00007674
florianbf516d12012-04-21 15:53:13 +00007675 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00007676 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007677 UInt d = amode->d;
florian7346c7a2012-04-13 21:14:24 +00007678 UInt regno = hregNumber(insn->variant.xindir.dst);
florian8844a632012-04-13 04:04:06 +00007679
florianbf516d12012-04-21 15:53:13 +00007680 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00007681
7682 /* load tchain_scratch, #disp_indir */
7683 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
7684 Ptr_to_ULong(disp_cp_xindir));
florianebaf8d92012-04-22 17:38:46 +00007685 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00007686 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
7687
7688 /* Fix up the conditional jump, if there was one. */
7689 if (cond != S390_CC_ALWAYS) {
7690 Int delta = buf - ptmp;
7691
7692 delta >>= 1; /* immediate constant is #half-words */
7693 vassert(delta > 0 && delta < (1 << 16));
7694 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7695 }
7696
7697 return buf;
7698}
7699
7700static UChar *
7701s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
7702 void *disp_cp_xassisted)
7703{
7704 /* Use ptmp for backpatching conditional jumps. */
7705 UChar *ptmp = buf;
7706
7707 /* First off, if this is conditional, create a conditional
7708 jump over the rest of it. */
7709 s390_cc_t cond = insn->variant.xdirect.cond;
7710
7711 if (cond != S390_CC_ALWAYS) {
7712 /* So we have something like this
7713 if (cond) do_xdirect;
7714 Y: ...
7715 We convert this into
7716 if (! cond) goto Y; // BRC opcode; 4 bytes
7717 do_xdirect;
7718 Y:
7719 */
7720 /* 4 bytes (a BRC insn) to be filled in here */
7721 buf += 4;
7722 }
7723
7724 /* Update the guest IA with the address in xassisted.dst. */
7725 const s390_amode *amode = insn->variant.xassisted.guest_IA;
7726
florianbf516d12012-04-21 15:53:13 +00007727 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00007728 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007729 UInt d = amode->d;
7730 UInt regno = hregNumber(insn->variant.xassisted.dst);
7731
florianbf516d12012-04-21 15:53:13 +00007732 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00007733
7734 UInt trcval = 0;
7735
7736 switch (insn->variant.xassisted.kind) {
7737 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
7738 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
florian8844a632012-04-13 04:04:06 +00007739 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
7740 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
7741 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
7742 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
7743 case Ijk_TInval: trcval = VEX_TRC_JMP_TINVAL; break;
7744 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
7745 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
7746 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
7747 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
7748 /* We don't expect to see the following being assisted. */
7749 case Ijk_Ret:
7750 case Ijk_Call:
7751 /* fallthrough */
7752 default:
7753 ppIRJumpKind(insn->variant.xassisted.kind);
7754 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
7755 }
7756
7757 vassert(trcval != 0);
7758
7759 /* guest_state_pointer = trcval */
7760 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
7761
7762 /* load tchain_scratch, #disp_assisted */
7763 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
7764 Ptr_to_ULong(disp_cp_xassisted));
7765
florianebaf8d92012-04-22 17:38:46 +00007766 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00007767 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
7768
7769 /* Fix up the conditional jump, if there was one. */
7770 if (cond != S390_CC_ALWAYS) {
7771 Int delta = buf - ptmp;
7772
7773 delta >>= 1; /* immediate constant is #half-words */
7774 vassert(delta > 0 && delta < (1 << 16));
7775 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7776 }
7777
7778 return buf;
7779}
7780
7781
7782/* Pseudo code:
7783
7784 guest_state[host_EvC_COUNTER] -= 1;
7785 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
7786 goto guest_state[host_EvC_FAILADDR];
7787 nofail: ;
7788
7789 The dispatch counter is a 32-bit value. */
7790static UChar *
7791s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn)
7792{
7793 s390_amode *amode;
florianbf516d12012-04-21 15:53:13 +00007794 UInt b, d;
florian8844a632012-04-13 04:04:06 +00007795 UChar *code_begin, *code_end;
7796
7797 code_begin = buf;
7798
7799 amode = insn->variant.evcheck.counter;
florianbf516d12012-04-21 15:53:13 +00007800 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00007801 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007802 d = amode->d;
7803
7804 /* Decrement the dispatch counter in the guest state */
florian0e047d62012-04-21 16:06:04 +00007805 if (s390_host_has_gie) {
7806 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
7807 } else {
7808 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
7809 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
7810 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
7811 }
florian8844a632012-04-13 04:04:06 +00007812
7813 /* Jump over the next insn if >= 0 */
7814 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
7815
7816 /* Computed goto to fail_address */
7817 amode = insn->variant.evcheck.fail_addr;
7818 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007819 d = amode->d;
florianbf516d12012-04-21 15:53:13 +00007820 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
florian8844a632012-04-13 04:04:06 +00007821 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
7822
7823 code_end = buf;
7824
7825 /* Make sure the size of the generated code is identical to the size
7826 returned by evCheckSzB_S390 */
7827 vassert(evCheckSzB_S390() == code_end - code_begin);
7828
7829 return buf;
7830}
7831
7832
7833static UChar *
7834s390_insn_profinc_emit(UChar *buf,
7835 const s390_insn *insn __attribute__((unused)))
7836{
7837 /* Generate a code template to increment a memory location whose
7838 address will be known later as an immediate value. This code
7839 template will be patched once the memory location is known.
7840 For now we do this with address == 0. */
7841 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
florian0e047d62012-04-21 16:06:04 +00007842 if (s390_host_has_gie) {
7843 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
7844 } else {
7845 buf = s390_emit_LGHI(buf, R0, 1);
7846 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
7847 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
7848 }
florian8844a632012-04-13 04:04:06 +00007849
7850 return buf;
7851}
7852
7853
sewardj2019a972011-03-07 16:04:07 +00007854Int
florian8844a632012-04-13 04:04:06 +00007855emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, s390_insn *insn,
7856 Bool mode64, void *disp_cp_chain_me_to_slowEP,
7857 void *disp_cp_chain_me_to_fastEP, void *disp_cp_xindir,
7858 void *disp_cp_xassisted)
sewardj2019a972011-03-07 16:04:07 +00007859{
7860 UChar *end;
7861
7862 switch (insn->tag) {
7863 case S390_INSN_LOAD:
7864 end = s390_insn_load_emit(buf, insn);
7865 break;
7866
7867 case S390_INSN_STORE:
7868 end = s390_insn_store_emit(buf, insn);
7869 break;
7870
7871 case S390_INSN_MOVE:
7872 end = s390_insn_move_emit(buf, insn);
7873 break;
7874
7875 case S390_INSN_COND_MOVE:
7876 end = s390_insn_cond_move_emit(buf, insn);
7877 break;
7878
7879 case S390_INSN_LOAD_IMMEDIATE:
7880 end = s390_insn_load_immediate_emit(buf, insn);
7881 break;
7882
7883 case S390_INSN_ALU:
7884 end = s390_insn_alu_emit(buf, insn);
7885 break;
7886
7887 case S390_INSN_MUL:
7888 end = s390_insn_mul_emit(buf, insn);
7889 break;
7890
7891 case S390_INSN_DIV:
7892 end = s390_insn_div_emit(buf, insn);
7893 break;
7894
7895 case S390_INSN_DIVS:
7896 end = s390_insn_divs_emit(buf, insn);
7897 break;
7898
sewardj611b06e2011-03-24 08:57:29 +00007899 case S390_INSN_CLZ:
7900 end = s390_insn_clz_emit(buf, insn);
sewardj2019a972011-03-07 16:04:07 +00007901 break;
7902
7903 case S390_INSN_UNOP:
7904 end = s390_insn_unop_emit(buf, insn);
7905 break;
7906
7907 case S390_INSN_TEST:
7908 end = s390_insn_test_emit(buf, insn);
7909 break;
7910
7911 case S390_INSN_CC2BOOL:
7912 end = s390_insn_cc2bool_emit(buf, insn);
7913 break;
7914
7915 case S390_INSN_CAS:
7916 end = s390_insn_cas_emit(buf, insn);
7917 break;
7918
florian448cbba2012-06-06 02:26:01 +00007919 case S390_INSN_CDAS:
7920 end = s390_insn_cdas_emit(buf, insn);
7921 break;
7922
sewardj2019a972011-03-07 16:04:07 +00007923 case S390_INSN_COMPARE:
7924 end = s390_insn_compare_emit(buf, insn);
7925 break;
7926
sewardj2019a972011-03-07 16:04:07 +00007927 case S390_INSN_HELPER_CALL:
7928 end = s390_insn_helper_call_emit(buf, insn);
7929 break;
7930
7931 case S390_INSN_BFP_TRIOP:
7932 end = s390_insn_bfp_triop_emit(buf, insn);
7933 break;
7934
7935 case S390_INSN_BFP_BINOP:
7936 end = s390_insn_bfp_binop_emit(buf, insn);
7937 break;
7938
7939 case S390_INSN_BFP_UNOP:
7940 end = s390_insn_bfp_unop_emit(buf, insn);
7941 break;
7942
7943 case S390_INSN_BFP_COMPARE:
7944 end = s390_insn_bfp_compare_emit(buf, insn);
7945 break;
7946
7947 case S390_INSN_BFP128_BINOP:
7948 end = s390_insn_bfp128_binop_emit(buf, insn);
7949 break;
7950
7951 case S390_INSN_BFP128_COMPARE:
7952 end = s390_insn_bfp128_compare_emit(buf, insn);
7953 break;
7954
7955 case S390_INSN_BFP128_UNOP:
7956 end = s390_insn_bfp128_unop_emit(buf, insn);
7957 break;
7958
7959 case S390_INSN_BFP128_CONVERT_TO:
7960 end = s390_insn_bfp128_convert_to_emit(buf, insn);
7961 break;
7962
7963 case S390_INSN_BFP128_CONVERT_FROM:
7964 end = s390_insn_bfp128_convert_from_emit(buf, insn);
7965 break;
7966
sewardja52e37e2011-04-28 18:48:06 +00007967 case S390_INSN_MFENCE:
7968 end = s390_insn_mfence_emit(buf, insn);
7969 break;
7970
florianad43b3a2012-02-20 15:01:14 +00007971 case S390_INSN_GZERO:
7972 end = s390_insn_gzero_emit(buf, insn);
7973 break;
7974
7975 case S390_INSN_GADD:
7976 end = s390_insn_gadd_emit(buf, insn);
7977 break;
7978
florian8844a632012-04-13 04:04:06 +00007979 case S390_INSN_PROFINC:
7980 end = s390_insn_profinc_emit(buf, insn);
7981 /* Tell the caller .. */
7982 vassert(*is_profinc == False);
7983 *is_profinc = True;
7984 break;
7985
7986 case S390_INSN_EVCHECK:
7987 end = s390_insn_evcheck_emit(buf, insn);
7988 break;
7989
7990 case S390_INSN_XDIRECT:
7991 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
7992 disp_cp_chain_me_to_fastEP);
7993 break;
7994
7995 case S390_INSN_XINDIR:
7996 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
7997 break;
7998
7999 case S390_INSN_XASSISTED:
8000 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
8001 break;
8002
sewardj2019a972011-03-07 16:04:07 +00008003 default:
florian616458b2012-03-25 16:17:18 +00008004 vpanic("emit_S390Instr");
sewardj2019a972011-03-07 16:04:07 +00008005 }
8006
8007 vassert(end - buf <= nbuf);
8008
8009 return end - buf;
8010}
8011
8012
florian8844a632012-04-13 04:04:06 +00008013/* Return the number of bytes emitted for an S390_INSN_EVCHECK.
8014 See s390_insn_evcheck_emit */
8015Int
8016evCheckSzB_S390(void)
8017{
florian0e047d62012-04-21 16:06:04 +00008018 return s390_host_has_gie ? 18 : 24;
florian8844a632012-04-13 04:04:06 +00008019}
8020
8021
8022/* Patch the counter address into CODE_TO_PATCH as previously
8023 generated by s390_insn_profinc_emit. */
8024VexInvalRange
8025patchProfInc_S390(void *code_to_patch, ULong *location_of_counter)
8026{
8027 vassert(sizeof(ULong *) == 8);
8028
8029 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
8030
8031 s390_tchain_patch_load64(code_to_patch, Ptr_to_ULong(location_of_counter));
8032
8033 VexInvalRange vir = {0, 0};
8034 return vir;
8035}
8036
8037
8038/* NB: what goes on here has to be very closely coordinated with the
8039 s390_insn_xdirect_emit code above. */
8040VexInvalRange
8041chainXDirect_S390(void *place_to_chain,
8042 void *disp_cp_chain_me_EXPECTED,
8043 void *place_to_jump_to)
8044{
florianebaf8d92012-04-22 17:38:46 +00008045 /* What we're expecting to see @ PLACE_TO_CHAIN is:
florian8844a632012-04-13 04:04:06 +00008046
florianebaf8d92012-04-22 17:38:46 +00008047 load tchain_scratch, #disp_cp_chain_me_EXPECTED
8048 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00008049 */
8050 const UChar *next;
8051 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
8052 Ptr_to_ULong(disp_cp_chain_me_EXPECTED));
florianebaf8d92012-04-22 17:38:46 +00008053 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +00008054
8055 /* And what we want to change it to is either:
8056 (general case):
8057
florianebaf8d92012-04-22 17:38:46 +00008058 load tchain_scratch, #place_to_jump_to
8059 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00008060
8061 ---OR---
8062
8063 in the case where the displacement is small enough
8064
8065 BRCL delta where delta is in half-words
8066 invalid opcodes
8067
8068 In both cases the replacement has the same length as the original.
8069 To remain sane & verifiable,
8070 (1) limit the displacement for the short form to
8071 (say) +/- one billion, so as to avoid wraparound
8072 off-by-ones
8073 (2) even if the short form is applicable, once every (say)
8074 1024 times use the long form anyway, so as to maintain
8075 verifiability
8076 */
8077
8078 /* This is the delta we need to put into a BRCL insn. Note, that the
8079 offset in BRCL is in half-words. Hence division by 2. */
8080 Long delta = (Long)((UChar *)place_to_jump_to - (UChar *)place_to_chain) / 2;
8081 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
8082
8083 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
8084 if (shortOK) {
8085 shortCTR++; // thread safety bleh
8086 if (0 == (shortCTR & 0x3FF)) {
8087 shortOK = False;
8088 if (0)
8089 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
8090 "using long jmp\n", shortCTR);
8091 }
8092 }
8093
8094 /* And make the modifications. */
8095 UChar *p = (UChar *)place_to_chain;
8096 if (shortOK) {
8097 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
8098
florian48cb9612012-04-20 02:50:28 +00008099 /* Make sure that BRCL fits into the patchable part of an xdirect
florian1c857042012-04-15 04:11:07 +00008100 code sequence */
florian48cb9612012-04-20 02:50:28 +00008101 vassert(6 <= s390_xdirect_patchable_len());
florian1c857042012-04-15 04:11:07 +00008102
florian8844a632012-04-13 04:04:06 +00008103 /* Fill remaining bytes with 0x00 (invalid opcode) */
8104 Int i;
8105 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
8106 p[i] = 0x00;
8107 } else {
florian1c857042012-04-15 04:11:07 +00008108 /*
florianebaf8d92012-04-22 17:38:46 +00008109 load tchain_scratch, #place_to_jump_to
8110 goto *tchain_scratch
florian1c857042012-04-15 04:11:07 +00008111 */
8112 ULong addr = Ptr_to_ULong(place_to_jump_to);
8113 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +00008114 /* There is not need to emit a BCR here, as it is already there. */
florian8844a632012-04-13 04:04:06 +00008115 }
8116
8117 VexInvalRange vir = {0, 0};
8118 return vir;
8119}
8120
8121
8122/* NB: what goes on here has to be very closely coordinated with the
8123 s390_insn_xdirect_emit code above. */
8124VexInvalRange
8125unchainXDirect_S390(void *place_to_unchain,
8126 void *place_to_jump_to_EXPECTED,
8127 void *disp_cp_chain_me)
8128{
8129 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
8130
florianebaf8d92012-04-22 17:38:46 +00008131 load tchain_scratch, #place_to_jump_to_EXPECTED
8132 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00008133
8134 ---OR---
8135 in the case where the displacement falls within 32 bits
8136
8137 BRCL delta
8138 invalid opcodes
8139 */
8140 UChar *p = place_to_unchain;
florian1c857042012-04-15 04:11:07 +00008141
florianebaf8d92012-04-22 17:38:46 +00008142 Bool uses_short_form = False;
8143
florian1c857042012-04-15 04:11:07 +00008144 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
florian8844a632012-04-13 04:04:06 +00008145 /* Looks like the short form */
8146 Int num_hw = *(Int *)&p[2];
8147 Int delta = 2 *num_hw;
8148
8149 vassert(p + delta == place_to_jump_to_EXPECTED);
8150
florian8844a632012-04-13 04:04:06 +00008151 Int i;
8152 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
florian1c857042012-04-15 04:11:07 +00008153 vassert(p[6+i] == 0x00);
florianebaf8d92012-04-22 17:38:46 +00008154 uses_short_form = True;
florian8844a632012-04-13 04:04:06 +00008155 } else {
8156 /* Should be the long form */
8157 const UChar *next;
8158
8159 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
8160 Ptr_to_ULong(place_to_jump_to_EXPECTED));
8161 /* Check for BR *tchain_scratch */
florian1c857042012-04-15 04:11:07 +00008162 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +00008163 }
8164
8165 /* And what we want to change it to is:
8166
8167 load tchain_scratch, #disp_cp_chain_me
florianebaf8d92012-04-22 17:38:46 +00008168 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00008169 */
florianebaf8d92012-04-22 17:38:46 +00008170
8171 /* Get the address of the beginning of the load64 code sequence into %r1.
8172 Do not change the register! This is part of the protocol with the
8173 dispatcher.
8174 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
8175 load64 insn sequence. That sequence is prefixed with a BASR to get its
8176 address (see s390_insn_xdirect_emit). */
8177 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
8178
florian8844a632012-04-13 04:04:06 +00008179 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
8180 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +00008181
8182 /* Emit the BCR in case the short form was used. In case of the long
8183 form, the BCR is already there. */
8184 if (uses_short_form)
8185 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00008186
8187 VexInvalRange vir = {0, 0};
8188 return vir;
8189}
8190
sewardj2019a972011-03-07 16:04:07 +00008191/*---------------------------------------------------------------*/
8192/*--- end host_s390_defs.c ---*/
8193/*---------------------------------------------------------------*/