1 //===-- SystemZInstPrinter.cpp - Convert SystemZ MCInst to assembly syntax --------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class prints an SystemZ MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13
14 /* Capstone Disassembly Engine */
15 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
16
17 #ifdef CAPSTONE_HAS_SYSZ
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <capstone/platform.h>
23
24 #include "SystemZInstPrinter.h"
25 #include "../../MCInst.h"
26 #include "../../utils.h"
27 #include "../../SStream.h"
28 #include "../../MCRegisterInfo.h"
29 #include "../../MathExtras.h"
30 #include "SystemZMapping.h"
31
32 static const char *getRegisterName(unsigned RegNo);
33
SystemZ_post_printer(csh ud,cs_insn * insn,char * insn_asm,MCInst * mci)34 void SystemZ_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
35 {
36 /*
37 if (((cs_struct *)ud)->detail != CS_OPT_ON)
38 return;
39 */
40 }
41
printAddress(MCInst * MI,unsigned Base,int64_t Disp,unsigned Index,SStream * O)42 static void printAddress(MCInst *MI, unsigned Base, int64_t Disp, unsigned Index, SStream *O)
43 {
44 printInt64(O, Disp);
45
46 if (Base) {
47 SStream_concat0(O, "(");
48 if (Index)
49 SStream_concat(O, "%%%s, ", getRegisterName(Index));
50 SStream_concat(O, "%%%s)", getRegisterName(Base));
51
52 if (MI->csh->detail) {
53 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_MEM;
54 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.base = (uint8_t)SystemZ_map_register(Base);
55 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.index = (uint8_t)SystemZ_map_register(Index);
56 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.disp = Disp;
57 MI->flat_insn->detail->sysz.op_count++;
58 }
59 } else if (!Index) {
60 if (MI->csh->detail) {
61 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
62 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Disp;
63 MI->flat_insn->detail->sysz.op_count++;
64 }
65 } else {
66 SStream_concat(O, "(%%%s)", getRegisterName(Index));
67 if (MI->csh->detail) {
68 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_MEM;
69 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.base = (uint8_t)SystemZ_map_register(Base);
70 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.index = (uint8_t)SystemZ_map_register(Index);
71 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.disp = Disp;
72 MI->flat_insn->detail->sysz.op_count++;
73 }
74 }
75 }
76
_printOperand(MCInst * MI,MCOperand * MO,SStream * O)77 static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O)
78 {
79 if (MCOperand_isReg(MO)) {
80 unsigned reg;
81
82 reg = MCOperand_getReg(MO);
83 SStream_concat(O, "%%%s", getRegisterName(reg));
84 reg = SystemZ_map_register(reg);
85
86 if (MI->csh->detail) {
87 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_REG;
88 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].reg = reg;
89 MI->flat_insn->detail->sysz.op_count++;
90 }
91 } else if (MCOperand_isImm(MO)) {
92 int64_t Imm = MCOperand_getImm(MO);
93
94 printInt64(O, Imm);
95
96 if (MI->csh->detail) {
97 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
98 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Imm;
99 MI->flat_insn->detail->sysz.op_count++;
100 }
101 }
102 }
103
printU1ImmOperand(MCInst * MI,int OpNum,SStream * O)104 static void printU1ImmOperand(MCInst *MI, int OpNum, SStream *O)
105 {
106 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
107 // assert(isUInt<1>(Value) && "Invalid u1imm argument");
108 printInt64(O, Value);
109
110 if (MI->csh->detail) {
111 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
112 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Value;
113 MI->flat_insn->detail->sysz.op_count++;
114 }
115 }
116
printU2ImmOperand(MCInst * MI,int OpNum,SStream * O)117 static void printU2ImmOperand(MCInst *MI, int OpNum, SStream *O)
118 {
119 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
120 // assert(isUInt<2>(Value) && "Invalid u2imm argument");
121 printInt64(O, Value);
122
123 if (MI->csh->detail) {
124 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
125 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Value;
126 MI->flat_insn->detail->sysz.op_count++;
127 }
128 }
129
printU3ImmOperand(MCInst * MI,int OpNum,SStream * O)130 static void printU3ImmOperand(MCInst *MI, int OpNum, SStream *O)
131 {
132 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
133 // assert(isUInt<3>(Value) && "Invalid u4imm argument");
134 printInt64(O, Value);
135
136 if (MI->csh->detail) {
137 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
138 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Value;
139 MI->flat_insn->detail->sysz.op_count++;
140 }
141 }
142
printU4ImmOperand(MCInst * MI,int OpNum,SStream * O)143 static void printU4ImmOperand(MCInst *MI, int OpNum, SStream *O)
144 {
145 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
146 // assert(isUInt<4>(Value) && "Invalid u4imm argument");
147 printInt64(O, Value);
148
149 if (MI->csh->detail) {
150 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
151 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Value;
152 MI->flat_insn->detail->sysz.op_count++;
153 }
154 }
155
printU6ImmOperand(MCInst * MI,int OpNum,SStream * O)156 static void printU6ImmOperand(MCInst *MI, int OpNum, SStream *O)
157 {
158 uint32_t Value = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
159 // assert(isUInt<6>(Value) && "Invalid u6imm argument");
160
161 printUInt32(O, Value);
162
163 if (MI->csh->detail) {
164 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
165 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
166 MI->flat_insn->detail->sysz.op_count++;
167 }
168 }
169
printS8ImmOperand(MCInst * MI,int OpNum,SStream * O)170 static void printS8ImmOperand(MCInst *MI, int OpNum, SStream *O)
171 {
172 int8_t Value = (int8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
173 // assert(isInt<8>(Value) && "Invalid s8imm argument");
174
175 if (Value >= 0) {
176 if (Value > HEX_THRESHOLD)
177 SStream_concat(O, "0x%x", Value);
178 else
179 SStream_concat(O, "%u", Value);
180 } else {
181 if (Value < -HEX_THRESHOLD)
182 SStream_concat(O, "-0x%x", -Value);
183 else
184 SStream_concat(O, "-%u", -Value);
185 }
186
187 if (MI->csh->detail) {
188 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
189 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
190 MI->flat_insn->detail->sysz.op_count++;
191 }
192 }
193
printU8ImmOperand(MCInst * MI,int OpNum,SStream * O)194 static void printU8ImmOperand(MCInst *MI, int OpNum, SStream *O)
195 {
196 uint8_t Value = (uint8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
197 // assert(isUInt<8>(Value) && "Invalid u8imm argument");
198
199 if (Value > HEX_THRESHOLD)
200 SStream_concat(O, "0x%x", Value);
201 else
202 SStream_concat(O, "%u", Value);
203
204 if (MI->csh->detail) {
205 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
206 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
207 MI->flat_insn->detail->sysz.op_count++;
208 }
209 }
210
printU12ImmOperand(MCInst * MI,int OpNum,SStream * O)211 static void printU12ImmOperand(MCInst *MI, int OpNum, SStream *O)
212 {
213 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
214 // assert(isUInt<12>(Value) && "Invalid u12imm argument");
215 printInt64(O, Value);
216
217 if (MI->csh->detail) {
218 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
219 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Value;
220 MI->flat_insn->detail->sysz.op_count++;
221 }
222 }
223
printS16ImmOperand(MCInst * MI,int OpNum,SStream * O)224 static void printS16ImmOperand(MCInst *MI, int OpNum, SStream *O)
225 {
226 int16_t Value = (int16_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
227 // assert(isInt<16>(Value) && "Invalid s16imm argument");
228
229 if (Value >= 0) {
230 if (Value > HEX_THRESHOLD)
231 SStream_concat(O, "0x%x", Value);
232 else
233 SStream_concat(O, "%u", Value);
234 } else {
235 if (Value < -HEX_THRESHOLD)
236 SStream_concat(O, "-0x%x", -Value);
237 else
238 SStream_concat(O, "-%u", -Value);
239 }
240
241 if (MI->csh->detail) {
242 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
243 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
244 MI->flat_insn->detail->sysz.op_count++;
245 }
246 }
247
printU16ImmOperand(MCInst * MI,int OpNum,SStream * O)248 static void printU16ImmOperand(MCInst *MI, int OpNum, SStream *O)
249 {
250 uint16_t Value = (uint16_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
251 // assert(isUInt<16>(Value) && "Invalid u16imm argument");
252
253 if (Value > HEX_THRESHOLD)
254 SStream_concat(O, "0x%x", Value);
255 else
256 SStream_concat(O, "%u", Value);
257
258 if (MI->csh->detail) {
259 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
260 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
261 MI->flat_insn->detail->sysz.op_count++;
262 }
263 }
264
printS32ImmOperand(MCInst * MI,int OpNum,SStream * O)265 static void printS32ImmOperand(MCInst *MI, int OpNum, SStream *O)
266 {
267 int32_t Value = (int32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
268 // assert(isInt<32>(Value) && "Invalid s32imm argument");
269
270 printInt32(O, Value);
271
272 if (MI->csh->detail) {
273 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
274 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
275 MI->flat_insn->detail->sysz.op_count++;
276 }
277 }
278
printU32ImmOperand(MCInst * MI,int OpNum,SStream * O)279 static void printU32ImmOperand(MCInst *MI, int OpNum, SStream *O)
280 {
281 uint32_t Value = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
282 // assert(isUInt<32>(Value) && "Invalid u32imm argument");
283
284 printUInt32(O, Value);
285
286 if (MI->csh->detail) {
287 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
288 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
289 MI->flat_insn->detail->sysz.op_count++;
290 }
291 }
292
printU48ImmOperand(MCInst * MI,int OpNum,SStream * O)293 static void printU48ImmOperand(MCInst *MI, int OpNum, SStream *O)
294 {
295 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
296 // assert(isUInt<48>(Value) && "Invalid u48imm argument");
297 printInt64(O, Value);
298
299 if (MI->csh->detail) {
300 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
301 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Value;
302 MI->flat_insn->detail->sysz.op_count++;
303 }
304 }
305
printPCRelOperand(MCInst * MI,int OpNum,SStream * O)306 static void printPCRelOperand(MCInst *MI, int OpNum, SStream *O)
307 {
308 MCOperand *MO = MCInst_getOperand(MI, OpNum);
309 int32_t imm;
310
311 if (MCOperand_isImm(MO)) {
312 imm = (int32_t)MCOperand_getImm(MO);
313
314 printInt32(O, imm);
315
316 if (MI->csh->detail) {
317 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
318 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)imm;
319 MI->flat_insn->detail->sysz.op_count++;
320 }
321 }
322 }
323
printPCRelTLSOperand(MCInst * MI,int OpNum,SStream * O)324 static void printPCRelTLSOperand(MCInst *MI, int OpNum, SStream *O)
325 {
326 // Output the PC-relative operand.
327 printPCRelOperand(MI, OpNum, O);
328 }
329
printOperand(MCInst * MI,int OpNum,SStream * O)330 static void printOperand(MCInst *MI, int OpNum, SStream *O)
331 {
332 _printOperand(MI, MCInst_getOperand(MI, OpNum), O);
333 }
334
printBDAddrOperand(MCInst * MI,int OpNum,SStream * O)335 static void printBDAddrOperand(MCInst *MI, int OpNum, SStream *O)
336 {
337 printAddress(MI, MCOperand_getReg(MCInst_getOperand(MI, OpNum)),
338 MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)), 0, O);
339 }
340
printBDXAddrOperand(MCInst * MI,int OpNum,SStream * O)341 static void printBDXAddrOperand(MCInst *MI, int OpNum, SStream *O)
342 {
343 printAddress(MI, MCOperand_getReg(MCInst_getOperand(MI, OpNum)),
344 MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)),
345 MCOperand_getReg(MCInst_getOperand(MI, OpNum + 2)), O);
346 }
347
printBDLAddrOperand(MCInst * MI,int OpNum,SStream * O)348 static void printBDLAddrOperand(MCInst *MI, int OpNum, SStream *O)
349 {
350 unsigned Base = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
351 uint64_t Disp = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
352 uint64_t Length = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 2));
353
354 if (Disp > HEX_THRESHOLD)
355 SStream_concat(O, "0x%"PRIx64, Disp);
356 else
357 SStream_concat(O, "%"PRIu64, Disp);
358
359 if (Length > HEX_THRESHOLD)
360 SStream_concat(O, "(0x%"PRIx64, Length);
361 else
362 SStream_concat(O, "(%"PRIu64, Length);
363
364 if (Base)
365 SStream_concat(O, ", %%%s", getRegisterName(Base));
366 SStream_concat0(O, ")");
367
368 if (MI->csh->detail) {
369 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_MEM;
370 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.base = (uint8_t)SystemZ_map_register(Base);
371 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.length = Length;
372 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.disp = (int64_t)Disp;
373 MI->flat_insn->detail->sysz.op_count++;
374 }
375 }
376
printBDRAddrOperand(MCInst * MI,int OpNum,SStream * O)377 static void printBDRAddrOperand(MCInst *MI, int OpNum, SStream *O)
378 {
379 unsigned Base = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
380 uint64_t Disp = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
381 uint64_t Length = MCOperand_getReg(MCInst_getOperand(MI, OpNum + 2));
382
383 if (Disp > HEX_THRESHOLD)
384 SStream_concat(O, "0x%"PRIx64, Disp);
385 else
386 SStream_concat(O, "%"PRIu64, Disp);
387
388 SStream_concat0(O, "(");
389 SStream_concat(O, "%%%s", getRegisterName(Length));
390
391 if (Base)
392 SStream_concat(O, ", %%%s", getRegisterName(Base));
393 SStream_concat0(O, ")");
394
395 if (MI->csh->detail) {
396 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_MEM;
397 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.base = (uint8_t)SystemZ_map_register(Base);
398 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.length = (uint8_t)SystemZ_map_register(Length);
399 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.disp = (int64_t)Disp;
400 MI->flat_insn->detail->sysz.op_count++;
401 }
402 }
403
printBDVAddrOperand(MCInst * MI,int OpNum,SStream * O)404 static void printBDVAddrOperand(MCInst *MI, int OpNum, SStream *O)
405 {
406 printAddress(MI, MCOperand_getReg(MCInst_getOperand(MI, OpNum)),
407 MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)),
408 MCOperand_getReg(MCInst_getOperand(MI, OpNum + 2)), O);
409 }
410
printCond4Operand(MCInst * MI,int OpNum,SStream * O)411 static void printCond4Operand(MCInst *MI, int OpNum, SStream *O)
412 {
413 static const char *const CondNames[] = {
414 "o", "h", "nle", "l", "nhe", "lh", "ne",
415 "e", "nlh", "he", "nl", "le", "nh", "no"
416 };
417
418 uint64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
419 // assert(Imm > 0 && Imm < 15 && "Invalid condition");
420 SStream_concat0(O, CondNames[Imm - 1]);
421
422 if (MI->csh->detail)
423 MI->flat_insn->detail->sysz.cc = (sysz_cc)Imm;
424 }
425
426 #define PRINT_ALIAS_INSTR
427 #include "SystemZGenAsmWriter.inc"
428
SystemZ_printInst(MCInst * MI,SStream * O,void * Info)429 void SystemZ_printInst(MCInst *MI, SStream *O, void *Info)
430 {
431 printInstruction(MI, O, Info);
432 }
433
434 #endif
435