• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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