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-2014 */
16
17 #ifdef CAPSTONE_HAS_SYSZ
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <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 if (Disp >= 0) {
45 if (Disp > HEX_THRESHOLD)
46 SStream_concat(O, "0x%"PRIx64, Disp);
47 else
48 SStream_concat(O, "%"PRIu64, Disp);
49 } else {
50 if (Disp < -HEX_THRESHOLD)
51 SStream_concat(O, "-0x%"PRIx64, -Disp);
52 else
53 SStream_concat(O, "-%"PRIu64, -Disp);
54 }
55
56 if (Base) {
57 SStream_concat0(O, "(");
58 if (Index)
59 SStream_concat(O, "%%%s, ", getRegisterName(Index));
60 SStream_concat(O, "%%%s)", getRegisterName(Base));
61
62 if (MI->csh->detail) {
63 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_MEM;
64 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.base = (uint8_t)SystemZ_map_register(Base);
65 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.index = (uint8_t)SystemZ_map_register(Index);
66 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.disp = Disp;
67 MI->flat_insn->detail->sysz.op_count++;
68 }
69 } else if (!Index) {
70 if (MI->csh->detail) {
71 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
72 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Disp;
73 MI->flat_insn->detail->sysz.op_count++;
74 }
75 }
76 }
77
_printOperand(MCInst * MI,MCOperand * MO,SStream * O)78 static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O)
79 {
80 if (MCOperand_isReg(MO)) {
81 unsigned reg;
82
83 reg = MCOperand_getReg(MO);
84 SStream_concat(O, "%%%s", getRegisterName(reg));
85 reg = SystemZ_map_register(reg);
86
87 if (MI->csh->detail) {
88 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_REG;
89 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].reg = reg;
90 MI->flat_insn->detail->sysz.op_count++;
91 }
92 } else if (MCOperand_isImm(MO)) {
93 int64_t Imm = MCOperand_getImm(MO);
94
95 if (Imm >= 0) {
96 if (Imm > HEX_THRESHOLD)
97 SStream_concat(O, "0x%"PRIx64, Imm);
98 else
99 SStream_concat(O, "%"PRIu64, Imm);
100 } else {
101 if (Imm < -HEX_THRESHOLD)
102 SStream_concat(O, "-0x%"PRIx64, -Imm);
103 else
104 SStream_concat(O, "-%"PRIu64, -Imm);
105 }
106
107 if (MI->csh->detail) {
108 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
109 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Imm;
110 MI->flat_insn->detail->sysz.op_count++;
111 }
112 }
113 }
114
printU4ImmOperand(MCInst * MI,int OpNum,SStream * O)115 static void printU4ImmOperand(MCInst *MI, int OpNum, SStream *O)
116 {
117 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
118 // assert(isUInt<4>(Value) && "Invalid u4imm argument");
119 if (Value >= 0) {
120 if (Value > HEX_THRESHOLD)
121 SStream_concat(O, "0x%"PRIx64, Value);
122 else
123 SStream_concat(O, "%"PRIu64, Value);
124 } else {
125 if (Value < -HEX_THRESHOLD)
126 SStream_concat(O, "-0x%"PRIx64, -Value);
127 else
128 SStream_concat(O, "-%"PRIu64, -Value);
129 }
130
131 if (MI->csh->detail) {
132 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
133 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Value;
134 MI->flat_insn->detail->sysz.op_count++;
135 }
136 }
137
printU6ImmOperand(MCInst * MI,int OpNum,SStream * O)138 static void printU6ImmOperand(MCInst *MI, int OpNum, SStream *O)
139 {
140 uint32_t Value = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
141 // assert(isUInt<6>(Value) && "Invalid u6imm argument");
142
143 if (Value > HEX_THRESHOLD)
144 SStream_concat(O, "0x%x", Value);
145 else
146 SStream_concat(O, "%u", Value);
147
148 if (MI->csh->detail) {
149 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
150 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
151 MI->flat_insn->detail->sysz.op_count++;
152 }
153 }
154
printS8ImmOperand(MCInst * MI,int OpNum,SStream * O)155 static void printS8ImmOperand(MCInst *MI, int OpNum, SStream *O)
156 {
157 int8_t Value = (int8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
158 // assert(isInt<8>(Value) && "Invalid s8imm argument");
159
160 if (Value >= 0) {
161 if (Value > HEX_THRESHOLD)
162 SStream_concat(O, "0x%x", Value);
163 else
164 SStream_concat(O, "%u", Value);
165 } else {
166 if (Value < -HEX_THRESHOLD)
167 SStream_concat(O, "-0x%x", -Value);
168 else
169 SStream_concat(O, "-%u", -Value);
170 }
171
172 if (MI->csh->detail) {
173 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
174 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
175 MI->flat_insn->detail->sysz.op_count++;
176 }
177 }
178
printU8ImmOperand(MCInst * MI,int OpNum,SStream * O)179 static void printU8ImmOperand(MCInst *MI, int OpNum, SStream *O)
180 {
181 uint8_t Value = (uint8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
182 // assert(isUInt<8>(Value) && "Invalid u8imm argument");
183
184 if (Value > HEX_THRESHOLD)
185 SStream_concat(O, "0x%x", Value);
186 else
187 SStream_concat(O, "%u", Value);
188
189 if (MI->csh->detail) {
190 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
191 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
192 MI->flat_insn->detail->sysz.op_count++;
193 }
194 }
195
printS16ImmOperand(MCInst * MI,int OpNum,SStream * O)196 static void printS16ImmOperand(MCInst *MI, int OpNum, SStream *O)
197 {
198 int16_t Value = (int16_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
199 // assert(isInt<16>(Value) && "Invalid s16imm argument");
200
201 if (Value >= 0) {
202 if (Value > HEX_THRESHOLD)
203 SStream_concat(O, "0x%x", Value);
204 else
205 SStream_concat(O, "%u", Value);
206 } else {
207 if (Value < -HEX_THRESHOLD)
208 SStream_concat(O, "-0x%x", -Value);
209 else
210 SStream_concat(O, "-%u", -Value);
211 }
212
213 if (MI->csh->detail) {
214 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
215 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
216 MI->flat_insn->detail->sysz.op_count++;
217 }
218 }
219
printU16ImmOperand(MCInst * MI,int OpNum,SStream * O)220 static void printU16ImmOperand(MCInst *MI, int OpNum, SStream *O)
221 {
222 uint16_t Value = (uint16_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
223 // assert(isUInt<16>(Value) && "Invalid u16imm argument");
224
225 if (Value > HEX_THRESHOLD)
226 SStream_concat(O, "0x%x", Value);
227 else
228 SStream_concat(O, "%u", Value);
229
230 if (MI->csh->detail) {
231 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
232 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
233 MI->flat_insn->detail->sysz.op_count++;
234 }
235 }
236
printS32ImmOperand(MCInst * MI,int OpNum,SStream * O)237 static void printS32ImmOperand(MCInst *MI, int OpNum, SStream *O)
238 {
239 int32_t Value = (int32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
240 // assert(isInt<32>(Value) && "Invalid s32imm argument");
241
242 if (Value >= 0) {
243 if (Value > HEX_THRESHOLD)
244 SStream_concat(O, "0x%x", Value);
245 else
246 SStream_concat(O, "%u", Value);
247 } else {
248 if (Value < -HEX_THRESHOLD)
249 SStream_concat(O, "-0x%x", -Value);
250 else
251 SStream_concat(O, "-%u", -Value);
252 }
253
254 if (MI->csh->detail) {
255 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
256 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
257 MI->flat_insn->detail->sysz.op_count++;
258 }
259 }
260
printU32ImmOperand(MCInst * MI,int OpNum,SStream * O)261 static void printU32ImmOperand(MCInst *MI, int OpNum, SStream *O)
262 {
263 uint32_t Value = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
264 // assert(isUInt<32>(Value) && "Invalid u32imm argument");
265
266 if (Value > HEX_THRESHOLD)
267 SStream_concat(O, "0x%x", Value);
268 else
269 SStream_concat(O, "%u", Value);
270
271 if (MI->csh->detail) {
272 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
273 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value;
274 MI->flat_insn->detail->sysz.op_count++;
275 }
276 }
277
printAccessRegOperand(MCInst * MI,int OpNum,SStream * O)278 static void printAccessRegOperand(MCInst *MI, int OpNum, SStream *O)
279 {
280 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
281 // assert(Value < 16 && "Invalid access register number");
282 SStream_concat(O, "%%a%u", (unsigned int)Value);
283
284 if (MI->csh->detail) {
285 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_ACREG;
286 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].reg = (unsigned int)Value;
287 MI->flat_insn->detail->sysz.op_count++;
288 }
289 }
290
printPCRelOperand(MCInst * MI,int OpNum,SStream * O)291 static void printPCRelOperand(MCInst *MI, int OpNum, SStream *O)
292 {
293 MCOperand *MO = MCInst_getOperand(MI, OpNum);
294 int32_t imm;
295
296 if (MCOperand_isImm(MO)) {
297 imm = (int32_t)MCOperand_getImm(MO);
298 if (imm >= 0) {
299 if (imm > HEX_THRESHOLD)
300 SStream_concat(O, "0x%x", imm);
301 else
302 SStream_concat(O, "%u", imm);
303 } else {
304 if (imm < -HEX_THRESHOLD)
305 SStream_concat(O, "-0x%x", -imm);
306 else
307 SStream_concat(O, "-%u", -imm);
308 }
309
310 if (MI->csh->detail) {
311 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM;
312 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)imm;
313 MI->flat_insn->detail->sysz.op_count++;
314 }
315 }
316 }
317
printOperand(MCInst * MI,int OpNum,SStream * O)318 static void printOperand(MCInst *MI, int OpNum, SStream *O)
319 {
320 _printOperand(MI, MCInst_getOperand(MI, OpNum), O);
321 }
322
printBDAddrOperand(MCInst * MI,int OpNum,SStream * O)323 static void printBDAddrOperand(MCInst *MI, int OpNum, SStream *O)
324 {
325 printAddress(MI, MCOperand_getReg(MCInst_getOperand(MI, OpNum)),
326 MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)), 0, O);
327 }
328
printBDXAddrOperand(MCInst * MI,int OpNum,SStream * O)329 static void printBDXAddrOperand(MCInst *MI, int OpNum, SStream *O)
330 {
331 printAddress(MI, MCOperand_getReg(MCInst_getOperand(MI, OpNum)),
332 MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)),
333 MCOperand_getReg(MCInst_getOperand(MI, OpNum + 2)), O);
334 }
335
printBDLAddrOperand(MCInst * MI,int OpNum,SStream * O)336 static void printBDLAddrOperand(MCInst *MI, int OpNum, SStream *O)
337 {
338 unsigned Base = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
339 uint64_t Disp = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
340 uint64_t Length = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 2));
341
342 if (Disp > HEX_THRESHOLD)
343 SStream_concat(O, "0x%"PRIx64, Disp);
344 else
345 SStream_concat(O, "%"PRIu64, Disp);
346
347 if (Length > HEX_THRESHOLD)
348 SStream_concat(O, "(0x%"PRIx64, Length);
349 else
350 SStream_concat(O, "(%"PRIu64, Length);
351
352 if (Base)
353 SStream_concat(O, ", %%%s", getRegisterName(Base));
354 SStream_concat0(O, ")");
355
356 if (MI->csh->detail) {
357 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_MEM;
358 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.base = (uint8_t)SystemZ_map_register(Base);
359 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.length = Length;
360 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.disp = (int64_t)Disp;
361 MI->flat_insn->detail->sysz.op_count++;
362 }
363 }
364
printCond4Operand(MCInst * MI,int OpNum,SStream * O)365 static void printCond4Operand(MCInst *MI, int OpNum, SStream *O)
366 {
367 static char *const CondNames[] = {
368 "o", "h", "nle", "l", "nhe", "lh", "ne",
369 "e", "nlh", "he", "nl", "le", "nh", "no"
370 };
371
372 uint64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
373 // assert(Imm > 0 && Imm < 15 && "Invalid condition");
374 SStream_concat0(O, CondNames[Imm - 1]);
375
376 if (MI->csh->detail)
377 MI->flat_insn->detail->sysz.cc = (sysz_cc)Imm;
378 }
379
380 #define PRINT_ALIAS_INSTR
381 #include "SystemZGenAsmWriter.inc"
382
SystemZ_printInst(MCInst * MI,SStream * O,void * Info)383 void SystemZ_printInst(MCInst *MI, SStream *O, void *Info)
384 {
385 printInstruction(MI, O, Info);
386 }
387
388 #endif
389