blob: 6fb6d0bbd1ee4ec7817610a420a151fcf161f606 [file] [log] [blame]
sewardj2019a972011-03-07 16:04:07 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
2
3/*---------------------------------------------------------------*/
4/*--- begin host_s390_defs.c ---*/
5/*---------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
florian61f23c12012-08-06 18:33:21 +000011 Copyright IBM Corp. 2010-2012
florian2c74d242012-09-12 19:38:42 +000012 Copyright (C) 2012-2012 Florian Krohm (britzel@acm.org)
sewardj2019a972011-03-07 16:04:07 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 02110-1301, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32/* Contributed by Florian Krohm */
33
34#include "libvex_basictypes.h"
35#include "libvex.h"
36#include "libvex_trc_values.h"
sewardj2019a972011-03-07 16:04:07 +000037#include "libvex_s390x_common.h"
38
39#include "main_util.h"
40#include "main_globals.h"
41#include "host_generic_regs.h"
42#include "host_s390_defs.h"
florian79af5752012-09-20 01:22:10 +000043#include "s390_disasm.h"
florian428dfdd2012-03-27 03:09:49 +000044#include "guest_s390_defs.h" /* S390X_GUEST_OFFSET */
sewardj2019a972011-03-07 16:04:07 +000045#include <stdarg.h>
46
47/* KLUDGE: We need to know the hwcaps of the host when generating
48 code. But that info is not passed to emit_S390Instr. Only mode64 is
49 being passed. So, ideally, we want this passed as an argument, too.
50 Until then, we use a global variable. This variable is set as a side
51 effect of iselSB_S390. This is safe because instructions are selected
52 before they are emitted. */
florianf26994a2012-04-21 03:34:54 +000053UInt s390_host_hwcaps;
sewardj2019a972011-03-07 16:04:07 +000054
florianb4df7682011-07-05 02:09:01 +000055
56/*------------------------------------------------------------*/
57/*--- Forward declarations ---*/
58/*------------------------------------------------------------*/
59
60static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
61static void s390_insn_map_regs(HRegRemap *, s390_insn *);
62static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
florian1c857042012-04-15 04:11:07 +000063static UInt s390_tchain_load64_len(void);
florianb4df7682011-07-05 02:09:01 +000064
65
sewardj2019a972011-03-07 16:04:07 +000066/*------------------------------------------------------------*/
67/*--- Registers ---*/
68/*------------------------------------------------------------*/
69
70/* Decompile the given register into a static buffer and return it */
71const HChar *
72s390_hreg_as_string(HReg reg)
73{
74 static HChar buf[10];
75
76 static const HChar ireg_names[16][5] = {
77 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
78 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
79 };
80
81 static const HChar freg_names[16][5] = {
82 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
83 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
84 };
85
86 UInt r; /* hregNumber() returns an UInt */
87
88 r = hregNumber(reg);
89
90 /* Be generic for all virtual regs. */
91 if (hregIsVirtual(reg)) {
92 buf[0] = '\0';
93 switch (hregClass(reg)) {
94 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
95 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
96 default: goto fail;
97 }
98 return buf;
99 }
100
101 /* But specific for real regs. */
102 vassert(r < 16);
103
104 switch (hregClass(reg)) {
105 case HRcInt64: return ireg_names[r];
106 case HRcFlt64: return freg_names[r];
107 default: goto fail;
108 }
109
110 fail: vpanic("s390_hreg_as_string");
111}
112
113
114/* Tell the register allocator which registers can be allocated. */
florianb4df7682011-07-05 02:09:01 +0000115static void
sewardj2019a972011-03-07 16:04:07 +0000116s390_hreg_get_allocable(Int *nregs, HReg **arr)
117{
118 UInt i;
119
120 /* Total number of allocable registers (all classes) */
121 *nregs = 16 /* GPRs */
122 - 1 /* r0 */
florian8844a632012-04-13 04:04:06 +0000123 - 1 /* r12 scratch register for translation chaining support */
sewardj2019a972011-03-07 16:04:07 +0000124 - 1 /* r13 guest state pointer */
125 - 1 /* r14 link register */
126 - 1 /* r15 stack pointer */
127 + 16 /* FPRs */
128 ;
129
130 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
131
132 i = 0;
133
134 /* GPR0 is not available because it is interpreted as 0, when used
135 as a base or index register. */
136 (*arr)[i++] = mkHReg(1, HRcInt64, False);
137 (*arr)[i++] = mkHReg(2, HRcInt64, False);
138 (*arr)[i++] = mkHReg(3, HRcInt64, False);
139 (*arr)[i++] = mkHReg(4, HRcInt64, False);
140 (*arr)[i++] = mkHReg(5, HRcInt64, False);
141 (*arr)[i++] = mkHReg(6, HRcInt64, False);
142 (*arr)[i++] = mkHReg(7, HRcInt64, False);
143 (*arr)[i++] = mkHReg(8, HRcInt64, False);
144 (*arr)[i++] = mkHReg(9, HRcInt64, False);
145 /* GPR10 and GPR11 are used for instructions that use register pairs.
146 Otherwise, they are available to the allocator */
147 (*arr)[i++] = mkHReg(10, HRcInt64, False);
148 (*arr)[i++] = mkHReg(11, HRcInt64, False);
florian8844a632012-04-13 04:04:06 +0000149 /* GPR12 is not available because it us used as a scratch register
150 in translation chaining. */
sewardj2019a972011-03-07 16:04:07 +0000151 /* GPR13 is not available because it is used as guest state pointer */
152 /* GPR14 is not available because it is used as link register */
153 /* GPR15 is not available because it is used as stack pointer */
154
155 /* Add the available real (non-virtual) FPRs */
156 (*arr)[i++] = mkHReg(0, HRcFlt64, False);
157 (*arr)[i++] = mkHReg(1, HRcFlt64, False);
158 (*arr)[i++] = mkHReg(2, HRcFlt64, False);
159 (*arr)[i++] = mkHReg(3, HRcFlt64, False);
160 (*arr)[i++] = mkHReg(4, HRcFlt64, False);
161 (*arr)[i++] = mkHReg(5, HRcFlt64, False);
162 (*arr)[i++] = mkHReg(6, HRcFlt64, False);
163 (*arr)[i++] = mkHReg(7, HRcFlt64, False);
164 (*arr)[i++] = mkHReg(8, HRcFlt64, False);
165 (*arr)[i++] = mkHReg(9, HRcFlt64, False);
166 (*arr)[i++] = mkHReg(10, HRcFlt64, False);
167 (*arr)[i++] = mkHReg(11, HRcFlt64, False);
168 (*arr)[i++] = mkHReg(12, HRcFlt64, False);
169 (*arr)[i++] = mkHReg(13, HRcFlt64, False);
170 (*arr)[i++] = mkHReg(14, HRcFlt64, False);
171 (*arr)[i++] = mkHReg(15, HRcFlt64, False);
172 /* FPR12 - FPR15 are also used as register pairs for 128-bit
173 floating point operations */
174}
175
176
177/* Return the real register that holds the guest state pointer */
178HReg
179s390_hreg_guest_state_pointer(void)
180{
181 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
182}
183
florian8844a632012-04-13 04:04:06 +0000184
sewardj2019a972011-03-07 16:04:07 +0000185/* Is VALUE within the domain of a 20-bit signed integer. */
186static __inline__ Bool
187fits_signed_20bit(Int value)
188{
189 return ((value << 12) >> 12) == value;
190}
191
192
193/* Is VALUE within the domain of a 12-bit unsigned integer. */
194static __inline__ Bool
195fits_unsigned_12bit(Int value)
196{
197 return (value & 0xFFF) == value;
198}
199
200/*------------------------------------------------------------*/
201/*--- Addressing modes (amodes) ---*/
202/*------------------------------------------------------------*/
203
204/* Construct a b12 amode. */
205s390_amode *
206s390_amode_b12(Int d, HReg b)
207{
208 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
209
210 vassert(fits_unsigned_12bit(d));
211
212 am->tag = S390_AMODE_B12;
213 am->d = d;
214 am->b = b;
215 am->x = 0; /* hregNumber(0) == 0 */
216
217 return am;
218}
219
220
221/* Construct a b20 amode. */
222s390_amode *
223s390_amode_b20(Int d, HReg b)
224{
225 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
226
227 vassert(fits_signed_20bit(d));
228
229 am->tag = S390_AMODE_B20;
230 am->d = d;
231 am->b = b;
232 am->x = 0; /* hregNumber(0) == 0 */
233
234 return am;
235}
236
237
238/* Construct a bx12 amode. */
239s390_amode *
240s390_amode_bx12(Int d, HReg b, HReg x)
241{
242 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
243
244 vassert(fits_unsigned_12bit(d));
245 vassert(b != 0);
246 vassert(x != 0);
247
248 am->tag = S390_AMODE_BX12;
249 am->d = d;
250 am->b = b;
251 am->x = x;
252
253 return am;
254}
255
256
257/* Construct a bx20 amode. */
258s390_amode *
259s390_amode_bx20(Int d, HReg b, HReg x)
260{
261 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
262
263 vassert(fits_signed_20bit(d));
264 vassert(b != 0);
265 vassert(x != 0);
266
267 am->tag = S390_AMODE_BX20;
268 am->d = d;
269 am->b = b;
270 am->x = x;
271
272 return am;
273}
274
275
276/* Construct an AMODE for accessing the guest state at OFFSET */
277s390_amode *
278s390_amode_for_guest_state(Int offset)
279{
280 if (fits_unsigned_12bit(offset))
281 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
sewardj2019a972011-03-07 16:04:07 +0000282
283 vpanic("invalid guest state offset");
284}
285
286
287/* Decompile the given amode into a static buffer and return it. */
288const HChar *
289s390_amode_as_string(const s390_amode *am)
290{
291 static HChar buf[30];
292 HChar *p;
293
294 buf[0] = '\0';
295 p = buf;
296
297 switch (am->tag) {
298 case S390_AMODE_B12:
299 case S390_AMODE_B20:
300 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
301 break;
302
303 case S390_AMODE_BX12:
304 case S390_AMODE_BX20:
305 /* s390_hreg_as_string returns pointer to local buffer. Need to
306 split this into two printfs */
307 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
308 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
309 break;
310
311 default:
312 vpanic("s390_amode_as_string");
313 }
314
315 return buf;
316}
317
318
319/* Helper function for s390_amode_is_sane */
320static __inline__ Bool
321is_virtual_gpr(HReg reg)
322{
323 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
324}
325
326
327/* Sanity check for an amode */
328Bool
329s390_amode_is_sane(const s390_amode *am)
330{
331 switch (am->tag) {
332 case S390_AMODE_B12:
333 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
334
335 case S390_AMODE_B20:
336 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
337
338 case S390_AMODE_BX12:
339 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
340 fits_unsigned_12bit(am->d);
341
342 case S390_AMODE_BX20:
343 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
344 fits_signed_20bit(am->d);
345
346 default:
347 vpanic("s390_amode_is_sane");
348 }
349}
350
351
352/* Record the register use of an amode */
florianb4df7682011-07-05 02:09:01 +0000353static void
sewardj2019a972011-03-07 16:04:07 +0000354s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
355{
356 switch (am->tag) {
357 case S390_AMODE_B12:
358 case S390_AMODE_B20:
359 addHRegUse(u, HRmRead, am->b);
360 return;
361
362 case S390_AMODE_BX12:
363 case S390_AMODE_BX20:
364 addHRegUse(u, HRmRead, am->b);
365 addHRegUse(u, HRmRead, am->x);
366 return;
367
368 default:
369 vpanic("s390_amode_get_reg_usage");
370 }
371}
372
373
florianb4df7682011-07-05 02:09:01 +0000374static void
sewardj2019a972011-03-07 16:04:07 +0000375s390_amode_map_regs(HRegRemap *m, s390_amode *am)
376{
377 switch (am->tag) {
378 case S390_AMODE_B12:
379 case S390_AMODE_B20:
380 am->b = lookupHRegRemap(m, am->b);
381 return;
382
383 case S390_AMODE_BX12:
384 case S390_AMODE_BX20:
385 am->b = lookupHRegRemap(m, am->b);
386 am->x = lookupHRegRemap(m, am->x);
387 return;
388
389 default:
390 vpanic("s390_amode_map_regs");
391 }
392}
393
394
sewardj2019a972011-03-07 16:04:07 +0000395void
florianb4df7682011-07-05 02:09:01 +0000396ppS390AMode(s390_amode *am)
sewardj2019a972011-03-07 16:04:07 +0000397{
398 vex_printf("%s", s390_amode_as_string(am));
399}
400
401void
florianb4df7682011-07-05 02:09:01 +0000402ppS390Instr(s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000403{
404 vex_printf("%s", s390_insn_as_string(insn));
405}
406
407void
408ppHRegS390(HReg reg)
409{
410 vex_printf("%s", s390_hreg_as_string(reg));
411}
412
413/*------------------------------------------------------------*/
414/*--- Helpers for register allocation ---*/
415/*------------------------------------------------------------*/
416
417/* Called once per translation. */
418void
419getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
420{
421 s390_hreg_get_allocable(nregs, arr);
422}
423
424
425/* Tell the register allocator how the given instruction uses the registers
426 it refers to. */
427void
florianb4df7682011-07-05 02:09:01 +0000428getRegUsage_S390Instr(HRegUsage *u, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000429{
430 s390_insn_get_reg_usage(u, insn);
431}
432
433
434/* Map the registers of the given instruction */
435void
florianb4df7682011-07-05 02:09:01 +0000436mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000437{
438 s390_insn_map_regs(m, insn);
439}
440
441
442/* Figure out if the given insn represents a reg-reg move, and if so
443 assign the source and destination to *src and *dst. If in doubt say No.
444 Used by the register allocator to do move coalescing. */
445Bool
florianb4df7682011-07-05 02:09:01 +0000446isMove_S390Instr(s390_insn *insn, HReg *src, HReg *dst)
sewardj2019a972011-03-07 16:04:07 +0000447{
448 return s390_insn_is_reg_reg_move(insn, src, dst);
449}
450
451
452/* Generate s390 spill/reload instructions under the direction of the
453 register allocator. Note it's critical these don't write the
454 condition codes. This is like an Ist_Put */
455void
456genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
457{
458 s390_amode *am;
459
460 vassert(offsetB >= 0);
461 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
462 vassert(!hregIsVirtual(rreg));
463
464 *i1 = *i2 = NULL;
465
466 am = s390_amode_for_guest_state(offsetB);
467
468 switch (hregClass(rreg)) {
469 case HRcInt64:
470 case HRcFlt64:
471 *i1 = s390_insn_store(8, am, rreg);
472 return;
473
474 default:
475 ppHRegClass(hregClass(rreg));
476 vpanic("genSpill_S390: unimplemented regclass");
477 }
478}
479
480
481/* This is like an Iex_Get */
482void
483genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
484{
485 s390_amode *am;
486
487 vassert(offsetB >= 0);
488 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
489 vassert(!hregIsVirtual(rreg));
490
491 *i1 = *i2 = NULL;
492
493 am = s390_amode_for_guest_state(offsetB);
494
495 switch (hregClass(rreg)) {
496 case HRcInt64:
497 case HRcFlt64:
498 *i1 = s390_insn_load(8, rreg, am);
499 return;
500
501 default:
502 ppHRegClass(hregClass(rreg));
503 vpanic("genReload_S390: unimplemented regclass");
504 }
505}
506
507/* Helper function for s390_insn_get_reg_usage */
508static void
509s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
510{
511 switch (op.tag) {
512 case S390_OPND_REG:
513 addHRegUse(u, HRmRead, op.variant.reg);
514 break;
515
516 case S390_OPND_AMODE:
517 s390_amode_get_reg_usage(u, op.variant.am);
518 break;
519
520 case S390_OPND_IMMEDIATE:
521 break;
522
523 default:
524 vpanic("s390_opnd_RMI_get_reg_usage");
525 }
526}
527
528
529/* Tell the register allocator how the given insn uses the registers */
florianb4df7682011-07-05 02:09:01 +0000530static void
sewardj2019a972011-03-07 16:04:07 +0000531s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
532{
533 initHRegUsage(u);
534
535 switch (insn->tag) {
536 case S390_INSN_LOAD:
537 addHRegUse(u, HRmWrite, insn->variant.load.dst);
538 s390_amode_get_reg_usage(u, insn->variant.load.src);
539 break;
540
541 case S390_INSN_LOAD_IMMEDIATE:
542 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
543 break;
544
545 case S390_INSN_STORE:
546 addHRegUse(u, HRmRead, insn->variant.store.src);
547 s390_amode_get_reg_usage(u, insn->variant.store.dst);
548 break;
549
550 case S390_INSN_MOVE:
551 addHRegUse(u, HRmRead, insn->variant.move.src);
552 addHRegUse(u, HRmWrite, insn->variant.move.dst);
553 break;
554
555 case S390_INSN_COND_MOVE:
556 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
557 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
558 break;
559
560 case S390_INSN_ALU:
561 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
562 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
563 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
564 break;
565
566 case S390_INSN_MUL:
567 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
568 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
569 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
570 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
571 break;
572
573 case S390_INSN_DIV:
574 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
575 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
576 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
577 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
578 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
579 break;
580
581 case S390_INSN_DIVS:
582 addHRegUse(u, HRmRead, insn->variant.divs.op1);
583 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
584 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
585 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
586 break;
587
sewardj611b06e2011-03-24 08:57:29 +0000588 case S390_INSN_CLZ:
589 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
590 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
591 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000592 break;
593
594 case S390_INSN_UNOP:
595 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
596 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
597 break;
598
599 case S390_INSN_TEST:
600 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
601 break;
602
603 case S390_INSN_CC2BOOL:
604 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
605 break;
606
607 case S390_INSN_CAS:
608 addHRegUse(u, HRmRead, insn->variant.cas.op1);
609 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
610 addHRegUse(u, HRmRead, insn->variant.cas.op3);
611 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
612 break;
613
florian448cbba2012-06-06 02:26:01 +0000614 case S390_INSN_CDAS:
615 addHRegUse(u, HRmRead, insn->variant.cdas.op1_high);
616 addHRegUse(u, HRmRead, insn->variant.cdas.op1_low);
617 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
618 addHRegUse(u, HRmRead, insn->variant.cdas.op3_high);
619 addHRegUse(u, HRmRead, insn->variant.cdas.op3_low);
620 addHRegUse(u, HRmWrite, insn->variant.cdas.old_mem_high);
621 addHRegUse(u, HRmWrite, insn->variant.cdas.old_mem_low);
622 addHRegUse(u, HRmWrite, insn->variant.cdas.scratch);
623 break;
624
sewardj2019a972011-03-07 16:04:07 +0000625 case S390_INSN_COMPARE:
626 addHRegUse(u, HRmRead, insn->variant.compare.src1);
627 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
628 break;
629
sewardj2019a972011-03-07 16:04:07 +0000630 case S390_INSN_HELPER_CALL: {
631 UInt i;
632
633 /* Assume that all volatile registers are clobbered. ABI says,
634 volatile registers are: r0 - r5. Valgrind's register allocator
635 does not know about r0, so we can leave that out */
636 for (i = 1; i <= 5; ++i) {
637 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
638 }
florian01ed6e72012-05-27 16:52:43 +0000639 if (insn->variant.helper_call.dst != INVALID_HREG)
640 addHRegUse(u, HRmWrite, insn->variant.helper_call.dst);
sewardj2019a972011-03-07 16:04:07 +0000641
642 /* Ditto for floating point registers. f0 - f7 are volatile */
643 for (i = 0; i <= 7; ++i) {
644 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
645 }
646
647 /* The registers that are used for passing arguments will be read.
648 Not all of them may, but in general we need to assume that. */
649 for (i = 0; i < insn->variant.helper_call.num_args; ++i) {
650 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
651 HRcInt64, False));
652 }
653
654 /* s390_insn_helper_call_emit also reads / writes the link register
655 and stack pointer. But those registers are not visible to the
656 register allocator. So we don't need to do anything for them. */
657 break;
658 }
659
660 case S390_INSN_BFP_TRIOP:
661 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
662 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
663 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
664 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
665 break;
666
667 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000668 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_hi);
669 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_hi); /* left */
670 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_hi); /* right */
671 if (insn->size == 16) {
672 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_lo);
673 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_lo); /* left */
674 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_lo); /* right */
675 }
sewardj2019a972011-03-07 16:04:07 +0000676 break;
677
678 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +0000679 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi);
680 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_hi); /* operand */
681 if (insn->size == 16) {
682 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo);
683 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_lo); /* operand */
684 }
sewardj2019a972011-03-07 16:04:07 +0000685 break;
686
687 case S390_INSN_BFP_COMPARE:
688 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +0000689 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_hi); /* left */
690 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_hi); /* right */
691 if (insn->size == 16) {
692 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_lo); /* left */
693 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_lo); /* right */
694 }
sewardj2019a972011-03-07 16:04:07 +0000695 break;
696
florian9fcff4c2012-09-10 03:09:04 +0000697 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +0000698 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi);
699 if (insn->variant.bfp_convert.dst_lo != INVALID_HREG)
700 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo);
701 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_hi);
702 if (insn->variant.bfp_convert.op_lo != INVALID_HREG)
703 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +0000704 break;
705
sewardja52e37e2011-04-28 18:48:06 +0000706 case S390_INSN_MFENCE:
florianad43b3a2012-02-20 15:01:14 +0000707 case S390_INSN_GZERO:
708 case S390_INSN_GADD:
sewardja52e37e2011-04-28 18:48:06 +0000709 break;
710
florian125e20d2012-10-07 15:42:37 +0000711 case S390_INSN_SET_FPC_BFPRM:
712 addHRegUse(u, HRmRead, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +0000713 break;
714
florianc8e4f562012-10-27 16:19:31 +0000715 case S390_INSN_SET_FPC_DFPRM:
716 addHRegUse(u, HRmRead, insn->variant.set_fpc_dfprm.mode);
717 break;
718
florian8844a632012-04-13 04:04:06 +0000719 case S390_INSN_EVCHECK:
720 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
721 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
722 break;
723
724 case S390_INSN_PROFINC:
725 /* Does not use any register visible to the register allocator */
726 break;
727
728 case S390_INSN_XDIRECT:
729 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
730 break;
731
732 case S390_INSN_XINDIR:
733 addHRegUse(u, HRmRead, insn->variant.xindir.dst);
734 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
735 break;
736
737 case S390_INSN_XASSISTED:
738 addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
739 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
740 break;
741
sewardj2019a972011-03-07 16:04:07 +0000742 default:
743 vpanic("s390_insn_get_reg_usage");
744 }
745}
746
747
748/* Helper function for s390_insn_map_regs */
749static void
750s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
751{
752 switch (op->tag) {
753 case S390_OPND_REG:
754 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
755 break;
756
757 case S390_OPND_IMMEDIATE:
758 break;
759
760 case S390_OPND_AMODE:
761 s390_amode_map_regs(m, op->variant.am);
762 break;
763
764 default:
765 vpanic("s390_opnd_RMI_map_regs");
766 }
767}
768
769
florianb4df7682011-07-05 02:09:01 +0000770static void
sewardj2019a972011-03-07 16:04:07 +0000771s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
772{
773 switch (insn->tag) {
774 case S390_INSN_LOAD:
775 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
776 s390_amode_map_regs(m, insn->variant.load.src);
777 break;
778
779 case S390_INSN_STORE:
780 s390_amode_map_regs(m, insn->variant.store.dst);
781 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
782 break;
783
784 case S390_INSN_MOVE:
785 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
786 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
787 break;
788
789 case S390_INSN_COND_MOVE:
790 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
791 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
792 break;
793
794 case S390_INSN_LOAD_IMMEDIATE:
795 insn->variant.load_immediate.dst =
796 lookupHRegRemap(m, insn->variant.load_immediate.dst);
797 break;
798
799 case S390_INSN_ALU:
800 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
801 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
802 break;
803
804 case S390_INSN_MUL:
805 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
806 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
807 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
808 break;
809
810 case S390_INSN_DIV:
811 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
812 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
813 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
814 break;
815
816 case S390_INSN_DIVS:
817 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
818 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
819 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
820 break;
821
sewardj611b06e2011-03-24 08:57:29 +0000822 case S390_INSN_CLZ:
823 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
824 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
825 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000826 break;
827
828 case S390_INSN_UNOP:
829 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
830 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
831 break;
832
833 case S390_INSN_TEST:
834 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
835 break;
836
837 case S390_INSN_CC2BOOL:
838 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
839 break;
840
841 case S390_INSN_CAS:
842 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
843 s390_amode_map_regs(m, insn->variant.cas.op2);
844 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
845 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
846 break;
847
florian448cbba2012-06-06 02:26:01 +0000848 case S390_INSN_CDAS:
849 insn->variant.cdas.op1_high = lookupHRegRemap(m, insn->variant.cdas.op1_high);
850 insn->variant.cdas.op1_low = lookupHRegRemap(m, insn->variant.cdas.op1_low);
851 s390_amode_map_regs(m, insn->variant.cdas.op2);
852 insn->variant.cdas.op3_high = lookupHRegRemap(m, insn->variant.cdas.op3_high);
853 insn->variant.cdas.op3_low = lookupHRegRemap(m, insn->variant.cdas.op3_low);
854 insn->variant.cdas.old_mem_high = lookupHRegRemap(m, insn->variant.cdas.old_mem_high);
855 insn->variant.cdas.old_mem_low = lookupHRegRemap(m, insn->variant.cdas.old_mem_low);
856 insn->variant.cdas.scratch = lookupHRegRemap(m, insn->variant.cdas.scratch);
857 break;
858
sewardj2019a972011-03-07 16:04:07 +0000859 case S390_INSN_COMPARE:
860 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
861 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
862 break;
863
sewardj2019a972011-03-07 16:04:07 +0000864 case S390_INSN_HELPER_CALL:
865 /* s390_insn_helper_call_emit also reads / writes the link register
866 and stack pointer. But those registers are not visible to the
867 register allocator. So we don't need to do anything for them.
868 As for the arguments of the helper call -- they will be loaded into
869 non-virtual registers. Again, we don't need to do anything for those
870 here. */
florian01ed6e72012-05-27 16:52:43 +0000871 if (insn->variant.helper_call.dst != INVALID_HREG)
872 insn->variant.helper_call.dst = lookupHRegRemap(m, insn->variant.helper_call.dst);
sewardj2019a972011-03-07 16:04:07 +0000873 break;
874
875 case S390_INSN_BFP_TRIOP:
floriancc491a62012-09-10 23:44:37 +0000876 insn->variant.bfp_triop.dst =
877 lookupHRegRemap(m, insn->variant.bfp_triop.dst);
878 insn->variant.bfp_triop.op2 =
879 lookupHRegRemap(m, insn->variant.bfp_triop.op2);
880 insn->variant.bfp_triop.op3 =
881 lookupHRegRemap(m, insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +0000882 break;
883
884 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000885 insn->variant.bfp_binop.dst_hi =
886 lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi);
887 insn->variant.bfp_binop.op2_hi =
888 lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi);
889 if (insn->size == 16) {
floriana1659202012-09-19 16:01:21 +0000890 insn->variant.bfp_binop.dst_lo =
floriancc491a62012-09-10 23:44:37 +0000891 lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo);
floriana1659202012-09-19 16:01:21 +0000892 insn->variant.bfp_binop.op2_lo =
floriancc491a62012-09-10 23:44:37 +0000893 lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo);
894 }
sewardj2019a972011-03-07 16:04:07 +0000895 break;
896
897 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +0000898 insn->variant.bfp_unop.dst_hi =
899 lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi);
900 insn->variant.bfp_unop.op_hi =
901 lookupHRegRemap(m, insn->variant.bfp_unop.op_hi);
902 if (insn->size == 16) {
903 insn->variant.bfp_unop.dst_lo =
904 lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo);
905 insn->variant.bfp_unop.op_lo =
906 lookupHRegRemap(m, insn->variant.bfp_unop.op_lo);
907 }
sewardj2019a972011-03-07 16:04:07 +0000908 break;
909
910 case S390_INSN_BFP_COMPARE:
floriancc491a62012-09-10 23:44:37 +0000911 insn->variant.bfp_compare.dst =
912 lookupHRegRemap(m, insn->variant.bfp_compare.dst);
913 insn->variant.bfp_compare.op1_hi =
914 lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi);
915 insn->variant.bfp_compare.op2_hi =
916 lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi);
917 if (insn->size == 16) {
918 insn->variant.bfp_compare.op1_lo =
919 lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo);
920 insn->variant.bfp_compare.op2_lo =
921 lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo);
922 }
sewardj2019a972011-03-07 16:04:07 +0000923 break;
924
florian9fcff4c2012-09-10 03:09:04 +0000925 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +0000926 insn->variant.bfp_convert.dst_hi =
927 lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi);
928 if (insn->variant.bfp_convert.dst_lo != INVALID_HREG)
929 insn->variant.bfp_convert.dst_lo =
930 lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo);
931 insn->variant.bfp_convert.op_hi =
932 lookupHRegRemap(m, insn->variant.bfp_convert.op_hi);
933 if (insn->variant.bfp_convert.op_lo != INVALID_HREG)
934 insn->variant.bfp_convert.op_lo =
935 lookupHRegRemap(m, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +0000936 break;
937
sewardja52e37e2011-04-28 18:48:06 +0000938 case S390_INSN_MFENCE:
florianad43b3a2012-02-20 15:01:14 +0000939 case S390_INSN_GZERO:
940 case S390_INSN_GADD:
sewardja52e37e2011-04-28 18:48:06 +0000941 break;
942
florian125e20d2012-10-07 15:42:37 +0000943 case S390_INSN_SET_FPC_BFPRM:
944 insn->variant.set_fpc_bfprm.mode =
945 lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +0000946 break;
947
florianc8e4f562012-10-27 16:19:31 +0000948 case S390_INSN_SET_FPC_DFPRM:
949 insn->variant.set_fpc_dfprm.mode =
950 lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode);
951 break;
952
florian8844a632012-04-13 04:04:06 +0000953 case S390_INSN_EVCHECK:
954 s390_amode_map_regs(m, insn->variant.evcheck.counter);
955 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
956 break;
957
958 case S390_INSN_PROFINC:
959 /* Does not use any register visible to the register allocator */
960 break;
961
962 case S390_INSN_XDIRECT:
963 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
964 break;
965
966 case S390_INSN_XINDIR:
967 s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
968 insn->variant.xindir.dst =
969 lookupHRegRemap(m, insn->variant.xindir.dst);
970 break;
971
972 case S390_INSN_XASSISTED:
973 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
974 insn->variant.xassisted.dst =
975 lookupHRegRemap(m, insn->variant.xassisted.dst);
976 break;
977
sewardj2019a972011-03-07 16:04:07 +0000978 default:
979 vpanic("s390_insn_map_regs");
980 }
981}
982
983
984/* Return True, if INSN is a move between two registers of the same class.
985 In that case assign the source and destination registers to SRC and DST,
986 respectively. */
florianb4df7682011-07-05 02:09:01 +0000987static Bool
sewardj2019a972011-03-07 16:04:07 +0000988s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
989{
990 if (insn->tag == S390_INSN_MOVE &&
991 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
992 *src = insn->variant.move.src;
993 *dst = insn->variant.move.dst;
994 return True;
995 }
996
997 return False;
998}
999
1000
sewardj2019a972011-03-07 16:04:07 +00001001/*------------------------------------------------------------*/
1002/*--- Functions to emit a sequence of bytes ---*/
1003/*------------------------------------------------------------*/
1004
sewardj2019a972011-03-07 16:04:07 +00001005static __inline__ UChar *
1006emit_2bytes(UChar *p, ULong val)
1007{
1008 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1009}
1010
1011
1012static __inline__ UChar *
1013emit_4bytes(UChar *p, ULong val)
1014{
1015 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1016}
1017
1018
1019static __inline__ UChar *
1020emit_6bytes(UChar *p, ULong val)
1021{
1022 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1023}
1024
1025
1026/*------------------------------------------------------------*/
1027/*--- Functions to emit various instruction formats ---*/
1028/*------------------------------------------------------------*/
1029
sewardj2019a972011-03-07 16:04:07 +00001030static UChar *
1031emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1032{
1033 ULong the_insn = op;
1034
1035 the_insn |= ((ULong)r1) << 20;
1036 the_insn |= ((ULong)i2) << 0;
1037
1038 return emit_4bytes(p, the_insn);
1039}
1040
1041
1042static UChar *
1043emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1044{
1045 ULong the_insn = op;
1046
1047 the_insn |= ((ULong)r1) << 36;
1048 the_insn |= ((ULong)i2) << 0;
1049
1050 return emit_6bytes(p, the_insn);
1051}
1052
1053
1054static UChar *
1055emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1056{
1057 ULong the_insn = op;
1058
1059 the_insn |= ((ULong)r1) << 4;
1060 the_insn |= ((ULong)r2) << 0;
1061
1062 return emit_2bytes(p, the_insn);
1063}
1064
1065
1066static UChar *
1067emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1068{
1069 ULong the_insn = op;
1070
1071 the_insn |= ((ULong)r1) << 4;
1072 the_insn |= ((ULong)r2) << 0;
1073
1074 return emit_4bytes(p, the_insn);
1075}
1076
1077
1078static UChar *
1079emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1080{
1081 ULong the_insn = op;
1082
1083 the_insn |= ((ULong)r1) << 12;
1084 the_insn |= ((ULong)r3) << 4;
1085 the_insn |= ((ULong)r2) << 0;
1086
1087 return emit_4bytes(p, the_insn);
1088}
1089
1090
1091static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00001092emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
1093{
1094 ULong the_insn = op;
1095
1096 the_insn |= ((ULong)m3) << 12;
1097 the_insn |= ((ULong)m4) << 8;
1098 the_insn |= ((ULong)r1) << 4;
1099 the_insn |= ((ULong)r2) << 0;
1100
1101 return emit_4bytes(p, the_insn);
1102}
1103
1104
1105static UChar *
sewardj2019a972011-03-07 16:04:07 +00001106emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1107{
1108 ULong the_insn = op;
1109
1110 the_insn |= ((ULong)r3) << 12;
1111 the_insn |= ((ULong)r1) << 4;
1112 the_insn |= ((ULong)r2) << 0;
1113
1114 return emit_4bytes(p, the_insn);
1115}
1116
1117
1118static UChar *
1119emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1120{
1121 ULong the_insn = op;
1122
1123 the_insn |= ((ULong)r1) << 20;
1124 the_insn |= ((ULong)r3) << 16;
1125 the_insn |= ((ULong)b2) << 12;
1126 the_insn |= ((ULong)d2) << 0;
1127
1128 return emit_4bytes(p, the_insn);
1129}
1130
1131
1132static UChar *
1133emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1134{
1135 ULong the_insn = op;
1136
1137 the_insn |= ((ULong)r1) << 36;
1138 the_insn |= ((ULong)r3) << 32;
1139 the_insn |= ((ULong)b2) << 28;
1140 the_insn |= ((ULong)dl2) << 16;
1141 the_insn |= ((ULong)dh2) << 8;
1142
1143 return emit_6bytes(p, the_insn);
1144}
1145
1146
1147static UChar *
1148emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1149{
1150 ULong the_insn = op;
1151
1152 the_insn |= ((ULong)r1) << 20;
1153 the_insn |= ((ULong)x2) << 16;
1154 the_insn |= ((ULong)b2) << 12;
1155 the_insn |= ((ULong)d2) << 0;
1156
1157 return emit_4bytes(p, the_insn);
1158}
1159
1160
1161static UChar *
1162emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1163{
1164 ULong the_insn = op;
1165
1166 the_insn |= ((ULong)r1) << 36;
1167 the_insn |= ((ULong)x2) << 32;
1168 the_insn |= ((ULong)b2) << 28;
1169 the_insn |= ((ULong)dl2) << 16;
1170 the_insn |= ((ULong)dh2) << 8;
1171
1172 return emit_6bytes(p, the_insn);
1173}
1174
1175
1176static UChar *
1177emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1178{
1179 ULong the_insn = op;
1180
1181 the_insn |= ((ULong)b2) << 12;
1182 the_insn |= ((ULong)d2) << 0;
1183
1184 return emit_4bytes(p, the_insn);
1185}
1186
1187
florianad43b3a2012-02-20 15:01:14 +00001188static UChar *
1189emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1190{
1191 ULong the_insn = op;
1192
1193 the_insn |= ((ULong)i2) << 32;
1194 the_insn |= ((ULong)b1) << 28;
1195 the_insn |= ((ULong)dl1) << 16;
1196 the_insn |= ((ULong)dh1) << 8;
1197
1198 return emit_6bytes(p, the_insn);
1199}
1200
1201
1202static UChar *
1203emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1204{
1205 ULong the_insn = op;
1206
1207 the_insn |= ((ULong)l) << 32;
1208 the_insn |= ((ULong)b1) << 28;
1209 the_insn |= ((ULong)d1) << 16;
1210 the_insn |= ((ULong)b2) << 12;
1211 the_insn |= ((ULong)d2) << 0;
1212
1213 return emit_6bytes(p, the_insn);
1214}
1215
1216
sewardj2019a972011-03-07 16:04:07 +00001217/*------------------------------------------------------------*/
1218/*--- Functions to emit particular instructions ---*/
1219/*------------------------------------------------------------*/
1220
sewardj9d31dfd2011-03-15 12:36:44 +00001221static UChar *
sewardj2019a972011-03-07 16:04:07 +00001222s390_emit_AR(UChar *p, UChar r1, UChar r2)
1223{
sewardj7ee97522011-05-09 21:45:04 +00001224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001225 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1226
1227 return emit_RR(p, 0x1a00, r1, r2);
1228}
1229
1230
sewardj9d31dfd2011-03-15 12:36:44 +00001231static UChar *
sewardj2019a972011-03-07 16:04:07 +00001232s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1233{
sewardj7ee97522011-05-09 21:45:04 +00001234 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001235 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1236
1237 return emit_RRE(p, 0xb9080000, r1, r2);
1238}
1239
1240
sewardj9d31dfd2011-03-15 12:36:44 +00001241static UChar *
sewardj2019a972011-03-07 16:04:07 +00001242s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1243{
sewardj7ee97522011-05-09 21:45:04 +00001244 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001245 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1246
1247 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1248}
1249
1250
sewardj9d31dfd2011-03-15 12:36:44 +00001251static UChar *
sewardj2019a972011-03-07 16:04:07 +00001252s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1253{
sewardj652b56a2011-04-13 15:38:17 +00001254 vassert(s390_host_has_ldisp);
1255
sewardj7ee97522011-05-09 21:45:04 +00001256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001257 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1258
1259 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1260}
1261
1262
sewardj9d31dfd2011-03-15 12:36:44 +00001263static UChar *
sewardj2019a972011-03-07 16:04:07 +00001264s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1265{
sewardj652b56a2011-04-13 15:38:17 +00001266 vassert(s390_host_has_ldisp || dh2 == 0);
1267
sewardj7ee97522011-05-09 21:45:04 +00001268 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001269 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1270
1271 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1272}
1273
1274
sewardj9d31dfd2011-03-15 12:36:44 +00001275static UChar *
sewardj2019a972011-03-07 16:04:07 +00001276s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1277{
sewardj652b56a2011-04-13 15:38:17 +00001278 vassert(s390_host_has_eimm);
1279
sewardj7ee97522011-05-09 21:45:04 +00001280 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001281 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1282
1283 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1284}
1285
1286
sewardj9d31dfd2011-03-15 12:36:44 +00001287static UChar *
sewardj2019a972011-03-07 16:04:07 +00001288s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1289{
sewardj652b56a2011-04-13 15:38:17 +00001290 vassert(s390_host_has_eimm);
1291
sewardj7ee97522011-05-09 21:45:04 +00001292 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001293 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1294
1295 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1296}
1297
1298
sewardj9d31dfd2011-03-15 12:36:44 +00001299static UChar *
sewardj2019a972011-03-07 16:04:07 +00001300s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1301{
sewardj7ee97522011-05-09 21:45:04 +00001302 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001303 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1304
1305 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1306}
1307
1308
sewardj9d31dfd2011-03-15 12:36:44 +00001309static UChar *
sewardj2019a972011-03-07 16:04:07 +00001310s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1311{
sewardj652b56a2011-04-13 15:38:17 +00001312 vassert(s390_host_has_ldisp);
1313
sewardj7ee97522011-05-09 21:45:04 +00001314 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001315 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1316
1317 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1318}
1319
1320
sewardj9d31dfd2011-03-15 12:36:44 +00001321static UChar *
sewardj2019a972011-03-07 16:04:07 +00001322s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1323{
sewardj7ee97522011-05-09 21:45:04 +00001324 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001325 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1326
1327 return emit_RI(p, 0xa70a0000, r1, i2);
1328}
1329
1330
sewardj9d31dfd2011-03-15 12:36:44 +00001331static UChar *
sewardj2019a972011-03-07 16:04:07 +00001332s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1333{
sewardj7ee97522011-05-09 21:45:04 +00001334 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001335 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1336
1337 return emit_RI(p, 0xa70b0000, r1, i2);
1338}
1339
1340
sewardj9d31dfd2011-03-15 12:36:44 +00001341static UChar *
florianad43b3a2012-02-20 15:01:14 +00001342s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1343{
1344 vassert(s390_host_has_gie);
1345
1346 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001347 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
florianad43b3a2012-02-20 15:01:14 +00001348
1349 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
1350}
1351
1352
1353static UChar *
florian0e047d62012-04-21 16:06:04 +00001354s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1355{
1356 vassert(s390_host_has_gie);
1357
1358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001359 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
florian0e047d62012-04-21 16:06:04 +00001360
1361 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
1362}
1363
1364
1365static UChar *
sewardj2019a972011-03-07 16:04:07 +00001366s390_emit_NR(UChar *p, UChar r1, UChar r2)
1367{
sewardj7ee97522011-05-09 21:45:04 +00001368 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001369 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1370
1371 return emit_RR(p, 0x1400, r1, r2);
1372}
1373
1374
sewardj9d31dfd2011-03-15 12:36:44 +00001375static UChar *
sewardj2019a972011-03-07 16:04:07 +00001376s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1377{
sewardj7ee97522011-05-09 21:45:04 +00001378 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001379 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1380
1381 return emit_RRE(p, 0xb9800000, r1, r2);
1382}
1383
1384
sewardj9d31dfd2011-03-15 12:36:44 +00001385static UChar *
sewardj2019a972011-03-07 16:04:07 +00001386s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1387{
sewardj7ee97522011-05-09 21:45:04 +00001388 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001389 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1390
1391 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1392}
1393
1394
sewardj9d31dfd2011-03-15 12:36:44 +00001395static UChar *
sewardj2019a972011-03-07 16:04:07 +00001396s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1397{
sewardj652b56a2011-04-13 15:38:17 +00001398 vassert(s390_host_has_ldisp);
1399
sewardj7ee97522011-05-09 21:45:04 +00001400 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001401 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1402
1403 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1404}
1405
1406
sewardj9d31dfd2011-03-15 12:36:44 +00001407static UChar *
sewardj2019a972011-03-07 16:04:07 +00001408s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1409{
sewardj652b56a2011-04-13 15:38:17 +00001410 vassert(s390_host_has_ldisp || dh2 == 0);
1411
sewardj7ee97522011-05-09 21:45:04 +00001412 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001413 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1414
1415 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1416}
1417
1418
sewardj9d31dfd2011-03-15 12:36:44 +00001419static UChar *
sewardj2019a972011-03-07 16:04:07 +00001420s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1421{
sewardj652b56a2011-04-13 15:38:17 +00001422 vassert(s390_host_has_eimm);
1423
sewardj7ee97522011-05-09 21:45:04 +00001424 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001425 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1426
1427 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1428}
1429
1430
sewardj9d31dfd2011-03-15 12:36:44 +00001431static UChar *
sewardj2019a972011-03-07 16:04:07 +00001432s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1433{
sewardj652b56a2011-04-13 15:38:17 +00001434 vassert(s390_host_has_eimm);
1435
sewardj7ee97522011-05-09 21:45:04 +00001436 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001437 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1438
1439 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1440}
1441
1442
sewardj9d31dfd2011-03-15 12:36:44 +00001443static UChar *
sewardj2019a972011-03-07 16:04:07 +00001444s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1445{
sewardj7ee97522011-05-09 21:45:04 +00001446 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001447 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1448
1449 return emit_RI(p, 0xa5070000, r1, i2);
1450}
1451
1452
sewardj9d31dfd2011-03-15 12:36:44 +00001453static UChar *
sewardj2019a972011-03-07 16:04:07 +00001454s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1455{
sewardj7ee97522011-05-09 21:45:04 +00001456 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001457 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1458
1459 return emit_RR(p, 0x0d00, r1, r2);
1460}
1461
1462
sewardj9d31dfd2011-03-15 12:36:44 +00001463static UChar *
sewardj2019a972011-03-07 16:04:07 +00001464s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1465{
sewardj7ee97522011-05-09 21:45:04 +00001466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001467 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1468
1469 return emit_RR(p, 0x0700, r1, r2);
1470}
1471
1472
sewardj9d31dfd2011-03-15 12:36:44 +00001473static UChar *
sewardj2019a972011-03-07 16:04:07 +00001474s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1475{
sewardj7ee97522011-05-09 21:45:04 +00001476 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001477 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1478
1479 return emit_RI(p, 0xa7040000, r1, i2);
1480}
1481
1482
sewardj9d31dfd2011-03-15 12:36:44 +00001483static UChar *
florian8844a632012-04-13 04:04:06 +00001484s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
1485{
1486 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1487 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
1488
1489 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
1490}
1491
1492
1493static UChar *
sewardj2019a972011-03-07 16:04:07 +00001494s390_emit_CR(UChar *p, UChar r1, UChar r2)
1495{
sewardj7ee97522011-05-09 21:45:04 +00001496 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001497 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1498
1499 return emit_RR(p, 0x1900, r1, r2);
1500}
1501
1502
sewardj9d31dfd2011-03-15 12:36:44 +00001503static UChar *
sewardj2019a972011-03-07 16:04:07 +00001504s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1505{
sewardj7ee97522011-05-09 21:45:04 +00001506 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001507 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1508
1509 return emit_RRE(p, 0xb9200000, r1, r2);
1510}
1511
1512
sewardj9d31dfd2011-03-15 12:36:44 +00001513static UChar *
sewardj2019a972011-03-07 16:04:07 +00001514s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1515{
sewardj7ee97522011-05-09 21:45:04 +00001516 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001517 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1518
1519 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1520}
1521
1522
sewardj9d31dfd2011-03-15 12:36:44 +00001523static UChar *
sewardj2019a972011-03-07 16:04:07 +00001524s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1525{
sewardj652b56a2011-04-13 15:38:17 +00001526 vassert(s390_host_has_ldisp);
1527
sewardj7ee97522011-05-09 21:45:04 +00001528 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001529 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1530
1531 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1532}
1533
1534
sewardj9d31dfd2011-03-15 12:36:44 +00001535static UChar *
sewardj2019a972011-03-07 16:04:07 +00001536s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1537{
sewardj652b56a2011-04-13 15:38:17 +00001538 vassert(s390_host_has_ldisp || dh2 == 0);
1539
sewardj7ee97522011-05-09 21:45:04 +00001540 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001541 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1542
1543 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1544}
1545
1546
sewardj9d31dfd2011-03-15 12:36:44 +00001547static UChar *
sewardj2019a972011-03-07 16:04:07 +00001548s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1549{
sewardj652b56a2011-04-13 15:38:17 +00001550 vassert(s390_host_has_eimm);
1551
sewardj7ee97522011-05-09 21:45:04 +00001552 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001553 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1554
1555 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1556}
1557
1558
sewardj9d31dfd2011-03-15 12:36:44 +00001559static UChar *
florian07d34552012-05-26 01:59:21 +00001560s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
1561{
1562 vassert(s390_host_has_eimm);
1563
1564 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1565 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
1566
1567 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
1568}
1569
1570
1571static UChar *
sewardj2019a972011-03-07 16:04:07 +00001572s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1573{
sewardj7ee97522011-05-09 21:45:04 +00001574 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001575 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1576
1577 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1578}
1579
1580
sewardj9d31dfd2011-03-15 12:36:44 +00001581static UChar *
sewardj2019a972011-03-07 16:04:07 +00001582s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1583{
sewardj652b56a2011-04-13 15:38:17 +00001584 vassert(s390_host_has_ldisp);
1585
sewardj7ee97522011-05-09 21:45:04 +00001586 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001587 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1588
1589 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1590}
1591
1592
sewardj9d31dfd2011-03-15 12:36:44 +00001593static UChar *
sewardj2019a972011-03-07 16:04:07 +00001594s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1595{
sewardj652b56a2011-04-13 15:38:17 +00001596 vassert(s390_host_has_ldisp || dh2 == 0);
1597
sewardj7ee97522011-05-09 21:45:04 +00001598 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001599 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1600
1601 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1602}
1603
1604
sewardj9d31dfd2011-03-15 12:36:44 +00001605static UChar *
florian448cbba2012-06-06 02:26:01 +00001606s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1607{
1608 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1609 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
1610
1611 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
1612}
1613
1614
1615static UChar *
1616s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1617{
1618 vassert(s390_host_has_ldisp);
1619
1620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1621 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
1622
1623 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
1624}
1625
1626
1627static UChar *
1628s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1629{
1630 vassert(s390_host_has_ldisp || dh2 == 0);
1631
1632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1633 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
1634
1635 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
1636}
1637
1638
1639static UChar *
sewardj2019a972011-03-07 16:04:07 +00001640s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1641{
sewardj7ee97522011-05-09 21:45:04 +00001642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001643 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1644
1645 return emit_RR(p, 0x1500, r1, r2);
1646}
1647
1648
sewardj9d31dfd2011-03-15 12:36:44 +00001649static UChar *
sewardj2019a972011-03-07 16:04:07 +00001650s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1651{
sewardj7ee97522011-05-09 21:45:04 +00001652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001653 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1654
1655 return emit_RRE(p, 0xb9210000, r1, r2);
1656}
1657
1658
sewardj9d31dfd2011-03-15 12:36:44 +00001659static UChar *
sewardj2019a972011-03-07 16:04:07 +00001660s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1661{
sewardj7ee97522011-05-09 21:45:04 +00001662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001663 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1664
1665 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1666}
1667
1668
sewardj9d31dfd2011-03-15 12:36:44 +00001669static UChar *
sewardj2019a972011-03-07 16:04:07 +00001670s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1671{
sewardj652b56a2011-04-13 15:38:17 +00001672 vassert(s390_host_has_ldisp);
1673
sewardj7ee97522011-05-09 21:45:04 +00001674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001675 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1676
1677 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1678}
1679
1680
sewardj9d31dfd2011-03-15 12:36:44 +00001681static UChar *
sewardj2019a972011-03-07 16:04:07 +00001682s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1683{
sewardj652b56a2011-04-13 15:38:17 +00001684 vassert(s390_host_has_ldisp || dh2 == 0);
1685
sewardj7ee97522011-05-09 21:45:04 +00001686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001687 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1688
1689 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1690}
1691
1692
sewardj9d31dfd2011-03-15 12:36:44 +00001693static UChar *
sewardj2019a972011-03-07 16:04:07 +00001694s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1695{
sewardj652b56a2011-04-13 15:38:17 +00001696 vassert(s390_host_has_eimm);
1697
sewardj7ee97522011-05-09 21:45:04 +00001698 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001699 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1700
1701 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1702}
1703
1704
sewardj9d31dfd2011-03-15 12:36:44 +00001705static UChar *
florian07d34552012-05-26 01:59:21 +00001706s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
1707{
1708 vassert(s390_host_has_eimm);
1709
1710 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1711 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
1712
1713 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
1714}
1715
1716
1717static UChar *
sewardj2019a972011-03-07 16:04:07 +00001718s390_emit_DR(UChar *p, UChar r1, UChar r2)
1719{
sewardj7ee97522011-05-09 21:45:04 +00001720 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001721 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1722
1723 return emit_RR(p, 0x1d00, r1, r2);
1724}
1725
1726
sewardj9d31dfd2011-03-15 12:36:44 +00001727static UChar *
sewardj2019a972011-03-07 16:04:07 +00001728s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1729{
sewardj7ee97522011-05-09 21:45:04 +00001730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001731 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1732
1733 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1734}
1735
1736
sewardj9d31dfd2011-03-15 12:36:44 +00001737static UChar *
sewardj2019a972011-03-07 16:04:07 +00001738s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1739{
sewardj7ee97522011-05-09 21:45:04 +00001740 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001741 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1742
1743 return emit_RRE(p, 0xb9970000, r1, r2);
1744}
1745
1746
sewardj9d31dfd2011-03-15 12:36:44 +00001747static UChar *
sewardj2019a972011-03-07 16:04:07 +00001748s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
1749{
sewardj7ee97522011-05-09 21:45:04 +00001750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001751 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
1752
1753 return emit_RRE(p, 0xb9870000, r1, r2);
1754}
1755
1756
sewardj9d31dfd2011-03-15 12:36:44 +00001757static UChar *
sewardj2019a972011-03-07 16:04:07 +00001758s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1759{
sewardj652b56a2011-04-13 15:38:17 +00001760 vassert(s390_host_has_ldisp || dh2 == 0);
1761
sewardj7ee97522011-05-09 21:45:04 +00001762 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001763 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
1764
1765 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
1766}
1767
1768
sewardj9d31dfd2011-03-15 12:36:44 +00001769static UChar *
sewardj2019a972011-03-07 16:04:07 +00001770s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1771{
sewardj652b56a2011-04-13 15:38:17 +00001772 vassert(s390_host_has_ldisp || dh2 == 0);
1773
sewardj7ee97522011-05-09 21:45:04 +00001774 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001775 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
1776
1777 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
1778}
1779
1780
sewardj9d31dfd2011-03-15 12:36:44 +00001781static UChar *
sewardj2019a972011-03-07 16:04:07 +00001782s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
1783{
sewardj7ee97522011-05-09 21:45:04 +00001784 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001785 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
1786
1787 return emit_RRE(p, 0xb90d0000, r1, r2);
1788}
1789
1790
sewardj9d31dfd2011-03-15 12:36:44 +00001791static UChar *
sewardj2019a972011-03-07 16:04:07 +00001792s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1793{
sewardj652b56a2011-04-13 15:38:17 +00001794 vassert(s390_host_has_ldisp || dh2 == 0);
1795
sewardj7ee97522011-05-09 21:45:04 +00001796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001797 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
1798
1799 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
1800}
1801
1802
sewardj9d31dfd2011-03-15 12:36:44 +00001803static UChar *
sewardj2019a972011-03-07 16:04:07 +00001804s390_emit_XR(UChar *p, UChar r1, UChar r2)
1805{
sewardj7ee97522011-05-09 21:45:04 +00001806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001807 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
1808
1809 return emit_RR(p, 0x1700, r1, r2);
1810}
1811
1812
sewardj9d31dfd2011-03-15 12:36:44 +00001813static UChar *
sewardj2019a972011-03-07 16:04:07 +00001814s390_emit_XGR(UChar *p, UChar r1, UChar r2)
1815{
sewardj7ee97522011-05-09 21:45:04 +00001816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001817 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
1818
1819 return emit_RRE(p, 0xb9820000, r1, r2);
1820}
1821
1822
sewardj9d31dfd2011-03-15 12:36:44 +00001823static UChar *
sewardj2019a972011-03-07 16:04:07 +00001824s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1825{
sewardj7ee97522011-05-09 21:45:04 +00001826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001827 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
1828
1829 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
1830}
1831
1832
sewardj9d31dfd2011-03-15 12:36:44 +00001833static UChar *
sewardj2019a972011-03-07 16:04:07 +00001834s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1835{
sewardj652b56a2011-04-13 15:38:17 +00001836 vassert(s390_host_has_ldisp);
1837
sewardj7ee97522011-05-09 21:45:04 +00001838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001839 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
1840
1841 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
1842}
1843
1844
sewardj9d31dfd2011-03-15 12:36:44 +00001845static UChar *
sewardj2019a972011-03-07 16:04:07 +00001846s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1847{
sewardj652b56a2011-04-13 15:38:17 +00001848 vassert(s390_host_has_ldisp || dh2 == 0);
1849
sewardj7ee97522011-05-09 21:45:04 +00001850 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001851 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
1852
1853 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
1854}
1855
1856
sewardj9d31dfd2011-03-15 12:36:44 +00001857static UChar *
sewardj2019a972011-03-07 16:04:07 +00001858s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
1859{
sewardj652b56a2011-04-13 15:38:17 +00001860 vassert(s390_host_has_eimm);
1861
sewardj7ee97522011-05-09 21:45:04 +00001862 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001863 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
1864
1865 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
1866}
1867
1868
sewardj9d31dfd2011-03-15 12:36:44 +00001869static UChar *
sewardj2019a972011-03-07 16:04:07 +00001870s390_emit_XILF(UChar *p, UChar r1, UInt i2)
1871{
sewardj652b56a2011-04-13 15:38:17 +00001872 vassert(s390_host_has_eimm);
1873
sewardj7ee97522011-05-09 21:45:04 +00001874 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001875 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
1876
1877 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
1878}
1879
1880
sewardj9d31dfd2011-03-15 12:36:44 +00001881static UChar *
florianad43b3a2012-02-20 15:01:14 +00001882s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
1883{
1884 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1885 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
1886
1887 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
1888}
1889
1890
1891static UChar *
sewardj2019a972011-03-07 16:04:07 +00001892s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
1893{
sewardj652b56a2011-04-13 15:38:17 +00001894 vassert(s390_host_has_eimm);
1895
sewardj7ee97522011-05-09 21:45:04 +00001896 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001897 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
1898
1899 return emit_RRE(p, 0xb9830000, r1, r2);
1900}
1901
1902
sewardj9d31dfd2011-03-15 12:36:44 +00001903static UChar *
sewardj2019a972011-03-07 16:04:07 +00001904s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1905{
sewardj7ee97522011-05-09 21:45:04 +00001906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001907 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
1908
1909 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
1910}
1911
1912
sewardj9d31dfd2011-03-15 12:36:44 +00001913static UChar *
sewardj2019a972011-03-07 16:04:07 +00001914s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1915{
sewardj652b56a2011-04-13 15:38:17 +00001916 vassert(s390_host_has_ldisp);
1917
sewardj7ee97522011-05-09 21:45:04 +00001918 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001919 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
1920
1921 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
1922}
1923
1924
sewardj9d31dfd2011-03-15 12:36:44 +00001925static UChar *
sewardj2019a972011-03-07 16:04:07 +00001926s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
1927{
sewardj652b56a2011-04-13 15:38:17 +00001928 vassert(s390_host_has_eimm);
1929
sewardj7ee97522011-05-09 21:45:04 +00001930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001931 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
1932
1933 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
1934}
1935
1936
sewardj9d31dfd2011-03-15 12:36:44 +00001937static UChar *
sewardj2019a972011-03-07 16:04:07 +00001938s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
1939{
sewardj7ee97522011-05-09 21:45:04 +00001940 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001941 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
1942
1943 return emit_RI(p, 0xa5000000, r1, i2);
1944}
1945
1946
sewardj9d31dfd2011-03-15 12:36:44 +00001947static UChar *
sewardj2019a972011-03-07 16:04:07 +00001948s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
1949{
sewardj7ee97522011-05-09 21:45:04 +00001950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001951 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
1952
1953 return emit_RI(p, 0xa5010000, r1, i2);
1954}
1955
1956
sewardj9d31dfd2011-03-15 12:36:44 +00001957static UChar *
sewardj2019a972011-03-07 16:04:07 +00001958s390_emit_IILF(UChar *p, UChar r1, UInt i2)
1959{
sewardj652b56a2011-04-13 15:38:17 +00001960 vassert(s390_host_has_eimm);
1961
sewardj7ee97522011-05-09 21:45:04 +00001962 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001963 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
1964
1965 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
1966}
1967
1968
sewardj9d31dfd2011-03-15 12:36:44 +00001969static UChar *
sewardj2019a972011-03-07 16:04:07 +00001970s390_emit_IILH(UChar *p, UChar r1, UShort i2)
1971{
sewardj7ee97522011-05-09 21:45:04 +00001972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001973 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
1974
1975 return emit_RI(p, 0xa5020000, r1, i2);
1976}
1977
1978
sewardj9d31dfd2011-03-15 12:36:44 +00001979static UChar *
sewardj2019a972011-03-07 16:04:07 +00001980s390_emit_IILL(UChar *p, UChar r1, UShort i2)
1981{
sewardj7ee97522011-05-09 21:45:04 +00001982 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001983 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
1984
1985 return emit_RI(p, 0xa5030000, r1, i2);
1986}
1987
1988
sewardj9d31dfd2011-03-15 12:36:44 +00001989static UChar *
sewardj2019a972011-03-07 16:04:07 +00001990s390_emit_IPM(UChar *p, UChar r1, UChar r2)
1991{
sewardj7ee97522011-05-09 21:45:04 +00001992 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001993 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
1994
1995 return emit_RRE(p, 0xb2220000, r1, r2);
1996}
1997
1998
sewardj9d31dfd2011-03-15 12:36:44 +00001999static UChar *
sewardj2019a972011-03-07 16:04:07 +00002000s390_emit_LR(UChar *p, UChar r1, UChar r2)
2001{
sewardj7ee97522011-05-09 21:45:04 +00002002 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002003 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
2004
2005 return emit_RR(p, 0x1800, r1, r2);
2006}
2007
2008
sewardj9d31dfd2011-03-15 12:36:44 +00002009static UChar *
sewardj2019a972011-03-07 16:04:07 +00002010s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2011{
sewardj7ee97522011-05-09 21:45:04 +00002012 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002013 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2014
2015 return emit_RRE(p, 0xb9040000, r1, r2);
2016}
2017
2018
sewardj9d31dfd2011-03-15 12:36:44 +00002019static UChar *
sewardj2019a972011-03-07 16:04:07 +00002020s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2021{
sewardj7ee97522011-05-09 21:45:04 +00002022 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002023 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2024
2025 return emit_RRE(p, 0xb9140000, r1, r2);
2026}
2027
2028
sewardj9d31dfd2011-03-15 12:36:44 +00002029static UChar *
sewardj2019a972011-03-07 16:04:07 +00002030s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2031{
sewardj7ee97522011-05-09 21:45:04 +00002032 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002033 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2034
2035 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2036}
2037
2038
sewardj9d31dfd2011-03-15 12:36:44 +00002039static UChar *
sewardj2019a972011-03-07 16:04:07 +00002040s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2041{
sewardj652b56a2011-04-13 15:38:17 +00002042 vassert(s390_host_has_ldisp);
2043
sewardj7ee97522011-05-09 21:45:04 +00002044 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002045 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2046
2047 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2048}
2049
2050
sewardj9d31dfd2011-03-15 12:36:44 +00002051static UChar *
sewardj2019a972011-03-07 16:04:07 +00002052s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2053{
sewardj652b56a2011-04-13 15:38:17 +00002054 vassert(s390_host_has_ldisp || dh2 == 0);
2055
sewardj7ee97522011-05-09 21:45:04 +00002056 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002057 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2058
2059 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2060}
2061
2062
sewardj9d31dfd2011-03-15 12:36:44 +00002063static UChar *
sewardj2019a972011-03-07 16:04:07 +00002064s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2065{
sewardj652b56a2011-04-13 15:38:17 +00002066 vassert(s390_host_has_ldisp || dh2 == 0);
2067
sewardj7ee97522011-05-09 21:45:04 +00002068 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002069 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2070
2071 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2072}
2073
2074
sewardj9d31dfd2011-03-15 12:36:44 +00002075static UChar *
sewardj2019a972011-03-07 16:04:07 +00002076s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2077{
sewardj652b56a2011-04-13 15:38:17 +00002078 vassert(s390_host_has_eimm);
2079
sewardj7ee97522011-05-09 21:45:04 +00002080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002081 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2082
2083 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2084}
2085
2086
sewardj9d31dfd2011-03-15 12:36:44 +00002087static UChar *
sewardj2019a972011-03-07 16:04:07 +00002088s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2089{
sewardj7ee97522011-05-09 21:45:04 +00002090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002091 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2092
2093 return emit_RR(p, 0x1200, r1, r2);
2094}
2095
2096
sewardj9d31dfd2011-03-15 12:36:44 +00002097static UChar *
sewardj2019a972011-03-07 16:04:07 +00002098s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2099{
sewardj7ee97522011-05-09 21:45:04 +00002100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002101 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2102
2103 return emit_RRE(p, 0xb9020000, r1, r2);
2104}
2105
2106
sewardj9d31dfd2011-03-15 12:36:44 +00002107static UChar *
sewardj2019a972011-03-07 16:04:07 +00002108s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2109{
sewardj652b56a2011-04-13 15:38:17 +00002110 vassert(s390_host_has_eimm);
2111
sewardj7ee97522011-05-09 21:45:04 +00002112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002113 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2114
2115 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2116}
2117
2118
sewardj9d31dfd2011-03-15 12:36:44 +00002119static UChar *
sewardj2019a972011-03-07 16:04:07 +00002120s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2121{
sewardj652b56a2011-04-13 15:38:17 +00002122 vassert(s390_host_has_eimm);
2123
sewardj7ee97522011-05-09 21:45:04 +00002124 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002125 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2126
2127 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2128}
2129
2130
sewardj9d31dfd2011-03-15 12:36:44 +00002131static UChar *
sewardj2019a972011-03-07 16:04:07 +00002132s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2133{
sewardj652b56a2011-04-13 15:38:17 +00002134 vassert(s390_host_has_eimm);
2135
sewardj7ee97522011-05-09 21:45:04 +00002136 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002137 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2138
2139 return emit_RRE(p, 0xb9260000, r1, r2);
2140}
2141
2142
sewardj9d31dfd2011-03-15 12:36:44 +00002143static UChar *
sewardj2019a972011-03-07 16:04:07 +00002144s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2145{
sewardj652b56a2011-04-13 15:38:17 +00002146 vassert(s390_host_has_eimm);
2147
sewardj7ee97522011-05-09 21:45:04 +00002148 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002149 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2150
2151 return emit_RRE(p, 0xb9060000, r1, r2);
2152}
2153
2154
sewardj9d31dfd2011-03-15 12:36:44 +00002155static UChar *
sewardj2019a972011-03-07 16:04:07 +00002156s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2157{
sewardj652b56a2011-04-13 15:38:17 +00002158 vassert(s390_host_has_ldisp);
2159
sewardj7ee97522011-05-09 21:45:04 +00002160 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002161 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2162
2163 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2164}
2165
2166
sewardj9d31dfd2011-03-15 12:36:44 +00002167static UChar *
sewardj2019a972011-03-07 16:04:07 +00002168s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2169{
sewardj652b56a2011-04-13 15:38:17 +00002170 vassert(s390_host_has_ldisp);
2171
sewardj7ee97522011-05-09 21:45:04 +00002172 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002173 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2174
2175 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2176}
2177
2178
sewardj9d31dfd2011-03-15 12:36:44 +00002179static UChar *
sewardj2019a972011-03-07 16:04:07 +00002180s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2181{
sewardj7ee97522011-05-09 21:45:04 +00002182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002183 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2184
2185 return emit_RR(p, 0x1300, r1, r2);
2186}
2187
2188
sewardj9d31dfd2011-03-15 12:36:44 +00002189static UChar *
sewardj2019a972011-03-07 16:04:07 +00002190s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2191{
sewardj7ee97522011-05-09 21:45:04 +00002192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002193 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2194
2195 return emit_RRE(p, 0xb9030000, r1, r2);
2196}
2197
2198
sewardj9d31dfd2011-03-15 12:36:44 +00002199static UChar *
sewardj2019a972011-03-07 16:04:07 +00002200s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2201{
sewardj652b56a2011-04-13 15:38:17 +00002202 vassert(s390_host_has_eimm);
2203
sewardj7ee97522011-05-09 21:45:04 +00002204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002205 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2206
2207 return emit_RRE(p, 0xb9270000, r1, r2);
2208}
2209
2210
sewardj9d31dfd2011-03-15 12:36:44 +00002211static UChar *
sewardj2019a972011-03-07 16:04:07 +00002212s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2213{
sewardj652b56a2011-04-13 15:38:17 +00002214 vassert(s390_host_has_eimm);
2215
sewardj7ee97522011-05-09 21:45:04 +00002216 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002217 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2218
2219 return emit_RRE(p, 0xb9070000, r1, r2);
2220}
2221
2222
sewardj9d31dfd2011-03-15 12:36:44 +00002223static UChar *
sewardj2019a972011-03-07 16:04:07 +00002224s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2225{
sewardj7ee97522011-05-09 21:45:04 +00002226 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002227 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2228
2229 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2230}
2231
2232
sewardj9d31dfd2011-03-15 12:36:44 +00002233static UChar *
sewardj2019a972011-03-07 16:04:07 +00002234s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2235{
sewardj652b56a2011-04-13 15:38:17 +00002236 vassert(s390_host_has_ldisp);
2237
sewardj7ee97522011-05-09 21:45:04 +00002238 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002239 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2240
2241 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2242}
2243
2244
sewardj9d31dfd2011-03-15 12:36:44 +00002245static UChar *
sewardj2019a972011-03-07 16:04:07 +00002246s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2247{
sewardj652b56a2011-04-13 15:38:17 +00002248 vassert(s390_host_has_ldisp || dh2 == 0);
2249
sewardj7ee97522011-05-09 21:45:04 +00002250 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002251 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2252
2253 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2254}
2255
2256
sewardj9d31dfd2011-03-15 12:36:44 +00002257static UChar *
sewardj2019a972011-03-07 16:04:07 +00002258s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2259{
sewardj7ee97522011-05-09 21:45:04 +00002260 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002261 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2262
2263 return emit_RI(p, 0xa7080000, r1, i2);
2264}
2265
2266
sewardj9d31dfd2011-03-15 12:36:44 +00002267static UChar *
sewardj2019a972011-03-07 16:04:07 +00002268s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2269{
sewardj7ee97522011-05-09 21:45:04 +00002270 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002271 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2272
2273 return emit_RI(p, 0xa7090000, r1, i2);
2274}
2275
2276
sewardj9d31dfd2011-03-15 12:36:44 +00002277static UChar *
sewardj2019a972011-03-07 16:04:07 +00002278s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2279{
sewardj7ee97522011-05-09 21:45:04 +00002280 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002281 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2282
2283 return emit_RRE(p, 0xb9160000, r1, r2);
2284}
2285
2286
sewardj9d31dfd2011-03-15 12:36:44 +00002287static UChar *
sewardj2019a972011-03-07 16:04:07 +00002288s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2289{
sewardj652b56a2011-04-13 15:38:17 +00002290 vassert(s390_host_has_ldisp || dh2 == 0);
2291
sewardj7ee97522011-05-09 21:45:04 +00002292 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002293 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2294
2295 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2296}
2297
2298
sewardj9d31dfd2011-03-15 12:36:44 +00002299static UChar *
sewardj2019a972011-03-07 16:04:07 +00002300s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2301{
sewardj652b56a2011-04-13 15:38:17 +00002302 vassert(s390_host_has_eimm);
2303
sewardj7ee97522011-05-09 21:45:04 +00002304 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002305 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2306
2307 return emit_RRE(p, 0xb9940000, r1, r2);
2308}
2309
2310
sewardj9d31dfd2011-03-15 12:36:44 +00002311static UChar *
sewardj2019a972011-03-07 16:04:07 +00002312s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2313{
sewardj652b56a2011-04-13 15:38:17 +00002314 vassert(s390_host_has_eimm);
2315
sewardj7ee97522011-05-09 21:45:04 +00002316 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002317 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2318
2319 return emit_RRE(p, 0xb9840000, r1, r2);
2320}
2321
2322
sewardj9d31dfd2011-03-15 12:36:44 +00002323static UChar *
sewardj2019a972011-03-07 16:04:07 +00002324s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2325{
sewardj652b56a2011-04-13 15:38:17 +00002326 vassert(s390_host_has_eimm);
2327
sewardj7ee97522011-05-09 21:45:04 +00002328 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002329 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2330
2331 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2332}
2333
2334
sewardj9d31dfd2011-03-15 12:36:44 +00002335static UChar *
sewardj2019a972011-03-07 16:04:07 +00002336s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2337{
sewardj652b56a2011-04-13 15:38:17 +00002338 vassert(s390_host_has_ldisp || dh2 == 0);
2339
sewardj7ee97522011-05-09 21:45:04 +00002340 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002341 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2342
2343 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2344}
2345
2346
sewardj9d31dfd2011-03-15 12:36:44 +00002347static UChar *
sewardj2019a972011-03-07 16:04:07 +00002348s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2349{
sewardj652b56a2011-04-13 15:38:17 +00002350 vassert(s390_host_has_eimm);
2351
sewardj7ee97522011-05-09 21:45:04 +00002352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002353 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2354
2355 return emit_RRE(p, 0xb9950000, r1, r2);
2356}
2357
2358
sewardj9d31dfd2011-03-15 12:36:44 +00002359static UChar *
sewardj2019a972011-03-07 16:04:07 +00002360s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2361{
sewardj652b56a2011-04-13 15:38:17 +00002362 vassert(s390_host_has_eimm);
2363
sewardj7ee97522011-05-09 21:45:04 +00002364 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002365 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2366
2367 return emit_RRE(p, 0xb9850000, r1, r2);
2368}
2369
2370
sewardj9d31dfd2011-03-15 12:36:44 +00002371static UChar *
sewardj2019a972011-03-07 16:04:07 +00002372s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2373{
sewardj652b56a2011-04-13 15:38:17 +00002374 vassert(s390_host_has_eimm);
2375
sewardj7ee97522011-05-09 21:45:04 +00002376 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002377 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2378
2379 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2380}
2381
2382
sewardj9d31dfd2011-03-15 12:36:44 +00002383static UChar *
sewardj2019a972011-03-07 16:04:07 +00002384s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2385{
sewardj652b56a2011-04-13 15:38:17 +00002386 vassert(s390_host_has_ldisp || dh2 == 0);
2387
sewardj7ee97522011-05-09 21:45:04 +00002388 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002389 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2390
2391 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2392}
2393
2394
sewardj9d31dfd2011-03-15 12:36:44 +00002395static UChar *
sewardj2019a972011-03-07 16:04:07 +00002396s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2397{
sewardj652b56a2011-04-13 15:38:17 +00002398 vassert(s390_host_has_eimm);
2399
sewardj7ee97522011-05-09 21:45:04 +00002400 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002401 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2402
2403 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2404}
2405
2406
sewardj9d31dfd2011-03-15 12:36:44 +00002407static UChar *
sewardj2019a972011-03-07 16:04:07 +00002408s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2409{
sewardj7ee97522011-05-09 21:45:04 +00002410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002411 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2412
2413 return emit_RI(p, 0xa50e0000, r1, i2);
2414}
2415
2416
sewardj9d31dfd2011-03-15 12:36:44 +00002417static UChar *
sewardj2019a972011-03-07 16:04:07 +00002418s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2419{
sewardj7ee97522011-05-09 21:45:04 +00002420 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002421 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2422
2423 return emit_RI(p, 0xa50f0000, r1, i2);
2424}
2425
2426
sewardj9d31dfd2011-03-15 12:36:44 +00002427static UChar *
sewardj2019a972011-03-07 16:04:07 +00002428s390_emit_MR(UChar *p, UChar r1, UChar r2)
2429{
sewardj7ee97522011-05-09 21:45:04 +00002430 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002431 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2432
2433 return emit_RR(p, 0x1c00, r1, r2);
2434}
2435
2436
sewardj9d31dfd2011-03-15 12:36:44 +00002437static UChar *
sewardj2019a972011-03-07 16:04:07 +00002438s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2439{
sewardj7ee97522011-05-09 21:45:04 +00002440 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002441 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2442
2443 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2444}
2445
2446
sewardj9d31dfd2011-03-15 12:36:44 +00002447static UChar *
sewardj2019a972011-03-07 16:04:07 +00002448s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2449{
sewardj652b56a2011-04-13 15:38:17 +00002450 vassert(s390_host_has_gie);
2451
sewardj7ee97522011-05-09 21:45:04 +00002452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002453 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2454
2455 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2456}
2457
2458
sewardj9d31dfd2011-03-15 12:36:44 +00002459static UChar *
sewardj2019a972011-03-07 16:04:07 +00002460s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2461{
sewardj7ee97522011-05-09 21:45:04 +00002462 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002463 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2464
2465 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2466}
2467
2468
sewardj9d31dfd2011-03-15 12:36:44 +00002469static UChar *
sewardj2019a972011-03-07 16:04:07 +00002470s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2471{
sewardj652b56a2011-04-13 15:38:17 +00002472 vassert(s390_host_has_gie);
2473
sewardj7ee97522011-05-09 21:45:04 +00002474 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002475 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2476
2477 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2478}
2479
2480
sewardj9d31dfd2011-03-15 12:36:44 +00002481static UChar *
sewardj2019a972011-03-07 16:04:07 +00002482s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2483{
sewardj7ee97522011-05-09 21:45:04 +00002484 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002485 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2486
2487 return emit_RI(p, 0xa70c0000, r1, i2);
2488}
2489
2490
sewardj9d31dfd2011-03-15 12:36:44 +00002491static UChar *
sewardj2019a972011-03-07 16:04:07 +00002492s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2493{
sewardj7ee97522011-05-09 21:45:04 +00002494 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002495 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2496
2497 return emit_RRE(p, 0xb9960000, r1, r2);
2498}
2499
2500
sewardj9d31dfd2011-03-15 12:36:44 +00002501static UChar *
sewardj2019a972011-03-07 16:04:07 +00002502s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2503{
sewardj7ee97522011-05-09 21:45:04 +00002504 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002505 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2506
2507 return emit_RRE(p, 0xb9860000, r1, r2);
2508}
2509
2510
sewardj9d31dfd2011-03-15 12:36:44 +00002511static UChar *
sewardj2019a972011-03-07 16:04:07 +00002512s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2513{
sewardj652b56a2011-04-13 15:38:17 +00002514 vassert(s390_host_has_ldisp || dh2 == 0);
2515
sewardj7ee97522011-05-09 21:45:04 +00002516 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002517 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2518
2519 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2520}
2521
2522
sewardj9d31dfd2011-03-15 12:36:44 +00002523static UChar *
sewardj2019a972011-03-07 16:04:07 +00002524s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2525{
sewardj652b56a2011-04-13 15:38:17 +00002526 vassert(s390_host_has_ldisp || dh2 == 0);
2527
sewardj7ee97522011-05-09 21:45:04 +00002528 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002529 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2530
2531 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2532}
2533
2534
sewardj9d31dfd2011-03-15 12:36:44 +00002535static UChar *
sewardj2019a972011-03-07 16:04:07 +00002536s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2537{
sewardj7ee97522011-05-09 21:45:04 +00002538 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002539 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2540
2541 return emit_RRE(p, 0xb2520000, r1, r2);
2542}
2543
2544
sewardj9d31dfd2011-03-15 12:36:44 +00002545static UChar *
sewardj2019a972011-03-07 16:04:07 +00002546s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2547{
sewardj7ee97522011-05-09 21:45:04 +00002548 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002549 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2550
2551 return emit_RRE(p, 0xb90c0000, r1, r2);
2552}
2553
2554
sewardj9d31dfd2011-03-15 12:36:44 +00002555static UChar *
sewardj2019a972011-03-07 16:04:07 +00002556s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2557{
sewardj7ee97522011-05-09 21:45:04 +00002558 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002559 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2560
2561 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2562}
2563
2564
sewardj9d31dfd2011-03-15 12:36:44 +00002565static UChar *
sewardj2019a972011-03-07 16:04:07 +00002566s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2567{
sewardj652b56a2011-04-13 15:38:17 +00002568 vassert(s390_host_has_ldisp);
2569
sewardj7ee97522011-05-09 21:45:04 +00002570 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002571 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2572
2573 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2574}
2575
2576
sewardj9d31dfd2011-03-15 12:36:44 +00002577static UChar *
sewardj2019a972011-03-07 16:04:07 +00002578s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2579{
sewardj652b56a2011-04-13 15:38:17 +00002580 vassert(s390_host_has_ldisp || dh2 == 0);
2581
sewardj7ee97522011-05-09 21:45:04 +00002582 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002583 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2584
2585 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2586}
2587
2588
sewardj9d31dfd2011-03-15 12:36:44 +00002589static UChar *
sewardj2019a972011-03-07 16:04:07 +00002590s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2591{
sewardj652b56a2011-04-13 15:38:17 +00002592 vassert(s390_host_has_gie);
2593
sewardj7ee97522011-05-09 21:45:04 +00002594 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002595 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2596
2597 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2598}
2599
2600
sewardj9d31dfd2011-03-15 12:36:44 +00002601static UChar *
sewardj2019a972011-03-07 16:04:07 +00002602s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2603{
sewardj652b56a2011-04-13 15:38:17 +00002604 vassert(s390_host_has_gie);
2605
sewardj7ee97522011-05-09 21:45:04 +00002606 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002607 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2608
2609 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2610}
2611
2612
sewardj9d31dfd2011-03-15 12:36:44 +00002613static UChar *
sewardj2019a972011-03-07 16:04:07 +00002614s390_emit_OR(UChar *p, UChar r1, UChar r2)
2615{
sewardj7ee97522011-05-09 21:45:04 +00002616 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002617 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2618
2619 return emit_RR(p, 0x1600, r1, r2);
2620}
2621
2622
sewardj9d31dfd2011-03-15 12:36:44 +00002623static UChar *
sewardj2019a972011-03-07 16:04:07 +00002624s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2625{
sewardj7ee97522011-05-09 21:45:04 +00002626 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002627 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2628
2629 return emit_RRE(p, 0xb9810000, r1, r2);
2630}
2631
2632
sewardj9d31dfd2011-03-15 12:36:44 +00002633static UChar *
sewardj2019a972011-03-07 16:04:07 +00002634s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2635{
sewardj7ee97522011-05-09 21:45:04 +00002636 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002637 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2638
2639 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2640}
2641
2642
sewardj9d31dfd2011-03-15 12:36:44 +00002643static UChar *
sewardj2019a972011-03-07 16:04:07 +00002644s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2645{
sewardj652b56a2011-04-13 15:38:17 +00002646 vassert(s390_host_has_ldisp);
2647
sewardj7ee97522011-05-09 21:45:04 +00002648 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002649 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2650
2651 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2652}
2653
2654
sewardj9d31dfd2011-03-15 12:36:44 +00002655static UChar *
sewardj2019a972011-03-07 16:04:07 +00002656s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2657{
sewardj652b56a2011-04-13 15:38:17 +00002658 vassert(s390_host_has_ldisp || dh2 == 0);
2659
sewardj7ee97522011-05-09 21:45:04 +00002660 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002661 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2662
2663 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2664}
2665
2666
sewardj9d31dfd2011-03-15 12:36:44 +00002667static UChar *
sewardj2019a972011-03-07 16:04:07 +00002668s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2669{
sewardj652b56a2011-04-13 15:38:17 +00002670 vassert(s390_host_has_eimm);
2671
sewardj7ee97522011-05-09 21:45:04 +00002672 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002673 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2674
2675 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2676}
2677
2678
sewardj9d31dfd2011-03-15 12:36:44 +00002679static UChar *
sewardj2019a972011-03-07 16:04:07 +00002680s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2681{
sewardj652b56a2011-04-13 15:38:17 +00002682 vassert(s390_host_has_eimm);
2683
sewardj7ee97522011-05-09 21:45:04 +00002684 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002685 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2686
2687 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2688}
2689
2690
sewardj9d31dfd2011-03-15 12:36:44 +00002691static UChar *
sewardj2019a972011-03-07 16:04:07 +00002692s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2693{
sewardj7ee97522011-05-09 21:45:04 +00002694 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002695 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2696
2697 return emit_RI(p, 0xa50b0000, r1, i2);
2698}
2699
2700
sewardj9d31dfd2011-03-15 12:36:44 +00002701static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002702s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002703{
sewardj7ee97522011-05-09 21:45:04 +00002704 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002705 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2706
sewardj3c49aaa2011-04-05 14:00:37 +00002707 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002708}
2709
2710
sewardj9d31dfd2011-03-15 12:36:44 +00002711static UChar *
sewardj2019a972011-03-07 16:04:07 +00002712s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2713{
sewardj652b56a2011-04-13 15:38:17 +00002714 vassert(s390_host_has_ldisp || dh2 == 0);
2715
sewardj7ee97522011-05-09 21:45:04 +00002716 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002717 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2718
2719 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2720}
2721
2722
sewardj9d31dfd2011-03-15 12:36:44 +00002723static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002724s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002725{
sewardj7ee97522011-05-09 21:45:04 +00002726 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002727 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
2728
sewardj3c49aaa2011-04-05 14:00:37 +00002729 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002730}
2731
2732
sewardj9d31dfd2011-03-15 12:36:44 +00002733static UChar *
sewardj2019a972011-03-07 16:04:07 +00002734s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2735{
sewardj652b56a2011-04-13 15:38:17 +00002736 vassert(s390_host_has_ldisp || dh2 == 0);
2737
sewardj7ee97522011-05-09 21:45:04 +00002738 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002739 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2740
2741 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2742}
2743
2744
sewardj9d31dfd2011-03-15 12:36:44 +00002745static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002746s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002747{
sewardj7ee97522011-05-09 21:45:04 +00002748 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002749 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
2750
sewardj3c49aaa2011-04-05 14:00:37 +00002751 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002752}
2753
2754
sewardj9d31dfd2011-03-15 12:36:44 +00002755static UChar *
sewardj2019a972011-03-07 16:04:07 +00002756s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2757{
sewardj652b56a2011-04-13 15:38:17 +00002758 vassert(s390_host_has_ldisp || dh2 == 0);
2759
sewardj7ee97522011-05-09 21:45:04 +00002760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002761 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
2762
2763 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
2764}
2765
2766
sewardj9d31dfd2011-03-15 12:36:44 +00002767static UChar *
sewardj2019a972011-03-07 16:04:07 +00002768s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2769{
sewardj7ee97522011-05-09 21:45:04 +00002770 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002771 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
2772
2773 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
2774}
2775
2776
sewardj9d31dfd2011-03-15 12:36:44 +00002777static UChar *
sewardj2019a972011-03-07 16:04:07 +00002778s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2779{
sewardj652b56a2011-04-13 15:38:17 +00002780 vassert(s390_host_has_ldisp);
2781
sewardj7ee97522011-05-09 21:45:04 +00002782 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002783 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
2784
2785 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
2786}
2787
2788
sewardj9d31dfd2011-03-15 12:36:44 +00002789static UChar *
sewardj2019a972011-03-07 16:04:07 +00002790s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2791{
sewardj652b56a2011-04-13 15:38:17 +00002792 vassert(s390_host_has_ldisp || dh2 == 0);
2793
sewardj7ee97522011-05-09 21:45:04 +00002794 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002795 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
2796
2797 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
2798}
2799
2800
sewardj9d31dfd2011-03-15 12:36:44 +00002801static UChar *
sewardj2019a972011-03-07 16:04:07 +00002802s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2803{
sewardj7ee97522011-05-09 21:45:04 +00002804 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002805 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
2806
2807 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
2808}
2809
2810
sewardj9d31dfd2011-03-15 12:36:44 +00002811static UChar *
sewardj2019a972011-03-07 16:04:07 +00002812s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2813{
sewardj652b56a2011-04-13 15:38:17 +00002814 vassert(s390_host_has_ldisp);
2815
sewardj7ee97522011-05-09 21:45:04 +00002816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002817 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
2818
2819 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
2820}
2821
2822
sewardj9d31dfd2011-03-15 12:36:44 +00002823static UChar *
sewardj2019a972011-03-07 16:04:07 +00002824s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2825{
sewardj7ee97522011-05-09 21:45:04 +00002826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002827 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
2828
2829 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
2830}
2831
2832
sewardj9d31dfd2011-03-15 12:36:44 +00002833static UChar *
sewardj2019a972011-03-07 16:04:07 +00002834s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2835{
sewardj652b56a2011-04-13 15:38:17 +00002836 vassert(s390_host_has_ldisp);
2837
sewardj7ee97522011-05-09 21:45:04 +00002838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002839 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
2840
2841 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
2842}
2843
2844
sewardj9d31dfd2011-03-15 12:36:44 +00002845static UChar *
sewardj2019a972011-03-07 16:04:07 +00002846s390_emit_SR(UChar *p, UChar r1, UChar r2)
2847{
sewardj7ee97522011-05-09 21:45:04 +00002848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002849 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
2850
2851 return emit_RR(p, 0x1b00, r1, r2);
2852}
2853
2854
sewardj9d31dfd2011-03-15 12:36:44 +00002855static UChar *
sewardj2019a972011-03-07 16:04:07 +00002856s390_emit_SGR(UChar *p, UChar r1, UChar r2)
2857{
sewardj7ee97522011-05-09 21:45:04 +00002858 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002859 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
2860
2861 return emit_RRE(p, 0xb9090000, r1, r2);
2862}
2863
2864
sewardj9d31dfd2011-03-15 12:36:44 +00002865static UChar *
sewardj2019a972011-03-07 16:04:07 +00002866s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2867{
sewardj7ee97522011-05-09 21:45:04 +00002868 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002869 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
2870
2871 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
2872}
2873
2874
sewardj9d31dfd2011-03-15 12:36:44 +00002875static UChar *
sewardj2019a972011-03-07 16:04:07 +00002876s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2877{
sewardj652b56a2011-04-13 15:38:17 +00002878 vassert(s390_host_has_ldisp);
2879
sewardj7ee97522011-05-09 21:45:04 +00002880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002881 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
2882
2883 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
2884}
2885
2886
sewardj9d31dfd2011-03-15 12:36:44 +00002887static UChar *
sewardj2019a972011-03-07 16:04:07 +00002888s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2889{
sewardj652b56a2011-04-13 15:38:17 +00002890 vassert(s390_host_has_ldisp || dh2 == 0);
2891
sewardj7ee97522011-05-09 21:45:04 +00002892 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002893 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
2894
2895 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
2896}
2897
2898
sewardj9d31dfd2011-03-15 12:36:44 +00002899static UChar *
sewardj2019a972011-03-07 16:04:07 +00002900s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2901{
sewardj7ee97522011-05-09 21:45:04 +00002902 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002903 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
2904
2905 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
2906}
2907
2908
sewardj9d31dfd2011-03-15 12:36:44 +00002909static UChar *
sewardj2019a972011-03-07 16:04:07 +00002910s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2911{
sewardj652b56a2011-04-13 15:38:17 +00002912 vassert(s390_host_has_ldisp);
2913
sewardj7ee97522011-05-09 21:45:04 +00002914 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002915 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
2916
2917 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
2918}
2919
2920
sewardj9d31dfd2011-03-15 12:36:44 +00002921static UChar *
sewardj2019a972011-03-07 16:04:07 +00002922s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
2923{
sewardj652b56a2011-04-13 15:38:17 +00002924 vassert(s390_host_has_eimm);
2925
sewardj7ee97522011-05-09 21:45:04 +00002926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002927 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
2928
2929 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
2930}
2931
2932
sewardj9d31dfd2011-03-15 12:36:44 +00002933static UChar *
sewardjb13a92a2011-04-13 14:44:29 +00002934s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
2935{
sewardj7ee97522011-05-09 21:45:04 +00002936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardjb13a92a2011-04-13 14:44:29 +00002937 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
2938
2939 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
2940}
2941
2942
2943static UChar *
sewardj2019a972011-03-07 16:04:07 +00002944s390_emit_LDR(UChar *p, UChar r1, UChar r2)
2945{
sewardj7ee97522011-05-09 21:45:04 +00002946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002947 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
2948
2949 return emit_RR(p, 0x2800, r1, r2);
2950}
2951
2952
sewardj9d31dfd2011-03-15 12:36:44 +00002953static UChar *
sewardj2019a972011-03-07 16:04:07 +00002954s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2955{
sewardj7ee97522011-05-09 21:45:04 +00002956 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002957 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
2958
2959 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
2960}
2961
2962
sewardj9d31dfd2011-03-15 12:36:44 +00002963static UChar *
sewardj2019a972011-03-07 16:04:07 +00002964s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2965{
sewardj7ee97522011-05-09 21:45:04 +00002966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002967 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
2968
2969 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
2970}
2971
2972
sewardj9d31dfd2011-03-15 12:36:44 +00002973static UChar *
sewardj2019a972011-03-07 16:04:07 +00002974s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2975{
sewardj652b56a2011-04-13 15:38:17 +00002976 vassert(s390_host_has_ldisp);
2977
sewardj7ee97522011-05-09 21:45:04 +00002978 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002979 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
2980
2981 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
2982}
2983
2984
sewardj9d31dfd2011-03-15 12:36:44 +00002985static UChar *
sewardj2019a972011-03-07 16:04:07 +00002986s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2987{
sewardj652b56a2011-04-13 15:38:17 +00002988 vassert(s390_host_has_ldisp);
2989
sewardj7ee97522011-05-09 21:45:04 +00002990 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002991 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
2992
2993 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
2994}
2995
2996
sewardj9d31dfd2011-03-15 12:36:44 +00002997static UChar *
sewardj2019a972011-03-07 16:04:07 +00002998s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
2999{
sewardj7ee97522011-05-09 21:45:04 +00003000 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003001 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
3002
3003 return emit_S(p, 0xb29d0000, b2, d2);
3004}
3005
3006
sewardj9d31dfd2011-03-15 12:36:44 +00003007static UChar *
sewardj2019a972011-03-07 16:04:07 +00003008s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3009{
sewardjd07b8562011-04-27 11:58:22 +00003010 vassert(s390_host_has_fgx);
3011
sewardj7ee97522011-05-09 21:45:04 +00003012 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003013 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
3014
3015 return emit_RRE(p, 0xb3c10000, r1, r2);
3016}
3017
3018
sewardj9d31dfd2011-03-15 12:36:44 +00003019static UChar *
sewardj2019a972011-03-07 16:04:07 +00003020s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3021{
sewardjd07b8562011-04-27 11:58:22 +00003022 vassert(s390_host_has_fgx);
3023
sewardj7ee97522011-05-09 21:45:04 +00003024 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003025 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3026
3027 return emit_RRE(p, 0xb3cd0000, r1, r2);
3028}
3029
3030
sewardj9d31dfd2011-03-15 12:36:44 +00003031static UChar *
sewardj2019a972011-03-07 16:04:07 +00003032s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3033{
sewardj7ee97522011-05-09 21:45:04 +00003034 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003035 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3036
3037 return emit_RRE(p, 0xb3740000, r1, r2);
3038}
3039
3040
sewardj9d31dfd2011-03-15 12:36:44 +00003041static UChar *
sewardj2019a972011-03-07 16:04:07 +00003042s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3043{
sewardj7ee97522011-05-09 21:45:04 +00003044 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003045 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3046
3047 return emit_RRE(p, 0xb3750000, r1, r2);
3048}
3049
3050
sewardj9d31dfd2011-03-15 12:36:44 +00003051static UChar *
florian6d8e26e2012-09-12 19:52:16 +00003052s390_emit_SFPC(UChar *p, UChar r1)
sewardj2019a972011-03-07 16:04:07 +00003053{
sewardj7ee97522011-05-09 21:45:04 +00003054 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003055 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3056
florian6d8e26e2012-09-12 19:52:16 +00003057 return emit_RRE(p, 0xb3840000, r1, 0);
sewardj2019a972011-03-07 16:04:07 +00003058}
3059
3060
sewardj9d31dfd2011-03-15 12:36:44 +00003061static UChar *
sewardj2019a972011-03-07 16:04:07 +00003062s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3063{
sewardj7ee97522011-05-09 21:45:04 +00003064 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003065 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3066
3067 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3068}
3069
3070
sewardj9d31dfd2011-03-15 12:36:44 +00003071static UChar *
sewardj2019a972011-03-07 16:04:07 +00003072s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3073{
sewardj7ee97522011-05-09 21:45:04 +00003074 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003075 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3076
3077 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3078}
3079
3080
sewardj9d31dfd2011-03-15 12:36:44 +00003081static UChar *
sewardj2019a972011-03-07 16:04:07 +00003082s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3083{
sewardj652b56a2011-04-13 15:38:17 +00003084 vassert(s390_host_has_ldisp);
3085
sewardj7ee97522011-05-09 21:45:04 +00003086 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003087 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3088
3089 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3090}
3091
3092
sewardj9d31dfd2011-03-15 12:36:44 +00003093static UChar *
sewardj2019a972011-03-07 16:04:07 +00003094s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3095{
sewardj652b56a2011-04-13 15:38:17 +00003096 vassert(s390_host_has_ldisp);
3097
sewardj7ee97522011-05-09 21:45:04 +00003098 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003099 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3100
3101 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3102}
3103
3104
sewardj9d31dfd2011-03-15 12:36:44 +00003105static UChar *
sewardj2019a972011-03-07 16:04:07 +00003106s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3107{
sewardj7ee97522011-05-09 21:45:04 +00003108 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003109 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3110
3111 return emit_S(p, 0xb29c0000, b2, d2);
3112}
3113
3114
sewardj9d31dfd2011-03-15 12:36:44 +00003115static UChar *
sewardj2019a972011-03-07 16:04:07 +00003116s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3117{
sewardj7ee97522011-05-09 21:45:04 +00003118 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003119 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3120
3121 return emit_RRE(p, 0xb30a0000, r1, r2);
3122}
3123
3124
sewardj9d31dfd2011-03-15 12:36:44 +00003125static UChar *
sewardj2019a972011-03-07 16:04:07 +00003126s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3127{
sewardj7ee97522011-05-09 21:45:04 +00003128 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003129 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3130
3131 return emit_RRE(p, 0xb31a0000, r1, r2);
3132}
3133
3134
sewardj9d31dfd2011-03-15 12:36:44 +00003135static UChar *
sewardj2019a972011-03-07 16:04:07 +00003136s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3137{
sewardj7ee97522011-05-09 21:45:04 +00003138 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003139 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3140
3141 return emit_RRE(p, 0xb34a0000, r1, r2);
3142}
3143
3144
sewardj9d31dfd2011-03-15 12:36:44 +00003145static UChar *
sewardj2019a972011-03-07 16:04:07 +00003146s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3147{
sewardj7ee97522011-05-09 21:45:04 +00003148 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003149 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3150
3151 return emit_RRE(p, 0xb3090000, r1, r2);
3152}
3153
3154
sewardj9d31dfd2011-03-15 12:36:44 +00003155static UChar *
sewardj2019a972011-03-07 16:04:07 +00003156s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3157{
sewardj7ee97522011-05-09 21:45:04 +00003158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003159 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3160
3161 return emit_RRE(p, 0xb3190000, r1, r2);
3162}
3163
3164
sewardj9d31dfd2011-03-15 12:36:44 +00003165static UChar *
sewardj2019a972011-03-07 16:04:07 +00003166s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3167{
sewardj7ee97522011-05-09 21:45:04 +00003168 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003169 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3170
3171 return emit_RRE(p, 0xb3490000, r1, r2);
3172}
3173
3174
sewardj9d31dfd2011-03-15 12:36:44 +00003175static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003176s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003177{
florian8c3ccaf2012-09-09 18:18:25 +00003178 vassert(m4 == 0);
3179 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003180
florian8c3ccaf2012-09-09 18:18:25 +00003181 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3182 if (m3 == 0)
3183 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3184 else
3185 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3186 "cefbra", r1, m3, r2, m4);
3187 }
3188
3189 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003190}
3191
3192
sewardj9d31dfd2011-03-15 12:36:44 +00003193static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003194s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003195{
florian8c3ccaf2012-09-09 18:18:25 +00003196 vassert(m4 == 0);
3197 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003198
florian8c3ccaf2012-09-09 18:18:25 +00003199 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3200 if (m3 == 0)
3201 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3202 else
3203 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3204 "cdfbra", r1, m3, r2, m4);
3205 }
3206
3207 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003208}
3209
3210
sewardj9d31dfd2011-03-15 12:36:44 +00003211static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003212s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003213{
florian8c3ccaf2012-09-09 18:18:25 +00003214 vassert(m4 == 0);
3215 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003216
florian8c3ccaf2012-09-09 18:18:25 +00003217 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3218 if (m3 == 0)
3219 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3220 else
3221 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3222 "cxfbra", r1, m3, r2, m4);
3223 }
3224
3225 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003226}
3227
3228
sewardj9d31dfd2011-03-15 12:36:44 +00003229static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003230s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003231{
florian8c3ccaf2012-09-09 18:18:25 +00003232 vassert(m4 == 0);
3233 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003234
florian8c3ccaf2012-09-09 18:18:25 +00003235 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3236 if (m3 == 0)
3237 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3238 else
3239 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3240 "cegbra", r1, m3, r2, m4);
3241 }
3242
3243 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003244}
3245
3246
sewardj9d31dfd2011-03-15 12:36:44 +00003247static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003248s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003249{
florian8c3ccaf2012-09-09 18:18:25 +00003250 vassert(m4 == 0);
3251 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003252
florian8c3ccaf2012-09-09 18:18:25 +00003253 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3254 if (m3 == 0)
3255 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3256 else
3257 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3258 "cdgbra", r1, m3, r2, m4);
3259 }
3260
3261 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003262}
3263
3264
sewardj9d31dfd2011-03-15 12:36:44 +00003265static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003266s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003267{
florian8c3ccaf2012-09-09 18:18:25 +00003268 vassert(m4 == 0);
3269 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003270
florian8c3ccaf2012-09-09 18:18:25 +00003271 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3272 if (m3 == 0)
3273 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3274 else
3275 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3276 "cxgbra", r1, m3, r2, m4);
3277 }
3278
3279 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003280}
3281
3282
sewardj9d31dfd2011-03-15 12:36:44 +00003283static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00003284s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3285{
florian606dbeb2012-09-09 18:12:28 +00003286 vassert(m4 == 0);
3287 vassert(s390_host_has_fpext);
3288
florian1c8f7ff2012-09-01 00:12:11 +00003289 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3290 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
3291
3292 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
3293}
3294
3295
3296static UChar *
3297s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3298{
florian606dbeb2012-09-09 18:12:28 +00003299 vassert(m4 == 0);
3300 vassert(s390_host_has_fpext);
3301
florian1c8f7ff2012-09-01 00:12:11 +00003302 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3303 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
3304
3305 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
3306}
3307
3308
3309static UChar *
3310s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3311{
florian606dbeb2012-09-09 18:12:28 +00003312 vassert(m4 == 0);
3313 vassert(s390_host_has_fpext);
3314
florian1c8f7ff2012-09-01 00:12:11 +00003315 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3316 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
3317
3318 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
3319}
3320
3321
3322static UChar *
3323s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3324{
florian606dbeb2012-09-09 18:12:28 +00003325 vassert(m4 == 0);
3326 vassert(s390_host_has_fpext);
3327
florian1c8f7ff2012-09-01 00:12:11 +00003328 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3329 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
3330
3331 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
3332}
3333
3334
3335static UChar *
3336s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3337{
florian606dbeb2012-09-09 18:12:28 +00003338 vassert(m4 == 0);
3339 vassert(s390_host_has_fpext);
3340
florian1c8f7ff2012-09-01 00:12:11 +00003341 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3342 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
3343
3344 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
3345}
3346
3347
3348static UChar *
3349s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3350{
florian606dbeb2012-09-09 18:12:28 +00003351 vassert(m4 == 0);
3352 vassert(s390_host_has_fpext);
3353
florian1c8f7ff2012-09-01 00:12:11 +00003354 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3355 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
3356
3357 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
3358}
3359
3360
3361static UChar *
3362s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3363{
florian606dbeb2012-09-09 18:12:28 +00003364 vassert(m4 == 0);
3365 vassert(s390_host_has_fpext);
3366
florian1c8f7ff2012-09-01 00:12:11 +00003367 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3368 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
3369
3370 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
3371}
3372
3373
3374static UChar *
3375s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3376{
florian606dbeb2012-09-09 18:12:28 +00003377 vassert(m4 == 0);
3378 vassert(s390_host_has_fpext);
3379
florian1c8f7ff2012-09-01 00:12:11 +00003380 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3381 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
3382
3383 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
3384}
3385
3386
3387static UChar *
3388s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3389{
florian606dbeb2012-09-09 18:12:28 +00003390 vassert(m4 == 0);
3391 vassert(s390_host_has_fpext);
3392
florian1c8f7ff2012-09-01 00:12:11 +00003393 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3394 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
3395
3396 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
3397}
3398
3399
3400static UChar *
3401s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3402{
florian606dbeb2012-09-09 18:12:28 +00003403 vassert(m4 == 0);
3404 vassert(s390_host_has_fpext);
3405
florian1c8f7ff2012-09-01 00:12:11 +00003406 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3407 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
3408
3409 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
3410}
3411
3412
3413static UChar *
3414s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3415{
florian606dbeb2012-09-09 18:12:28 +00003416 vassert(m4 == 0);
3417 vassert(s390_host_has_fpext);
3418
florian1c8f7ff2012-09-01 00:12:11 +00003419 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3420 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
3421
3422 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
3423}
3424
3425
3426static UChar *
3427s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3428{
florian606dbeb2012-09-09 18:12:28 +00003429 vassert(m4 == 0);
3430 vassert(s390_host_has_fpext);
3431
florian1c8f7ff2012-09-01 00:12:11 +00003432 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3433 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
3434
3435 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
3436}
3437
3438
3439static UChar *
sewardj2019a972011-03-07 16:04:07 +00003440s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3441{
sewardj7ee97522011-05-09 21:45:04 +00003442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003443 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3444
3445 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3446}
3447
3448
sewardj9d31dfd2011-03-15 12:36:44 +00003449static UChar *
sewardj2019a972011-03-07 16:04:07 +00003450s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3451{
sewardj7ee97522011-05-09 21:45:04 +00003452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003453 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3454
3455 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3456}
3457
3458
sewardj9d31dfd2011-03-15 12:36:44 +00003459static UChar *
sewardj2019a972011-03-07 16:04:07 +00003460s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3461{
sewardj7ee97522011-05-09 21:45:04 +00003462 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003463 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3464
3465 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3466}
3467
3468
sewardj9d31dfd2011-03-15 12:36:44 +00003469static UChar *
sewardj2019a972011-03-07 16:04:07 +00003470s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3471{
sewardj7ee97522011-05-09 21:45:04 +00003472 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003473 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3474
3475 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3476}
3477
3478
sewardj9d31dfd2011-03-15 12:36:44 +00003479static UChar *
sewardj2019a972011-03-07 16:04:07 +00003480s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3481{
sewardj7ee97522011-05-09 21:45:04 +00003482 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003483 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3484
3485 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3486}
3487
3488
sewardj9d31dfd2011-03-15 12:36:44 +00003489static UChar *
sewardj2019a972011-03-07 16:04:07 +00003490s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3491{
sewardj7ee97522011-05-09 21:45:04 +00003492 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003493 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3494
3495 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3496}
3497
3498
sewardj9d31dfd2011-03-15 12:36:44 +00003499static UChar *
sewardj2019a972011-03-07 16:04:07 +00003500s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3501{
sewardj7ee97522011-05-09 21:45:04 +00003502 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003503 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3504
3505 return emit_RRE(p, 0xb30d0000, r1, r2);
3506}
3507
3508
sewardj9d31dfd2011-03-15 12:36:44 +00003509static UChar *
sewardj2019a972011-03-07 16:04:07 +00003510s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3511{
sewardj7ee97522011-05-09 21:45:04 +00003512 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003513 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3514
3515 return emit_RRE(p, 0xb31d0000, r1, r2);
3516}
3517
3518
sewardj9d31dfd2011-03-15 12:36:44 +00003519static UChar *
sewardj2019a972011-03-07 16:04:07 +00003520s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3521{
sewardj7ee97522011-05-09 21:45:04 +00003522 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003523 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3524
3525 return emit_RRE(p, 0xb34d0000, r1, r2);
3526}
3527
3528
sewardj9d31dfd2011-03-15 12:36:44 +00003529static UChar *
sewardj2019a972011-03-07 16:04:07 +00003530s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3531{
sewardj7ee97522011-05-09 21:45:04 +00003532 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003533 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3534
3535 return emit_RRE(p, 0xb3030000, r1, r2);
3536}
3537
3538
sewardj9d31dfd2011-03-15 12:36:44 +00003539static UChar *
sewardj2019a972011-03-07 16:04:07 +00003540s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3541{
sewardj7ee97522011-05-09 21:45:04 +00003542 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003543 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3544
3545 return emit_RRE(p, 0xb3130000, r1, r2);
3546}
3547
3548
sewardj9d31dfd2011-03-15 12:36:44 +00003549static UChar *
sewardj2019a972011-03-07 16:04:07 +00003550s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3551{
sewardj7ee97522011-05-09 21:45:04 +00003552 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003553 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3554
3555 return emit_RRE(p, 0xb3430000, r1, r2);
3556}
3557
3558
sewardj9d31dfd2011-03-15 12:36:44 +00003559static UChar *
sewardj2019a972011-03-07 16:04:07 +00003560s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3561{
sewardj7ee97522011-05-09 21:45:04 +00003562 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003563 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3564
3565 return emit_RRE(p, 0xb3040000, r1, r2);
3566}
3567
3568
sewardj9d31dfd2011-03-15 12:36:44 +00003569static UChar *
sewardj2019a972011-03-07 16:04:07 +00003570s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3571{
sewardj7ee97522011-05-09 21:45:04 +00003572 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003573 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3574
3575 return emit_RRE(p, 0xb3050000, r1, r2);
3576}
3577
3578
sewardj9d31dfd2011-03-15 12:36:44 +00003579static UChar *
sewardj2019a972011-03-07 16:04:07 +00003580s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3581{
sewardj7ee97522011-05-09 21:45:04 +00003582 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003583 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3584
3585 return emit_RRE(p, 0xb3060000, r1, r2);
3586}
3587
3588
sewardj9d31dfd2011-03-15 12:36:44 +00003589static UChar *
sewardj2019a972011-03-07 16:04:07 +00003590s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3591{
sewardj7ee97522011-05-09 21:45:04 +00003592 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003593 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3594
3595 return emit_RRE(p, 0xb3010000, r1, r2);
3596}
3597
3598
sewardj9d31dfd2011-03-15 12:36:44 +00003599static UChar *
sewardj2019a972011-03-07 16:04:07 +00003600s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3601{
sewardj7ee97522011-05-09 21:45:04 +00003602 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003603 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3604
3605 return emit_RRE(p, 0xb3110000, r1, r2);
3606}
3607
3608
sewardj9d31dfd2011-03-15 12:36:44 +00003609static UChar *
sewardj2019a972011-03-07 16:04:07 +00003610s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3611{
sewardj7ee97522011-05-09 21:45:04 +00003612 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003613 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3614
3615 return emit_RRE(p, 0xb3410000, r1, r2);
3616}
3617
3618
sewardj9d31dfd2011-03-15 12:36:44 +00003619static UChar *
sewardj2019a972011-03-07 16:04:07 +00003620s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3621{
sewardj7ee97522011-05-09 21:45:04 +00003622 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003623 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3624
3625 return emit_RRE(p, 0xb3000000, r1, r2);
3626}
3627
3628
sewardj9d31dfd2011-03-15 12:36:44 +00003629static UChar *
sewardj2019a972011-03-07 16:04:07 +00003630s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3631{
sewardj7ee97522011-05-09 21:45:04 +00003632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003633 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3634
3635 return emit_RRE(p, 0xb3100000, r1, r2);
3636}
3637
3638
sewardj9d31dfd2011-03-15 12:36:44 +00003639static UChar *
sewardj2019a972011-03-07 16:04:07 +00003640s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3641{
sewardj7ee97522011-05-09 21:45:04 +00003642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003643 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3644
3645 return emit_RRE(p, 0xb3400000, r1, r2);
3646}
3647
3648
sewardj9d31dfd2011-03-15 12:36:44 +00003649static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003650s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003651{
florian8c3ccaf2012-09-09 18:18:25 +00003652 vassert(m4 == 0);
3653 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003654
florian8c3ccaf2012-09-09 18:18:25 +00003655 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3656 if (m3 == 0)
3657 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3658 else
3659 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3660 "ledbra", r1, m3, r2, m4);
3661 }
3662
3663 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003664}
3665
3666
sewardj9d31dfd2011-03-15 12:36:44 +00003667static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003668s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003669{
florian8c3ccaf2012-09-09 18:18:25 +00003670 vassert(m4 == 0);
3671 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003672
florian8c3ccaf2012-09-09 18:18:25 +00003673 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3674 if (m3 == 0)
3675 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3676 else
3677 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3678 "ldxbra", r1, m3, r2, m4);
3679 }
3680
3681 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003682}
3683
3684
sewardj9d31dfd2011-03-15 12:36:44 +00003685static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003686s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003687{
florian8c3ccaf2012-09-09 18:18:25 +00003688 vassert(m4 == 0);
3689 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003690
florian8c3ccaf2012-09-09 18:18:25 +00003691 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3692 if (m3 == 0)
3693 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3694 else
3695 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3696 "lexbra", r1, m3, r2, m4);
3697 }
3698
3699 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003700}
3701
3702
sewardj9d31dfd2011-03-15 12:36:44 +00003703static UChar *
sewardj2019a972011-03-07 16:04:07 +00003704s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3705{
sewardj7ee97522011-05-09 21:45:04 +00003706 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003707 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3708
3709 return emit_RRE(p, 0xb3170000, r1, r2);
3710}
3711
3712
sewardj9d31dfd2011-03-15 12:36:44 +00003713static UChar *
sewardj2019a972011-03-07 16:04:07 +00003714s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3715{
sewardj7ee97522011-05-09 21:45:04 +00003716 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003717 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3718
3719 return emit_RRE(p, 0xb31c0000, r1, r2);
3720}
3721
3722
sewardj9d31dfd2011-03-15 12:36:44 +00003723static UChar *
sewardj2019a972011-03-07 16:04:07 +00003724s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3725{
sewardj7ee97522011-05-09 21:45:04 +00003726 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003727 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3728
3729 return emit_RRE(p, 0xb34c0000, r1, r2);
3730}
3731
3732
sewardj9d31dfd2011-03-15 12:36:44 +00003733static UChar *
sewardj2019a972011-03-07 16:04:07 +00003734s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3735{
sewardj7ee97522011-05-09 21:45:04 +00003736 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003737 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3738
3739 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3740}
3741
3742
sewardj9d31dfd2011-03-15 12:36:44 +00003743static UChar *
sewardj2019a972011-03-07 16:04:07 +00003744s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3745{
sewardj7ee97522011-05-09 21:45:04 +00003746 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003747 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3748
3749 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3750}
3751
3752
sewardj9d31dfd2011-03-15 12:36:44 +00003753static UChar *
sewardj2019a972011-03-07 16:04:07 +00003754s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3755{
sewardj7ee97522011-05-09 21:45:04 +00003756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003757 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3758
3759 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3760}
3761
3762
sewardj9d31dfd2011-03-15 12:36:44 +00003763static UChar *
sewardj2019a972011-03-07 16:04:07 +00003764s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3765{
sewardj7ee97522011-05-09 21:45:04 +00003766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003767 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3768
3769 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
3770}
3771
3772
sewardj9d31dfd2011-03-15 12:36:44 +00003773static UChar *
sewardj2019a972011-03-07 16:04:07 +00003774s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
3775{
sewardj7ee97522011-05-09 21:45:04 +00003776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003777 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
3778
3779 return emit_RRE(p, 0xb3140000, r1, r2);
3780}
3781
3782
sewardj9d31dfd2011-03-15 12:36:44 +00003783static UChar *
sewardj2019a972011-03-07 16:04:07 +00003784s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
3785{
sewardj7ee97522011-05-09 21:45:04 +00003786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003787 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
3788
3789 return emit_RRE(p, 0xb3150000, r1, r2);
3790}
3791
3792
sewardj9d31dfd2011-03-15 12:36:44 +00003793static UChar *
sewardj2019a972011-03-07 16:04:07 +00003794s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
3795{
sewardj7ee97522011-05-09 21:45:04 +00003796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003797 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
3798
3799 return emit_RRE(p, 0xb3160000, r1, r2);
3800}
3801
3802
sewardj9d31dfd2011-03-15 12:36:44 +00003803static UChar *
sewardj2019a972011-03-07 16:04:07 +00003804s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
3805{
sewardj7ee97522011-05-09 21:45:04 +00003806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003807 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
3808
3809 return emit_RRE(p, 0xb30b0000, r1, r2);
3810}
3811
3812
sewardj9d31dfd2011-03-15 12:36:44 +00003813static UChar *
sewardj2019a972011-03-07 16:04:07 +00003814s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
3815{
sewardj7ee97522011-05-09 21:45:04 +00003816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003817 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
3818
3819 return emit_RRE(p, 0xb31b0000, r1, r2);
3820}
3821
3822
sewardj9d31dfd2011-03-15 12:36:44 +00003823static UChar *
sewardj2019a972011-03-07 16:04:07 +00003824s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
3825{
sewardj7ee97522011-05-09 21:45:04 +00003826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003827 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
3828
3829 return emit_RRE(p, 0xb34b0000, r1, r2);
3830}
3831
sewardj2019a972011-03-07 16:04:07 +00003832
3833/* Provide a symbolic name for register "R0" */
3834#define R0 0
3835
3836/* Split up a 20-bit displacement into its high and low piece
3837 suitable for passing as function arguments */
sewardjcd2b0252011-05-09 20:35:41 +00003838#define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
sewardj2019a972011-03-07 16:04:07 +00003839
3840/*---------------------------------------------------------------*/
3841/*--- Helper functions ---*/
3842/*---------------------------------------------------------------*/
3843
3844static __inline__ Bool
3845uint_fits_signed_16bit(UInt val)
3846{
3847 int v = val & 0xFFFFu;
3848
3849 /* sign extend */
3850 v = (v << 16) >> 16;
3851
3852 return val == (UInt)v;
3853}
3854
3855
3856static __inline__ Bool
3857ulong_fits_signed_16bit(ULong val)
3858{
3859 Long v = val & 0xFFFFu;
3860
3861 /* sign extend */
3862 v = (v << 48) >> 48;
3863
3864 return val == (ULong)v;
3865}
3866
3867
3868static __inline__ Bool
3869ulong_fits_signed_32bit(ULong val)
3870{
3871 Long v = val & 0xFFFFFFFFu;
3872
3873 /* sign extend */
3874 v = (v << 32) >> 32;
3875
3876 return val == (ULong)v;
3877}
3878
3879
3880static __inline__ Bool
3881ulong_fits_unsigned_32bit(ULong val)
3882{
3883 return (val & 0xFFFFFFFFu) == val;
3884}
3885
3886
3887/* Load a 64-bit immediate VAL into register REG. */
3888static UChar *
3889s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
3890{
3891 if (ulong_fits_signed_16bit(val)) {
3892 return s390_emit_LGHI(p, reg, val);
3893 }
3894
3895 if (s390_host_has_eimm) {
3896 if (ulong_fits_unsigned_32bit(val)) {
3897 return s390_emit_LLILF(p, reg, val);
3898 }
3899 if (ulong_fits_signed_32bit(val)) {
3900 /* LGFI's sign extension will recreate the correct 64-bit value */
3901 return s390_emit_LGFI(p, reg, val);
3902 }
3903 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
3904 p = s390_emit_IIHF(p, reg, val >> 32);
3905 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
3906 }
3907
3908 /* Fall back */
3909 if (ulong_fits_unsigned_32bit(val)) {
3910 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
3911 val[0:31] = 0 */
3912 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
3913 return p;
3914 }
3915
3916 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
3917 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
3918 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3919 p = s390_emit_IILL(p, reg, val & 0xFFFF);
3920
3921 return p;
3922}
3923
3924/* Load a 32-bit immediate VAL into register REG. */
3925static UChar *
3926s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
3927{
3928 if (uint_fits_signed_16bit(val)) {
3929 /* LHI's sign extension will recreate the correct 32-bit value */
3930 return s390_emit_LHI(p, reg, val);
3931 }
3932 if (s390_host_has_eimm) {
3933 return s390_emit_IILF(p, reg, val);
3934 }
3935 /* val[0:15] --> (val >> 16) & 0xFFFF
3936 val[16:31] --> val & 0xFFFF */
3937 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3938 return s390_emit_IILL(p, reg, val & 0xFFFF);
3939}
3940
3941/*------------------------------------------------------------*/
3942/*--- Wrapper functions ---*/
3943/*------------------------------------------------------------*/
3944
sewardjeae8db52011-03-24 09:01:50 +00003945/* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
sewardj2019a972011-03-07 16:04:07 +00003946static UChar *
3947s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3948{
3949 if (s390_host_has_gie) {
3950 return s390_emit_MFY(p, r1, x, b, dl, dh);
3951 }
3952
3953 /* Load from memory into R0, then MULTIPLY with R1 */
3954 p = s390_emit_LY(p, R0, x, b, dl, dh);
3955 return s390_emit_MR(p, r1, R0);
3956}
3957
sewardjeae8db52011-03-24 09:01:50 +00003958/* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
3959static UChar *
3960s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3961{
3962 if (s390_host_has_gie) {
3963 return s390_emit_MHY(p, r1, x, b, dl, dh);
3964 }
3965
3966 /* Load from memory into R0, then MULTIPLY with R1 */
3967 p = s390_emit_LHY(p, R0, x, b, dl, dh);
3968 return s390_emit_MSR(p, r1, R0);
3969}
3970
sewardj2019a972011-03-07 16:04:07 +00003971/* r1[32:63] = r1[32:63] * i2 */
3972static UChar *
3973s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
3974{
3975 if (s390_host_has_gie) {
3976 return s390_emit_MSFI(p, r1, i2);
3977 }
3978
3979 /* Load I2 into R0; then MULTIPLY R0 with R1 */
3980 p = s390_emit_load_32imm(p, R0, i2);
3981 return s390_emit_MSR(p, r1, R0);
3982}
3983
3984
3985/* r1[32:63] = r1[32:63] & i2 */
3986static UChar *
3987s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
3988{
3989 if (s390_host_has_eimm) {
3990 return s390_emit_NILF(p, r1, i2);
3991 }
3992
3993 /* Load I2 into R0; then AND R0 with R1 */
3994 p = s390_emit_load_32imm(p, R0, i2);
3995 return s390_emit_NR(p, r1, R0);
3996}
3997
3998
3999/* r1[32:63] = r1[32:63] | i2 */
4000static UChar *
4001s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
4002{
4003 if (s390_host_has_eimm) {
4004 return s390_emit_OILF(p, r1, i2);
4005 }
4006
4007 /* Load I2 into R0; then AND R0 with R1 */
4008 p = s390_emit_load_32imm(p, R0, i2);
4009 return s390_emit_OR(p, r1, R0);
4010}
4011
4012
4013/* r1[32:63] = r1[32:63] ^ i2 */
4014static UChar *
4015s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
4016{
4017 if (s390_host_has_eimm) {
4018 return s390_emit_XILF(p, r1, i2);
4019 }
4020
4021 /* Load I2 into R0; then AND R0 with R1 */
4022 p = s390_emit_load_32imm(p, R0, i2);
4023 return s390_emit_XR(p, r1, R0);
4024}
4025
4026
sewardj652b56a2011-04-13 15:38:17 +00004027/* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
4028static UChar *
4029s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
4030{
4031 vassert(s390_host_has_ldisp || dh2 == 0);
4032
4033 if (s390_host_has_ldisp) {
4034 return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
4035 }
4036
4037 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
4038 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4039 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
4040}
4041
4042
sewardj2019a972011-03-07 16:04:07 +00004043/* r1[32:63] = sign_extend(r2[56:63]) */
4044static UChar *
4045s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
4046{
4047 if (s390_host_has_eimm) {
4048 return s390_emit_LBR(p, r1, r2);
4049 }
4050
4051 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004052 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4053 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
sewardj2019a972011-03-07 16:04:07 +00004054}
4055
4056
sewardj652b56a2011-04-13 15:38:17 +00004057/* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
4058static UChar *
4059s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
4060{
4061 vassert(s390_host_has_ldisp || dh2 == 0);
4062
4063 if (s390_host_has_ldisp) {
4064 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
4065 }
4066
4067 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
4068 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4069 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4070}
4071
4072
sewardj2019a972011-03-07 16:04:07 +00004073/* r1[0:63] = sign_extend(r2[56:63]) */
4074static UChar *
4075s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
4076{
4077 if (s390_host_has_eimm) {
4078 return s390_emit_LGBR(p, r1, r2);
4079 }
4080
4081 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4082 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4083 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4084}
4085
4086
4087/* r1[32:63] = sign_extend(r2[48:63]) */
4088static UChar *
4089s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
4090{
4091 if (s390_host_has_eimm) {
4092 return s390_emit_LHR(p, r1, r2);
4093 }
4094
4095 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004096 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
4097 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
sewardj2019a972011-03-07 16:04:07 +00004098}
4099
4100
4101/* r1[0:63] = sign_extend(r2[48:63]) */
4102static UChar *
4103s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
4104{
4105 if (s390_host_has_eimm) {
4106 return s390_emit_LGHR(p, r1, r2);
4107 }
4108
4109 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4110 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
4111 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
4112}
4113
4114
4115/* r1[0:63] = sign_extend(i2) */
4116static UChar *
4117s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
4118{
4119 if (s390_host_has_eimm) {
4120 return s390_emit_LGFI(p, r1, i2);
4121 }
4122
4123 p = s390_emit_load_32imm(p, R0, i2);
4124 return s390_emit_LGFR(p, r1, R0);
4125}
4126
4127
4128/* r1[32:63] = zero_extend($r2[56:63]) */
4129static UChar *
4130s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
4131{
4132 if (s390_host_has_eimm) {
4133 return s390_emit_LLCR(p, r1, r2);
4134 }
4135
4136 p = s390_emit_LR(p, r1, r2);
4137 p = s390_emit_LHI(p, R0, 0xFF);
4138 return s390_emit_NR(p, r1, R0);
4139}
4140
4141
4142/* r1[0:63] = zero_extend($r2[56:63]) */
4143static UChar *
4144s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
4145{
4146 if (s390_host_has_eimm) {
4147 return s390_emit_LLGCR(p, r1, r2);
4148 }
4149
4150 p = s390_emit_LR(p, r1, r2);
4151 p = s390_emit_LLILL(p, R0, 0xFF);
4152 return s390_emit_NGR(p, r1, R0);
4153}
4154
4155
4156/* r1[32:63] = zero_extend(r2[48:63]) */
4157static UChar *
4158s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
4159{
4160 if (s390_host_has_eimm) {
4161 return s390_emit_LLHR(p, r1, r2);
4162 }
4163
4164 p = s390_emit_LR(p, r1, r2);
4165 p = s390_emit_LLILL(p, R0, 0xFFFF);
4166 return s390_emit_NR(p, r1, R0);
4167}
4168
4169
4170/* r1[0:63] = zero_extend(r2[48:63]) */
4171static UChar *
4172s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
4173{
4174 if (s390_host_has_eimm) {
4175 return s390_emit_LLGHR(p, r1, r2);
4176 }
4177
4178 p = s390_emit_LR(p, r1, r2);
4179 p = s390_emit_LLILL(p, R0, 0xFFFF);
4180 return s390_emit_NGR(p, r1, R0);
4181}
4182
4183
4184/* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
4185static UChar *
4186s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4187{
4188 if (s390_host_has_eimm) {
4189 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
4190 }
4191
4192 if (dh == 0) {
4193 p = s390_emit_IC(p, r1, x2, b2, dl);
4194 } else {
4195 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
4196 }
4197 p = s390_emit_LLILL(p, R0, 0xFF);
4198 return s390_emit_NR(p, r1, R0);
4199}
4200
4201
4202/* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
4203static UChar *
4204s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4205{
4206 if (s390_host_has_eimm) {
4207 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
4208 }
4209
4210 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
4211 p = s390_emit_LLILL(p, R0, 0xFFFF);
4212 return s390_emit_NR(p, r1, R0);
4213}
4214
4215
4216/* r1[0:63] = zero_extend(i2) */
4217static UChar *
4218s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
4219{
4220 if (s390_host_has_eimm) {
4221 return s390_emit_LLILF(p, r1, i2);
4222 }
4223
4224 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
4225 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
4226}
4227
4228
4229/* r1[32:63] = r1[32:63] + i2 */
4230static UChar *
4231s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
4232{
4233 if (s390_host_has_eimm) {
4234 return s390_emit_AFI(p, r1, i2);
4235 }
4236 /* Load 32 bit immediate to R0 then add */
4237 p = s390_emit_load_32imm(p, R0, i2);
4238 return s390_emit_AR(p, r1, R0);
4239}
4240
4241
4242/* r1[32:63] = r1[32:63] - i2 */
4243static UChar *
4244s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
4245{
4246 if (s390_host_has_eimm) {
4247 return s390_emit_SLFI(p, r1, i2);
4248 }
4249
4250 /* Load 32 bit immediate to R0 then subtract */
4251 p = s390_emit_load_32imm(p, R0, i2);
4252 return s390_emit_SR(p, r1, R0);
4253}
4254
4255
sewardjb13a92a2011-04-13 14:44:29 +00004256/* r1[0:63] = r1[0:63] - zero_extend(i2) */
4257static UChar *
4258s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
4259{
4260 if (s390_host_has_eimm) {
4261 return s390_emit_SLGFI(p, r1, i2);
4262 }
4263
4264 /* Load zero-extended 32 bit immediate to R0 then subtract */
4265 p = s390_emit_load_64imm(p, R0, i2);
4266 return s390_emit_SGR(p, r1, R0);
4267}
4268
4269
sewardj2019a972011-03-07 16:04:07 +00004270static UChar *
4271s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4272{
4273 if (s390_host_has_eimm) {
4274 return s390_emit_LT(p, r1, x2, b2, dl, dh);
4275 }
4276 /* Load 32 bit from memory to R0 then compare */
4277 if (dh == 0) {
4278 p = s390_emit_L(p, R0, x2, b2, dl);
4279 } else {
4280 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
4281 }
4282 return s390_emit_LTR(p, r1, R0);
4283}
4284
4285
4286static UChar *
4287s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4288{
4289 if (s390_host_has_eimm) {
4290 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
4291 }
4292 /* Load 64 bit from memory to R0 then compare */
4293 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
4294 return s390_emit_LTGR(p, r1, R0);
4295}
4296
4297
4298static UChar *
4299s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
4300{
4301 if (s390_host_has_eimm) {
4302 return s390_emit_CFI(p, r1, i2);
4303 }
4304 /* Load 32 bit immediate to R0 then compare */
4305 p = s390_emit_load_32imm(p, R0, i2);
4306 return s390_emit_CR(p, r1, R0);
4307}
4308
4309
4310static UChar *
4311s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
4312{
4313 if (s390_host_has_eimm) {
4314 return s390_emit_CLFI(p, r1, i2);
4315 }
4316 /* Load 32 bit immediate to R0 then compare */
4317 p = s390_emit_load_32imm(p, R0, i2);
4318 return s390_emit_CLR(p, r1, R0);
4319}
4320
sewardjd07b8562011-04-27 11:58:22 +00004321
4322static UChar *
4323s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
4324{
4325 if (s390_host_has_fgx) {
4326 return s390_emit_LGDR(p, r1, r2);
4327 }
4328
4329 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
4330 smaller addresses and is 8-byte aligned. Then load the GPR from that
4331 memory location/ */
4332 if (s390_host_has_ldisp) {
4333 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4334 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4335 }
4336
4337 /* No long displacement. Need to adjust SP explicitly as to avoid negative
4338 displacements. */
4339 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4340 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
4341 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4342 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4343}
4344
4345
4346static UChar *
4347s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
4348{
4349 if (s390_host_has_fgx) {
4350 return s390_emit_LDGR(p, r1, r2);
4351 }
4352
4353 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
4354 smaller addresses and is 8-byte aligned. Then load the FPR from that
4355 memory location/ */
4356 if (s390_host_has_ldisp) {
4357 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4358 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4359 }
4360
4361 /* No long displacement. Need to adjust SP explicitly as to avoid negative
4362 displacements. */
4363 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4364 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4365 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
4366 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4367}
4368
4369
sewardj2019a972011-03-07 16:04:07 +00004370/*---------------------------------------------------------------*/
4371/*--- Constructors for the various s390_insn kinds ---*/
4372/*---------------------------------------------------------------*/
4373
4374s390_insn *
4375s390_insn_load(UChar size, HReg dst, s390_amode *src)
4376{
4377 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4378
4379 insn->tag = S390_INSN_LOAD;
4380 insn->size = size;
4381 insn->variant.load.src = src;
4382 insn->variant.load.dst = dst;
4383
4384 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4385
4386 return insn;
4387}
4388
4389
4390s390_insn *
4391s390_insn_store(UChar size, s390_amode *dst, HReg src)
4392{
4393 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4394
4395 insn->tag = S390_INSN_STORE;
4396 insn->size = size;
4397 insn->variant.store.src = src;
4398 insn->variant.store.dst = dst;
4399
4400 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4401
4402 return insn;
4403}
4404
4405
4406s390_insn *
4407s390_insn_move(UChar size, HReg dst, HReg src)
4408{
4409 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4410
4411 insn->tag = S390_INSN_MOVE;
4412 insn->size = size;
4413 insn->variant.move.src = src;
4414 insn->variant.move.dst = dst;
4415
4416 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4417
4418 return insn;
4419}
4420
4421
4422s390_insn *
4423s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
4424{
4425 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4426
4427 insn->tag = S390_INSN_COND_MOVE;
4428 insn->size = size;
4429 insn->variant.cond_move.cond = cond;
4430 insn->variant.cond_move.src = src;
4431 insn->variant.cond_move.dst = dst;
4432
4433 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4434
4435 return insn;
4436}
4437
4438
4439s390_insn *
4440s390_insn_load_immediate(UChar size, HReg dst, ULong value)
4441{
4442 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4443
4444 insn->tag = S390_INSN_LOAD_IMMEDIATE;
4445 insn->size = size;
4446 insn->variant.load_immediate.dst = dst;
4447 insn->variant.load_immediate.value = value;
4448
4449 return insn;
4450}
4451
4452
4453s390_insn *
4454s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
4455{
4456 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4457
4458 insn->tag = S390_INSN_ALU;
4459 insn->size = size;
4460 insn->variant.alu.tag = tag;
4461 insn->variant.alu.dst = dst;
4462 insn->variant.alu.op2 = op2;
4463
4464 return insn;
4465}
4466
4467
4468s390_insn *
4469s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
4470 Bool signed_multiply)
4471{
4472 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4473
4474 vassert(! hregIsVirtual(dst_hi));
4475 vassert(! hregIsVirtual(dst_lo));
4476
4477 insn->tag = S390_INSN_MUL;
4478 insn->size = size;
4479 insn->variant.mul.dst_hi = dst_hi;
4480 insn->variant.mul.dst_lo = dst_lo;
4481 insn->variant.mul.op2 = op2;
4482 insn->variant.mul.signed_multiply = signed_multiply;
4483
4484 return insn;
4485}
4486
4487
4488s390_insn *
4489s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
4490 Bool signed_divide)
4491{
4492 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4493
4494 vassert(size == 4 || size == 8);
4495 vassert(! hregIsVirtual(op1_hi));
4496 vassert(! hregIsVirtual(op1_lo));
4497
4498 insn->tag = S390_INSN_DIV;
4499 insn->size = size;
4500 insn->variant.div.op1_hi = op1_hi;
4501 insn->variant.div.op1_lo = op1_lo;
4502 insn->variant.div.op2 = op2;
4503 insn->variant.div.signed_divide = signed_divide;
4504
4505 return insn;
4506}
4507
4508
4509s390_insn *
4510s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
4511{
4512 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4513
4514 vassert(size == 8);
4515 vassert(! hregIsVirtual(op1));
4516 vassert(! hregIsVirtual(rem));
4517
4518 insn->tag = S390_INSN_DIVS;
4519 insn->size = size;
4520 insn->variant.divs.rem = rem; /* remainder */
4521 insn->variant.divs.op1 = op1; /* also quotient */
4522 insn->variant.divs.op2 = op2;
4523
4524 return insn;
4525}
4526
4527
4528s390_insn *
sewardj611b06e2011-03-24 08:57:29 +00004529s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
sewardj2019a972011-03-07 16:04:07 +00004530{
4531 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4532
4533 vassert(size == 8);
sewardj611b06e2011-03-24 08:57:29 +00004534 vassert(! hregIsVirtual(num_bits));
4535 vassert(! hregIsVirtual(clobber));
sewardj2019a972011-03-07 16:04:07 +00004536
sewardj611b06e2011-03-24 08:57:29 +00004537 insn->tag = S390_INSN_CLZ;
sewardj2019a972011-03-07 16:04:07 +00004538 insn->size = size;
sewardj611b06e2011-03-24 08:57:29 +00004539 insn->variant.clz.num_bits = num_bits;
4540 insn->variant.clz.clobber = clobber;
4541 insn->variant.clz.src = src;
sewardj2019a972011-03-07 16:04:07 +00004542
4543 return insn;
4544}
4545
4546
4547s390_insn *
4548s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
4549{
4550 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4551
4552 insn->tag = S390_INSN_UNOP;
4553 insn->size = size;
4554 insn->variant.unop.tag = tag;
4555 insn->variant.unop.dst = dst;
4556 insn->variant.unop.src = opnd;
4557
4558 return insn;
4559}
4560
4561
4562s390_insn *
4563s390_insn_test(UChar size, s390_opnd_RMI src)
4564{
4565 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4566
4567 vassert(size == 4 || size == 8);
4568
4569 insn->tag = S390_INSN_TEST;
4570 insn->size = size;
4571 insn->variant.test.src = src;
4572
4573 return insn;
4574}
4575
4576
4577s390_insn *
4578s390_insn_cc2bool(HReg dst, s390_cc_t cond)
4579{
4580 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4581
4582 insn->tag = S390_INSN_CC2BOOL;
4583 insn->size = 0; /* does not matter */
4584 insn->variant.cc2bool.cond = cond;
4585 insn->variant.cc2bool.dst = dst;
4586
4587 return insn;
4588}
4589
4590
4591s390_insn *
4592s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
4593{
4594 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4595
4596 vassert(size == 4 || size == 8);
4597 vassert(op2->x == 0);
4598
4599 insn->tag = S390_INSN_CAS;
4600 insn->size = size;
4601 insn->variant.cas.op1 = op1;
4602 insn->variant.cas.op2 = op2;
4603 insn->variant.cas.op3 = op3;
4604 insn->variant.cas.old_mem = old_mem;
4605
4606 return insn;
4607}
4608
4609
4610s390_insn *
florian448cbba2012-06-06 02:26:01 +00004611s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
4612 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
4613 HReg scratch)
4614{
4615 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4616
4617 vassert(size == 4 || size == 8);
4618 vassert(op2->x == 0);
4619 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
4620
4621 insn->tag = S390_INSN_CDAS;
4622 insn->size = size;
4623 insn->variant.cdas.op1_high = op1_high;
4624 insn->variant.cdas.op1_low = op1_low;
4625 insn->variant.cdas.op2 = op2;
4626 insn->variant.cdas.op3_high = op3_high;
4627 insn->variant.cdas.op3_low = op3_low;
4628 insn->variant.cdas.old_mem_high = old_mem_high;
4629 insn->variant.cdas.old_mem_low = old_mem_low;
4630 insn->variant.cdas.scratch = scratch;
4631
4632 return insn;
4633}
4634
4635
4636s390_insn *
sewardj2019a972011-03-07 16:04:07 +00004637s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
4638 Bool signed_comparison)
4639{
4640 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4641
4642 vassert(size == 4 || size == 8);
4643
4644 insn->tag = S390_INSN_COMPARE;
4645 insn->size = size;
4646 insn->variant.compare.src1 = src1;
4647 insn->variant.compare.src2 = src2;
4648 insn->variant.compare.signed_comparison = signed_comparison;
4649
4650 return insn;
4651}
4652
4653
4654s390_insn *
sewardj2019a972011-03-07 16:04:07 +00004655s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
florian1ff47562012-10-21 02:09:51 +00004656 const HChar *name, HReg dst)
sewardj2019a972011-03-07 16:04:07 +00004657{
4658 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4659
4660 insn->tag = S390_INSN_HELPER_CALL;
4661 insn->size = 0; /* does not matter */
4662 insn->variant.helper_call.cond = cond;
4663 insn->variant.helper_call.target = target;
4664 insn->variant.helper_call.num_args = num_args;
4665 insn->variant.helper_call.name = name;
florian01ed6e72012-05-27 16:52:43 +00004666 insn->variant.helper_call.dst = dst;
sewardj2019a972011-03-07 16:04:07 +00004667
4668 return insn;
4669}
4670
4671
4672s390_insn *
4673s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
florian2c74d242012-09-12 19:38:42 +00004674 HReg op3)
sewardj2019a972011-03-07 16:04:07 +00004675{
4676 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4677
floriancc491a62012-09-10 23:44:37 +00004678 vassert(size == 4 || size == 8);
4679
sewardj2019a972011-03-07 16:04:07 +00004680 insn->tag = S390_INSN_BFP_TRIOP;
4681 insn->size = size;
4682 insn->variant.bfp_triop.tag = tag;
4683 insn->variant.bfp_triop.dst = dst;
4684 insn->variant.bfp_triop.op2 = op2;
4685 insn->variant.bfp_triop.op3 = op3;
sewardj2019a972011-03-07 16:04:07 +00004686
4687 return insn;
4688}
4689
4690
4691s390_insn *
florian2c74d242012-09-12 19:38:42 +00004692s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
sewardj2019a972011-03-07 16:04:07 +00004693{
4694 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4695
floriancc491a62012-09-10 23:44:37 +00004696 vassert(size == 4 || size == 8);
4697
sewardj2019a972011-03-07 16:04:07 +00004698 insn->tag = S390_INSN_BFP_BINOP;
4699 insn->size = size;
4700 insn->variant.bfp_binop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00004701 insn->variant.bfp_binop.dst_hi = dst;
4702 insn->variant.bfp_binop.op2_hi = op2;
4703 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
4704 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00004705
4706 return insn;
4707}
4708
4709
4710s390_insn *
florian2c74d242012-09-12 19:38:42 +00004711s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
sewardj2019a972011-03-07 16:04:07 +00004712{
4713 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4714
floriancc491a62012-09-10 23:44:37 +00004715 vassert(size == 4 || size == 8);
4716
sewardj2019a972011-03-07 16:04:07 +00004717 insn->tag = S390_INSN_BFP_UNOP;
4718 insn->size = size;
4719 insn->variant.bfp_unop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00004720 insn->variant.bfp_unop.dst_hi = dst;
4721 insn->variant.bfp_unop.op_hi = op;
4722 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
4723 insn->variant.bfp_unop.op_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00004724
4725 return insn;
4726}
4727
4728
4729s390_insn *
4730s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
4731{
4732 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4733
4734 vassert(size == 4 || size == 8);
4735
4736 insn->tag = S390_INSN_BFP_COMPARE;
4737 insn->size = size;
4738 insn->variant.bfp_compare.dst = dst;
floriancc491a62012-09-10 23:44:37 +00004739 insn->variant.bfp_compare.op1_hi = op1;
4740 insn->variant.bfp_compare.op2_hi = op2;
4741 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
4742 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00004743
4744 return insn;
4745}
4746
4747
4748s390_insn *
florian9fcff4c2012-09-10 03:09:04 +00004749s390_insn_bfp_convert(UChar size, s390_conv_t tag, HReg dst, HReg op,
florian125e20d2012-10-07 15:42:37 +00004750 s390_bfp_round_t rounding_mode)
florian9fcff4c2012-09-10 03:09:04 +00004751{
4752 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4753
floriancc491a62012-09-10 23:44:37 +00004754 vassert(size == 4 || size == 8);
4755
florian9fcff4c2012-09-10 03:09:04 +00004756 insn->tag = S390_INSN_BFP_CONVERT;
4757 insn->size = size;
4758 insn->variant.bfp_convert.tag = tag;
floriancc491a62012-09-10 23:44:37 +00004759 insn->variant.bfp_convert.dst_hi = dst;
4760 insn->variant.bfp_convert.op_hi = op;
4761 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
4762 insn->variant.bfp_convert.op_lo = INVALID_HREG;
florian9fcff4c2012-09-10 03:09:04 +00004763 insn->variant.bfp_convert.rounding_mode = rounding_mode;
4764
4765 return insn;
4766}
4767
4768
floriancc491a62012-09-10 23:44:37 +00004769/* Check validity of a register pair for 128-bit BFP. Valid register
4770 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
4771 and (13, 15). */
4772static Bool
4773is_valid_bfp128_regpair(HReg hi, HReg lo)
4774{
4775 UInt hi_regno = hregNumber(hi);
4776 UInt lo_regno = hregNumber(lo);
4777
4778 if (lo_regno != hi_regno + 2) return False;
4779 if ((hi_regno & 0x2) != 0) return False;
4780
4781 return True;
4782}
4783
florian9fcff4c2012-09-10 03:09:04 +00004784s390_insn *
sewardj2019a972011-03-07 16:04:07 +00004785s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00004786 HReg dst_lo, HReg op2_hi, HReg op2_lo)
sewardj2019a972011-03-07 16:04:07 +00004787{
4788 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4789
floriancc491a62012-09-10 23:44:37 +00004790 vassert(size == 16);
4791 vassert(is_valid_bfp128_regpair(dst_hi, dst_lo));
4792 vassert(is_valid_bfp128_regpair(op2_hi, op2_lo));
4793
4794 insn->tag = S390_INSN_BFP_BINOP;
sewardj2019a972011-03-07 16:04:07 +00004795 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00004796 insn->variant.bfp_binop.tag = tag;
4797 insn->variant.bfp_binop.dst_hi = dst_hi;
4798 insn->variant.bfp_binop.dst_lo = dst_lo;
4799 insn->variant.bfp_binop.op2_hi = op2_hi;
4800 insn->variant.bfp_binop.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00004801
4802 return insn;
4803}
4804
4805
4806s390_insn *
sewardja970c402011-04-28 18:38:42 +00004807s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00004808 HReg dst_lo, HReg op_hi, HReg op_lo)
sewardj2019a972011-03-07 16:04:07 +00004809{
4810 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4811
floriancc491a62012-09-10 23:44:37 +00004812 vassert(size == 16);
4813 vassert(is_valid_bfp128_regpair(dst_hi, dst_lo));
4814 vassert(is_valid_bfp128_regpair(op_hi, op_lo));
4815
4816 insn->tag = S390_INSN_BFP_UNOP;
sewardj2019a972011-03-07 16:04:07 +00004817 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00004818 insn->variant.bfp_unop.tag = tag;
4819 insn->variant.bfp_unop.dst_hi = dst_hi;
4820 insn->variant.bfp_unop.dst_lo = dst_lo;
4821 insn->variant.bfp_unop.op_hi = op_hi;
4822 insn->variant.bfp_unop.op_lo = op_lo;
sewardj2019a972011-03-07 16:04:07 +00004823
4824 return insn;
4825}
4826
4827
4828s390_insn *
4829s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
4830 HReg op2_hi, HReg op2_lo)
4831{
4832 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4833
floriancc491a62012-09-10 23:44:37 +00004834 vassert(size == 16);
4835 vassert(is_valid_bfp128_regpair(op1_hi, op1_lo));
4836 vassert(is_valid_bfp128_regpair(op2_hi, op2_lo));
4837
4838 insn->tag = S390_INSN_BFP_COMPARE;
sewardj2019a972011-03-07 16:04:07 +00004839 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00004840 insn->variant.bfp_compare.dst = dst;
4841 insn->variant.bfp_compare.op1_hi = op1_hi;
4842 insn->variant.bfp_compare.op1_lo = op1_lo;
4843 insn->variant.bfp_compare.op2_hi = op2_hi;
4844 insn->variant.bfp_compare.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00004845
4846 return insn;
4847}
4848
4849
florian9fcff4c2012-09-10 03:09:04 +00004850static s390_insn *
4851s390_insn_bfp128_convert(UChar size, s390_conv_t tag, HReg dst_hi,
4852 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00004853 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00004854{
4855 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4856
floriancc491a62012-09-10 23:44:37 +00004857 if (size == 16) {
4858 /* From smaller size to 16 bytes */
4859 vassert(is_valid_bfp128_regpair(dst_hi, dst_lo));
4860 vassert(op_lo == INVALID_HREG);
4861 } else {
4862 /* From 16 bytes to smaller size */
4863 vassert(is_valid_bfp128_regpair(op_hi, op_lo));
4864 vassert(dst_lo == INVALID_HREG);
4865 }
4866
4867 insn->tag = S390_INSN_BFP_CONVERT;
sewardj2019a972011-03-07 16:04:07 +00004868 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00004869 insn->variant.bfp_convert.tag = tag;
4870 insn->variant.bfp_convert.dst_hi = dst_hi;
4871 insn->variant.bfp_convert.dst_lo = dst_lo;
4872 insn->variant.bfp_convert.op_hi = op_hi;
4873 insn->variant.bfp_convert.op_lo = op_lo;
4874 insn->variant.bfp_convert.rounding_mode = rounding_mode;
sewardj2019a972011-03-07 16:04:07 +00004875
4876 return insn;
4877}
4878
4879
4880s390_insn *
florian9fcff4c2012-09-10 03:09:04 +00004881s390_insn_bfp128_convert_to(UChar size, s390_conv_t tag, HReg dst_hi,
4882 HReg dst_lo, HReg op)
4883{
4884 /* Conversion to bfp128 never requires a rounding mode. Provide default
4885 rounding mode. It will not be used when emitting insns. */
florian125e20d2012-10-07 15:42:37 +00004886 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
florian9fcff4c2012-09-10 03:09:04 +00004887
4888 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
4889 INVALID_HREG, rounding_mode);
4890}
4891
4892
4893s390_insn *
4894s390_insn_bfp128_convert_from(UChar size, s390_conv_t tag, HReg dst,
sewardj2019a972011-03-07 16:04:07 +00004895 HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00004896 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00004897{
florian9fcff4c2012-09-10 03:09:04 +00004898 return s390_insn_bfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
4899 rounding_mode);
sewardj2019a972011-03-07 16:04:07 +00004900}
4901
4902
sewardja52e37e2011-04-28 18:48:06 +00004903s390_insn *
4904s390_insn_mfence(void)
4905{
4906 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4907
4908 insn->tag = S390_INSN_MFENCE;
4909 insn->size = 0; /* not needed */
4910
4911 return insn;
4912}
4913
4914
florianad43b3a2012-02-20 15:01:14 +00004915s390_insn *
4916s390_insn_gzero(UChar size, UInt offset)
4917{
4918 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4919
4920 insn->tag = S390_INSN_GZERO;
4921 insn->size = size;
4922 insn->variant.gzero.offset = offset;
4923
4924 return insn;
4925}
4926
4927
4928s390_insn *
4929s390_insn_gadd(UChar size, UInt offset, UChar delta, ULong value)
4930{
4931 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4932
4933 insn->tag = S390_INSN_GADD;
4934 insn->size = size;
4935 insn->variant.gadd.offset = offset;
4936 insn->variant.gadd.delta = delta;
4937 insn->variant.gadd.value = value;
4938
4939 return insn;
4940}
4941
4942
florian8844a632012-04-13 04:04:06 +00004943s390_insn *
florian125e20d2012-10-07 15:42:37 +00004944s390_insn_set_fpc_bfprm(UChar size, HReg mode)
florian2c74d242012-09-12 19:38:42 +00004945{
4946 vassert(size == 4);
4947
4948 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4949
florian125e20d2012-10-07 15:42:37 +00004950 insn->tag = S390_INSN_SET_FPC_BFPRM;
florian2c74d242012-09-12 19:38:42 +00004951 insn->size = size;
florian125e20d2012-10-07 15:42:37 +00004952 insn->variant.set_fpc_bfprm.mode = mode;
florian2c74d242012-09-12 19:38:42 +00004953
4954 return insn;
4955}
4956
4957
4958s390_insn *
florianc8e4f562012-10-27 16:19:31 +00004959s390_insn_set_fpc_dfprm(UChar size, HReg mode)
4960{
4961 vassert(size == 4);
4962
4963 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4964
4965 insn->tag = S390_INSN_SET_FPC_DFPRM;
4966 insn->size = size;
4967 insn->variant.set_fpc_dfprm.mode = mode;
4968
4969 return insn;
4970}
4971
4972
4973s390_insn *
florian8844a632012-04-13 04:04:06 +00004974s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
4975 Bool to_fast_entry)
4976{
4977 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4978
4979 insn->tag = S390_INSN_XDIRECT;
4980 insn->size = 0; /* does not matter */
4981
4982 insn->variant.xdirect.cond = cond;
4983 insn->variant.xdirect.dst = dst;
4984 insn->variant.xdirect.guest_IA = guest_IA;
4985 insn->variant.xdirect.to_fast_entry = to_fast_entry;
4986
4987 return insn;
4988}
4989
4990
4991s390_insn *
4992s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
4993{
4994 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4995
florian7346c7a2012-04-13 21:14:24 +00004996 insn->tag = S390_INSN_XINDIR;
florian8844a632012-04-13 04:04:06 +00004997 insn->size = 0; /* does not matter */
4998
florian7346c7a2012-04-13 21:14:24 +00004999 insn->variant.xindir.cond = cond;
5000 insn->variant.xindir.dst = dst;
5001 insn->variant.xindir.guest_IA = guest_IA;
florian8844a632012-04-13 04:04:06 +00005002
5003 return insn;
5004}
5005
5006
5007s390_insn *
5008s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
5009 IRJumpKind kind)
5010{
5011 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5012
5013 insn->tag = S390_INSN_XASSISTED;
5014 insn->size = 0; /* does not matter */
5015
5016 insn->variant.xassisted.cond = cond;
5017 insn->variant.xassisted.dst = dst;
5018 insn->variant.xassisted.guest_IA = guest_IA;
5019 insn->variant.xassisted.kind = kind;
5020
5021 return insn;
5022}
5023
5024
5025s390_insn *
5026s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
5027{
5028 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5029
florianbf516d12012-04-21 15:53:13 +00005030 vassert(counter->tag == S390_AMODE_B12);
5031 vassert(fail_addr->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00005032
5033 insn->tag = S390_INSN_EVCHECK;
5034 insn->size = 0; /* does not matter */
5035
5036 insn->variant.evcheck.counter = counter;
5037 insn->variant.evcheck.fail_addr = fail_addr;
5038
5039 return insn;
5040}
5041
5042
5043s390_insn *
5044s390_insn_profinc(void)
5045{
5046 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5047
5048 insn->tag = S390_INSN_PROFINC;
5049 insn->size = 0; /* does not matter */
5050
5051 return insn;
5052}
5053
5054
sewardj2019a972011-03-07 16:04:07 +00005055/*---------------------------------------------------------------*/
5056/*--- Debug print ---*/
5057/*---------------------------------------------------------------*/
5058
5059static const HChar *
5060s390_cc_as_string(s390_cc_t cc)
5061{
5062 switch (cc) {
5063 case S390_CC_NEVER: return "never";
5064 case S390_CC_OVFL: return "overflow";
5065 case S390_CC_H: return "greater than"; /* A > B ; high */
5066 case S390_CC_NLE: return "not low or equal";
5067 case S390_CC_L: return "less than"; /* A < B ; low */
5068 case S390_CC_NHE: return "not high or equal";
5069 case S390_CC_LH: return "low or high";
5070 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
5071 case S390_CC_E: return "equal"; /* A == B ; zero */
5072 case S390_CC_NLH: return "not low or high";
5073 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
5074 case S390_CC_NL: return "not low"; /* not low */
5075 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
5076 case S390_CC_NH: return "not high";
5077 case S390_CC_NO: return "not overflow";
5078 case S390_CC_ALWAYS: return "always";
5079 default:
5080 vpanic("s390_cc_as_string");
5081 }
5082}
5083
5084
florian8844a632012-04-13 04:04:06 +00005085static const HChar *
5086s390_jump_kind_as_string(IRJumpKind kind)
5087{
5088 switch (kind) {
5089 case Ijk_Boring: return "Boring";
5090 case Ijk_Call: return "Call";
5091 case Ijk_Ret: return "Return";
5092 case Ijk_ClientReq: return "ClientReq";
5093 case Ijk_Yield: return "Yield";
5094 case Ijk_EmWarn: return "EmWarn";
5095 case Ijk_EmFail: return "EmFail";
5096 case Ijk_NoDecode: return "NoDecode";
5097 case Ijk_MapFail: return "MapFail";
5098 case Ijk_TInval: return "Invalidate";
5099 case Ijk_NoRedir: return "NoRedir";
5100 case Ijk_SigTRAP: return "SigTRAP";
5101 case Ijk_SigSEGV: return "SigSEGV";
5102 case Ijk_SigBUS: return "SigBUS";
5103 case Ijk_Sys_syscall: return "Sys_syscall";
5104 default:
5105 vpanic("s390_jump_kind_as_string");
5106 }
5107}
5108
5109
sewardj2019a972011-03-07 16:04:07 +00005110/* Helper function for writing out a V insn */
5111static void
5112s390_sprintf(HChar *buf, HChar *fmt, ...)
5113{
5114 HChar *p;
5115 ULong value;
5116 va_list args;
5117 va_start(args, fmt);
5118
5119 p = buf;
5120 for ( ; *fmt; ++fmt) {
5121 Int c = *fmt;
5122
5123 if (c != '%') {
5124 *p++ = c;
5125 continue;
5126 }
5127
5128 c = *++fmt; /* next char */
5129 switch (c) {
5130 case '%':
5131 *p++ = c; /* %% */
5132 continue;
5133
5134 case 's': /* %s */
5135 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
5136 continue;
5137
5138 case 'M': /* %M = mnemonic */
5139 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
5140 continue;
5141
5142 case 'R': /* %R = register */
5143 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
5144 continue;
5145
5146 case 'A': /* %A = amode */
5147 p += vex_sprintf(p, "%s",
5148 s390_amode_as_string(va_arg(args, s390_amode *)));
5149 continue;
5150
florianad43b3a2012-02-20 15:01:14 +00005151 case 'G': /* %G = guest state @ offset */
5152 p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt));
5153 continue;
5154
sewardj2019a972011-03-07 16:04:07 +00005155 case 'C': /* %C = condition code */
5156 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
5157 continue;
5158
florian8844a632012-04-13 04:04:06 +00005159 case 'J': /* &J = jump kind */
5160 p += vex_sprintf(p, "%s",
5161 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
5162 continue;
5163
sewardj2019a972011-03-07 16:04:07 +00005164 case 'L': { /* %L = argument list in helper call*/
5165 UInt i, num_args;
5166
5167 num_args = va_arg(args, UInt);
5168
5169 for (i = 0; i < num_args; ++i) {
5170 if (i != 0) p += vex_sprintf(p, ", ");
5171 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
5172 }
5173 continue;
5174 }
5175
5176 case 'O': { /* %O = RMI operand */
5177 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
5178
5179 switch (op->tag) {
5180 case S390_OPND_REG:
5181 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
5182 continue;
5183
5184 case S390_OPND_AMODE:
5185 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
5186 continue;
5187
5188 case S390_OPND_IMMEDIATE:
5189 value = op->variant.imm;
5190 goto print_value;
5191
5192 default:
5193 goto fail;
5194 }
5195 }
5196
5197 case 'I': /* %I = immediate value */
5198 value = va_arg(args, ULong);
5199 goto print_value;
5200
5201 print_value:
5202 if ((Long)value < 0)
5203 p += vex_sprintf(p, "%lld", (Long)value);
5204 else if (value < 100)
5205 p += vex_sprintf(p, "%llu", value);
5206 else
5207 p += vex_sprintf(p, "0x%llx", value);
5208 continue;
5209
5210 default:
5211 goto fail;
5212 }
5213 }
5214 *p = '\0';
5215 va_end(args);
5216
5217 return;
5218
5219 fail: vpanic("s390_printf");
5220}
5221
5222
5223/* Decompile the given insn into a static buffer and return it */
5224const HChar *
5225s390_insn_as_string(const s390_insn *insn)
5226{
5227 static HChar buf[300];
5228 const HChar *op;
5229 HChar *p;
5230
5231 buf[0] = '\0';
5232
5233 switch (insn->tag) {
5234 case S390_INSN_LOAD:
5235 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
5236 insn->variant.load.src);
5237 break;
5238
5239 case S390_INSN_STORE:
5240 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
5241 insn->variant.store.dst);
5242 break;
5243
5244 case S390_INSN_MOVE:
5245 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
5246 insn->variant.move.src);
5247 break;
5248
5249 case S390_INSN_COND_MOVE:
5250 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
5251 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
5252 &insn->variant.cond_move.src);
5253 break;
5254
5255 case S390_INSN_LOAD_IMMEDIATE:
5256 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
5257 insn->variant.load_immediate.value);
5258 break;
5259
5260 case S390_INSN_ALU:
5261 switch (insn->variant.alu.tag) {
5262 case S390_ALU_ADD: op = "v-add"; break;
5263 case S390_ALU_SUB: op = "v-sub"; break;
5264 case S390_ALU_MUL: op = "v-mul"; break;
5265 case S390_ALU_AND: op = "v-and"; break;
5266 case S390_ALU_OR: op = "v-or"; break;
5267 case S390_ALU_XOR: op = "v-xor"; break;
5268 case S390_ALU_LSH: op = "v-lsh"; break;
5269 case S390_ALU_RSH: op = "v-rsh"; break;
5270 case S390_ALU_RSHA: op = "v-rsha"; break;
5271 default: goto fail;
5272 }
florian043af212012-06-06 02:44:53 +00005273 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
sewardj2019a972011-03-07 16:04:07 +00005274 &insn->variant.alu.op2);
5275 break;
5276
5277 case S390_INSN_MUL:
5278 if (insn->variant.mul.signed_multiply) {
5279 op = "v-muls";
5280 } else {
5281 op = "v-mulu";
5282 }
5283 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
5284 &insn->variant.mul.op2);
5285 break;
5286
5287 case S390_INSN_DIV:
5288 if (insn->variant.div.signed_divide) {
5289 op = "v-divs";
5290 } else {
5291 op = "v-divu";
5292 }
5293 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
5294 &insn->variant.div.op2);
5295 break;
5296
5297 case S390_INSN_DIVS:
5298 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
5299 &insn->variant.divs.op2);
5300 break;
5301
sewardj611b06e2011-03-24 08:57:29 +00005302 case S390_INSN_CLZ:
5303 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
5304 &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +00005305 break;
5306
5307 case S390_INSN_UNOP:
5308 switch (insn->variant.unop.tag) {
5309 case S390_ZERO_EXTEND_8:
5310 case S390_ZERO_EXTEND_16:
5311 case S390_ZERO_EXTEND_32:
5312 op = "v-zerox";
5313 break;
5314
5315 case S390_SIGN_EXTEND_8:
5316 case S390_SIGN_EXTEND_16:
5317 case S390_SIGN_EXTEND_32:
5318 op = "v-signx";
5319 break;
5320
5321 case S390_NEGATE:
5322 op = "v-neg";
5323 break;
5324
5325 default:
5326 goto fail;
5327 }
5328 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
5329 &insn->variant.unop.src);
5330 break;
5331
5332 case S390_INSN_TEST:
5333 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
5334 break;
5335
5336 case S390_INSN_CC2BOOL:
5337 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
5338 insn->variant.cc2bool.cond);
5339 break;
5340
5341 case S390_INSN_CAS:
5342 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
5343 insn->variant.cas.op2, insn->variant.cas.op3,
5344 insn->variant.cas.old_mem);
5345 break;
5346
florian448cbba2012-06-06 02:26:01 +00005347 case S390_INSN_CDAS:
5348 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
5349 insn->variant.cdas.op1_high, insn->variant.cdas.op1_low,
5350 insn->variant.cdas.op2, insn->variant.cdas.op3_high,
5351 insn->variant.cdas.op3_low, insn->variant.cdas.old_mem_high,
5352 insn->variant.cdas.old_mem_low);
5353 break;
5354
sewardj2019a972011-03-07 16:04:07 +00005355 case S390_INSN_COMPARE:
5356 if (insn->variant.compare.signed_comparison) {
5357 op = "v-cmps";
5358 } else {
5359 op = "v-cmpu";
5360 }
5361 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
5362 &insn->variant.compare.src2);
5363 break;
5364
sewardj2019a972011-03-07 16:04:07 +00005365 case S390_INSN_HELPER_CALL: {
florian01ed6e72012-05-27 16:52:43 +00005366 if (insn->variant.helper_call.dst != INVALID_HREG) {
5367 s390_sprintf(buf, "%M if (%C) %R = %s{%I}(%L)", "v-call",
5368 insn->variant.helper_call.cond,
5369 insn->variant.helper_call.dst,
5370 insn->variant.helper_call.name,
5371 insn->variant.helper_call.target,
5372 insn->variant.helper_call.num_args);
5373 } else {
5374 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
5375 insn->variant.helper_call.cond,
5376 insn->variant.helper_call.name,
5377 insn->variant.helper_call.target,
5378 insn->variant.helper_call.num_args);
5379 }
florian8844a632012-04-13 04:04:06 +00005380 return buf; /* avoid printing "size = ..." which is meaningless */
sewardj2019a972011-03-07 16:04:07 +00005381 }
5382
5383 case S390_INSN_BFP_TRIOP:
5384 switch (insn->variant.bfp_triop.tag) {
5385 case S390_BFP_MADD: op = "v-fmadd"; break;
5386 case S390_BFP_MSUB: op = "v-fmsub"; break;
5387 default: goto fail;
5388 }
florian043af212012-06-06 02:44:53 +00005389 s390_sprintf(buf, "%M %R,%R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00005390 insn->variant.bfp_triop.dst /* op1 same as dst */,
5391 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
5392 break;
5393
5394 case S390_INSN_BFP_BINOP:
5395 switch (insn->variant.bfp_binop.tag) {
5396 case S390_BFP_ADD: op = "v-fadd"; break;
5397 case S390_BFP_SUB: op = "v-fsub"; break;
5398 case S390_BFP_MUL: op = "v-fmul"; break;
5399 case S390_BFP_DIV: op = "v-fdiv"; break;
5400 default: goto fail;
5401 }
florian043af212012-06-06 02:44:53 +00005402 s390_sprintf(buf, "%M %R,%R", op,
floriancc491a62012-09-10 23:44:37 +00005403 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
5404 insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00005405 break;
5406
5407 case S390_INSN_BFP_COMPARE:
5408 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
floriancc491a62012-09-10 23:44:37 +00005409 insn->variant.bfp_compare.op1_hi,
5410 insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00005411 break;
5412
5413 case S390_INSN_BFP_UNOP:
5414 switch (insn->variant.bfp_unop.tag) {
5415 case S390_BFP_ABS: op = "v-fabs"; break;
5416 case S390_BFP_NABS: op = "v-fnabs"; break;
5417 case S390_BFP_NEG: op = "v-fneg"; break;
5418 case S390_BFP_SQRT: op = "v-fsqrt"; break;
florian9fcff4c2012-09-10 03:09:04 +00005419 default: goto fail;
5420 }
floriancc491a62012-09-10 23:44:37 +00005421 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
5422 insn->variant.bfp_unop.op_hi);
florian9fcff4c2012-09-10 03:09:04 +00005423 break;
5424
5425 case S390_INSN_BFP_CONVERT:
5426 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00005427 case S390_BFP_I32_TO_F32:
5428 case S390_BFP_I32_TO_F64:
5429 case S390_BFP_I32_TO_F128:
5430 case S390_BFP_I64_TO_F32:
5431 case S390_BFP_I64_TO_F64:
5432 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
florian1c8f7ff2012-09-01 00:12:11 +00005433 case S390_BFP_U32_TO_F32:
5434 case S390_BFP_U32_TO_F64:
5435 case S390_BFP_U32_TO_F128:
5436 case S390_BFP_U64_TO_F32:
5437 case S390_BFP_U64_TO_F64:
5438 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
sewardj2019a972011-03-07 16:04:07 +00005439 case S390_BFP_F32_TO_I32:
5440 case S390_BFP_F32_TO_I64:
5441 case S390_BFP_F64_TO_I32:
5442 case S390_BFP_F64_TO_I64:
5443 case S390_BFP_F128_TO_I32:
5444 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
florian1c8f7ff2012-09-01 00:12:11 +00005445 case S390_BFP_F32_TO_U32:
5446 case S390_BFP_F32_TO_U64:
5447 case S390_BFP_F64_TO_U32:
5448 case S390_BFP_F64_TO_U64:
5449 case S390_BFP_F128_TO_U32:
5450 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
sewardj2019a972011-03-07 16:04:07 +00005451 case S390_BFP_F32_TO_F64:
5452 case S390_BFP_F32_TO_F128:
5453 case S390_BFP_F64_TO_F32:
5454 case S390_BFP_F64_TO_F128:
5455 case S390_BFP_F128_TO_F32:
5456 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
5457 default: goto fail;
5458 }
floriancc491a62012-09-10 23:44:37 +00005459 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
5460 insn->variant.bfp_convert.op_hi);
sewardj2019a972011-03-07 16:04:07 +00005461 break;
5462
sewardja52e37e2011-04-28 18:48:06 +00005463 case S390_INSN_MFENCE:
5464 s390_sprintf(buf, "%M", "v-mfence");
5465 return buf; /* avoid printing "size = ..." which is meaningless */
5466
florianad43b3a2012-02-20 15:01:14 +00005467 case S390_INSN_GZERO:
5468 s390_sprintf(buf, "%M %G", "v-gzero", insn->variant.gzero.offset);
5469 break;
5470
5471 case S390_INSN_GADD:
5472 s390_sprintf(buf, "%M %G += %I (= %I)", "v-gadd",
5473 insn->variant.gadd.offset,
5474 (Long)(Char)insn->variant.gadd.delta,
5475 insn->variant.gadd.value);
5476 break;
5477
florian125e20d2012-10-07 15:42:37 +00005478 case S390_INSN_SET_FPC_BFPRM:
5479 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
5480 insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00005481 break;
5482
florianc8e4f562012-10-27 16:19:31 +00005483 case S390_INSN_SET_FPC_DFPRM:
5484 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
5485 insn->variant.set_fpc_dfprm.mode);
5486 break;
5487
florian8844a632012-04-13 04:04:06 +00005488 case S390_INSN_EVCHECK:
5489 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
5490 insn->variant.evcheck.counter,
5491 insn->variant.evcheck.fail_addr);
5492 return buf; /* avoid printing "size = ..." which is meaningless */
5493
5494 case S390_INSN_PROFINC:
5495 s390_sprintf(buf, "%M", "v-profinc");
5496 return buf; /* avoid printing "size = ..." which is meaningless */
5497
5498 case S390_INSN_XDIRECT:
5499 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
5500 insn->variant.xdirect.cond,
5501 insn->variant.xdirect.guest_IA,
5502 insn->variant.xdirect.dst,
5503 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
5504 return buf; /* avoid printing "size = ..." which is meaningless */
5505
5506 case S390_INSN_XINDIR:
5507 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
5508 insn->variant.xindir.cond,
5509 insn->variant.xindir.guest_IA,
5510 insn->variant.xindir.dst);
5511 return buf; /* avoid printing "size = ..." which is meaningless */
5512
5513 case S390_INSN_XASSISTED:
5514 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
5515 insn->variant.xassisted.cond,
5516 insn->variant.xassisted.kind,
5517 insn->variant.xassisted.guest_IA,
5518 insn->variant.xassisted.dst);
5519 return buf; /* avoid printing "size = ..." which is meaningless */
5520
sewardj2019a972011-03-07 16:04:07 +00005521 default: goto fail;
5522 }
5523
5524 /* Write out how many bytes are involved in the operation */
5525
5526 {
5527 UInt len, i;
5528
5529 for (p = buf; *p; ++p)
5530 continue;
5531
5532 len = p - buf;
5533
5534 if (len < 32) {
5535 for (i = len; i < 32; ++i)
5536 p += vex_sprintf(p, " ");
5537 } else {
5538 p += vex_sprintf(p, "\t");
5539 }
5540 }
5541
5542 /* Special cases first */
5543 switch (insn->tag) {
5544 case S390_INSN_UNOP:
5545 switch (insn->variant.unop.tag) {
5546 case S390_SIGN_EXTEND_8:
5547 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
5548 case S390_SIGN_EXTEND_16:
5549 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
5550 case S390_SIGN_EXTEND_32:
5551 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
5552 default:
5553 goto common;
5554 }
5555
floriancc491a62012-09-10 23:44:37 +00005556 case S390_INSN_BFP_CONVERT:
5557 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00005558 case S390_BFP_I32_TO_F32:
5559 case S390_BFP_I32_TO_F64:
5560 case S390_BFP_I32_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00005561 case S390_BFP_U32_TO_F32:
5562 case S390_BFP_U32_TO_F64:
5563 case S390_BFP_U32_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00005564 case S390_BFP_F32_TO_I32:
5565 case S390_BFP_F32_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00005566 case S390_BFP_F32_TO_U32:
5567 case S390_BFP_F32_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00005568 case S390_BFP_F32_TO_F64:
5569 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
5570 case S390_BFP_I64_TO_F32:
5571 case S390_BFP_I64_TO_F64:
5572 case S390_BFP_I64_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00005573 case S390_BFP_U64_TO_F32:
5574 case S390_BFP_U64_TO_F64:
5575 case S390_BFP_U64_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00005576 case S390_BFP_F64_TO_I32:
5577 case S390_BFP_F64_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00005578 case S390_BFP_F64_TO_U32:
5579 case S390_BFP_F64_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00005580 case S390_BFP_F64_TO_F32:
5581 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
5582 case S390_BFP_F128_TO_I32:
5583 case S390_BFP_F128_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00005584 case S390_BFP_F128_TO_U32:
5585 case S390_BFP_F128_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00005586 case S390_BFP_F128_TO_F32:
5587 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
5588 default:
5589 goto common;
5590 }
5591
sewardj2019a972011-03-07 16:04:07 +00005592 default:
5593 goto common;
5594 }
5595
5596 /* Common case */
5597 common:
5598 vex_sprintf(p, "%u bytes", (UInt)insn->size);
5599
5600 return buf;
5601
5602 fail: vpanic("s390_insn_as_string");
5603}
5604
5605
5606
5607/* Load NUM bytes from memory into register REG using addressing mode AM. */
5608static UChar *
5609s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
5610{
5611 UInt b = hregNumber(am->b);
5612 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
5613 UInt d = am->d;
5614
5615 switch (am->tag) {
5616 case S390_AMODE_B12:
5617 case S390_AMODE_BX12:
5618 switch (num) {
5619 case 1: return s390_emit_IC(p, reg, x, b, d);
5620 case 2: return s390_emit_LH(p, reg, x, b, d);
5621 case 4: return s390_emit_L(p, reg, x, b, d);
5622 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
5623 default: goto fail;
5624 }
5625 break;
5626
5627 case S390_AMODE_B20:
5628 case S390_AMODE_BX20:
5629 switch (num) {
5630 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
5631 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
5632 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
5633 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
5634 default: goto fail;
5635 }
5636 break;
5637
5638 default: goto fail;
5639 }
5640
5641 fail:
5642 vpanic("s390_emit_load_mem");
5643}
5644
5645
5646/* Load condition code into register REG */
5647static UChar *
5648s390_emit_load_cc(UChar *p, UChar reg)
5649{
5650 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
5651 p = s390_emit_IPM(p, reg, reg);
5652 /* Shift 28 bits to the right --> [0,1,2,3] */
sewardjf74c86f2011-04-05 14:04:53 +00005653 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
sewardj2019a972011-03-07 16:04:07 +00005654}
5655
5656
5657/*---------------------------------------------------------------*/
5658/*--- Code generation ---*/
5659/*---------------------------------------------------------------*/
5660
5661/* Do not load more bytes than requested. */
5662static UChar *
5663s390_insn_load_emit(UChar *buf, const s390_insn *insn)
5664{
5665 UInt r, x, b, d;
5666 const s390_amode *src;
5667
5668 src = insn->variant.load.src;
5669
5670 r = hregNumber(insn->variant.load.dst);
5671
5672 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
5673 b = hregNumber(src->b);
5674 x = hregNumber(src->x); /* 0 for B12 and B20 */
5675 d = src->d;
5676
5677 switch (insn->size) {
5678
5679 case 4:
5680 switch (src->tag) {
5681 case S390_AMODE_B12:
5682 case S390_AMODE_BX12:
5683 return s390_emit_LE(buf, r, x, b, d);
5684
5685 case S390_AMODE_B20:
5686 case S390_AMODE_BX20:
5687 return s390_emit_LEY(buf, r, x, b, DISP20(d));
5688 }
5689 break;
5690
5691 case 8:
5692 switch (src->tag) {
5693 case S390_AMODE_B12:
5694 case S390_AMODE_BX12:
5695 return s390_emit_LD(buf, r, x, b, d);
5696
5697 case S390_AMODE_B20:
5698 case S390_AMODE_BX20:
5699 return s390_emit_LDY(buf, r, x, b, DISP20(d));
5700 }
5701 break;
5702 }
5703 vpanic("s390_insn_load_emit");
5704 }
5705
5706 /* Integer stuff */
5707 return s390_emit_load_mem(buf, insn->size, r, src);
5708}
5709
5710
5711static UChar *
5712s390_insn_store_emit(UChar *buf, const s390_insn *insn)
5713{
5714 UInt r, x, b, d;
5715 const s390_amode *dst;
5716
5717 dst = insn->variant.store.dst;
5718
5719 r = hregNumber(insn->variant.store.src);
5720 b = hregNumber(dst->b);
5721 x = hregNumber(dst->x); /* 0 for B12 and B20 */
5722 d = dst->d;
5723
5724 if (hregClass(insn->variant.store.src) == HRcFlt64) {
5725 switch (insn->size) {
5726
5727 case 4:
5728 switch (dst->tag) {
5729 case S390_AMODE_B12:
5730 case S390_AMODE_BX12:
5731 return s390_emit_STE(buf, r, x, b, d);
5732
5733 case S390_AMODE_B20:
5734 case S390_AMODE_BX20:
5735 return s390_emit_STEY(buf, r, x, b, DISP20(d));
5736 }
5737 break;
5738
5739 case 8:
5740 switch (dst->tag) {
5741 case S390_AMODE_B12:
5742 case S390_AMODE_BX12:
5743 return s390_emit_STD(buf, r, x, b, d);
5744
5745 case S390_AMODE_B20:
5746 case S390_AMODE_BX20:
5747 return s390_emit_STDY(buf, r, x, b, DISP20(d));
5748 }
5749 break;
5750 }
5751 vpanic("s390_insn_store_emit");
5752 }
5753
5754 /* Integer stuff */
5755 switch (insn->size) {
5756 case 1:
5757 switch (dst->tag) {
5758 case S390_AMODE_B12:
5759 case S390_AMODE_BX12:
5760 return s390_emit_STC(buf, r, x, b, d);
5761
5762 case S390_AMODE_B20:
5763 case S390_AMODE_BX20:
5764 return s390_emit_STCY(buf, r, x, b, DISP20(d));
5765 }
5766 break;
5767
5768 case 2:
5769 switch (dst->tag) {
5770 case S390_AMODE_B12:
5771 case S390_AMODE_BX12:
5772 return s390_emit_STH(buf, r, x, b, d);
5773
5774 case S390_AMODE_B20:
5775 case S390_AMODE_BX20:
5776 return s390_emit_STHY(buf, r, x, b, DISP20(d));
5777 }
5778 break;
5779
5780 case 4:
5781 switch (dst->tag) {
5782 case S390_AMODE_B12:
5783 case S390_AMODE_BX12:
5784 return s390_emit_ST(buf, r, x, b, d);
5785
5786 case S390_AMODE_B20:
5787 case S390_AMODE_BX20:
5788 return s390_emit_STY(buf, r, x, b, DISP20(d));
5789 }
5790 break;
5791
5792 case 8:
5793 return s390_emit_STG(buf, r, x, b, DISP20(d));
5794
5795 default:
5796 break;
5797 }
5798
5799 vpanic("s390_insn_store_emit");
5800}
5801
5802
5803static UChar *
5804s390_insn_move_emit(UChar *buf, const s390_insn *insn)
5805{
5806 UInt dst, src;
5807 HRegClass dst_class, src_class;
5808
5809 dst = hregNumber(insn->variant.move.dst);
5810 src = hregNumber(insn->variant.move.src);
5811
5812 dst_class = hregClass(insn->variant.move.dst);
5813 src_class = hregClass(insn->variant.move.src);
5814
5815 if (dst_class == src_class) {
5816 if (dst_class == HRcInt64)
5817 return s390_emit_LGR(buf, dst, src);
5818 if (dst_class == HRcFlt64)
5819 return s390_emit_LDR(buf, dst, src);
5820 } else {
floriana782a172011-12-18 15:51:54 +00005821 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
5822 if (insn->size == 4) {
5823 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
5824 return s390_emit_LDGRw(buf, dst, R0);
5825 } else {
5826 return s390_emit_LDGRw(buf, dst, src);
5827 }
5828 }
5829 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
5830 if (insn->size == 4) {
5831 buf = s390_emit_LGDRw(buf, dst, src);
5832 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
5833 } else {
5834 return s390_emit_LGDRw(buf, dst, src);
5835 }
5836 }
sewardj2019a972011-03-07 16:04:07 +00005837 /* A move between floating point registers and general purpose
5838 registers of different size should never occur and indicates
5839 an error elsewhere. */
5840 }
5841
5842 vpanic("s390_insn_move_emit");
5843}
5844
5845
5846static UChar *
5847s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
5848{
5849 UInt r;
5850 ULong value = insn->variant.load_immediate.value;
5851
5852 r = hregNumber(insn->variant.load_immediate.dst);
5853
5854 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
5855 vassert(value == 0);
5856 switch (insn->size) {
5857 case 4: return s390_emit_LZER(buf, r, value);
5858 case 8: return s390_emit_LZDR(buf, r, value);
5859 }
5860 vpanic("s390_insn_load_immediate_emit");
5861 }
5862
5863 switch (insn->size) {
5864 case 1:
5865 case 2:
5866 /* Load the immediate values as a 4 byte value. That does not hurt as
5867 those extra bytes will not be looked at. Fall through .... */
5868 case 4:
5869 return s390_emit_load_32imm(buf, r, value);
5870
5871 case 8:
5872 return s390_emit_load_64imm(buf, r, value);
5873 }
5874
5875 vpanic("s390_insn_load_immediate_emit");
5876}
5877
5878
5879/* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
5880 So we simply perform a 4-byte operation. Doing so uses possibly undefined
5881 bits and produces an undefined result in those extra bit positions. But
5882 upstream does not look at those positions, so this is OK. */
5883static UChar *
5884s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
5885{
5886 s390_opnd_RMI op2;
5887 UInt dst;
5888
5889 dst = hregNumber(insn->variant.alu.dst);
5890 op2 = insn->variant.alu.op2;
5891
5892 /* Second operand is in a register */
5893 if (op2.tag == S390_OPND_REG) {
5894 UInt r2 = hregNumber(op2.variant.reg);
5895
5896 switch (insn->size) {
5897 case 1:
5898 case 2:
5899 case 4:
5900 switch (insn->variant.alu.tag) {
5901 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
5902 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
5903 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
5904 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
5905 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
5906 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
sewardj3c49aaa2011-04-05 14:00:37 +00005907 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
5908 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
5909 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
sewardj2019a972011-03-07 16:04:07 +00005910 }
5911 goto fail;
5912
5913 case 8:
5914 switch (insn->variant.alu.tag) {
5915 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
5916 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
5917 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
5918 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
5919 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
5920 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
5921 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
5922 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
5923 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
5924 }
5925 goto fail;
5926 }
5927 goto fail;
5928 }
5929
5930 /* 2nd operand is in memory */
5931 if (op2.tag == S390_OPND_AMODE) {
5932 UInt b, x, d;
5933 const s390_amode *src = op2.variant.am;
5934
5935 b = hregNumber(src->b);
5936 x = hregNumber(src->x); /* 0 for B12 and B20 */
5937 d = src->d;
5938
5939 /* Shift operands are special here as there are no opcodes that
sewardje0dd77e2011-04-27 12:07:01 +00005940 allow a memory operand. So we first load the 2nd operand into
5941 some register. R0 is used to save restore the contents of the
5942 chosen register.. */
sewardj652b56a2011-04-13 15:38:17 +00005943
sewardj2019a972011-03-07 16:04:07 +00005944 if (insn->variant.alu.tag == S390_ALU_LSH ||
5945 insn->variant.alu.tag == S390_ALU_RSH ||
5946 insn->variant.alu.tag == S390_ALU_RSHA) {
sewardje0dd77e2011-04-27 12:07:01 +00005947 UInt b2;
sewardj2019a972011-03-07 16:04:07 +00005948
sewardje0dd77e2011-04-27 12:07:01 +00005949 /* Choose a register (other than DST or R0) into which to stick the
5950 shift amount. The following works because r15 is reserved and
5951 thusly dst != 15. */
5952 vassert(dst != 15); /* extra paranoia */
5953 b2 = (dst + 1) % 16;
5954
5955 buf = s390_emit_LGR(buf, R0, b2); /* save */
5956
5957 /* Loading SRC to B2 does not modify R0. */
5958 buf = s390_emit_load_mem(buf, insn->size, b2, src);
sewardj2019a972011-03-07 16:04:07 +00005959
5960 if (insn->size == 8) {
sewardje0dd77e2011-04-27 12:07:01 +00005961 switch (insn->variant.alu.tag) {
5962 case S390_ALU_LSH:
5963 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
5964 break;
5965 case S390_ALU_RSH:
5966 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
5967 break;
5968 case S390_ALU_RSHA:
5969 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
5970 break;
5971 default: /* unreachable */
5972 goto fail;
5973 }
sewardj2019a972011-03-07 16:04:07 +00005974 } else {
sewardje0dd77e2011-04-27 12:07:01 +00005975 switch (insn->variant.alu.tag) {
5976 case S390_ALU_LSH:
5977 buf = s390_emit_SLL(buf, dst, b2, 0);
5978 break;
5979 case S390_ALU_RSH:
5980 buf = s390_emit_SRL(buf, dst, b2, 0);
5981 break;
5982 case S390_ALU_RSHA:
5983 buf = s390_emit_SRA(buf, dst, b2, 0);
5984 break;
5985 default: /* unreachable */
5986 goto fail;
5987 }
sewardj2019a972011-03-07 16:04:07 +00005988 }
sewardje0dd77e2011-04-27 12:07:01 +00005989 return s390_emit_LGR(buf, b2, R0); /* restore */
sewardj2019a972011-03-07 16:04:07 +00005990 }
5991
5992 switch (insn->size) {
5993 case 1:
5994 /* Move the byte from memory into scratch register r0 */
5995 buf = s390_emit_load_mem(buf, 1, R0, src);
5996
5997 switch (insn->variant.alu.tag) {
5998 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
5999 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
6000 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
6001 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
6002 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
6003 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
6004 case S390_ALU_LSH:
6005 case S390_ALU_RSH:
6006 case S390_ALU_RSHA: ; /* avoid GCC warning */
6007 }
6008 goto fail;
6009
6010 case 2:
6011 switch (src->tag) {
6012 case S390_AMODE_B12:
6013 case S390_AMODE_BX12:
6014 switch (insn->variant.alu.tag) {
6015 case S390_ALU_ADD:
6016 return s390_emit_AH(buf, dst, x, b, d);
6017
6018 case S390_ALU_SUB:
6019 return s390_emit_SH(buf, dst, x, b, d);
6020
6021 case S390_ALU_MUL:
6022 return s390_emit_MH(buf, dst, x, b, d);
6023
6024 /* For bitwise operations: Move two bytes from memory into scratch
6025 register r0; then perform operation */
6026 case S390_ALU_AND:
6027 buf = s390_emit_LH(buf, R0, x, b, d);
6028 return s390_emit_NR(buf, dst, R0);
6029
6030 case S390_ALU_OR:
6031 buf = s390_emit_LH(buf, R0, x, b, d);
6032 return s390_emit_OR(buf, dst, R0);
6033
6034 case S390_ALU_XOR:
6035 buf = s390_emit_LH(buf, R0, x, b, d);
6036 return s390_emit_XR(buf, dst, R0);
6037
6038 case S390_ALU_LSH:
6039 case S390_ALU_RSH:
6040 case S390_ALU_RSHA: ; /* avoid GCC warning */
6041 }
6042 goto fail;
6043
6044 case S390_AMODE_B20:
6045 case S390_AMODE_BX20:
6046 switch (insn->variant.alu.tag) {
6047 case S390_ALU_ADD:
6048 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
6049
6050 case S390_ALU_SUB:
6051 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
6052
6053 case S390_ALU_MUL:
sewardjeae8db52011-03-24 09:01:50 +00006054 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006055
6056 /* For bitwise operations: Move two bytes from memory into scratch
6057 register r0; then perform operation */
6058 case S390_ALU_AND:
6059 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6060 return s390_emit_NR(buf, dst, R0);
6061
6062 case S390_ALU_OR:
6063 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6064 return s390_emit_OR(buf, dst, R0);
6065
6066 case S390_ALU_XOR:
6067 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
6068 return s390_emit_XR(buf, dst, R0);
6069
6070 case S390_ALU_LSH:
6071 case S390_ALU_RSH:
6072 case S390_ALU_RSHA: ; /* avoid GCC warning */
6073 }
6074 goto fail;
6075 }
6076 goto fail;
6077
6078 case 4:
6079 switch (src->tag) {
6080 case S390_AMODE_B12:
6081 case S390_AMODE_BX12:
6082 switch (insn->variant.alu.tag) {
6083 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
6084 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
6085 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
6086 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
6087 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
6088 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
6089 case S390_ALU_LSH:
6090 case S390_ALU_RSH:
6091 case S390_ALU_RSHA: ; /* avoid GCC warning */
6092 }
6093 goto fail;
6094
6095 case S390_AMODE_B20:
6096 case S390_AMODE_BX20:
6097 switch (insn->variant.alu.tag) {
6098 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
6099 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
6100 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
6101 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
6102 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
6103 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
6104 case S390_ALU_LSH:
6105 case S390_ALU_RSH:
6106 case S390_ALU_RSHA: ; /* avoid GCC warning */
6107 }
6108 goto fail;
6109 }
6110 goto fail;
6111
6112 case 8:
6113 switch (insn->variant.alu.tag) {
6114 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
6115 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
6116 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
6117 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
6118 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
6119 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
6120 case S390_ALU_LSH:
6121 case S390_ALU_RSH:
6122 case S390_ALU_RSHA: ; /* avoid GCC warning */
6123 }
6124 goto fail;
6125 }
6126 goto fail;
6127 }
6128
6129 /* 2nd operand is an immediate value */
6130 if (op2.tag == S390_OPND_IMMEDIATE) {
6131 ULong value;
6132
6133 /* No masking of the value is required as it is not sign extended */
6134 value = op2.variant.imm;
6135
6136 switch (insn->size) {
6137 case 1:
6138 case 2:
6139 /* There is no 1-byte opcode. Do the computation in
6140 2 bytes. The extra byte will be ignored. */
6141 switch (insn->variant.alu.tag) {
6142 case S390_ALU_ADD:
6143 return s390_emit_AHI(buf, dst, value);
6144
6145 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00006146 return s390_emit_SLFIw(buf, dst, value);
sewardj2019a972011-03-07 16:04:07 +00006147
6148 case S390_ALU_MUL:
6149 return s390_emit_MHI(buf, dst, value);
6150
6151 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
6152 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
6153 case S390_ALU_XOR:
6154 /* There is no XILL instruction. Load the immediate value into
6155 R0 and combine with the destination register. */
6156 buf = s390_emit_LHI(buf, R0, value);
6157 return s390_emit_XR(buf, dst, R0);
6158
6159 case S390_ALU_LSH:
sewardj3c49aaa2011-04-05 14:00:37 +00006160 return s390_emit_SLL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006161
6162 case S390_ALU_RSH:
sewardj3c49aaa2011-04-05 14:00:37 +00006163 return s390_emit_SRL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006164
6165 case S390_ALU_RSHA:
sewardj3c49aaa2011-04-05 14:00:37 +00006166 return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006167 }
6168 goto fail;
6169
6170 case 4:
6171 switch (insn->variant.alu.tag) {
6172 case S390_ALU_ADD:
6173 if (uint_fits_signed_16bit(value)) {
6174 return s390_emit_AHI(buf, dst, value);
6175 }
6176 return s390_emit_AFIw(buf, dst, value);
6177
6178 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
6179 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
6180 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
6181 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
6182 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
sewardj3c49aaa2011-04-05 14:00:37 +00006183 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
6184 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
6185 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00006186 }
6187 goto fail;
6188
6189 case 8:
6190 switch (insn->variant.alu.tag) {
6191 case S390_ALU_ADD:
6192 if (ulong_fits_signed_16bit(value)) {
6193 return s390_emit_AGHI(buf, dst, value);
6194 }
6195 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
6196 return s390_emit_AGFI(buf, dst, value);
6197 }
6198 /* Load constant into R0 then add */
6199 buf = s390_emit_load_64imm(buf, R0, value);
6200 return s390_emit_AGR(buf, dst, R0);
6201
6202 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00006203 if (ulong_fits_unsigned_32bit(value)) {
6204 return s390_emit_SLGFIw(buf, dst, value);
6205 }
sewardj2019a972011-03-07 16:04:07 +00006206 /* Load value into R0; then subtract from destination reg */
6207 buf = s390_emit_load_64imm(buf, R0, value);
6208 return s390_emit_SGR(buf, dst, R0);
6209
6210 case S390_ALU_MUL:
6211 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
6212 return s390_emit_MSGFI(buf, dst, value);
6213 }
6214 /* Load constant into R0 then add */
6215 buf = s390_emit_load_64imm(buf, R0, value);
6216 return s390_emit_MSGR(buf, dst, R0);
6217
6218 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
6219 case S390_ALU_AND:
6220 if (s390_host_has_eimm) {
6221 buf = s390_emit_NIHF(buf, dst, value >> 32);
6222 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
6223 }
6224 /* Load value into R0; then combine with destination reg */
6225 buf = s390_emit_load_64imm(buf, R0, value);
6226 return s390_emit_NGR(buf, dst, R0);
6227
6228 case S390_ALU_OR:
6229 if (s390_host_has_eimm) {
6230 buf = s390_emit_OIHF(buf, dst, value >> 32);
6231 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
6232 }
6233 /* Load value into R0; then combine with destination reg */
6234 buf = s390_emit_load_64imm(buf, R0, value);
6235 return s390_emit_OGR(buf, dst, R0);
6236
6237 case S390_ALU_XOR:
6238 if (s390_host_has_eimm) {
6239 buf = s390_emit_XIHF(buf, dst, value >> 32);
6240 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
6241 }
6242 /* Load value into R0; then combine with destination reg */
6243 buf = s390_emit_load_64imm(buf, R0, value);
6244 return s390_emit_XGR(buf, dst, R0);
6245
sewardj652b56a2011-04-13 15:38:17 +00006246 /* No special considerations for long displacement here. Only the six
6247 least significant bits of VALUE will be taken; all other bits are
6248 ignored. So the DH2 bits are irrelevant and do not influence the
6249 shift operation, independent of whether long-displacement is available
6250 or not. */
sewardj2019a972011-03-07 16:04:07 +00006251 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
6252 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
6253 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
6254 }
6255 goto fail;
6256 }
6257 goto fail;
6258 }
6259
6260 fail:
6261 vpanic("s390_insn_alu_emit");
6262}
6263
6264
6265static UChar *
6266s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
6267 Bool sign_extend)
6268{
sewardj06122e72011-03-28 12:14:48 +00006269 s390_opnd_RMI opnd = insn->variant.unop.src;
sewardj2019a972011-03-07 16:04:07 +00006270
6271 switch (opnd.tag) {
6272 case S390_OPND_REG: {
6273 UChar r1 = hregNumber(insn->variant.unop.dst);
6274 UChar r2 = hregNumber(opnd.variant.reg);
6275
6276 switch (from_size) {
6277 case 1:
6278 /* Widening to a half-word is implemented like widening to a word
6279 because the upper half-word will not be looked at. */
6280 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
6281 if (sign_extend)
6282 return s390_emit_LBRw(buf, r1, r2);
6283 else
6284 return s390_emit_LLCRw(buf, r1, r2);
6285 }
6286 if (insn->size == 8) { /* 8 --> 64 */
6287 if (sign_extend)
6288 return s390_emit_LGBRw(buf, r1, r2);
6289 else
6290 return s390_emit_LLGCRw(buf, r1, r2);
6291 }
6292 goto fail;
6293
6294 case 2:
6295 if (insn->size == 4) { /* 16 --> 32 */
6296 if (sign_extend)
6297 return s390_emit_LHRw(buf, r1, r2);
6298 else
6299 return s390_emit_LLHRw(buf, r1, r2);
6300 }
6301 if (insn->size == 8) { /* 16 --> 64 */
6302 if (sign_extend)
6303 return s390_emit_LGHRw(buf, r1, r2);
6304 else
6305 return s390_emit_LLGHRw(buf, r1, r2);
6306 }
6307 goto fail;
6308
6309 case 4:
6310 if (insn->size == 8) { /* 32 --> 64 */
6311 if (sign_extend)
6312 return s390_emit_LGFR(buf, r1, r2);
6313 else
6314 return s390_emit_LLGFR(buf, r1, r2);
6315 }
6316 goto fail;
6317
6318 default: /* unexpected "from" size */
6319 goto fail;
6320 }
6321 }
6322
6323 case S390_OPND_AMODE: {
6324 UChar r1 = hregNumber(insn->variant.unop.dst);
6325 const s390_amode *src = opnd.variant.am;
6326 UChar b = hregNumber(src->b);
6327 UChar x = hregNumber(src->x);
6328 Int d = src->d;
6329
6330 switch (from_size) {
6331 case 1:
6332 if (insn->size == 4 || insn->size == 2) {
6333 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00006334 return s390_emit_LBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006335 else
6336 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
6337 }
6338 if (insn->size == 8) {
6339 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00006340 return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006341 else
sewardj2019a972011-03-07 16:04:07 +00006342 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
6343 }
6344 goto fail;
6345
6346 case 2:
6347 if (insn->size == 4) { /* 16 --> 32 */
6348 if (sign_extend == 0)
6349 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
6350
6351 switch (src->tag) {
6352 case S390_AMODE_B12:
6353 case S390_AMODE_BX12:
6354 return s390_emit_LH(buf, r1, x, b, d);
6355
6356 case S390_AMODE_B20:
6357 case S390_AMODE_BX20:
6358 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
6359 }
6360 goto fail;
6361 }
6362 if (insn->size == 8) { /* 16 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00006363 if (sign_extend)
6364 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
6365 else
6366 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
6367 }
6368 goto fail;
6369
6370 case 4:
6371 if (insn->size == 8) { /* 32 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00006372 if (sign_extend)
6373 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
6374 else
6375 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
6376 }
6377 goto fail;
6378
6379 default: /* unexpected "from" size */
6380 goto fail;
6381 }
6382 }
6383
6384 case S390_OPND_IMMEDIATE: {
6385 UChar r1 = hregNumber(insn->variant.unop.dst);
6386 ULong value = opnd.variant.imm;
6387
6388 switch (from_size) {
6389 case 1:
6390 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
6391 if (sign_extend) {
6392 /* host can do the sign extension to 16-bit; LHI does the rest */
6393 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
6394 } else {
6395 return s390_emit_LHI(buf, r1, value);
6396 }
6397 }
6398 if (insn->size == 8) { /* 8 --> 64 */
6399 if (sign_extend) {
6400 /* host can do the sign extension to 16-bit; LGHI does the rest */
6401 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
6402 } else {
6403 return s390_emit_LGHI(buf, r1, value);
6404 }
6405 }
6406 goto fail;
6407
6408 case 2:
6409 if (insn->size == 4) { /* 16 --> 32 */
6410 return s390_emit_LHI(buf, r1, value);
6411 }
6412 if (insn->size == 8) { /* 16 --> 64 */
6413 if (sign_extend)
6414 return s390_emit_LGHI(buf, r1, value);
6415 else
6416 return s390_emit_LLILL(buf, r1, value);
6417 }
6418 goto fail;
6419
6420 case 4:
6421 if (insn->size == 8) { /* 32 --> 64 */
6422 if (sign_extend)
6423 return s390_emit_LGFIw(buf, r1, value);
6424 else
6425 return s390_emit_LLILFw(buf, r1, value);
6426 }
6427 goto fail;
6428
6429 default: /* unexpected "from" size */
6430 goto fail;
6431 }
6432 }
6433 }
6434
6435 fail:
6436 vpanic("s390_widen_emit");
6437}
6438
6439
6440static UChar *
6441s390_negate_emit(UChar *buf, const s390_insn *insn)
6442{
6443 s390_opnd_RMI opnd;
6444
6445 opnd = insn->variant.unop.src;
6446
6447 switch (opnd.tag) {
6448 case S390_OPND_REG: {
6449 UChar r1 = hregNumber(insn->variant.unop.dst);
6450 UChar r2 = hregNumber(opnd.variant.reg);
6451
6452 switch (insn->size) {
6453 case 1:
6454 case 2:
6455 case 4:
6456 return s390_emit_LCR(buf, r1, r2);
6457
6458 case 8:
6459 return s390_emit_LCGR(buf, r1, r2);
6460
6461 default:
6462 goto fail;
6463 }
6464 }
6465
6466 case S390_OPND_AMODE: {
6467 UChar r1 = hregNumber(insn->variant.unop.dst);
6468
6469 /* Load bytes into scratch register R0, then negate */
6470 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
6471
6472 switch (insn->size) {
6473 case 1:
6474 case 2:
6475 case 4:
6476 return s390_emit_LCR(buf, r1, R0);
6477
6478 case 8:
6479 return s390_emit_LCGR(buf, r1, R0);
6480
6481 default:
6482 goto fail;
6483 }
6484 }
6485
6486 case S390_OPND_IMMEDIATE: {
6487 UChar r1 = hregNumber(insn->variant.unop.dst);
6488 ULong value = opnd.variant.imm;
6489
6490 value = ~value + 1; /* two's complement */
6491
6492 switch (insn->size) {
6493 case 1:
6494 case 2:
6495 /* Load the immediate values as a 4 byte value. That does not hurt as
6496 those extra bytes will not be looked at. Fall through .... */
6497 case 4:
6498 return s390_emit_load_32imm(buf, r1, value);
6499
6500 case 8:
6501 return s390_emit_load_64imm(buf, r1, value);
6502
6503 default:
6504 goto fail;
6505 }
6506 }
6507 }
6508
6509 fail:
6510 vpanic("s390_negate_emit");
6511}
6512
6513
6514static UChar *
6515s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
6516{
6517 switch (insn->variant.unop.tag) {
6518 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
6519 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
6520 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
6521
6522 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
6523 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
6524 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
6525
6526 case S390_NEGATE: return s390_negate_emit(buf, insn);
6527 }
6528
6529 vpanic("s390_insn_unop_emit");
6530}
6531
6532
6533/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
6534 comparisons will have been converted to 4-byte comparisons in
6535 s390_isel_cc and should not occur here. */
6536static UChar *
6537s390_insn_test_emit(UChar *buf, const s390_insn *insn)
6538{
6539 s390_opnd_RMI opnd;
6540
6541 opnd = insn->variant.test.src;
6542
6543 switch (opnd.tag) {
6544 case S390_OPND_REG: {
6545 UInt reg = hregNumber(opnd.variant.reg);
6546
6547 switch (insn->size) {
6548 case 4:
6549 return s390_emit_LTR(buf, reg, reg);
6550
6551 case 8:
6552 return s390_emit_LTGR(buf, reg, reg);
6553
6554 default:
6555 goto fail;
6556 }
6557 }
6558
6559 case S390_OPND_AMODE: {
6560 const s390_amode *am = opnd.variant.am;
6561 UChar b = hregNumber(am->b);
6562 UChar x = hregNumber(am->x);
6563 Int d = am->d;
6564
6565 switch (insn->size) {
6566 case 4:
6567 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
6568
6569 case 8:
6570 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
6571
6572 default:
6573 goto fail;
6574 }
6575 }
6576
6577 case S390_OPND_IMMEDIATE: {
6578 ULong value = opnd.variant.imm;
6579
6580 switch (insn->size) {
6581 case 4:
6582 buf = s390_emit_load_32imm(buf, R0, value);
6583 return s390_emit_LTR(buf, R0, R0);
6584
6585 case 8:
6586 buf = s390_emit_load_64imm(buf, R0, value);
6587 return s390_emit_LTGR(buf, R0, R0);
6588
6589 default:
6590 goto fail;
6591 }
6592 }
6593
6594 default:
6595 goto fail;
6596 }
6597
6598 fail:
6599 vpanic("s390_insn_test_emit");
6600}
6601
6602
6603static UChar *
6604s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
6605{
6606 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
6607 s390_cc_t cond = insn->variant.cc2bool.cond;
6608
6609 /* Make the destination register be 1 or 0, depending on whether
6610 the relevant condition holds. A 64-bit value is computed. */
6611 if (cond == S390_CC_ALWAYS)
6612 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
6613
6614 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
6615 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
6616 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
6617 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
6618 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
6619
6620 return buf;
6621}
6622
6623
6624/* Only 4-byte and 8-byte operands are handled. */
6625static UChar *
6626s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
6627{
6628 UChar r1, r3, b, old;
6629 Int d;
6630 s390_amode *am;
6631
6632 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
6633 r3 = hregNumber(insn->variant.cas.op3);
6634 old= hregNumber(insn->variant.cas.old_mem);
6635 am = insn->variant.cas.op2;
6636 b = hregNumber(am->b);
6637 d = am->d;
6638
6639 switch (insn->size) {
6640 case 4:
6641 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
6642 buf = s390_emit_LR(buf, R0, r1);
6643 if (am->tag == S390_AMODE_B12)
6644 buf = s390_emit_CS(buf, R0, r3, b, d);
6645 else
6646 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
6647 /* Now copy R0 which has the old memory value to OLD */
6648 return s390_emit_LR(buf, old, R0);
6649
6650 case 8:
6651 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
6652 buf = s390_emit_LGR(buf, R0, r1);
6653 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
6654 /* Now copy R0 which has the old memory value to OLD */
6655 return s390_emit_LGR(buf, old, R0);
6656
6657 default:
6658 goto fail;
6659 }
6660
6661 fail:
6662 vpanic("s390_insn_cas_emit");
6663}
6664
6665
florian448cbba2012-06-06 02:26:01 +00006666/* Only 4-byte and 8-byte operands are handled. */
6667static UChar *
6668s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
6669{
sewardja90622a2012-06-19 13:29:00 +00006670 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
florian448cbba2012-06-06 02:26:01 +00006671 Int d;
6672 s390_amode *am;
6673
6674 r1 = hregNumber(insn->variant.cdas.op1_high); /* expected value */
6675 r1p1 = hregNumber(insn->variant.cdas.op1_low); /* expected value */
6676 r3 = hregNumber(insn->variant.cdas.op3_high);
sewardja90622a2012-06-19 13:29:00 +00006677 /* r3p1 = hregNumber(insn->variant.cdas.op3_low); */ /* unused */
florian448cbba2012-06-06 02:26:01 +00006678 old_high = hregNumber(insn->variant.cdas.old_mem_high);
6679 old_low = hregNumber(insn->variant.cdas.old_mem_low);
6680 scratch = hregNumber(insn->variant.cdas.scratch);
6681 am = insn->variant.cdas.op2;
6682 b = hregNumber(am->b);
6683 d = am->d;
6684
6685 vassert(scratch == 1);
6686
6687 switch (insn->size) {
6688 case 4:
6689 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
6690 and let CDS/CDSY clobber it */
6691 buf = s390_emit_LR(buf, R0, r1);
6692 buf = s390_emit_LR(buf, scratch, r1p1);
6693
6694 if (am->tag == S390_AMODE_B12)
6695 buf = s390_emit_CDS(buf, R0, r3, b, d);
6696 else
6697 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
6698
6699 /* Now copy R0,scratch which has the old memory value to OLD */
6700 buf = s390_emit_LR(buf, old_high, R0);
6701 buf = s390_emit_LR(buf, old_low, scratch);
6702 return buf;
6703
6704 case 8:
6705 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
6706 and let CDSG clobber it */
6707 buf = s390_emit_LGR(buf, R0, r1);
6708 buf = s390_emit_LGR(buf, scratch, r1p1);
6709
6710 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
6711
6712 /* Now copy R0,scratch which has the old memory value to OLD */
6713 buf = s390_emit_LGR(buf, old_high, R0);
6714 buf = s390_emit_LGR(buf, old_low, scratch);
6715 return buf;
6716
6717 default:
6718 goto fail;
6719 }
6720
6721 fail:
6722 vpanic("s390_insn_cas_emit");
6723}
6724
6725
sewardj2019a972011-03-07 16:04:07 +00006726/* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
6727 comparisons will have been converted to 4-byte comparisons in
6728 s390_isel_cc and should not occur here. */
6729static UChar *
6730s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
6731{
6732 s390_opnd_RMI op2;
6733 HReg op1;
6734 Bool signed_comparison;
6735
6736 op1 = insn->variant.compare.src1;
6737 op2 = insn->variant.compare.src2;
6738 signed_comparison = insn->variant.compare.signed_comparison;
6739
6740 switch (op2.tag) {
6741 case S390_OPND_REG: {
6742 UInt r1 = hregNumber(op1);
6743 UInt r2 = hregNumber(op2.variant.reg);
6744
6745 switch (insn->size) {
6746 case 4:
6747 if (signed_comparison)
6748 return s390_emit_CR(buf, r1, r2);
6749 else
6750 return s390_emit_CLR(buf, r1, r2);
6751
6752 case 8:
6753 if (signed_comparison)
6754 return s390_emit_CGR(buf, r1, r2);
6755 else
6756 return s390_emit_CLGR(buf, r1, r2);
6757
6758 default:
6759 goto fail;
6760 }
6761 }
6762
6763 case S390_OPND_AMODE: {
6764 UChar r1 = hregNumber(op1);
6765 const s390_amode *am = op2.variant.am;
6766 UChar b = hregNumber(am->b);
6767 UChar x = hregNumber(am->x);
6768 Int d = am->d;
6769
6770 switch (insn->size) {
6771 case 4:
6772 switch (am->tag) {
6773 case S390_AMODE_B12:
6774 case S390_AMODE_BX12:
6775 if (signed_comparison)
6776 return s390_emit_C(buf, r1, x, b, d);
6777 else
6778 return s390_emit_CL(buf, r1, x, b, d);
6779
6780 case S390_AMODE_B20:
6781 case S390_AMODE_BX20:
6782 if (signed_comparison)
6783 return s390_emit_CY(buf, r1, x, b, DISP20(d));
6784 else
6785 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
6786 }
6787 goto fail;
6788
6789 case 8:
6790 if (signed_comparison)
6791 return s390_emit_CG(buf, r1, x, b, DISP20(d));
6792 else
6793 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
6794
6795 default:
6796 goto fail;
6797 }
6798 }
6799
6800 case S390_OPND_IMMEDIATE: {
6801 UChar r1 = hregNumber(op1);
6802 ULong value = op2.variant.imm;
6803
6804 switch (insn->size) {
6805 case 4:
6806 if (signed_comparison)
6807 return s390_emit_CFIw(buf, r1, value);
6808 else
6809 return s390_emit_CLFIw(buf, r1, value);
6810
6811 case 8:
florian07d34552012-05-26 01:59:21 +00006812 if (s390_host_has_eimm) {
6813 if (signed_comparison) {
6814 if (ulong_fits_signed_32bit(value))
6815 return s390_emit_CGFI(buf, r1, value);
6816 } else {
6817 if (ulong_fits_unsigned_32bit(value))
6818 return s390_emit_CLGFI(buf, r1, value);
6819 }
6820 }
sewardj2019a972011-03-07 16:04:07 +00006821 buf = s390_emit_load_64imm(buf, R0, value);
6822 if (signed_comparison)
6823 return s390_emit_CGR(buf, r1, R0);
6824 else
6825 return s390_emit_CLGR(buf, r1, R0);
6826
6827 default:
6828 goto fail;
6829 }
6830 }
6831
6832 default:
6833 goto fail;
6834 }
6835
6836 fail:
6837 vpanic("s390_insn_compare_emit");
6838}
6839
6840
6841static UChar *
6842s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
6843{
6844 s390_opnd_RMI op2;
6845 UChar r1;
6846 Bool signed_multiply;
6847
6848 /* The register number identifying the register pair */
6849 r1 = hregNumber(insn->variant.mul.dst_hi);
6850
6851 op2 = insn->variant.mul.op2;
6852 signed_multiply = insn->variant.mul.signed_multiply;
6853
6854 switch (op2.tag) {
6855 case S390_OPND_REG: {
6856 UInt r2 = hregNumber(op2.variant.reg);
6857
6858 switch (insn->size) {
6859 case 1:
6860 case 2:
6861 case 4:
6862 if (signed_multiply)
6863 return s390_emit_MR(buf, r1, r2);
6864 else
6865 return s390_emit_MLR(buf, r1, r2);
6866
6867 case 8:
6868 if (signed_multiply)
6869 vpanic("s390_insn_mul_emit");
6870 else
6871 return s390_emit_MLGR(buf, r1, r2);
6872
6873 default:
6874 goto fail;
6875 }
6876 }
6877
6878 case S390_OPND_AMODE: {
6879 const s390_amode *am = op2.variant.am;
6880 UChar b = hregNumber(am->b);
6881 UChar x = hregNumber(am->x);
6882 Int d = am->d;
6883
6884 switch (insn->size) {
6885 case 1:
6886 case 2:
6887 /* Load bytes into scratch register R0, then multiply */
6888 buf = s390_emit_load_mem(buf, insn->size, R0, am);
6889 if (signed_multiply)
6890 return s390_emit_MR(buf, r1, R0);
6891 else
6892 return s390_emit_MLR(buf, r1, R0);
6893
6894 case 4:
6895 switch (am->tag) {
6896 case S390_AMODE_B12:
6897 case S390_AMODE_BX12:
6898 if (signed_multiply)
6899 return s390_emit_M(buf, r1, x, b, d);
6900 else
6901 return s390_emit_ML(buf, r1, x, b, DISP20(d));
6902
6903 case S390_AMODE_B20:
6904 case S390_AMODE_BX20:
6905 if (signed_multiply)
6906 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
6907 else
sewardjb13a92a2011-04-13 14:44:29 +00006908 return s390_emit_ML(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006909 }
6910 goto fail;
6911
6912 case 8:
6913 if (signed_multiply)
6914 vpanic("s390_insn_mul_emit");
6915 else
6916 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
6917
6918 default:
6919 goto fail;
6920 }
6921 }
6922
6923 case S390_OPND_IMMEDIATE: {
6924 ULong value = op2.variant.imm;
6925
6926 switch (insn->size) {
6927 case 1:
6928 case 2:
6929 case 4:
6930 buf = s390_emit_load_32imm(buf, R0, value);
6931 if (signed_multiply)
6932 return s390_emit_MR(buf, r1, R0);
6933 else
6934 return s390_emit_MLR(buf, r1, R0);
6935
6936 case 8:
6937 buf = s390_emit_load_64imm(buf, R0, value);
6938 if (signed_multiply)
6939 vpanic("s390_insn_mul_emit");
6940 else
6941 return s390_emit_MLGR(buf, r1, R0);
6942
6943 default:
6944 goto fail;
6945 }
6946 }
6947
6948 default:
6949 goto fail;
6950 }
6951
6952 fail:
6953 vpanic("s390_insn_mul_emit");
6954}
6955
6956
6957static UChar *
6958s390_insn_div_emit(UChar *buf, const s390_insn *insn)
6959{
6960 s390_opnd_RMI op2;
6961 UChar r1;
6962 Bool signed_divide;
6963
6964 r1 = hregNumber(insn->variant.div.op1_hi);
6965 op2 = insn->variant.div.op2;
6966 signed_divide = insn->variant.div.signed_divide;
6967
6968 switch (op2.tag) {
6969 case S390_OPND_REG: {
6970 UInt r2 = hregNumber(op2.variant.reg);
6971
6972 switch (insn->size) {
6973 case 4:
6974 if (signed_divide)
6975 return s390_emit_DR(buf, r1, r2);
6976 else
6977 return s390_emit_DLR(buf, r1, r2);
6978
6979 case 8:
6980 if (signed_divide)
6981 vpanic("s390_insn_div_emit");
6982 else
6983 return s390_emit_DLGR(buf, r1, r2);
6984
6985 default:
6986 goto fail;
6987 }
6988 }
6989
6990 case S390_OPND_AMODE: {
6991 const s390_amode *am = op2.variant.am;
6992 UChar b = hregNumber(am->b);
6993 UChar x = hregNumber(am->x);
6994 Int d = am->d;
6995
6996 switch (insn->size) {
6997 case 4:
6998 switch (am->tag) {
6999 case S390_AMODE_B12:
7000 case S390_AMODE_BX12:
7001 if (signed_divide)
7002 return s390_emit_D(buf, r1, x, b, d);
7003 else
7004 return s390_emit_DL(buf, r1, x, b, DISP20(d));
7005
7006 case S390_AMODE_B20:
7007 case S390_AMODE_BX20:
sewardjb13a92a2011-04-13 14:44:29 +00007008 if (signed_divide) {
7009 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007010 return s390_emit_DR(buf, r1, R0);
sewardjb13a92a2011-04-13 14:44:29 +00007011 } else
7012 return s390_emit_DL(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007013 }
7014 goto fail;
7015
7016 case 8:
7017 if (signed_divide)
7018 vpanic("s390_insn_div_emit");
7019 else
7020 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
7021
7022 default:
7023 goto fail;
7024 }
7025 }
7026
7027 case S390_OPND_IMMEDIATE: {
7028 ULong value = op2.variant.imm;
7029
7030 switch (insn->size) {
7031 case 4:
7032 buf = s390_emit_load_32imm(buf, R0, value);
7033 if (signed_divide)
7034 return s390_emit_DR(buf, r1, R0);
7035 else
7036 return s390_emit_DLR(buf, r1, R0);
7037
7038 case 8:
7039 buf = s390_emit_load_64imm(buf, R0, value);
7040 if (signed_divide)
7041 vpanic("s390_insn_div_emit");
7042 else
7043 return s390_emit_DLGR(buf, r1, R0);
7044
7045 default:
7046 goto fail;
7047 }
7048 }
7049
7050 default:
7051 goto fail;
7052 }
7053
7054 fail:
7055 vpanic("s390_insn_div_emit");
7056}
7057
7058
7059static UChar *
7060s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
7061{
7062 s390_opnd_RMI op2;
7063 UChar r1;
7064
7065 r1 = hregNumber(insn->variant.divs.rem);
7066 op2 = insn->variant.divs.op2;
7067
7068 switch (op2.tag) {
7069 case S390_OPND_REG: {
7070 UInt r2 = hregNumber(op2.variant.reg);
7071
7072 return s390_emit_DSGR(buf, r1, r2);
7073 }
7074
7075 case S390_OPND_AMODE: {
7076 const s390_amode *am = op2.variant.am;
7077 UChar b = hregNumber(am->b);
7078 UChar x = hregNumber(am->x);
7079 Int d = am->d;
7080
7081 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
7082 }
7083
7084 case S390_OPND_IMMEDIATE: {
7085 ULong value = op2.variant.imm;
7086
7087 buf = s390_emit_load_64imm(buf, R0, value);
7088 return s390_emit_DSGR(buf, r1, R0);
7089 }
7090
7091 default:
7092 goto fail;
7093 }
7094
7095 fail:
7096 vpanic("s390_insn_divs_emit");
7097}
7098
7099
7100static UChar *
sewardj611b06e2011-03-24 08:57:29 +00007101s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
sewardj2019a972011-03-07 16:04:07 +00007102{
7103 s390_opnd_RMI src;
sewardj611b06e2011-03-24 08:57:29 +00007104 UChar r1, r1p1, r2, *p;
sewardj2019a972011-03-07 16:04:07 +00007105
sewardj611b06e2011-03-24 08:57:29 +00007106 r1 = hregNumber(insn->variant.clz.num_bits);
7107 r1p1 = hregNumber(insn->variant.clz.clobber);
sewardj2019a972011-03-07 16:04:07 +00007108
7109 vassert((r1 & 0x1) == 0);
7110 vassert(r1p1 == r1 + 1);
7111
sewardj611b06e2011-03-24 08:57:29 +00007112 p = buf;
7113 src = insn->variant.clz.src;
sewardj2019a972011-03-07 16:04:07 +00007114
sewardj611b06e2011-03-24 08:57:29 +00007115 /* Get operand and move it to r2 */
sewardj2019a972011-03-07 16:04:07 +00007116 switch (src.tag) {
sewardj611b06e2011-03-24 08:57:29 +00007117 case S390_OPND_REG:
7118 r2 = hregNumber(src.variant.reg);
7119 break;
sewardj2019a972011-03-07 16:04:07 +00007120
7121 case S390_OPND_AMODE: {
7122 const s390_amode *am = src.variant.am;
7123 UChar b = hregNumber(am->b);
7124 UChar x = hregNumber(am->x);
7125 Int d = am->d;
7126
sewardj611b06e2011-03-24 08:57:29 +00007127 p = s390_emit_LG(p, R0, x, b, DISP20(d));
7128 r2 = R0;
7129 break;
sewardj2019a972011-03-07 16:04:07 +00007130 }
7131
7132 case S390_OPND_IMMEDIATE: {
7133 ULong value = src.variant.imm;
7134
sewardj611b06e2011-03-24 08:57:29 +00007135 p = s390_emit_load_64imm(p, R0, value);
7136 r2 = R0;
7137 break;
sewardj2019a972011-03-07 16:04:07 +00007138 }
7139
7140 default:
7141 goto fail;
7142 }
7143
sewardj611b06e2011-03-24 08:57:29 +00007144 /* Use FLOGR if you can */
7145 if (s390_host_has_eimm) {
7146 return s390_emit_FLOGR(p, r1, r2);
7147 }
7148
7149 /*
7150 r0 = r2;
7151 r1 = 64;
7152 while (r0 != 0) {
7153 r1 -= 1;
7154 r0 >>= 1;
7155 }
7156 */
7157 p = s390_emit_LTGR(p, R0, r2);
7158 p = s390_emit_LLILL(p, r1, 64);
7159
7160 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
7161 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
7162 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
7163 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
7164 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
7165 (UShort)(-(4 + 6 + 4) / 2));
7166 return p;
7167
sewardj2019a972011-03-07 16:04:07 +00007168 fail:
sewardj611b06e2011-03-24 08:57:29 +00007169 vpanic("s390_insn_clz_emit");
sewardj2019a972011-03-07 16:04:07 +00007170}
7171
7172
7173static UChar *
sewardj2019a972011-03-07 16:04:07 +00007174s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
7175{
7176 s390_cc_t cond;
7177 ULong target;
7178 UChar *ptmp = buf;
7179
7180 cond = insn->variant.helper_call.cond;
7181 target = insn->variant.helper_call.target;
7182
7183 if (cond != S390_CC_ALWAYS) {
7184 /* So we have something like this
7185 if (cond) call X;
7186 Y: ...
7187 We convert this into
7188 if (! cond) goto Y; // BRC opcode; 4 bytes
7189 call X;
7190 Y:
7191 */
7192 /* 4 bytes (a BRC insn) to be filled in here */
7193 buf += 4;
7194 }
7195
7196 /* Load the target address into a register, that
7197 (a) is not used for passing parameters to the helper and
7198 (b) can be clobbered by the callee
florianc9e90e52012-05-27 17:20:47 +00007199 (c) is not special to the BASR insn
7200 r1 is the only choice.
sewardj2019a972011-03-07 16:04:07 +00007201 Also, need to arrange for the return address be put into the
7202 link-register */
7203 buf = s390_emit_load_64imm(buf, 1, target);
7204
7205 /* Stash away the client's FPC register because the helper might change it. */
7206 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
7207
7208 /* Before we can call the helper, we need to save the link register,
7209 because the BASR will overwrite it. We cannot use a register for that.
7210 (a) Volatile registers will be modified by the helper.
7211 (b) For saved registers the client code assumes that they have not
7212 changed after the function returns. So we cannot use it to store
7213 the link register.
7214 In the dispatcher, before calling the client code, we have arranged for
7215 a location on the stack for this purpose. See dispatch-s390x-linux.S. */
7216 buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR
7217 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
7218 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
florian01ed6e72012-05-27 16:52:43 +00007219
7220 /* Move the return value to the destination register */
7221 if (insn->variant.helper_call.dst != INVALID_HREG) {
7222 buf = s390_emit_LGR(buf, hregNumber(insn->variant.helper_call.dst),
7223 S390_REGNO_RETURN_VALUE);
7224 }
7225
sewardj2019a972011-03-07 16:04:07 +00007226 buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR
7227 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
7228 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
7229 S390_OFFSET_SAVED_FPC_C);
7230
7231 if (cond != S390_CC_ALWAYS) {
7232 Int delta = buf - ptmp;
7233
7234 delta >>= 1; /* immediate constant is #half-words */
7235 vassert(delta > 0 && delta < (1 << 16));
7236 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7237 }
7238
7239 return buf;
7240}
7241
7242
7243static UChar *
7244s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
7245{
7246 HReg dst;
7247 s390_opnd_RMI src;
7248 s390_cc_t cond;
7249 UChar *p, *ptmp = 0; /* avoid compiler warnings */
7250
7251 cond = insn->variant.cond_move.cond;
7252 dst = insn->variant.cond_move.dst;
7253 src = insn->variant.cond_move.src;
7254
7255 p = buf;
7256
7257 /* Branch (if cond fails) over move instrs */
7258 if (cond != S390_CC_ALWAYS) {
7259 /* Don't know how many bytes to jump over yet.
7260 Make space for a BRC instruction (4 bytes) and fill in later. */
7261 ptmp = p; /* to be filled in here */
7262 p += 4;
7263 }
7264
7265 // cond true: move src => dst
7266
7267 switch (src.tag) {
7268 case S390_OPND_REG:
7269 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
7270 break;
7271
7272 case S390_OPND_AMODE:
7273 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
7274 break;
7275
7276 case S390_OPND_IMMEDIATE: {
7277 ULong value = src.variant.imm;
7278 UInt r = hregNumber(dst);
7279
7280 switch (insn->size) {
7281 case 1:
7282 case 2:
7283 /* Load the immediate values as a 4 byte value. That does not hurt as
7284 those extra bytes will not be looked at. Fall through .... */
7285 case 4:
7286 p = s390_emit_load_32imm(p, r, value);
7287 break;
7288
7289 case 8:
7290 p = s390_emit_load_64imm(p, r, value);
7291 break;
7292 }
7293 break;
7294 }
7295
7296 default:
7297 goto fail;
7298 }
7299
7300 if (cond != S390_CC_ALWAYS) {
7301 Int delta = p - ptmp;
7302
7303 delta >>= 1; /* immediate constant is #half-words */
7304 vassert(delta > 0 && delta < (1 << 16));
7305 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7306 }
7307
7308 return p;
7309
7310 fail:
7311 vpanic("s390_insn_cond_move_emit");
7312}
7313
7314
sewardj2019a972011-03-07 16:04:07 +00007315static UChar *
7316s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
7317{
7318 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
7319 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
7320 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +00007321
7322 switch (insn->size) {
7323 case 4:
7324 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00007325 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
7326 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00007327 default: goto fail;
7328 }
7329 break;
7330
7331 case 8:
7332 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00007333 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
7334 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00007335 default: goto fail;
7336 }
7337 break;
7338
7339 default: goto fail;
7340 }
7341
sewardj2019a972011-03-07 16:04:07 +00007342 fail:
7343 vpanic("s390_insn_bfp_triop_emit");
7344}
7345
7346
7347static UChar *
7348s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
7349{
floriancc491a62012-09-10 23:44:37 +00007350 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
7351 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00007352
7353 switch (insn->size) {
7354 case 4:
7355 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00007356 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
7357 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
7358 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
7359 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00007360 default: goto fail;
7361 }
7362 break;
7363
7364 case 8:
7365 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00007366 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
7367 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
7368 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
7369 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00007370 default: goto fail;
7371 }
7372 break;
7373
floriancc491a62012-09-10 23:44:37 +00007374 case 16:
7375 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00007376 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
7377 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
7378 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
7379 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00007380 default: goto fail;
7381 }
7382 break;
7383
sewardj2019a972011-03-07 16:04:07 +00007384 default: goto fail;
7385 }
7386
sewardj2019a972011-03-07 16:04:07 +00007387 fail:
7388 vpanic("s390_insn_bfp_binop_emit");
7389}
7390
7391
7392static UChar *
7393s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
7394{
floriancc491a62012-09-10 23:44:37 +00007395 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
7396 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
sewardj2019a972011-03-07 16:04:07 +00007397
7398 switch (insn->variant.bfp_unop.tag) {
7399 case S390_BFP_ABS:
7400 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00007401 case 4: return s390_emit_LPEBR(buf, r1, r2);
7402 case 8: return s390_emit_LPDBR(buf, r1, r2);
7403 case 16: return s390_emit_LPXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00007404 default: goto fail;
7405 }
7406 break;
7407
7408 case S390_BFP_NABS:
7409 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00007410 case 4: return s390_emit_LNEBR(buf, r1, r2);
7411 case 8: return s390_emit_LNDBR(buf, r1, r2);
7412 case 16: return s390_emit_LNXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00007413 default: goto fail;
7414 }
7415 break;
7416
7417 case S390_BFP_NEG:
7418 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00007419 case 4: return s390_emit_LCEBR(buf, r1, r2);
7420 case 8: return s390_emit_LCDBR(buf, r1, r2);
7421 case 16: return s390_emit_LCXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00007422 default: goto fail;
7423 }
7424 break;
7425
7426 case S390_BFP_SQRT:
7427 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00007428 case 4: return s390_emit_SQEBR(buf, r1, r2);
7429 case 8: return s390_emit_SQDBR(buf, r1, r2);
7430 case 16: return s390_emit_SQXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00007431 default: goto fail;
7432 }
7433 break;
7434
florian9fcff4c2012-09-10 03:09:04 +00007435 default: goto fail;
7436 }
7437
florian9fcff4c2012-09-10 03:09:04 +00007438 fail:
7439 vpanic("s390_insn_bfp_unop_emit");
7440}
7441
7442
7443static UChar *
7444s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
7445{
floriancc491a62012-09-10 23:44:37 +00007446 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
7447 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
florian125e20d2012-10-07 15:42:37 +00007448 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
florian2c74d242012-09-12 19:38:42 +00007449 /* The IEEE-inexact-exception control is not modelled. So the
7450 m4 field is 0 (which is what GCC does, too) */
7451 const UInt m4 = 0;
florian9fcff4c2012-09-10 03:09:04 +00007452
florian9fcff4c2012-09-10 03:09:04 +00007453 switch (insn->variant.bfp_convert.tag) {
floriancc491a62012-09-10 23:44:37 +00007454 /* Convert to fixed */
florian9fcff4c2012-09-10 03:09:04 +00007455 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
7456 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00007457 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00007458 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
7459 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00007460 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00007461
floriancc491a62012-09-10 23:44:37 +00007462 /* Convert to logical */
florian2c74d242012-09-12 19:38:42 +00007463 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
7464 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
7465 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
7466 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
7467 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
7468 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00007469
florian2c74d242012-09-12 19:38:42 +00007470 /* Convert from fixed */
7471 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
7472 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
7473 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
7474 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
7475 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
7476 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
7477
7478 /* Convert from logical */
7479 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
7480 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
7481 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
7482 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
7483 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
7484 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
7485
7486 /* Load lengthened */
7487 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00007488 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
7489 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00007490
florian2c74d242012-09-12 19:38:42 +00007491 /* Load rounded */
7492 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
7493 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
7494 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
floriancc491a62012-09-10 23:44:37 +00007495
sewardj2019a972011-03-07 16:04:07 +00007496 default: goto fail;
7497 }
7498
sewardj2019a972011-03-07 16:04:07 +00007499 fail:
florian9fcff4c2012-09-10 03:09:04 +00007500 vpanic("s390_insn_bfp_convert_emit");
sewardj2019a972011-03-07 16:04:07 +00007501}
7502
7503
7504static UChar *
7505s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
7506{
7507 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +00007508 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
7509 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00007510
7511 switch (insn->size) {
floriancc491a62012-09-10 23:44:37 +00007512 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
7513 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
7514 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
sewardj2019a972011-03-07 16:04:07 +00007515 default: goto fail;
7516 }
7517
7518 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
7519
7520 fail:
7521 vpanic("s390_insn_bfp_compare_emit");
7522}
7523
7524
7525static UChar *
sewardja52e37e2011-04-28 18:48:06 +00007526s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
7527{
7528 return s390_emit_BCR(buf, 0xF, 0x0);
7529}
7530
7531
florianad43b3a2012-02-20 15:01:14 +00007532static UChar *
7533s390_insn_gzero_emit(UChar *buf, const s390_insn *insn)
7534{
7535 return s390_emit_XC(buf, insn->size - 1,
7536 S390_REGNO_GUEST_STATE_POINTER, insn->variant.gzero.offset,
7537 S390_REGNO_GUEST_STATE_POINTER, insn->variant.gzero.offset);
7538}
7539
7540
7541static UChar *
7542s390_insn_gadd_emit(UChar *buf, const s390_insn *insn)
7543{
7544 return s390_emit_AGSI(buf, insn->variant.gadd.delta,
7545 S390_REGNO_GUEST_STATE_POINTER,
7546 DISP20(insn->variant.gadd.offset));
7547}
7548
7549
florian2c74d242012-09-12 19:38:42 +00007550static UChar *
florian125e20d2012-10-07 15:42:37 +00007551s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
florian2c74d242012-09-12 19:38:42 +00007552{
florian125e20d2012-10-07 15:42:37 +00007553 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00007554
7555 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
7556 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
7557 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
7558
7559 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
7560 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
florian6d8e26e2012-09-12 19:52:16 +00007561 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
florian2c74d242012-09-12 19:38:42 +00007562
7563 return buf;
7564}
7565
7566
florianc8e4f562012-10-27 16:19:31 +00007567static UChar *
7568s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
7569{
7570 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
7571
7572 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
7573 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
7574 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
7575
7576 /* DFP rounding mode is set at bit position 25:27 in FPC register */
7577 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
7578 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
7579 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
7580 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
7581
7582 return buf;
7583}
7584
7585
florian8844a632012-04-13 04:04:06 +00007586/* Define convenience functions needed for translation chaining.
7587 Any changes need to be applied to the functions in concert. */
7588
florian1c857042012-04-15 04:11:07 +00007589static __inline__ Bool
7590s390_insn_is_BRCL(const UChar *p, UChar condition)
7591{
7592 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
7593}
7594
7595static __inline__ Bool
7596s390_insn_is_BR(const UChar *p, UChar reg)
7597{
7598 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
7599}
7600
florianebaf8d92012-04-22 17:38:46 +00007601
7602/* The length of the BASR insn */
7603#define S390_BASR_LEN 2
7604
florian1c857042012-04-15 04:11:07 +00007605
florian8844a632012-04-13 04:04:06 +00007606/* Load the 64-bit VALUE into REG. Note that this function must NOT
7607 optimise the generated code by looking at the value. I.e. using
floriane09e8bb2012-05-07 03:28:18 +00007608 LGHI if value == 0 would be very wrong. */
florian8844a632012-04-13 04:04:06 +00007609static UChar *
7610s390_tchain_load64(UChar *buf, UChar regno, ULong value)
7611{
florian1c857042012-04-15 04:11:07 +00007612 UChar *begin = buf;
7613
florian1c2b4db2012-04-22 17:46:31 +00007614 if (s390_host_has_eimm) {
7615 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
7616 buf = s390_emit_IIHF(buf, regno, value >> 32);
7617 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
7618 } else {
7619 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
7620 value >>= 16;
7621 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
7622 value >>= 16;
7623 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
7624 value >>= 16;
7625 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
7626 }
florian8844a632012-04-13 04:04:06 +00007627
florian1c857042012-04-15 04:11:07 +00007628 vassert(buf - begin == s390_tchain_load64_len());
7629
florian8844a632012-04-13 04:04:06 +00007630 return buf;
7631}
7632
7633/* Return number of bytes generated by s390_tchain_load64 */
7634static UInt
7635s390_tchain_load64_len(void)
7636{
florian1c2b4db2012-04-22 17:46:31 +00007637 if (s390_host_has_eimm) {
7638 return 6 + 6; /* IIHF + IILF */
7639 }
florianebaf8d92012-04-22 17:38:46 +00007640 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
florian8844a632012-04-13 04:04:06 +00007641}
7642
7643/* Verify that CODE is the code sequence generated by s390_tchain_load64
7644 to load VALUE into REGNO. Return pointer to the byte following the
7645 insn sequence. */
7646static const UChar *
7647s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
7648{
7649 UInt regmask = regno << 4;
7650 UInt hw;
7651
florian1c2b4db2012-04-22 17:46:31 +00007652 if (s390_host_has_eimm) {
7653 /* Check for IIHF */
7654 vassert(code[0] == 0xC0);
7655 vassert(code[1] == (0x08 | regmask));
7656 vassert(*(const UInt *)&code[2] == (value >> 32));
7657 /* Check for IILF */
7658 vassert(code[6] == 0xC0);
7659 vassert(code[7] == (0x09 | regmask));
7660 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
7661 } else {
7662 /* Check for IILL */
7663 hw = value & 0xFFFF;
7664 vassert(code[0] == 0xA5);
7665 vassert(code[1] == (0x03 | regmask));
7666 vassert(code[2] == (hw >> 8));
7667 vassert(code[3] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00007668
florian1c2b4db2012-04-22 17:46:31 +00007669 /* Check for IILH */
7670 hw = (value >> 16) & 0xFFFF;
7671 vassert(code[4] == 0xA5);
7672 vassert(code[5] == (0x02 | regmask));
7673 vassert(code[6] == (hw >> 8));
7674 vassert(code[7] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00007675
florian1c2b4db2012-04-22 17:46:31 +00007676 /* Check for IIHL */
7677 hw = (value >> 32) & 0xFFFF;
7678 vassert(code[8] == 0xA5);
7679 vassert(code[9] == (0x01 | regmask));
7680 vassert(code[10] == (hw >> 8));
7681 vassert(code[11] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00007682
florian1c2b4db2012-04-22 17:46:31 +00007683 /* Check for IIHH */
7684 hw = (value >> 48) & 0xFFFF;
7685 vassert(code[12] == 0xA5);
7686 vassert(code[13] == (0x00 | regmask));
7687 vassert(code[14] == (hw >> 8));
7688 vassert(code[15] == (hw & 0xFF));
7689 }
florian8844a632012-04-13 04:04:06 +00007690
florian1c857042012-04-15 04:11:07 +00007691 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00007692}
7693
7694/* CODE points to the code sequence as generated by s390_tchain_load64.
florian5ea257b2012-09-29 17:05:46 +00007695 Change the loaded value to IMM64. Return pointer to the byte following
florian8844a632012-04-13 04:04:06 +00007696 the patched code sequence. */
7697static UChar *
7698s390_tchain_patch_load64(UChar *code, ULong imm64)
7699{
florian1c2b4db2012-04-22 17:46:31 +00007700 if (s390_host_has_eimm) {
7701 /* Patch IIHF */
7702 *(UInt *)&code[2] = imm64 >> 32;
7703 /* Patch IILF */
7704 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
7705 } else {
7706 code[3] = imm64 & 0xFF; imm64 >>= 8;
7707 code[2] = imm64 & 0xFF; imm64 >>= 8;
7708 code[7] = imm64 & 0xFF; imm64 >>= 8;
7709 code[6] = imm64 & 0xFF; imm64 >>= 8;
7710 code[11] = imm64 & 0xFF; imm64 >>= 8;
7711 code[10] = imm64 & 0xFF; imm64 >>= 8;
7712 code[15] = imm64 & 0xFF; imm64 >>= 8;
7713 code[14] = imm64 & 0xFF; imm64 >>= 8;
7714 }
florian8844a632012-04-13 04:04:06 +00007715
florian1c857042012-04-15 04:11:07 +00007716 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00007717}
7718
7719
7720/* NB: what goes on here has to be very closely coordinated with the
7721 chainXDirect_S390 and unchainXDirect_S390 below. */
7722static UChar *
7723s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
7724 void *disp_cp_chain_me_to_slowEP,
7725 void *disp_cp_chain_me_to_fastEP)
7726{
7727 /* We're generating chain-me requests here, so we need to be
7728 sure this is actually allowed -- no-redir translations can't
7729 use chain-me's. Hence: */
7730 vassert(disp_cp_chain_me_to_slowEP != NULL);
7731 vassert(disp_cp_chain_me_to_fastEP != NULL);
7732
7733 /* Use ptmp for backpatching conditional jumps. */
7734 UChar *ptmp = buf;
7735
7736 /* First off, if this is conditional, create a conditional
7737 jump over the rest of it. */
7738 s390_cc_t cond = insn->variant.xdirect.cond;
7739
7740 if (cond != S390_CC_ALWAYS) {
7741 /* So we have something like this
7742 if (cond) do_xdirect;
7743 Y: ...
7744 We convert this into
7745 if (! cond) goto Y; // BRC opcode; 4 bytes
7746 do_xdirect;
7747 Y:
7748 */
7749 /* 4 bytes (a BRC insn) to be filled in here */
7750 buf += 4;
7751 }
7752
7753 /* Update the guest IA. */
7754 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
7755
7756 const s390_amode *amode = insn->variant.xdirect.guest_IA;
florianbf516d12012-04-21 15:53:13 +00007757 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00007758 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007759 UInt d = amode->d;
7760
florianbf516d12012-04-21 15:53:13 +00007761 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00007762
florian8844a632012-04-13 04:04:06 +00007763 /* Load the chosen entry point into the scratch reg */
7764 void *disp_cp_chain_me;
7765
7766 disp_cp_chain_me =
7767 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
7768 : disp_cp_chain_me_to_slowEP;
florianebaf8d92012-04-22 17:38:46 +00007769 /* Get the address of the beginning of the load64 code sequence into %r1.
7770 Do not change the register! This is part of the protocol with the
7771 dispatcher. */
7772 buf = s390_emit_BASR(buf, 1, R0);
florian8844a632012-04-13 04:04:06 +00007773
florianebaf8d92012-04-22 17:38:46 +00007774 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
florian8844a632012-04-13 04:04:06 +00007775 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
7776 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
7777
florianebaf8d92012-04-22 17:38:46 +00007778 /* goto *tchain_scratch */
7779 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00007780
7781 /* --- END of PATCHABLE BYTES --- */
7782
7783 /* Fix up the conditional jump, if there was one. */
7784 if (cond != S390_CC_ALWAYS) {
7785 Int delta = buf - ptmp;
7786
7787 delta >>= 1; /* immediate constant is #half-words */
7788 vassert(delta > 0 && delta < (1 << 16));
7789 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7790 }
7791
7792 return buf;
7793}
7794
7795/* Return the number of patchable bytes from an xdirect insn. */
7796static UInt
7797s390_xdirect_patchable_len(void)
7798{
florianebaf8d92012-04-22 17:38:46 +00007799 return s390_tchain_load64_len() + S390_BASR_LEN;
florian8844a632012-04-13 04:04:06 +00007800}
7801
7802
7803static UChar *
7804s390_insn_xindir_emit(UChar *buf, const s390_insn *insn, void *disp_cp_xindir)
7805{
7806 /* We're generating transfers that could lead indirectly to a
7807 chain-me, so we need to be sure this is actually allowed --
7808 no-redir translations are not allowed to reach normal
7809 translations without going through the scheduler. That means
7810 no XDirects or XIndirs out from no-redir translations.
7811 Hence: */
7812 vassert(disp_cp_xindir != NULL);
7813
7814 /* Use ptmp for backpatching conditional jumps. */
7815 UChar *ptmp = buf;
7816
7817 /* First off, if this is conditional, create a conditional
7818 jump over the rest of it. */
7819 s390_cc_t cond = insn->variant.xdirect.cond;
7820
7821 if (cond != S390_CC_ALWAYS) {
7822 /* So we have something like this
7823 if (cond) do_xdirect;
7824 Y: ...
7825 We convert this into
7826 if (! cond) goto Y; // BRC opcode; 4 bytes
7827 do_xdirect;
7828 Y:
7829 */
7830 /* 4 bytes (a BRC insn) to be filled in here */
7831 buf += 4;
7832 }
7833
7834 /* Update the guest IA with the address in xdirect.dst. */
florian7346c7a2012-04-13 21:14:24 +00007835 const s390_amode *amode = insn->variant.xindir.guest_IA;
florian8844a632012-04-13 04:04:06 +00007836
florianbf516d12012-04-21 15:53:13 +00007837 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00007838 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007839 UInt d = amode->d;
florian7346c7a2012-04-13 21:14:24 +00007840 UInt regno = hregNumber(insn->variant.xindir.dst);
florian8844a632012-04-13 04:04:06 +00007841
florianbf516d12012-04-21 15:53:13 +00007842 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00007843
7844 /* load tchain_scratch, #disp_indir */
7845 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
7846 Ptr_to_ULong(disp_cp_xindir));
florianebaf8d92012-04-22 17:38:46 +00007847 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00007848 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
7849
7850 /* Fix up the conditional jump, if there was one. */
7851 if (cond != S390_CC_ALWAYS) {
7852 Int delta = buf - ptmp;
7853
7854 delta >>= 1; /* immediate constant is #half-words */
7855 vassert(delta > 0 && delta < (1 << 16));
7856 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7857 }
7858
7859 return buf;
7860}
7861
7862static UChar *
7863s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
7864 void *disp_cp_xassisted)
7865{
7866 /* Use ptmp for backpatching conditional jumps. */
7867 UChar *ptmp = buf;
7868
7869 /* First off, if this is conditional, create a conditional
7870 jump over the rest of it. */
7871 s390_cc_t cond = insn->variant.xdirect.cond;
7872
7873 if (cond != S390_CC_ALWAYS) {
7874 /* So we have something like this
7875 if (cond) do_xdirect;
7876 Y: ...
7877 We convert this into
7878 if (! cond) goto Y; // BRC opcode; 4 bytes
7879 do_xdirect;
7880 Y:
7881 */
7882 /* 4 bytes (a BRC insn) to be filled in here */
7883 buf += 4;
7884 }
7885
7886 /* Update the guest IA with the address in xassisted.dst. */
7887 const s390_amode *amode = insn->variant.xassisted.guest_IA;
7888
florianbf516d12012-04-21 15:53:13 +00007889 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00007890 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007891 UInt d = amode->d;
7892 UInt regno = hregNumber(insn->variant.xassisted.dst);
7893
florianbf516d12012-04-21 15:53:13 +00007894 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00007895
7896 UInt trcval = 0;
7897
7898 switch (insn->variant.xassisted.kind) {
7899 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
7900 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
florian8844a632012-04-13 04:04:06 +00007901 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
7902 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
florian4e0083e2012-08-26 03:41:56 +00007903 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
florian8844a632012-04-13 04:04:06 +00007904 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
7905 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
7906 case Ijk_TInval: trcval = VEX_TRC_JMP_TINVAL; break;
7907 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
7908 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
7909 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
7910 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
7911 /* We don't expect to see the following being assisted. */
7912 case Ijk_Ret:
7913 case Ijk_Call:
7914 /* fallthrough */
7915 default:
7916 ppIRJumpKind(insn->variant.xassisted.kind);
7917 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
7918 }
7919
7920 vassert(trcval != 0);
7921
7922 /* guest_state_pointer = trcval */
7923 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
7924
7925 /* load tchain_scratch, #disp_assisted */
7926 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
7927 Ptr_to_ULong(disp_cp_xassisted));
7928
florianebaf8d92012-04-22 17:38:46 +00007929 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00007930 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
7931
7932 /* Fix up the conditional jump, if there was one. */
7933 if (cond != S390_CC_ALWAYS) {
7934 Int delta = buf - ptmp;
7935
7936 delta >>= 1; /* immediate constant is #half-words */
7937 vassert(delta > 0 && delta < (1 << 16));
7938 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7939 }
7940
7941 return buf;
7942}
7943
7944
7945/* Pseudo code:
7946
7947 guest_state[host_EvC_COUNTER] -= 1;
7948 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
7949 goto guest_state[host_EvC_FAILADDR];
7950 nofail: ;
7951
7952 The dispatch counter is a 32-bit value. */
7953static UChar *
7954s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn)
7955{
7956 s390_amode *amode;
florianbf516d12012-04-21 15:53:13 +00007957 UInt b, d;
florian8844a632012-04-13 04:04:06 +00007958 UChar *code_begin, *code_end;
7959
7960 code_begin = buf;
7961
7962 amode = insn->variant.evcheck.counter;
florianbf516d12012-04-21 15:53:13 +00007963 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00007964 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007965 d = amode->d;
7966
7967 /* Decrement the dispatch counter in the guest state */
florian0e047d62012-04-21 16:06:04 +00007968 if (s390_host_has_gie) {
7969 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
7970 } else {
7971 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
7972 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
7973 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
7974 }
florian8844a632012-04-13 04:04:06 +00007975
7976 /* Jump over the next insn if >= 0 */
7977 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
7978
7979 /* Computed goto to fail_address */
7980 amode = insn->variant.evcheck.fail_addr;
7981 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00007982 d = amode->d;
florianbf516d12012-04-21 15:53:13 +00007983 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
florian8844a632012-04-13 04:04:06 +00007984 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
7985
7986 code_end = buf;
7987
7988 /* Make sure the size of the generated code is identical to the size
7989 returned by evCheckSzB_S390 */
7990 vassert(evCheckSzB_S390() == code_end - code_begin);
7991
7992 return buf;
7993}
7994
7995
7996static UChar *
7997s390_insn_profinc_emit(UChar *buf,
7998 const s390_insn *insn __attribute__((unused)))
7999{
8000 /* Generate a code template to increment a memory location whose
8001 address will be known later as an immediate value. This code
8002 template will be patched once the memory location is known.
8003 For now we do this with address == 0. */
8004 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
florian0e047d62012-04-21 16:06:04 +00008005 if (s390_host_has_gie) {
8006 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8007 } else {
8008 buf = s390_emit_LGHI(buf, R0, 1);
8009 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8010 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
8011 }
florian8844a632012-04-13 04:04:06 +00008012
8013 return buf;
8014}
8015
8016
sewardj2019a972011-03-07 16:04:07 +00008017Int
florian8844a632012-04-13 04:04:06 +00008018emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, s390_insn *insn,
8019 Bool mode64, void *disp_cp_chain_me_to_slowEP,
8020 void *disp_cp_chain_me_to_fastEP, void *disp_cp_xindir,
8021 void *disp_cp_xassisted)
sewardj2019a972011-03-07 16:04:07 +00008022{
8023 UChar *end;
8024
8025 switch (insn->tag) {
8026 case S390_INSN_LOAD:
8027 end = s390_insn_load_emit(buf, insn);
8028 break;
8029
8030 case S390_INSN_STORE:
8031 end = s390_insn_store_emit(buf, insn);
8032 break;
8033
8034 case S390_INSN_MOVE:
8035 end = s390_insn_move_emit(buf, insn);
8036 break;
8037
8038 case S390_INSN_COND_MOVE:
8039 end = s390_insn_cond_move_emit(buf, insn);
8040 break;
8041
8042 case S390_INSN_LOAD_IMMEDIATE:
8043 end = s390_insn_load_immediate_emit(buf, insn);
8044 break;
8045
8046 case S390_INSN_ALU:
8047 end = s390_insn_alu_emit(buf, insn);
8048 break;
8049
8050 case S390_INSN_MUL:
8051 end = s390_insn_mul_emit(buf, insn);
8052 break;
8053
8054 case S390_INSN_DIV:
8055 end = s390_insn_div_emit(buf, insn);
8056 break;
8057
8058 case S390_INSN_DIVS:
8059 end = s390_insn_divs_emit(buf, insn);
8060 break;
8061
sewardj611b06e2011-03-24 08:57:29 +00008062 case S390_INSN_CLZ:
8063 end = s390_insn_clz_emit(buf, insn);
sewardj2019a972011-03-07 16:04:07 +00008064 break;
8065
8066 case S390_INSN_UNOP:
8067 end = s390_insn_unop_emit(buf, insn);
8068 break;
8069
8070 case S390_INSN_TEST:
8071 end = s390_insn_test_emit(buf, insn);
8072 break;
8073
8074 case S390_INSN_CC2BOOL:
8075 end = s390_insn_cc2bool_emit(buf, insn);
8076 break;
8077
8078 case S390_INSN_CAS:
8079 end = s390_insn_cas_emit(buf, insn);
8080 break;
8081
florian448cbba2012-06-06 02:26:01 +00008082 case S390_INSN_CDAS:
8083 end = s390_insn_cdas_emit(buf, insn);
8084 break;
8085
sewardj2019a972011-03-07 16:04:07 +00008086 case S390_INSN_COMPARE:
8087 end = s390_insn_compare_emit(buf, insn);
8088 break;
8089
sewardj2019a972011-03-07 16:04:07 +00008090 case S390_INSN_HELPER_CALL:
8091 end = s390_insn_helper_call_emit(buf, insn);
8092 break;
8093
8094 case S390_INSN_BFP_TRIOP:
8095 end = s390_insn_bfp_triop_emit(buf, insn);
8096 break;
8097
8098 case S390_INSN_BFP_BINOP:
8099 end = s390_insn_bfp_binop_emit(buf, insn);
8100 break;
8101
8102 case S390_INSN_BFP_UNOP:
8103 end = s390_insn_bfp_unop_emit(buf, insn);
8104 break;
8105
8106 case S390_INSN_BFP_COMPARE:
8107 end = s390_insn_bfp_compare_emit(buf, insn);
8108 break;
8109
florian9fcff4c2012-09-10 03:09:04 +00008110 case S390_INSN_BFP_CONVERT:
8111 end = s390_insn_bfp_convert_emit(buf, insn);
8112 break;
8113
sewardja52e37e2011-04-28 18:48:06 +00008114 case S390_INSN_MFENCE:
8115 end = s390_insn_mfence_emit(buf, insn);
8116 break;
8117
florianad43b3a2012-02-20 15:01:14 +00008118 case S390_INSN_GZERO:
8119 end = s390_insn_gzero_emit(buf, insn);
8120 break;
8121
8122 case S390_INSN_GADD:
8123 end = s390_insn_gadd_emit(buf, insn);
8124 break;
8125
florian125e20d2012-10-07 15:42:37 +00008126 case S390_INSN_SET_FPC_BFPRM:
8127 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
florian2c74d242012-09-12 19:38:42 +00008128 break;
8129
florianc8e4f562012-10-27 16:19:31 +00008130 case S390_INSN_SET_FPC_DFPRM:
8131 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
8132 break;
8133
florian8844a632012-04-13 04:04:06 +00008134 case S390_INSN_PROFINC:
8135 end = s390_insn_profinc_emit(buf, insn);
8136 /* Tell the caller .. */
8137 vassert(*is_profinc == False);
8138 *is_profinc = True;
8139 break;
8140
8141 case S390_INSN_EVCHECK:
8142 end = s390_insn_evcheck_emit(buf, insn);
8143 break;
8144
8145 case S390_INSN_XDIRECT:
8146 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
8147 disp_cp_chain_me_to_fastEP);
8148 break;
8149
8150 case S390_INSN_XINDIR:
8151 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
8152 break;
8153
8154 case S390_INSN_XASSISTED:
8155 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
8156 break;
8157
sewardj2019a972011-03-07 16:04:07 +00008158 default:
florian616458b2012-03-25 16:17:18 +00008159 vpanic("emit_S390Instr");
sewardj2019a972011-03-07 16:04:07 +00008160 }
8161
8162 vassert(end - buf <= nbuf);
8163
8164 return end - buf;
8165}
8166
8167
florian8844a632012-04-13 04:04:06 +00008168/* Return the number of bytes emitted for an S390_INSN_EVCHECK.
8169 See s390_insn_evcheck_emit */
8170Int
8171evCheckSzB_S390(void)
8172{
florian0e047d62012-04-21 16:06:04 +00008173 return s390_host_has_gie ? 18 : 24;
florian8844a632012-04-13 04:04:06 +00008174}
8175
8176
8177/* Patch the counter address into CODE_TO_PATCH as previously
8178 generated by s390_insn_profinc_emit. */
8179VexInvalRange
8180patchProfInc_S390(void *code_to_patch, ULong *location_of_counter)
8181{
8182 vassert(sizeof(ULong *) == 8);
8183
8184 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
8185
florian5ea257b2012-09-29 17:05:46 +00008186 UChar *p = s390_tchain_patch_load64(code_to_patch,
8187 Ptr_to_ULong(location_of_counter));
florian8844a632012-04-13 04:04:06 +00008188
florian5ea257b2012-09-29 17:05:46 +00008189 UInt len = p - (UChar *)code_to_patch;
8190 VexInvalRange vir = { (HWord)code_to_patch, len };
florian8844a632012-04-13 04:04:06 +00008191 return vir;
8192}
8193
8194
8195/* NB: what goes on here has to be very closely coordinated with the
8196 s390_insn_xdirect_emit code above. */
8197VexInvalRange
8198chainXDirect_S390(void *place_to_chain,
8199 void *disp_cp_chain_me_EXPECTED,
8200 void *place_to_jump_to)
8201{
florianebaf8d92012-04-22 17:38:46 +00008202 /* What we're expecting to see @ PLACE_TO_CHAIN is:
florian8844a632012-04-13 04:04:06 +00008203
florianebaf8d92012-04-22 17:38:46 +00008204 load tchain_scratch, #disp_cp_chain_me_EXPECTED
8205 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00008206 */
8207 const UChar *next;
8208 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
8209 Ptr_to_ULong(disp_cp_chain_me_EXPECTED));
florianebaf8d92012-04-22 17:38:46 +00008210 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +00008211
8212 /* And what we want to change it to is either:
8213 (general case):
8214
florianebaf8d92012-04-22 17:38:46 +00008215 load tchain_scratch, #place_to_jump_to
8216 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00008217
8218 ---OR---
8219
8220 in the case where the displacement is small enough
8221
8222 BRCL delta where delta is in half-words
8223 invalid opcodes
8224
8225 In both cases the replacement has the same length as the original.
8226 To remain sane & verifiable,
8227 (1) limit the displacement for the short form to
8228 (say) +/- one billion, so as to avoid wraparound
8229 off-by-ones
8230 (2) even if the short form is applicable, once every (say)
8231 1024 times use the long form anyway, so as to maintain
8232 verifiability
8233 */
8234
8235 /* This is the delta we need to put into a BRCL insn. Note, that the
8236 offset in BRCL is in half-words. Hence division by 2. */
8237 Long delta = (Long)((UChar *)place_to_jump_to - (UChar *)place_to_chain) / 2;
8238 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
8239
8240 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
8241 if (shortOK) {
8242 shortCTR++; // thread safety bleh
8243 if (0 == (shortCTR & 0x3FF)) {
8244 shortOK = False;
8245 if (0)
8246 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
8247 "using long jmp\n", shortCTR);
8248 }
8249 }
8250
8251 /* And make the modifications. */
8252 UChar *p = (UChar *)place_to_chain;
8253 if (shortOK) {
8254 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
8255
florian48cb9612012-04-20 02:50:28 +00008256 /* Make sure that BRCL fits into the patchable part of an xdirect
florian1c857042012-04-15 04:11:07 +00008257 code sequence */
florian48cb9612012-04-20 02:50:28 +00008258 vassert(6 <= s390_xdirect_patchable_len());
florian1c857042012-04-15 04:11:07 +00008259
florian8844a632012-04-13 04:04:06 +00008260 /* Fill remaining bytes with 0x00 (invalid opcode) */
8261 Int i;
8262 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
8263 p[i] = 0x00;
8264 } else {
florian1c857042012-04-15 04:11:07 +00008265 /*
florianebaf8d92012-04-22 17:38:46 +00008266 load tchain_scratch, #place_to_jump_to
8267 goto *tchain_scratch
florian1c857042012-04-15 04:11:07 +00008268 */
8269 ULong addr = Ptr_to_ULong(place_to_jump_to);
8270 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +00008271 /* There is not need to emit a BCR here, as it is already there. */
florian8844a632012-04-13 04:04:06 +00008272 }
8273
florian5ea257b2012-09-29 17:05:46 +00008274 UInt len = p - (UChar *)place_to_chain;
8275 VexInvalRange vir = { (HWord)place_to_chain, len };
florian8844a632012-04-13 04:04:06 +00008276 return vir;
8277}
8278
8279
8280/* NB: what goes on here has to be very closely coordinated with the
8281 s390_insn_xdirect_emit code above. */
8282VexInvalRange
8283unchainXDirect_S390(void *place_to_unchain,
8284 void *place_to_jump_to_EXPECTED,
8285 void *disp_cp_chain_me)
8286{
8287 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
8288
florianebaf8d92012-04-22 17:38:46 +00008289 load tchain_scratch, #place_to_jump_to_EXPECTED
8290 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00008291
8292 ---OR---
8293 in the case where the displacement falls within 32 bits
8294
8295 BRCL delta
8296 invalid opcodes
8297 */
8298 UChar *p = place_to_unchain;
florian1c857042012-04-15 04:11:07 +00008299
florianebaf8d92012-04-22 17:38:46 +00008300 Bool uses_short_form = False;
8301
florian1c857042012-04-15 04:11:07 +00008302 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
florian8844a632012-04-13 04:04:06 +00008303 /* Looks like the short form */
8304 Int num_hw = *(Int *)&p[2];
8305 Int delta = 2 *num_hw;
8306
8307 vassert(p + delta == place_to_jump_to_EXPECTED);
8308
florian8844a632012-04-13 04:04:06 +00008309 Int i;
8310 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
florian1c857042012-04-15 04:11:07 +00008311 vassert(p[6+i] == 0x00);
florianebaf8d92012-04-22 17:38:46 +00008312 uses_short_form = True;
florian8844a632012-04-13 04:04:06 +00008313 } else {
8314 /* Should be the long form */
8315 const UChar *next;
8316
8317 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
8318 Ptr_to_ULong(place_to_jump_to_EXPECTED));
8319 /* Check for BR *tchain_scratch */
florian1c857042012-04-15 04:11:07 +00008320 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +00008321 }
8322
8323 /* And what we want to change it to is:
8324
8325 load tchain_scratch, #disp_cp_chain_me
florianebaf8d92012-04-22 17:38:46 +00008326 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00008327 */
florianebaf8d92012-04-22 17:38:46 +00008328
8329 /* Get the address of the beginning of the load64 code sequence into %r1.
8330 Do not change the register! This is part of the protocol with the
8331 dispatcher.
8332 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
8333 load64 insn sequence. That sequence is prefixed with a BASR to get its
8334 address (see s390_insn_xdirect_emit). */
8335 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
8336
florian8844a632012-04-13 04:04:06 +00008337 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
8338 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +00008339
8340 /* Emit the BCR in case the short form was used. In case of the long
8341 form, the BCR is already there. */
8342 if (uses_short_form)
8343 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00008344
florian5ea257b2012-09-29 17:05:46 +00008345 UInt len = p - (UChar *)place_to_unchain;
8346 VexInvalRange vir = { (HWord)place_to_unchain, len };
florian8844a632012-04-13 04:04:06 +00008347 return vir;
8348}
8349
sewardj2019a972011-03-07 16:04:07 +00008350/*---------------------------------------------------------------*/
8351/*--- end host_s390_defs.c ---*/
8352/*---------------------------------------------------------------*/