• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===//
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 file includes code for rendering MCInst instances as AT&T-style
11 // assembly.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 /* Capstone Disassembly Engine */
16 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
17 
18 // this code is only relevant when DIET mode is disable
19 #if defined(CAPSTONE_HAS_X86) && !defined(CAPSTONE_DIET) && !defined(CAPSTONE_X86_ATT_DISABLE)
20 
21 #if !defined(CAPSTONE_HAS_OSXKERNEL)
22 #include <ctype.h>
23 #endif
24 #include <platform.h>
25 #if defined(CAPSTONE_HAS_OSXKERNEL)
26 #include <libkern/libkern.h>
27 #else
28 #include <stdio.h>
29 #include <stdlib.h>
30 #endif
31 
32 #include <string.h>
33 
34 #include "../../utils.h"
35 #include "../../MCInst.h"
36 #include "../../SStream.h"
37 #include "../../MCRegisterInfo.h"
38 #include "X86Mapping.h"
39 #include "X86BaseInfo.h"
40 
41 
42 #define GET_INSTRINFO_ENUM
43 #ifdef CAPSTONE_X86_REDUCE
44 #include "X86GenInstrInfo_reduce.inc"
45 #else
46 #include "X86GenInstrInfo.inc"
47 #endif
48 
49 static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
50 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
51 
52 
set_mem_access(MCInst * MI,bool status)53 static void set_mem_access(MCInst *MI, bool status)
54 {
55 	if (MI->csh->detail != CS_OPT_ON)
56 		return;
57 
58 	MI->csh->doing_mem = status;
59 	if (!status)
60 		// done, create the next operand slot
61 		MI->flat_insn->detail->x86.op_count++;
62 }
63 
printopaquemem(MCInst * MI,unsigned OpNo,SStream * O)64 static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
65 {
66 	switch(MI->csh->mode) {
67 		case CS_MODE_16:
68 			MI->x86opsize = 2;
69 			break;
70 		case CS_MODE_32:
71 			MI->x86opsize = 4;
72 			break;
73 		case CS_MODE_64:
74 			MI->x86opsize = 8;
75 			break;
76 		default:	// never reach
77 			break;
78 	}
79 
80 	printMemReference(MI, OpNo, O);
81 }
82 
printi8mem(MCInst * MI,unsigned OpNo,SStream * O)83 static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
84 {
85 	MI->x86opsize = 1;
86 	printMemReference(MI, OpNo, O);
87 }
88 
printi16mem(MCInst * MI,unsigned OpNo,SStream * O)89 static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
90 {
91 	MI->x86opsize = 2;
92 
93 	printMemReference(MI, OpNo, O);
94 }
95 
printi32mem(MCInst * MI,unsigned OpNo,SStream * O)96 static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
97 {
98 	MI->x86opsize = 4;
99 
100 	printMemReference(MI, OpNo, O);
101 }
102 
printi64mem(MCInst * MI,unsigned OpNo,SStream * O)103 static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
104 {
105 	MI->x86opsize = 8;
106 	printMemReference(MI, OpNo, O);
107 }
108 
printi128mem(MCInst * MI,unsigned OpNo,SStream * O)109 static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
110 {
111 	MI->x86opsize = 16;
112 	printMemReference(MI, OpNo, O);
113 }
114 
115 #ifndef CAPSTONE_X86_REDUCE
printi256mem(MCInst * MI,unsigned OpNo,SStream * O)116 static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
117 {
118 	MI->x86opsize = 32;
119 	printMemReference(MI, OpNo, O);
120 }
121 
printi512mem(MCInst * MI,unsigned OpNo,SStream * O)122 static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
123 {
124 	MI->x86opsize = 64;
125 	printMemReference(MI, OpNo, O);
126 }
127 
printf32mem(MCInst * MI,unsigned OpNo,SStream * O)128 static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
129 {
130 	MI->x86opsize = 4;
131 	printMemReference(MI, OpNo, O);
132 }
133 
printf64mem(MCInst * MI,unsigned OpNo,SStream * O)134 static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
135 {
136 	MI->x86opsize = 8;
137 	printMemReference(MI, OpNo, O);
138 }
139 
printf80mem(MCInst * MI,unsigned OpNo,SStream * O)140 static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
141 {
142 	MI->x86opsize = 10;
143 	printMemReference(MI, OpNo, O);
144 }
145 
printf128mem(MCInst * MI,unsigned OpNo,SStream * O)146 static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
147 {
148 	MI->x86opsize = 16;
149 	printMemReference(MI, OpNo, O);
150 }
151 
printf256mem(MCInst * MI,unsigned OpNo,SStream * O)152 static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
153 {
154 	MI->x86opsize = 32;
155 	printMemReference(MI, OpNo, O);
156 }
157 
printf512mem(MCInst * MI,unsigned OpNo,SStream * O)158 static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
159 {
160 	MI->x86opsize = 64;
161 	printMemReference(MI, OpNo, O);
162 }
163 
printSSECC(MCInst * MI,unsigned Op,SStream * OS)164 static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
165 {
166 	int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 7;
167 	switch (Imm) {
168 		default: break;	// never reach
169 		case    0: SStream_concat0(OS, "eq"); op_addSseCC(MI, X86_SSE_CC_EQ); break;
170 		case    1: SStream_concat0(OS, "lt"); op_addSseCC(MI, X86_SSE_CC_LT); break;
171 		case    2: SStream_concat0(OS, "le"); op_addSseCC(MI, X86_SSE_CC_LE); break;
172 		case    3: SStream_concat0(OS, "unord"); op_addSseCC(MI, X86_SSE_CC_UNORD); break;
173 		case    4: SStream_concat0(OS, "neq"); op_addSseCC(MI, X86_SSE_CC_NEQ); break;
174 		case    5: SStream_concat0(OS, "nlt"); op_addSseCC(MI, X86_SSE_CC_NLT); break;
175 		case    6: SStream_concat0(OS, "nle"); op_addSseCC(MI, X86_SSE_CC_NLE); break;
176 		case    7: SStream_concat0(OS, "ord"); op_addSseCC(MI, X86_SSE_CC_ORD); break;
177 		case    8: SStream_concat0(OS, "eq_uq"); op_addSseCC(MI, X86_SSE_CC_EQ_UQ); break;
178 		case    9: SStream_concat0(OS, "nge"); op_addSseCC(MI, X86_SSE_CC_NGE); break;
179 		case  0xa: SStream_concat0(OS, "ngt"); op_addSseCC(MI, X86_SSE_CC_NGT); break;
180 		case  0xb: SStream_concat0(OS, "false"); op_addSseCC(MI, X86_SSE_CC_FALSE); break;
181 		case  0xc: SStream_concat0(OS, "neq_oq"); op_addSseCC(MI, X86_SSE_CC_NEQ_OQ); break;
182 		case  0xd: SStream_concat0(OS, "ge"); op_addSseCC(MI, X86_SSE_CC_GE); break;
183 		case  0xe: SStream_concat0(OS, "gt"); op_addSseCC(MI, X86_SSE_CC_GT); break;
184 		case  0xf: SStream_concat0(OS, "true"); op_addSseCC(MI, X86_SSE_CC_TRUE); break;
185 	}
186 }
187 
printAVXCC(MCInst * MI,unsigned Op,SStream * O)188 static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
189 {
190 	int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f;
191 	switch (Imm) {
192 		default: break;//printf("Invalid avxcc argument!\n"); break;
193 		case    0: SStream_concat0(O, "eq"); op_addAvxCC(MI, X86_AVX_CC_EQ); break;
194 		case    1: SStream_concat0(O, "lt"); op_addAvxCC(MI, X86_AVX_CC_LT); break;
195 		case    2: SStream_concat0(O, "le"); op_addAvxCC(MI, X86_AVX_CC_LE); break;
196 		case    3: SStream_concat0(O, "unord"); op_addAvxCC(MI, X86_AVX_CC_UNORD); break;
197 		case    4: SStream_concat0(O, "neq"); op_addAvxCC(MI, X86_AVX_CC_NEQ); break;
198 		case    5: SStream_concat0(O, "nlt"); op_addAvxCC(MI, X86_AVX_CC_NLT); break;
199 		case    6: SStream_concat0(O, "nle"); op_addAvxCC(MI, X86_AVX_CC_NLE); break;
200 		case    7: SStream_concat0(O, "ord"); op_addAvxCC(MI, X86_AVX_CC_ORD); break;
201 		case    8: SStream_concat0(O, "eq_uq"); op_addAvxCC(MI, X86_AVX_CC_EQ_UQ); break;
202 		case    9: SStream_concat0(O, "nge"); op_addAvxCC(MI, X86_AVX_CC_NGE); break;
203 		case  0xa: SStream_concat0(O, "ngt"); op_addAvxCC(MI, X86_AVX_CC_NGT); break;
204 		case  0xb: SStream_concat0(O, "false"); op_addAvxCC(MI, X86_AVX_CC_FALSE); break;
205 		case  0xc: SStream_concat0(O, "neq_oq"); op_addAvxCC(MI, X86_AVX_CC_NEQ_OQ); break;
206 		case  0xd: SStream_concat0(O, "ge"); op_addAvxCC(MI, X86_AVX_CC_GE); break;
207 		case  0xe: SStream_concat0(O, "gt"); op_addAvxCC(MI, X86_AVX_CC_GT); break;
208 		case  0xf: SStream_concat0(O, "true"); op_addAvxCC(MI, X86_AVX_CC_TRUE); break;
209 		case 0x10: SStream_concat0(O, "eq_os"); op_addAvxCC(MI, X86_AVX_CC_EQ_OS); break;
210 		case 0x11: SStream_concat0(O, "lt_oq"); op_addAvxCC(MI, X86_AVX_CC_LT_OQ); break;
211 		case 0x12: SStream_concat0(O, "le_oq"); op_addAvxCC(MI, X86_AVX_CC_LE_OQ); break;
212 		case 0x13: SStream_concat0(O, "unord_s"); op_addAvxCC(MI, X86_AVX_CC_UNORD_S); break;
213 		case 0x14: SStream_concat0(O, "neq_us"); op_addAvxCC(MI, X86_AVX_CC_NEQ_US); break;
214 		case 0x15: SStream_concat0(O, "nlt_uq"); op_addAvxCC(MI, X86_AVX_CC_NLT_UQ); break;
215 		case 0x16: SStream_concat0(O, "nle_uq"); op_addAvxCC(MI, X86_AVX_CC_NLE_UQ); break;
216 		case 0x17: SStream_concat0(O, "ord_s"); op_addAvxCC(MI, X86_AVX_CC_ORD_S); break;
217 		case 0x18: SStream_concat0(O, "eq_us"); op_addAvxCC(MI, X86_AVX_CC_EQ_US); break;
218 		case 0x19: SStream_concat0(O, "nge_uq"); op_addAvxCC(MI, X86_AVX_CC_NGE_UQ); break;
219 		case 0x1a: SStream_concat0(O, "ngt_uq"); op_addAvxCC(MI, X86_AVX_CC_NGT_UQ); break;
220 		case 0x1b: SStream_concat0(O, "false_os"); op_addAvxCC(MI, X86_AVX_CC_FALSE_OS); break;
221 		case 0x1c: SStream_concat0(O, "neq_os"); op_addAvxCC(MI, X86_AVX_CC_NEQ_OS); break;
222 		case 0x1d: SStream_concat0(O, "ge_oq"); op_addAvxCC(MI, X86_AVX_CC_GE_OQ); break;
223 		case 0x1e: SStream_concat0(O, "gt_oq"); op_addAvxCC(MI, X86_AVX_CC_GT_OQ); break;
224 		case 0x1f: SStream_concat0(O, "true_us"); op_addAvxCC(MI, X86_AVX_CC_TRUE_US); break;
225 	}
226 }
227 
printRoundingControl(MCInst * MI,unsigned Op,SStream * O)228 static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O)
229 {
230 	int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3;
231 	switch (Imm) {
232 		case 0: SStream_concat0(O, "{rn-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RN); break;
233 		case 1: SStream_concat0(O, "{rd-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RD); break;
234 		case 2: SStream_concat0(O, "{ru-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RU); break;
235 		case 3: SStream_concat0(O, "{rz-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RZ); break;
236 		default: break;	// nev0er reach
237 	}
238 }
239 
240 #endif
241 
242 static void printRegName(SStream *OS, unsigned RegNo);
243 
244 // local printOperand, without updating public operands
_printOperand(MCInst * MI,unsigned OpNo,SStream * O)245 static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
246 {
247 	MCOperand *Op  = MCInst_getOperand(MI, OpNo);
248 	if (MCOperand_isReg(Op)) {
249 		printRegName(O, MCOperand_getReg(Op));
250 	} else if (MCOperand_isImm(Op)) {
251 		// Print X86 immediates as signed values.
252 		int64_t imm = MCOperand_getImm(Op);
253 		if (imm < 0) {
254 			if (imm < -HEX_THRESHOLD)
255 				SStream_concat(O, "$-0x%"PRIx64, -imm);
256 			else
257 				SStream_concat(O, "$-%"PRIu64, -imm);
258 		} else {
259 			if (imm > HEX_THRESHOLD)
260 				SStream_concat(O, "$0x%"PRIx64, imm);
261 			else
262 				SStream_concat(O, "$%"PRIu64, imm);
263 		}
264 	}
265 }
266 
printSrcIdx(MCInst * MI,unsigned Op,SStream * O)267 static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
268 {
269 	MCOperand *SegReg;
270 	int reg;
271 
272 	if (MI->csh->detail) {
273 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
274 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
275 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
276 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
277 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
278 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
279 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
280 	}
281 
282 	SegReg = MCInst_getOperand(MI, Op+1);
283 	reg = MCOperand_getReg(SegReg);
284 
285 	// If this has a segment register, print it.
286 	if (reg) {
287 		_printOperand(MI, Op+1, O);
288 		if (MI->csh->detail) {
289 			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
290 		}
291 
292 		SStream_concat0(O, ":");
293 	}
294 
295 	SStream_concat0(O, "(");
296 	set_mem_access(MI, true);
297 
298 	printOperand(MI, Op, O);
299 
300 	SStream_concat0(O, ")");
301 	set_mem_access(MI, false);
302 }
303 
printDstIdx(MCInst * MI,unsigned Op,SStream * O)304 static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
305 {
306 	if (MI->csh->detail) {
307 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
308 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
309 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
310 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
311 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
312 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
313 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
314 	}
315 
316 	// DI accesses are always ES-based on non-64bit mode
317 	if (MI->csh->mode != CS_MODE_64) {
318 		SStream_concat0(O, "%es:(");
319 		if (MI->csh->detail) {
320 			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_ES;
321 		}
322 	} else
323 		SStream_concat0(O, "(");
324 
325 	set_mem_access(MI, true);
326 
327 	printOperand(MI, Op, O);
328 
329 	SStream_concat0(O, ")");
330 	set_mem_access(MI, false);
331 }
332 
printSrcIdx8(MCInst * MI,unsigned OpNo,SStream * O)333 static void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
334 {
335 	MI->x86opsize = 1;
336 	printSrcIdx(MI, OpNo, O);
337 }
338 
printSrcIdx16(MCInst * MI,unsigned OpNo,SStream * O)339 static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
340 {
341 	MI->x86opsize = 2;
342 	printSrcIdx(MI, OpNo, O);
343 }
344 
printSrcIdx32(MCInst * MI,unsigned OpNo,SStream * O)345 static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
346 {
347 	MI->x86opsize = 4;
348 	printSrcIdx(MI, OpNo, O);
349 }
350 
printSrcIdx64(MCInst * MI,unsigned OpNo,SStream * O)351 static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
352 {
353 	MI->x86opsize = 8;
354 	printSrcIdx(MI, OpNo, O);
355 }
356 
printDstIdx8(MCInst * MI,unsigned OpNo,SStream * O)357 static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
358 {
359 	MI->x86opsize = 1;
360 	printDstIdx(MI, OpNo, O);
361 }
362 
printDstIdx16(MCInst * MI,unsigned OpNo,SStream * O)363 static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
364 {
365 	MI->x86opsize = 2;
366 	printDstIdx(MI, OpNo, O);
367 }
368 
printDstIdx32(MCInst * MI,unsigned OpNo,SStream * O)369 static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
370 {
371 	MI->x86opsize = 4;
372 	printDstIdx(MI, OpNo, O);
373 }
374 
printDstIdx64(MCInst * MI,unsigned OpNo,SStream * O)375 static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
376 {
377 	MI->x86opsize = 8;
378 	printDstIdx(MI, OpNo, O);
379 }
380 
printMemOffset(MCInst * MI,unsigned Op,SStream * O)381 static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
382 {
383 	MCOperand *DispSpec = MCInst_getOperand(MI, Op);
384 	MCOperand *SegReg = MCInst_getOperand(MI, Op+1);
385 	int reg;
386 
387 	if (MI->csh->detail) {
388 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
389 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
390 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
391 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
392 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
393 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
394 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
395 	}
396 
397 	// If this has a segment register, print it.
398 	reg = MCOperand_getReg(SegReg);
399 	if (reg) {
400 		_printOperand(MI, Op + 1, O);
401 		SStream_concat0(O, ":");
402 		if (MI->csh->detail) {
403 			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
404 		}
405 	}
406 
407 	if (MCOperand_isImm(DispSpec)) {
408 		int64_t imm = MCOperand_getImm(DispSpec);
409 		if (MI->csh->detail)
410 			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
411 		if (imm < 0) {
412 			SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm);
413 		} else {
414 			if (imm > HEX_THRESHOLD)
415 				SStream_concat(O, "0x%"PRIx64, imm);
416 			else
417 				SStream_concat(O, "%"PRIu64, imm);
418 		}
419 	}
420 
421 	if (MI->csh->detail)
422 		MI->flat_insn->detail->x86.op_count++;
423 }
424 
printMemOffs8(MCInst * MI,unsigned OpNo,SStream * O)425 static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
426 {
427 	MI->x86opsize = 1;
428 	printMemOffset(MI, OpNo, O);
429 }
430 
printMemOffs16(MCInst * MI,unsigned OpNo,SStream * O)431 static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
432 {
433 	MI->x86opsize = 2;
434 	printMemOffset(MI, OpNo, O);
435 }
436 
printMemOffs32(MCInst * MI,unsigned OpNo,SStream * O)437 static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
438 {
439 	MI->x86opsize = 4;
440 	printMemOffset(MI, OpNo, O);
441 }
442 
printMemOffs64(MCInst * MI,unsigned OpNo,SStream * O)443 static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
444 {
445 	MI->x86opsize = 8;
446 	printMemOffset(MI, OpNo, O);
447 }
448 
449 /// printPCRelImm - This is used to print an immediate value that ends up
450 /// being encoded as a pc-relative value (e.g. for jumps and calls).  These
451 /// print slightly differently than normal immediates.  For example, a $ is not
452 /// emitted.
printPCRelImm(MCInst * MI,unsigned OpNo,SStream * O)453 static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
454 {
455 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
456 	if (MCOperand_isImm(Op)) {
457 		int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + MI->address;
458 
459 		// truncat imm for non-64bit
460 		if (MI->csh->mode != CS_MODE_64) {
461 			imm = imm & 0xffffffff;
462 		}
463 
464 		if (MI->csh->mode == CS_MODE_16 &&
465 				(MI->Opcode != X86_JMP_4 && MI->Opcode != X86_CALLpcrel32))
466 			imm = imm & 0xffff;
467 
468 		// Hack: X86 16bit with opcode X86_JMP_4
469 		if (MI->csh->mode == CS_MODE_16 &&
470 				(MI->Opcode == X86_JMP_4 && MI->x86_prefix[2] != 0x66))
471 			imm = imm & 0xffff;
472 
473 		// CALL/JMP rel16 is special
474 		if (MI->Opcode == X86_CALLpcrel16 || MI->Opcode == X86_JMP_2)
475 			imm = imm & 0xffff;
476 
477 		if (imm < 0) {
478 			SStream_concat(O, "0x%"PRIx64, imm);
479 		} else {
480 			if (imm > HEX_THRESHOLD)
481 				SStream_concat(O, "0x%"PRIx64, imm);
482 			else
483 				SStream_concat(O, "%"PRIu64, imm);
484 		}
485 		if (MI->csh->detail) {
486 			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
487 			MI->has_imm = true;
488 			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
489 			MI->flat_insn->detail->x86.op_count++;
490 		}
491 	}
492 }
493 
printOperand(MCInst * MI,unsigned OpNo,SStream * O)494 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
495 {
496 	uint8_t opsize = 0;
497 	MCOperand *Op  = MCInst_getOperand(MI, OpNo);
498 
499 	if (MCOperand_isReg(Op)) {
500 		unsigned int reg = MCOperand_getReg(Op);
501 		printRegName(O, reg);
502 		if (MI->csh->detail) {
503 			if (MI->csh->doing_mem) {
504 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
505 			} else {
506 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
507 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
508 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];
509 				MI->flat_insn->detail->x86.op_count++;
510 			}
511 		}
512 	} else if (MCOperand_isImm(Op)) {
513 		// Print X86 immediates as signed values.
514 		int64_t imm = MCOperand_getImm(Op);
515 
516 		switch(MCInst_getOpcode(MI)) {
517 			default:
518 				break;
519 
520 			case X86_AAD8i8:
521 			case X86_AAM8i8:
522 			case X86_ADC8i8:
523 			case X86_ADD8i8:
524 			case X86_AND8i8:
525 			case X86_CMP8i8:
526 			case X86_OR8i8:
527 			case X86_SBB8i8:
528 			case X86_SUB8i8:
529 			case X86_TEST8i8:
530 			case X86_XOR8i8:
531 			case X86_ROL8ri:
532 			case X86_ADC8ri:
533 			case X86_ADD8ri:
534 			case X86_ADD8ri8:
535 			case X86_AND8ri:
536 			case X86_AND8ri8:
537 			case X86_CMP8ri:
538 			case X86_MOV8ri:
539 			case X86_MOV8ri_alt:
540 			case X86_OR8ri:
541 			case X86_OR8ri8:
542 			case X86_RCL8ri:
543 			case X86_RCR8ri:
544 			case X86_ROR8ri:
545 			case X86_SAL8ri:
546 			case X86_SAR8ri:
547 			case X86_SBB8ri:
548 			case X86_SHL8ri:
549 			case X86_SHR8ri:
550 			case X86_SUB8ri:
551 			case X86_SUB8ri8:
552 			case X86_TEST8ri:
553 			case X86_TEST8ri_NOREX:
554 			case X86_TEST8ri_alt:
555 			case X86_XOR8ri:
556 			case X86_XOR8ri8:
557 			case X86_OUT8ir:
558 
559 			case X86_ADC8mi:
560 			case X86_ADD8mi:
561 			case X86_AND8mi:
562 			case X86_CMP8mi:
563 			case X86_LOCK_ADD8mi:
564 			case X86_LOCK_AND8mi:
565 			case X86_LOCK_OR8mi:
566 			case X86_LOCK_SUB8mi:
567 			case X86_LOCK_XOR8mi:
568 			case X86_MOV8mi:
569 			case X86_OR8mi:
570 			case X86_RCL8mi:
571 			case X86_RCR8mi:
572 			case X86_ROL8mi:
573 			case X86_ROR8mi:
574 			case X86_SAL8mi:
575 			case X86_SAR8mi:
576 			case X86_SBB8mi:
577 			case X86_SHL8mi:
578 			case X86_SHR8mi:
579 			case X86_SUB8mi:
580 			case X86_TEST8mi:
581 			case X86_TEST8mi_alt:
582 			case X86_XOR8mi:
583 			case X86_PUSH64i8:
584 			case X86_CMP32ri8:
585 			case X86_CMP64ri8:
586 
587 				imm = imm & 0xff;
588 				opsize = 1;     // immediate of 1 byte
589 				break;
590 		}
591 
592 		switch(MI->flat_insn->id) {
593 			default:
594 				if (imm >= 0) {
595 					if (imm > HEX_THRESHOLD)
596 						SStream_concat(O, "$0x%"PRIx64, imm);
597 					else
598 						SStream_concat(O, "$%"PRIu64, imm);
599 				} else {
600 					if (imm < -HEX_THRESHOLD)
601 						SStream_concat(O, "$-0x%"PRIx64, -imm);
602 					else
603 						SStream_concat(O, "$-%"PRIu64, -imm);
604 				}
605 				break;
606 
607 			case X86_INS_INT:
608 				// do not print number in negative form
609 				imm = imm & 0xff;
610 				if (imm >= 0 && imm <= HEX_THRESHOLD)
611 					SStream_concat(O, "$%u", imm);
612 				else {
613 					SStream_concat(O, "$0x%x", imm);
614 				}
615 				break;
616 
617 			case X86_INS_LCALL:
618 			case X86_INS_LJMP:
619 				// always print address in positive form
620 				if (OpNo == 1) { // selector is ptr16
621 					imm = imm & 0xffff;
622 					opsize = 2;
623 				}
624 				SStream_concat(O, "$0x%"PRIx64, imm);
625 				break;
626 
627 			case X86_INS_AND:
628 			case X86_INS_OR:
629 			case X86_INS_XOR:
630 				// do not print number in negative form
631 				if (imm >= 0 && imm <= HEX_THRESHOLD)
632 					SStream_concat(O, "$%u", imm);
633 				else {
634 					imm = arch_masks[MI->op1_size? MI->op1_size : MI->imm_size] & imm;
635 					SStream_concat(O, "$0x%"PRIx64, imm);
636 				}
637 				break;
638 
639 			case X86_INS_RET:
640 				// RET imm16
641 				if (imm >= 0 && imm <= HEX_THRESHOLD)
642 					SStream_concat(O, "$%u", imm);
643 				else {
644 					imm = 0xffff & imm;
645 					SStream_concat(O, "$0x%x", imm);
646 				}
647 				break;
648 		}
649 
650 		if (MI->csh->detail) {
651 			if (MI->csh->doing_mem) {
652 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
653 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
654 			} else {
655 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
656 				MI->has_imm = true;
657 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
658 
659 				if (opsize > 0)
660 					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
661 				else if (MI->op1_size > 0)
662 					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->op1_size;
663 				else
664 					MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
665 
666 				MI->flat_insn->detail->x86.op_count++;
667 			}
668 		}
669 	}
670 }
671 
printMemReference(MCInst * MI,unsigned Op,SStream * O)672 static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
673 {
674 	MCOperand *BaseReg  = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
675 	MCOperand *IndexReg  = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
676 	MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
677 	MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
678 	uint64_t ScaleVal;
679 	int segreg;
680 
681 	if (MI->csh->detail) {
682 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
683 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
684 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
685 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg);
686 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
687 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
688 		MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
689 	}
690 
691 	// If this has a segment register, print it.
692 	segreg = MCOperand_getReg(SegReg);
693 	if (segreg) {
694 		_printOperand(MI, Op + X86_AddrSegmentReg, O);
695 		if (MI->csh->detail) {
696 			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = segreg;
697 		}
698 
699 		SStream_concat0(O, ":");
700 	}
701 
702 	if (MCOperand_isImm(DispSpec)) {
703 		int64_t DispVal = MCOperand_getImm(DispSpec);
704 		if (MI->csh->detail)
705 			MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal;
706 		if (DispVal) {
707 			if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
708 				if (DispVal < 0) {
709 					if (DispVal <  -HEX_THRESHOLD)
710 						SStream_concat(O, "-0x%"PRIx64, -DispVal);
711 					else
712 						SStream_concat(O, "-%"PRIu64, -DispVal);
713 				} else {
714 					if (DispVal > HEX_THRESHOLD)
715 						SStream_concat(O, "0x%"PRIx64, DispVal);
716 					else
717 						SStream_concat(O, "%"PRIu64, DispVal);
718 				}
719 			} else {
720 				// only immediate as address of memory
721 				if (DispVal < 0) {
722 					SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal);
723 				} else {
724 					if (DispVal > HEX_THRESHOLD)
725 						SStream_concat(O, "0x%"PRIx64, DispVal);
726 					else
727 						SStream_concat(O, "%"PRIu64, DispVal);
728 				}
729 			}
730 		} else {
731 			if (segreg)
732 				SStream_concat0(O, "0");
733 		}
734 	}
735 
736 	if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
737 		SStream_concat0(O, "(");
738 
739 		if (MCOperand_getReg(BaseReg))
740 			_printOperand(MI, Op + X86_AddrBaseReg, O);
741 
742 		if (MCOperand_getReg(IndexReg)) {
743 			SStream_concat0(O, ", ");
744 			_printOperand(MI, Op + X86_AddrIndexReg, O);
745 			ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
746 			if (MI->csh->detail)
747 				MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal;
748 			if (ScaleVal != 1) {
749 				SStream_concat(O, ", %u", ScaleVal);
750 			}
751 		}
752 		SStream_concat0(O, ")");
753 	}
754 
755 	if (MI->csh->detail)
756 		MI->flat_insn->detail->x86.op_count++;
757 }
758 
759 #include "X86InstPrinter.h"
760 
761 #define GET_REGINFO_ENUM
762 #include "X86GenRegisterInfo.inc"
763 
764 // Include the auto-generated portion of the assembly writer.
765 #define PRINT_ALIAS_INSTR
766 #ifdef CAPSTONE_X86_REDUCE
767 #include "X86GenAsmWriter_reduce.inc"
768 #else
769 #include "X86GenAsmWriter.inc"
770 #endif
771 
printRegName(SStream * OS,unsigned RegNo)772 static void printRegName(SStream *OS, unsigned RegNo)
773 {
774 	SStream_concat(OS, "%%%s", getRegisterName(RegNo));
775 }
776 
X86_ATT_printInst(MCInst * MI,SStream * OS,void * info)777 void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
778 {
779 	char *mnem;
780 	x86_reg reg, reg2;
781 	int i;
782 
783 	// Output CALLpcrel32 as "callq" in 64-bit mode.
784 	// In Intel annotation it's always emitted as "call".
785 	//
786 	// TODO: Probably this hack should be redesigned via InstAlias in
787 	// InstrInfo.td as soon as Requires clause is supported properly
788 	// for InstAlias.
789 	if (MI->csh->mode == CS_MODE_64 && MCInst_getOpcode(MI) == X86_CALLpcrel32) {
790 		SStream_concat0(OS, "callq\t");
791 		MCInst_setOpcodePub(MI, X86_INS_CALL);
792 		printPCRelImm(MI, 0, OS);
793 		return;
794 	}
795 
796 	// Try to print any aliases first.
797 	mnem = printAliasInstr(MI, OS, info);
798 	if (mnem)
799 		cs_mem_free(mnem);
800 	else
801 		printInstruction(MI, OS, info);
802 
803 	// HACK TODO: fix this in machine description
804 	switch(MI->flat_insn->id) {
805 		default: break;
806 		case X86_INS_SYSEXIT:
807 				 SStream_Init(OS);
808 				 SStream_concat0(OS, "sysexit");
809 				 break;
810 	}
811 
812 	if (MI->has_imm) {
813 		// if op_count > 1, then this operand's size is taken from the destination op
814 		if (MI->flat_insn->detail->x86.op_count > 1) {
815 			if (MI->flat_insn->id != X86_INS_LCALL && MI->flat_insn->id != X86_INS_LJMP) {
816 				for (i = 0; i < MI->flat_insn->detail->x86.op_count; i++) {
817 					if (MI->flat_insn->detail->x86.operands[i].type == X86_OP_IMM)
818 						MI->flat_insn->detail->x86.operands[i].size =
819 							MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count - 1].size;
820 				}
821 			}
822 		} else
823 			MI->flat_insn->detail->x86.operands[0].size = MI->imm_size;
824 	}
825 
826 	if (MI->csh->detail) {
827         // some instructions need to supply immediate 1 in the first op
828         switch(MCInst_getOpcode(MI)) {
829             default:
830                 break;
831             case X86_SHL8r1:
832             case X86_SHL16r1:
833             case X86_SHL32r1:
834             case X86_SHL64r1:
835             case X86_SAL8r1:
836             case X86_SAL16r1:
837             case X86_SAL32r1:
838             case X86_SAL64r1:
839             case X86_SHR8r1:
840             case X86_SHR16r1:
841             case X86_SHR32r1:
842             case X86_SHR64r1:
843             case X86_SAR8r1:
844             case X86_SAR16r1:
845             case X86_SAR32r1:
846             case X86_SAR64r1:
847             case X86_RCL8r1:
848             case X86_RCL16r1:
849             case X86_RCL32r1:
850             case X86_RCL64r1:
851             case X86_RCR8r1:
852             case X86_RCR16r1:
853             case X86_RCR32r1:
854             case X86_RCR64r1:
855             case X86_ROL8r1:
856             case X86_ROL16r1:
857             case X86_ROL32r1:
858             case X86_ROL64r1:
859             case X86_ROR8r1:
860             case X86_ROR16r1:
861             case X86_ROR32r1:
862             case X86_ROR64r1:
863             case X86_SHL8m1:
864             case X86_SHL16m1:
865             case X86_SHL32m1:
866             case X86_SHL64m1:
867             case X86_SAL8m1:
868             case X86_SAL16m1:
869             case X86_SAL32m1:
870             case X86_SAL64m1:
871             case X86_SHR8m1:
872             case X86_SHR16m1:
873             case X86_SHR32m1:
874             case X86_SHR64m1:
875             case X86_SAR8m1:
876             case X86_SAR16m1:
877             case X86_SAR32m1:
878             case X86_SAR64m1:
879             case X86_RCL8m1:
880             case X86_RCL16m1:
881             case X86_RCL32m1:
882             case X86_RCL64m1:
883             case X86_RCR8m1:
884             case X86_RCR16m1:
885             case X86_RCR32m1:
886             case X86_RCR64m1:
887             case X86_ROL8m1:
888             case X86_ROL16m1:
889             case X86_ROL32m1:
890             case X86_ROL64m1:
891             case X86_ROR8m1:
892             case X86_ROR16m1:
893             case X86_ROR32m1:
894             case X86_ROR64m1:
895                 // shift all the ops right to leave 1st slot for this new register op
896                 memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
897                         sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
898                 MI->flat_insn->detail->x86.operands[0].type = X86_OP_IMM;
899                 MI->flat_insn->detail->x86.operands[0].imm = 1;
900                 MI->flat_insn->detail->x86.operands[0].size = 1;
901                 MI->flat_insn->detail->x86.op_count++;
902         }
903 
904 		// special instruction needs to supply register op
905 		// first op can be embedded in the asm by llvm.
906 		// so we have to add the missing register as the first operand
907 		reg = X86_insn_reg_att(MCInst_getOpcode(MI));
908 		if (reg) {
909 			// shift all the ops right to leave 1st slot for this new register op
910 			memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
911 					sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
912 			MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
913 			MI->flat_insn->detail->x86.operands[0].reg = reg;
914 			MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
915 			MI->flat_insn->detail->x86.op_count++;
916 		} else {
917 			if (X86_insn_reg_att2(MCInst_getOpcode(MI), &reg, &reg2)) {
918 				MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
919 				MI->flat_insn->detail->x86.operands[0].reg = reg;
920 				MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
921 				MI->flat_insn->detail->x86.operands[1].type = X86_OP_REG;
922 				MI->flat_insn->detail->x86.operands[1].reg = reg2;
923 				MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg2];
924 				MI->flat_insn->detail->x86.op_count = 2;
925 			}
926 		}
927 	}
928 }
929 
930 #endif
931