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