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
32static const char *getRegisterName(unsigned RegNo);
33
34void 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
42static 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
78static 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
115static 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
138static 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
155static 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
179static 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
196static 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
220static 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
237static 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
261static 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
278static 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
291static 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
318static void printOperand(MCInst *MI, int OpNum, SStream *O)
319{
320	_printOperand(MI, MCInst_getOperand(MI, OpNum), O);
321}
322
323static 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
329static 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
336static 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
365static 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
383void SystemZ_printInst(MCInst *MI, SStream *O, void *Info)
384{
385	printInstruction(MI, O, Info);
386}
387
388#endif
389