1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* -*- mode: C; c-basic-offset: 3; -*- */
2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------------------------------------------------*/
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- begin                                     s390_disasm.c ---*/
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------------------------------------------------*/
6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This file is part of Valgrind, a dynamic binary instrumentation
9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   framework.
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright IBM Corp. 2010-2013
12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This program is free software; you can redistribute it and/or
14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   modify it under the terms of the GNU General Public License as
15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   published by the Free Software Foundation; either version 2 of the
16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   License, or (at your option) any later version.
17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This program is distributed in the hope that it will be useful, but
19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   WITHOUT ANY WARRANTY; without even the implied warranty of
20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   General Public License for more details.
22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   You should have received a copy of the GNU General Public License
24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   along with this program; if not, write to the Free Software
25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   02110-1301, USA.
27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   The GNU General Public License is contained in the file COPYING.
29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Contributed by Florian Krohm */
32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdarg.h>
34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "libvex_basictypes.h"
35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "main_util.h"        // vassert
36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "main_globals.h"     // vex_traceflags
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "s390_defs.h"        // S390_MAX_MNEMONIC_LEN
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "s390_disasm.h"
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Return the mnemonic padded with blanks to its right */
42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic const HChar *
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovmnemonic(const HChar *mnm)
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(vex_strlen(mnm) <= S390_MAX_MNEMONIC_LEN);
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   static HChar buf[S390_MAX_MNEMONIC_LEN + 1];
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_sprintf(buf, "%-*s", S390_MAX_MNEMONIC_LEN, mnm);
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return buf;
52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the name of a general purpose register for dis-assembly purposes. */
56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovgpr_operand(UInt archreg)
58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   static const HChar names[16][5] = {
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%r0", "%r1", "%r2", "%r3",
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%r4", "%r5", "%r6", "%r7",
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%r8", "%r9", "%r10", "%r11",
63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%r12", "%r13", "%r14", "%r15",
64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   };
65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(archreg < 16);
67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return names[archreg];
69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the name of a floating point register for dis-assembly purposes. */
73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovfpr_operand(UInt archreg)
75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   static const HChar names[16][5] = {
77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%f0", "%f1", "%f2", "%f3",
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%f4", "%f5", "%f6", "%f7",
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%f8", "%f9", "%f10", "%f11",
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%f12", "%f13", "%f14", "%f15",
81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   };
82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(archreg < 16);
84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return names[archreg];
86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the name of an access register for dis-assembly purposes. */
90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovar_operand(UInt archreg)
92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   static const HChar names[16][5] = {
94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%a0", "%a1", "%a2", "%a3",
95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%a4", "%a5", "%a6", "%a7",
96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%a8", "%a9", "%a10", "%a11",
97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "%a12", "%a13", "%a14", "%a15",
98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   };
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(archreg < 16);
101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return names[archreg];
103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Build and return the extended mnemonic for the compare and branch
107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   opcodes as introduced by z10. See also the opcodes in file
108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   opcodes/s390-opc.txt (from binutils) that have a '$' in their name. */
109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovcab_operand(const HChar *base, UInt mask)
111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar *to;
113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   const HChar *from;
114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   static HChar buf[S390_MAX_MNEMONIC_LEN + 1];
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   static const HChar suffix[8][3] = {
118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "", "h", "l", "ne", "e", "nl", "nh", ""
119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   };
120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Guard against buffer overflow */
122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(vex_strlen(base) + sizeof suffix[0] <= sizeof buf);
123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* strcpy(buf, from); */
125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (from = base, to = buf; *from; ++from, ++to) {
126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *to = *from;
127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* strcat(buf, suffix); */
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (from = suffix[mask >> 1]; *from; ++from, ++to) {
130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *to = *from;
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *to = '\0';
133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return buf;
135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Common function used to construct a mnemonic based on a condition code
139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mask. */
140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovconstruct_mnemonic(const HChar *prefix, const HChar *suffix, UInt mask)
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar *to;
144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   const HChar *from;
145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   static HChar buf[S390_MAX_MNEMONIC_LEN + 1];
147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   static HChar mask_id[16][4] = {
149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "", /* 0 -> unused */
150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "o", "h", "nle", "l", "nhe", "lh", "ne",
151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "e", "nlh", "he", "nl", "le", "nh", "no",
152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ""  /* 15 -> unused */
153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   };
154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Guard against buffer overflow */
156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(vex_strlen(prefix) + vex_strlen(suffix) +
157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           sizeof mask_id[0] <= sizeof buf);
158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* strcpy(buf, prefix); */
160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (from = prefix, to = buf; *from; ++from, ++to) {
161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *to = *from;
162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* strcat(buf, mask_id); */
164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (from = mask_id[mask]; *from; ++from, ++to) {
165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *to = *from;
166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* strcat(buf, suffix); */
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (from = suffix; *from; ++from, ++to) {
169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *to = *from;
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *to = '\0';
172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return buf;
174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the special mnemonic for the BCR opcode */
178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovbcr_operand(UInt m1)
180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m1 ==  0) return "nopr";
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m1 == 15) return "br";
183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return construct_mnemonic("b", "r", m1);
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the special mnemonic for the BC opcode */
189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovbc_operand(UInt m1)
191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m1 ==  0) return "nop";
193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m1 == 15) return "b";
194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return construct_mnemonic("b", "", m1);
196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the special mnemonic for the BRC opcode */
200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovbrc_operand(UInt m1)
202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m1 == 0)  return "brc";
204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m1 == 15) return "j";
205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return construct_mnemonic("j", "", m1);
207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the special mnemonic for the BRCL opcode */
211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovbrcl_operand(UInt m1)
213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m1 == 0)  return "brcl";
215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m1 == 15) return "jg";
216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return construct_mnemonic("jg", "", m1);
218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the special mnemonic for a conditional load/store  opcode */
222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const HChar *
223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovcls_operand(Int kind, UInt mask)
224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar *prefix;
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (kind) {
228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case S390_XMNM_LOCR:   prefix = "locr";  break;
229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case S390_XMNM_LOCGR:  prefix = "locgr"; break;
230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case S390_XMNM_LOC:    prefix = "loc";   break;
231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case S390_XMNM_LOCG:   prefix = "locg";  break;
232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case S390_XMNM_STOC:   prefix = "stoc";  break;
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case S390_XMNM_STOCG:  prefix = "stocg"; break;
234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   default:
235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vpanic("cls_operand");
236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return construct_mnemonic(prefix, "", mask);
239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* An operand with a base register, an index register, and a displacement.
243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   If the displacement is signed, the rightmost 20 bit of D need to be
244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sign extended */
245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic HChar *
246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdxb_operand(HChar *p, UInt d, UInt x, UInt b, Bool displacement_is_signed)
247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (displacement_is_signed) {
249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Int displ = ((Int)d << 12) >> 12;  /* sign extend */
250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p += vex_sprintf(p, "%d", displ);
252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p += vex_sprintf(p, "%u", d);
254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (x != 0) {
256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p += vex_sprintf(p, "(%s", gpr_operand(x));
257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (b != 0) {
258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p += vex_sprintf(p, ",%s", gpr_operand(b));
259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p += vex_sprintf(p, ")");
261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (b != 0) {
263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p += vex_sprintf(p, "(%s)", gpr_operand(b));
264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return p;
268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* An operand with base register, unsigned length, and a 12-bit
272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   unsigned displacement */
273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic HChar *
274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovudlb_operand(HChar *p, UInt d, UInt length, UInt b)
275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p += vex_sprintf(p, "%u", d);
277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p += vex_sprintf(p, "(%u", length + 1);  // actual length is +1
278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (b != 0) {
279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p += vex_sprintf(p, ",%s", gpr_operand(b));
280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p += vex_sprintf(p, ")");
282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return p;
284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* The first argument is the command that says how to write the disassembled
288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   insn. It is understood that the mnemonic comes first and that arguments
289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   are separated by a ','. The command holds the arguments. Each argument is
290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   encoded using a 4-bit S390_ARG_xyz value. The first argument is placed
291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   in the least significant bits of the command and so on. There are at most
292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   5 arguments in an insn and a sentinel (S390_ARG_DONE) is needed to identify
293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   the end of the argument list. 6 * 4 = 24 bits are required for the
294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   command. */
295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid
296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovs390_disasm(UInt command, ...)
297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_list  args;
299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt argkind;
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar buf[128];  /* holds the disassembled insn */
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar *p;
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar separator;
303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int mask_suffix = -1;
304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_start(args, command);
306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p = buf;
308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   separator = 0;
309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   while (42) {
311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      argkind = command & 0xF;
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      command >>= 4;
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (argkind == S390_ARG_DONE) goto done;
315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (argkind == S390_ARG_CABM) separator = 0;  /* optional */
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Write out the separator */
319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (separator) *p++ = separator;
320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* argument */
322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (argkind) {
323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_MNM:
324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         p += vex_sprintf(p, "%s", mnemonic(va_arg(args, HChar *)));
325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         separator = ' ';
326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         continue;
327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_XMNM: {
329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UInt mask, kind;
330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         const HChar *mnm;
331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         kind = va_arg(args, UInt);
333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         separator = ' ';
335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (kind) {
336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_BC:
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_BCR:
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mask = va_arg(args, UInt);
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mnm = kind == S390_XMNM_BCR ? bcr_operand(mask) : bc_operand(mask);
340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            p  += vex_sprintf(p, "%s", mnemonic(mnm));
341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* mask == 0 is a NOP and has no argument */
342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (mask == 0) goto done;
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_BRC:
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_BRCL:
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mask = va_arg(args, UInt);
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mnm = kind == S390_XMNM_BRC ? brc_operand(mask) : brcl_operand(mask);
349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            p  += vex_sprintf(p, "%s", mnemonic(mnm));
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* mask == 0 has no special mnemonic */
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (mask == 0) {
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               p += vex_sprintf(p, " 0");
354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               separator = ',';
355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_CAB:
359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mnm  = va_arg(args, HChar *);
360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mask = va_arg(args, UInt);
361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            p  += vex_sprintf(p, "%s", mnemonic(cab_operand(mnm, mask)));
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_LOCR:
365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_LOCGR:
366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_LOC:
367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_LOCG:
368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_STOC:
369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case S390_XMNM_STOCG:
370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mask = va_arg(args, UInt);
371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mnm = cls_operand(kind, mask);
372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            p  += vex_sprintf(p, "%s", mnemonic(mnm));
373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* There are no special opcodes when mask == 0 or 15. In that case
374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               the integer mask is appended as the final operand */
375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (mask == 0 || mask == 15) mask_suffix = mask;
376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      continue;
380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_GPR:
382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p += vex_sprintf(p, "%s", gpr_operand(va_arg(args, UInt)));
383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_FPR:
386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p += vex_sprintf(p, "%s", fpr_operand(va_arg(args, UInt)));
387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_AR:
390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p += vex_sprintf(p, "%s", ar_operand(va_arg(args, UInt)));
391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_UINT:
394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p += vex_sprintf(p, "%u", va_arg(args, UInt));
395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_INT:
398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p += vex_sprintf(p, "%d", (Int)(va_arg(args, UInt)));
399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_PCREL: {
402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Int offset = (Int)(va_arg(args, UInt));
403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Convert # halfwords to # bytes */
405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         offset <<= 1;
406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (offset < 0) {
408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            p += vex_sprintf(p, ".%d", offset);
409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            p += vex_sprintf(p, ".+%u", offset);
411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_SDXB: {
416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UInt dh, dl, x, b;
417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         dh = va_arg(args, UInt);
419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         dl = va_arg(args, UInt);
420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         x  = va_arg(args, UInt);
421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b  = va_arg(args, UInt);
422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p = dxb_operand(p, (dh << 12) | dl, x, b, 1 /* signed_displacement */);
424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_UDXB: {
428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UInt d, x, b;
429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         d = va_arg(args, UInt);
431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         x = va_arg(args, UInt);
432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b = va_arg(args, UInt);
433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p = dxb_operand(p, d, x, b, 0 /* signed_displacement */);
435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_UDLB: {
439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UInt d, l, b;
440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         d = va_arg(args, UInt);
442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         l = va_arg(args, UInt);
443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b = va_arg(args, UInt);
444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p = udlb_operand(p, d, l, b);
446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case S390_ARG_CABM: {
450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UInt mask;
451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mask = va_arg(args, UInt) & 0xE;
453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (mask == 0 || mask == 14) {
454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            p += vex_sprintf(p, ",%u", mask);
455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      separator = ',';
461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov done:
464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_end(args);
465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (mask_suffix != -1)
467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p += vex_sprintf(p, ",%d", mask_suffix);
468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *p = '\0';
469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(p < buf + sizeof buf);  /* detect buffer overwrite */
471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Finally, write out the disassembled insn */
473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vex_printf("%s\n", buf);
474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------------------------------------------------*/
477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- end                                       s390_disasm.c ---*/
478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------------------------------------------------*/
479