1 //===-- X86IntelInstPrinter.cpp - Intel 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 Intel-style
11 // assembly.
12 //
13 //===----------------------------------------------------------------------===//
14
15 /* Capstone Disassembly Engine */
16 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
17
18 #ifdef CAPSTONE_HAS_X86
19
20 #if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
21 #pragma warning(disable:4996) // disable MSVC's warning on strncpy()
22 #pragma warning(disable:28719) // disable MSVC's warning on strncpy()
23 #endif
24
25 #if !defined(CAPSTONE_HAS_OSXKERNEL)
26 #include <ctype.h>
27 #endif
28 #include <capstone/platform.h>
29
30 #if defined(CAPSTONE_HAS_OSXKERNEL)
31 #include <Availability.h>
32 #include <libkern/libkern.h>
33 #else
34 #include <stdio.h>
35 #include <stdlib.h>
36 #endif
37 #include <string.h>
38
39 #include "../../utils.h"
40 #include "../../MCInst.h"
41 #include "../../SStream.h"
42 #include "../../MCRegisterInfo.h"
43
44 #include "X86InstPrinter.h"
45 #include "X86Mapping.h"
46
47 #define GET_INSTRINFO_ENUM
48 #ifdef CAPSTONE_X86_REDUCE
49 #include "X86GenInstrInfo_reduce.inc"
50 #else
51 #include "X86GenInstrInfo.inc"
52 #endif
53
54 #include "X86BaseInfo.h"
55
56 static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
57 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
58
59
set_mem_access(MCInst * MI,bool status)60 static void set_mem_access(MCInst *MI, bool status)
61 {
62 if (MI->csh->detail != CS_OPT_ON)
63 return;
64
65 MI->csh->doing_mem = status;
66 if (!status)
67 // done, create the next operand slot
68 MI->flat_insn->detail->x86.op_count++;
69
70 }
71
printopaquemem(MCInst * MI,unsigned OpNo,SStream * O)72 static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
73 {
74 // FIXME: do this with autogen
75 // printf(">>> ID = %u\n", MI->flat_insn->id);
76 switch(MI->flat_insn->id) {
77 default:
78 SStream_concat0(O, "ptr ");
79 break;
80 case X86_INS_SGDT:
81 case X86_INS_SIDT:
82 case X86_INS_LGDT:
83 case X86_INS_LIDT:
84 case X86_INS_FXRSTOR:
85 case X86_INS_FXSAVE:
86 case X86_INS_LJMP:
87 case X86_INS_LCALL:
88 // do not print "ptr"
89 break;
90 }
91
92 switch(MI->csh->mode) {
93 case CS_MODE_16:
94 switch(MI->flat_insn->id) {
95 default:
96 MI->x86opsize = 2;
97 break;
98 case X86_INS_LJMP:
99 case X86_INS_LCALL:
100 MI->x86opsize = 4;
101 break;
102 case X86_INS_SGDT:
103 case X86_INS_SIDT:
104 case X86_INS_LGDT:
105 case X86_INS_LIDT:
106 MI->x86opsize = 6;
107 break;
108 }
109 break;
110 case CS_MODE_32:
111 switch(MI->flat_insn->id) {
112 default:
113 MI->x86opsize = 4;
114 break;
115 case X86_INS_LJMP:
116 case X86_INS_LCALL:
117 case X86_INS_SGDT:
118 case X86_INS_SIDT:
119 case X86_INS_LGDT:
120 case X86_INS_LIDT:
121 MI->x86opsize = 6;
122 break;
123 }
124 break;
125 case CS_MODE_64:
126 switch(MI->flat_insn->id) {
127 default:
128 MI->x86opsize = 8;
129 break;
130 case X86_INS_LJMP:
131 case X86_INS_LCALL:
132 case X86_INS_SGDT:
133 case X86_INS_SIDT:
134 case X86_INS_LGDT:
135 case X86_INS_LIDT:
136 MI->x86opsize = 10;
137 break;
138 }
139 break;
140 default: // never reach
141 break;
142 }
143
144 printMemReference(MI, OpNo, O);
145 }
146
printi8mem(MCInst * MI,unsigned OpNo,SStream * O)147 static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
148 {
149 SStream_concat0(O, "byte ptr ");
150 MI->x86opsize = 1;
151 printMemReference(MI, OpNo, O);
152 }
153
printi16mem(MCInst * MI,unsigned OpNo,SStream * O)154 static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
155 {
156 MI->x86opsize = 2;
157 SStream_concat0(O, "word ptr ");
158 printMemReference(MI, OpNo, O);
159 }
160
printi32mem(MCInst * MI,unsigned OpNo,SStream * O)161 static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
162 {
163 MI->x86opsize = 4;
164 SStream_concat0(O, "dword ptr ");
165 printMemReference(MI, OpNo, O);
166 }
167
printi64mem(MCInst * MI,unsigned OpNo,SStream * O)168 static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
169 {
170 SStream_concat0(O, "qword ptr ");
171 MI->x86opsize = 8;
172 printMemReference(MI, OpNo, O);
173 }
174
printi128mem(MCInst * MI,unsigned OpNo,SStream * O)175 static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
176 {
177 SStream_concat0(O, "xmmword ptr ");
178 MI->x86opsize = 16;
179 printMemReference(MI, OpNo, O);
180 }
181
182 #ifndef CAPSTONE_X86_REDUCE
printi256mem(MCInst * MI,unsigned OpNo,SStream * O)183 static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
184 {
185 SStream_concat0(O, "ymmword ptr ");
186 MI->x86opsize = 32;
187 printMemReference(MI, OpNo, O);
188 }
189
printi512mem(MCInst * MI,unsigned OpNo,SStream * O)190 static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
191 {
192 SStream_concat0(O, "zmmword ptr ");
193 MI->x86opsize = 64;
194 printMemReference(MI, OpNo, O);
195 }
196
printf32mem(MCInst * MI,unsigned OpNo,SStream * O)197 static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
198 {
199 switch(MCInst_getOpcode(MI)) {
200 default:
201 SStream_concat0(O, "dword ptr ");
202 MI->x86opsize = 4;
203 break;
204 case X86_FBSTPm:
205 case X86_FBLDm:
206 // TODO: fix this in tablegen instead
207 SStream_concat0(O, "tbyte ptr ");
208 MI->x86opsize = 10;
209 break;
210 case X86_FSTENVm:
211 case X86_FLDENVm:
212 // TODO: fix this in tablegen instead
213 switch(MI->csh->mode) {
214 default: // never reach
215 break;
216 case CS_MODE_16:
217 MI->x86opsize = 14;
218 break;
219 case CS_MODE_32:
220 case CS_MODE_64:
221 MI->x86opsize = 28;
222 break;
223 }
224 break;
225 }
226
227 printMemReference(MI, OpNo, O);
228 }
229
printf64mem(MCInst * MI,unsigned OpNo,SStream * O)230 static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
231 {
232 SStream_concat0(O, "qword ptr ");
233 MI->x86opsize = 8;
234 printMemReference(MI, OpNo, O);
235 }
236
printf80mem(MCInst * MI,unsigned OpNo,SStream * O)237 static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
238 {
239 SStream_concat0(O, "xword ptr ");
240 MI->x86opsize = 10;
241 printMemReference(MI, OpNo, O);
242 }
243
printf128mem(MCInst * MI,unsigned OpNo,SStream * O)244 static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
245 {
246 SStream_concat0(O, "xmmword ptr ");
247 MI->x86opsize = 16;
248 printMemReference(MI, OpNo, O);
249 }
250
printf256mem(MCInst * MI,unsigned OpNo,SStream * O)251 static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
252 {
253 SStream_concat0(O, "ymmword ptr ");
254 MI->x86opsize = 32;
255 printMemReference(MI, OpNo, O);
256 }
257
printf512mem(MCInst * MI,unsigned OpNo,SStream * O)258 static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
259 {
260 SStream_concat0(O, "zmmword ptr ");
261 MI->x86opsize = 64;
262 printMemReference(MI, OpNo, O);
263 }
264
printSSECC(MCInst * MI,unsigned Op,SStream * OS)265 static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
266 {
267 uint8_t Imm = (uint8_t)(MCOperand_getImm(MCInst_getOperand(MI, Op)) & 7);
268 switch (Imm) {
269 default: break; // never reach
270 case 0: SStream_concat0(OS, "eq"); op_addSseCC(MI, X86_SSE_CC_EQ); break;
271 case 1: SStream_concat0(OS, "lt"); op_addSseCC(MI, X86_SSE_CC_LT); break;
272 case 2: SStream_concat0(OS, "le"); op_addSseCC(MI, X86_SSE_CC_LE); break;
273 case 3: SStream_concat0(OS, "unord"); op_addSseCC(MI, X86_SSE_CC_UNORD); break;
274 case 4: SStream_concat0(OS, "neq"); op_addSseCC(MI, X86_SSE_CC_NEQ); break;
275 case 5: SStream_concat0(OS, "nlt"); op_addSseCC(MI, X86_SSE_CC_NLT); break;
276 case 6: SStream_concat0(OS, "nle"); op_addSseCC(MI, X86_SSE_CC_NLE); break;
277 case 7: SStream_concat0(OS, "ord"); op_addSseCC(MI, X86_SSE_CC_ORD); break;
278 }
279
280 MI->popcode_adjust = Imm + 1;
281 }
282
printAVXCC(MCInst * MI,unsigned Op,SStream * O)283 static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
284 {
285 uint8_t Imm = (uint8_t)(MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f);
286 switch (Imm) {
287 default: break;//printf("Invalid avxcc argument!\n"); break;
288 case 0: SStream_concat0(O, "eq"); op_addAvxCC(MI, X86_AVX_CC_EQ); break;
289 case 1: SStream_concat0(O, "lt"); op_addAvxCC(MI, X86_AVX_CC_LT); break;
290 case 2: SStream_concat0(O, "le"); op_addAvxCC(MI, X86_AVX_CC_LE); break;
291 case 3: SStream_concat0(O, "unord"); op_addAvxCC(MI, X86_AVX_CC_UNORD); break;
292 case 4: SStream_concat0(O, "neq"); op_addAvxCC(MI, X86_AVX_CC_NEQ); break;
293 case 5: SStream_concat0(O, "nlt"); op_addAvxCC(MI, X86_AVX_CC_NLT); break;
294 case 6: SStream_concat0(O, "nle"); op_addAvxCC(MI, X86_AVX_CC_NLE); break;
295 case 7: SStream_concat0(O, "ord"); op_addAvxCC(MI, X86_AVX_CC_ORD); break;
296 case 8: SStream_concat0(O, "eq_uq"); op_addAvxCC(MI, X86_AVX_CC_EQ_UQ); break;
297 case 9: SStream_concat0(O, "nge"); op_addAvxCC(MI, X86_AVX_CC_NGE); break;
298 case 0xa: SStream_concat0(O, "ngt"); op_addAvxCC(MI, X86_AVX_CC_NGT); break;
299 case 0xb: SStream_concat0(O, "false"); op_addAvxCC(MI, X86_AVX_CC_FALSE); break;
300 case 0xc: SStream_concat0(O, "neq_oq"); op_addAvxCC(MI, X86_AVX_CC_NEQ_OQ); break;
301 case 0xd: SStream_concat0(O, "ge"); op_addAvxCC(MI, X86_AVX_CC_GE); break;
302 case 0xe: SStream_concat0(O, "gt"); op_addAvxCC(MI, X86_AVX_CC_GT); break;
303 case 0xf: SStream_concat0(O, "true"); op_addAvxCC(MI, X86_AVX_CC_TRUE); break;
304 case 0x10: SStream_concat0(O, "eq_os"); op_addAvxCC(MI, X86_AVX_CC_EQ_OS); break;
305 case 0x11: SStream_concat0(O, "lt_oq"); op_addAvxCC(MI, X86_AVX_CC_LT_OQ); break;
306 case 0x12: SStream_concat0(O, "le_oq"); op_addAvxCC(MI, X86_AVX_CC_LE_OQ); break;
307 case 0x13: SStream_concat0(O, "unord_s"); op_addAvxCC(MI, X86_AVX_CC_UNORD_S); break;
308 case 0x14: SStream_concat0(O, "neq_us"); op_addAvxCC(MI, X86_AVX_CC_NEQ_US); break;
309 case 0x15: SStream_concat0(O, "nlt_uq"); op_addAvxCC(MI, X86_AVX_CC_NLT_UQ); break;
310 case 0x16: SStream_concat0(O, "nle_uq"); op_addAvxCC(MI, X86_AVX_CC_NLE_UQ); break;
311 case 0x17: SStream_concat0(O, "ord_s"); op_addAvxCC(MI, X86_AVX_CC_ORD_S); break;
312 case 0x18: SStream_concat0(O, "eq_us"); op_addAvxCC(MI, X86_AVX_CC_EQ_US); break;
313 case 0x19: SStream_concat0(O, "nge_uq"); op_addAvxCC(MI, X86_AVX_CC_NGE_UQ); break;
314 case 0x1a: SStream_concat0(O, "ngt_uq"); op_addAvxCC(MI, X86_AVX_CC_NGT_UQ); break;
315 case 0x1b: SStream_concat0(O, "false_os"); op_addAvxCC(MI, X86_AVX_CC_FALSE_OS); break;
316 case 0x1c: SStream_concat0(O, "neq_os"); op_addAvxCC(MI, X86_AVX_CC_NEQ_OS); break;
317 case 0x1d: SStream_concat0(O, "ge_oq"); op_addAvxCC(MI, X86_AVX_CC_GE_OQ); break;
318 case 0x1e: SStream_concat0(O, "gt_oq"); op_addAvxCC(MI, X86_AVX_CC_GT_OQ); break;
319 case 0x1f: SStream_concat0(O, "true_us"); op_addAvxCC(MI, X86_AVX_CC_TRUE_US); break;
320 }
321
322 MI->popcode_adjust = Imm + 1;
323 }
324
printXOPCC(MCInst * MI,unsigned Op,SStream * O)325 static void printXOPCC(MCInst *MI, unsigned Op, SStream *O)
326 {
327 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op));
328
329 switch (Imm) {
330 default: // llvm_unreachable("Invalid xopcc argument!");
331 case 0: SStream_concat0(O, "lt"); op_addXopCC(MI, X86_XOP_CC_LT); break;
332 case 1: SStream_concat0(O, "le"); op_addXopCC(MI, X86_XOP_CC_LE); break;
333 case 2: SStream_concat0(O, "gt"); op_addXopCC(MI, X86_XOP_CC_GT); break;
334 case 3: SStream_concat0(O, "ge"); op_addXopCC(MI, X86_XOP_CC_GE); break;
335 case 4: SStream_concat0(O, "eq"); op_addXopCC(MI, X86_XOP_CC_EQ); break;
336 case 5: SStream_concat0(O, "neq"); op_addXopCC(MI, X86_XOP_CC_NEQ); break;
337 case 6: SStream_concat0(O, "false"); op_addXopCC(MI, X86_XOP_CC_FALSE); break;
338 case 7: SStream_concat0(O, "true"); op_addXopCC(MI, X86_XOP_CC_TRUE); break;
339 }
340 }
341
printRoundingControl(MCInst * MI,unsigned Op,SStream * O)342 static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O)
343 {
344 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3;
345 switch (Imm) {
346 case 0: SStream_concat0(O, "{rn-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RN); break;
347 case 1: SStream_concat0(O, "{rd-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RD); break;
348 case 2: SStream_concat0(O, "{ru-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RU); break;
349 case 3: SStream_concat0(O, "{rz-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RZ); break;
350 default: break; // never reach
351 }
352 }
353
354 #endif
355
356 static const char *getRegisterName(unsigned RegNo);
printRegName(SStream * OS,unsigned RegNo)357 static void printRegName(SStream *OS, unsigned RegNo)
358 {
359 SStream_concat0(OS, getRegisterName(RegNo));
360 }
361
362 // for MASM syntax, 0x123 = 123h, 0xA123 = 0A123h
363 // this function tell us if we need to have prefix 0 in front of a number
need_zero_prefix(uint64_t imm)364 static bool need_zero_prefix(uint64_t imm)
365 {
366 // find the first hex letter representing imm
367 while(imm >= 0x10)
368 imm >>= 4;
369
370 if (imm < 0xa)
371 return false;
372 else // this need 0 prefix
373 return true;
374 }
375
printImm(MCInst * MI,SStream * O,int64_t imm,bool positive)376 static void printImm(MCInst *MI, SStream *O, int64_t imm, bool positive)
377 {
378 if (positive) {
379 // always print this number in positive form
380 if (MI->csh->syntax == CS_OPT_SYNTAX_MASM) {
381 if (imm < 0) {
382 if (MI->op1_size) {
383 switch(MI->op1_size) {
384 default:
385 break;
386 case 1:
387 imm &= 0xff;
388 break;
389 case 2:
390 imm &= 0xffff;
391 break;
392 case 4:
393 imm &= 0xffffffff;
394 break;
395 }
396 }
397
398 if (imm == 0x8000000000000000LL) // imm == -imm
399 SStream_concat0(O, "8000000000000000h");
400 else if (need_zero_prefix(imm))
401 SStream_concat(O, "0%"PRIx64"h", imm);
402 else
403 SStream_concat(O, "%"PRIx64"h", imm);
404 } else {
405 if (imm > HEX_THRESHOLD) {
406 if (need_zero_prefix(imm))
407 SStream_concat(O, "0%"PRIx64"h", imm);
408 else
409 SStream_concat(O, "%"PRIx64"h", imm);
410 } else
411 SStream_concat(O, "%"PRIu64, imm);
412 }
413 } else { // Intel syntax
414 if (imm < 0) {
415 if (MI->op1_size) {
416 switch(MI->op1_size) {
417 default:
418 break;
419 case 1:
420 imm &= 0xff;
421 break;
422 case 2:
423 imm &= 0xffff;
424 break;
425 case 4:
426 imm &= 0xffffffff;
427 break;
428 }
429 }
430
431 SStream_concat(O, "0x%"PRIx64, imm);
432 } else {
433 if (imm > HEX_THRESHOLD)
434 SStream_concat(O, "0x%"PRIx64, imm);
435 else
436 SStream_concat(O, "%"PRIu64, imm);
437 }
438 }
439 } else {
440 if (MI->csh->syntax == CS_OPT_SYNTAX_MASM) {
441 if (imm < 0) {
442 if (imm == 0x8000000000000000LL) // imm == -imm
443 SStream_concat0(O, "8000000000000000h");
444 else if (imm < -HEX_THRESHOLD) {
445 if (need_zero_prefix(imm))
446 SStream_concat(O, "-0%"PRIx64"h", -imm);
447 else
448 SStream_concat(O, "-%"PRIx64"h", -imm);
449 } else
450 SStream_concat(O, "-%"PRIu64, -imm);
451 } else {
452 if (imm > HEX_THRESHOLD) {
453 if (need_zero_prefix(imm))
454 SStream_concat(O, "0%"PRIx64"h", imm);
455 else
456 SStream_concat(O, "%"PRIx64"h", imm);
457 } else
458 SStream_concat(O, "%"PRIu64, imm);
459 }
460 } else { // Intel syntax
461 if (imm < 0) {
462 if (imm == 0x8000000000000000LL) // imm == -imm
463 SStream_concat0(O, "0x8000000000000000");
464 else if (imm < -HEX_THRESHOLD)
465 SStream_concat(O, "-0x%"PRIx64, -imm);
466 else
467 SStream_concat(O, "-%"PRIu64, -imm);
468
469 } else {
470 if (imm > HEX_THRESHOLD)
471 SStream_concat(O, "0x%"PRIx64, imm);
472 else
473 SStream_concat(O, "%"PRIu64, imm);
474 }
475 }
476 }
477 }
478
479 // local printOperand, without updating public operands
_printOperand(MCInst * MI,unsigned OpNo,SStream * O)480 static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
481 {
482 MCOperand *Op = MCInst_getOperand(MI, OpNo);
483 if (MCOperand_isReg(Op)) {
484 printRegName(O, MCOperand_getReg(Op));
485 } else if (MCOperand_isImm(Op)) {
486 int64_t imm = MCOperand_getImm(Op);
487 printImm(MI, O, imm, MI->csh->imm_unsigned);
488 }
489 }
490
491 #ifndef CAPSTONE_DIET
492 // copy & normalize access info
get_op_access(cs_struct * h,unsigned int id,uint8_t * access,uint64_t * eflags)493 static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64_t *eflags)
494 {
495 #ifndef CAPSTONE_DIET
496 uint8_t i;
497 uint8_t *arr = X86_get_op_access(h, id, eflags);
498
499 if (!arr) {
500 access[0] = 0;
501 return;
502 }
503
504 // copy to access but zero out CS_AC_IGNORE
505 for(i = 0; arr[i]; i++) {
506 if (arr[i] != CS_AC_IGNORE)
507 access[i] = arr[i];
508 else
509 access[i] = 0;
510 }
511
512 // mark the end of array
513 access[i] = 0;
514 #endif
515 }
516 #endif
517
printSrcIdx(MCInst * MI,unsigned Op,SStream * O)518 static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
519 {
520 MCOperand *SegReg;
521 int reg;
522
523 if (MI->csh->detail) {
524 #ifndef CAPSTONE_DIET
525 uint8_t access[6];
526 #endif
527
528 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
529 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
530 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
531 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
532 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
533 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
534 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
535
536 #ifndef CAPSTONE_DIET
537 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
538 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
539 #endif
540 }
541
542 SegReg = MCInst_getOperand(MI, Op+1);
543 reg = MCOperand_getReg(SegReg);
544
545 // If this has a segment register, print it.
546 if (reg) {
547 _printOperand(MI, Op+1, O);
548 if (MI->csh->detail) {
549 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
550 }
551 SStream_concat0(O, ":");
552 }
553
554 SStream_concat0(O, "[");
555 set_mem_access(MI, true);
556 printOperand(MI, Op, O);
557 SStream_concat0(O, "]");
558 set_mem_access(MI, false);
559 }
560
printDstIdx(MCInst * MI,unsigned Op,SStream * O)561 static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
562 {
563 if (MI->csh->detail) {
564 #ifndef CAPSTONE_DIET
565 uint8_t access[6];
566 #endif
567
568 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
569 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
570 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
571 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
572 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
573 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
574 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
575
576 #ifndef CAPSTONE_DIET
577 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
578 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
579 #endif
580 }
581
582 // DI accesses are always ES-based on non-64bit mode
583 if (MI->csh->mode != CS_MODE_64) {
584 SStream_concat(O, "es:[");
585 if (MI->csh->detail) {
586 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_ES;
587 }
588 } else
589 SStream_concat(O, "[");
590
591 set_mem_access(MI, true);
592 printOperand(MI, Op, O);
593 SStream_concat0(O, "]");
594 set_mem_access(MI, false);
595 }
596
printSrcIdx8(MCInst * MI,unsigned OpNo,SStream * O)597 static void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
598 {
599 SStream_concat0(O, "byte ptr ");
600 MI->x86opsize = 1;
601 printSrcIdx(MI, OpNo, O);
602 }
603
printSrcIdx16(MCInst * MI,unsigned OpNo,SStream * O)604 static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
605 {
606 SStream_concat0(O, "word ptr ");
607 MI->x86opsize = 2;
608 printSrcIdx(MI, OpNo, O);
609 }
610
printSrcIdx32(MCInst * MI,unsigned OpNo,SStream * O)611 static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
612 {
613 SStream_concat0(O, "dword ptr ");
614 MI->x86opsize = 4;
615 printSrcIdx(MI, OpNo, O);
616 }
617
printSrcIdx64(MCInst * MI,unsigned OpNo,SStream * O)618 static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
619 {
620 SStream_concat0(O, "qword ptr ");
621 MI->x86opsize = 8;
622 printSrcIdx(MI, OpNo, O);
623 }
624
printDstIdx8(MCInst * MI,unsigned OpNo,SStream * O)625 static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
626 {
627 SStream_concat0(O, "byte ptr ");
628 MI->x86opsize = 1;
629 printDstIdx(MI, OpNo, O);
630 }
631
printDstIdx16(MCInst * MI,unsigned OpNo,SStream * O)632 static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
633 {
634 SStream_concat0(O, "word ptr ");
635 MI->x86opsize = 2;
636 printDstIdx(MI, OpNo, O);
637 }
638
printDstIdx32(MCInst * MI,unsigned OpNo,SStream * O)639 static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
640 {
641 SStream_concat0(O, "dword ptr ");
642 MI->x86opsize = 4;
643 printDstIdx(MI, OpNo, O);
644 }
645
printDstIdx64(MCInst * MI,unsigned OpNo,SStream * O)646 static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
647 {
648 SStream_concat0(O, "qword ptr ");
649 MI->x86opsize = 8;
650 printDstIdx(MI, OpNo, O);
651 }
652
printMemOffset(MCInst * MI,unsigned Op,SStream * O)653 static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
654 {
655 MCOperand *DispSpec = MCInst_getOperand(MI, Op);
656 MCOperand *SegReg = MCInst_getOperand(MI, Op + 1);
657 int reg;
658
659 if (MI->csh->detail) {
660 #ifndef CAPSTONE_DIET
661 uint8_t access[6];
662 #endif
663
664 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
665 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
666 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
667 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
668 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
669 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
670 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
671
672 #ifndef CAPSTONE_DIET
673 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
674 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
675 #endif
676 }
677
678 // If this has a segment register, print it.
679 reg = MCOperand_getReg(SegReg);
680 if (reg) {
681 _printOperand(MI, Op + 1, O);
682 SStream_concat0(O, ":");
683 if (MI->csh->detail) {
684 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
685 }
686 }
687
688 SStream_concat0(O, "[");
689
690 if (MCOperand_isImm(DispSpec)) {
691 int64_t imm = MCOperand_getImm(DispSpec);
692 if (MI->csh->detail)
693 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
694
695 if (imm < 0)
696 printImm(MI, O, arch_masks[MI->csh->mode] & imm, true);
697 else
698 printImm(MI, O, imm, true);
699 }
700
701 SStream_concat0(O, "]");
702
703 if (MI->csh->detail)
704 MI->flat_insn->detail->x86.op_count++;
705
706 if (MI->op1_size == 0)
707 MI->op1_size = MI->x86opsize;
708 }
709
710 #ifndef CAPSTONE_X86_REDUCE
printU8Imm(MCInst * MI,unsigned Op,SStream * O)711 static void printU8Imm(MCInst *MI, unsigned Op, SStream *O)
712 {
713 uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff;
714
715 printImm(MI, O, val, true);
716
717 if (MI->csh->detail) {
718 #ifndef CAPSTONE_DIET
719 uint8_t access[6];
720 #endif
721
722 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
723 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = val;
724 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = 1;
725
726 #ifndef CAPSTONE_DIET
727 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
728 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
729 #endif
730
731 MI->flat_insn->detail->x86.op_count++;
732 }
733 }
734 #endif
735
printMemOffs8(MCInst * MI,unsigned OpNo,SStream * O)736 static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
737 {
738 SStream_concat0(O, "byte ptr ");
739 MI->x86opsize = 1;
740 printMemOffset(MI, OpNo, O);
741 }
742
printMemOffs16(MCInst * MI,unsigned OpNo,SStream * O)743 static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
744 {
745 SStream_concat0(O, "word ptr ");
746 MI->x86opsize = 2;
747 printMemOffset(MI, OpNo, O);
748 }
749
printMemOffs32(MCInst * MI,unsigned OpNo,SStream * O)750 static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
751 {
752 SStream_concat0(O, "dword ptr ");
753 MI->x86opsize = 4;
754 printMemOffset(MI, OpNo, O);
755 }
756
printMemOffs64(MCInst * MI,unsigned OpNo,SStream * O)757 static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
758 {
759 SStream_concat0(O, "qword ptr ");
760 MI->x86opsize = 8;
761 printMemOffset(MI, OpNo, O);
762 }
763
764 #ifndef CAPSTONE_DIET
765 static char *printAliasInstr(MCInst *MI, SStream *OS, void *info);
766 #endif
767 static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
768
X86_Intel_printInst(MCInst * MI,SStream * O,void * Info)769 void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info)
770 {
771 #ifndef CAPSTONE_DIET
772 char *mnem;
773 #endif
774 x86_reg reg, reg2;
775 enum cs_ac_type access1, access2;
776
777 // perhaps this instruction does not need printer
778 if (MI->assembly[0]) {
779 strncpy(O->buffer, MI->assembly, sizeof(O->buffer));
780 return;
781 }
782
783 #ifndef CAPSTONE_DIET
784 // Try to print any aliases first.
785 mnem = printAliasInstr(MI, O, Info);
786 if (mnem)
787 cs_mem_free(mnem);
788 else
789 #endif
790 printInstruction(MI, O, Info);
791
792 reg = X86_insn_reg_intel(MCInst_getOpcode(MI), &access1);
793 if (MI->csh->detail) {
794 #ifndef CAPSTONE_DIET
795 uint8_t access[6] = {0};
796 #endif
797
798 // first op can be embedded in the asm by llvm.
799 // so we have to add the missing register as the first operand
800 if (reg) {
801 // shift all the ops right to leave 1st slot for this new register op
802 memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
803 sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
804 MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
805 MI->flat_insn->detail->x86.operands[0].reg = reg;
806 MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
807 MI->flat_insn->detail->x86.operands[0].access = access1;
808 MI->flat_insn->detail->x86.op_count++;
809 } else {
810 if (X86_insn_reg_intel2(MCInst_getOpcode(MI), ®, &access1, ®2, &access2)) {
811 MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
812 MI->flat_insn->detail->x86.operands[0].reg = reg;
813 MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
814 MI->flat_insn->detail->x86.operands[0].access = access1;
815 MI->flat_insn->detail->x86.operands[1].type = X86_OP_REG;
816 MI->flat_insn->detail->x86.operands[1].reg = reg2;
817 MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg2];
818 MI->flat_insn->detail->x86.operands[1].access = access2;
819 MI->flat_insn->detail->x86.op_count = 2;
820 }
821 }
822
823 #ifndef CAPSTONE_DIET
824 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
825 MI->flat_insn->detail->x86.operands[0].access = access[0];
826 MI->flat_insn->detail->x86.operands[1].access = access[1];
827 #endif
828 }
829
830 if (MI->op1_size == 0 && reg)
831 MI->op1_size = MI->csh->regsize_map[reg];
832 }
833
834 /// printPCRelImm - This is used to print an immediate value that ends up
835 /// being encoded as a pc-relative value.
printPCRelImm(MCInst * MI,unsigned OpNo,SStream * O)836 static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
837 {
838 MCOperand *Op = MCInst_getOperand(MI, OpNo);
839 if (MCOperand_isImm(Op)) {
840 int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + MI->address;
841 uint8_t opsize = X86_immediate_size(MI->Opcode, NULL);
842
843 // truncat imm for non-64bit
844 if (MI->csh->mode != CS_MODE_64) {
845 imm = imm & 0xffffffff;
846 }
847
848 if (MI->csh->mode == CS_MODE_16 &&
849 (MI->Opcode != X86_JMP_4 && MI->Opcode != X86_CALLpcrel32))
850 imm = imm & 0xffff;
851
852 // Hack: X86 16bit with opcode X86_JMP_4
853 if (MI->csh->mode == CS_MODE_16 &&
854 (MI->Opcode == X86_JMP_4 && MI->x86_prefix[2] != 0x66))
855 imm = imm & 0xffff;
856
857 // CALL/JMP rel16 is special
858 if (MI->Opcode == X86_CALLpcrel16 || MI->Opcode == X86_JMP_2)
859 imm = imm & 0xffff;
860
861 printImm(MI, O, imm, true);
862
863 if (MI->csh->detail) {
864 #ifndef CAPSTONE_DIET
865 uint8_t access[6];
866 #endif
867
868 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
869 // if op_count > 0, then this operand's size is taken from the destination op
870 if (MI->flat_insn->detail->x86.op_count > 0)
871 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size;
872 else if (opsize > 0)
873 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
874 else
875 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
876 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
877
878 #ifndef CAPSTONE_DIET
879 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
880 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
881 #endif
882
883 MI->flat_insn->detail->x86.op_count++;
884 }
885
886 if (MI->op1_size == 0)
887 MI->op1_size = MI->imm_size;
888 }
889 }
890
printOperand(MCInst * MI,unsigned OpNo,SStream * O)891 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
892 {
893 MCOperand *Op = MCInst_getOperand(MI, OpNo);
894
895 if (MCOperand_isReg(Op)) {
896 unsigned int reg = MCOperand_getReg(Op);
897
898 printRegName(O, reg);
899 if (MI->csh->detail) {
900 if (MI->csh->doing_mem) {
901 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
902 } else {
903 #ifndef CAPSTONE_DIET
904 uint8_t access[6];
905 #endif
906
907 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
908 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
909 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];
910
911 #ifndef CAPSTONE_DIET
912 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
913 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
914 #endif
915
916 MI->flat_insn->detail->x86.op_count++;
917 }
918 }
919
920 if (MI->op1_size == 0)
921 MI->op1_size = MI->csh->regsize_map[reg];
922 } else if (MCOperand_isImm(Op)) {
923 uint8_t encsize;
924 int64_t imm = MCOperand_getImm(Op);
925 uint8_t opsize = X86_immediate_size(MCInst_getOpcode(MI), &encsize);
926
927 if (opsize == 1) // print 1 byte immediate in positive form
928 imm = imm & 0xff;
929
930 // printf(">>> id = %u\n", MI->flat_insn->id);
931 switch(MI->flat_insn->id) {
932 default:
933 printImm(MI, O, imm, MI->csh->imm_unsigned);
934 break;
935
936 case X86_INS_MOVABS:
937 // do not print number in negative form
938 printImm(MI, O, imm, true);
939 break;
940
941 case X86_INS_IN:
942 case X86_INS_OUT:
943 case X86_INS_INT:
944 // do not print number in negative form
945 imm = imm & 0xff;
946 printImm(MI, O, imm, true);
947 break;
948
949 case X86_INS_LCALL:
950 case X86_INS_LJMP:
951 // always print address in positive form
952 if (OpNo == 1) { // ptr16 part
953 imm = imm & 0xffff;
954 opsize = 2;
955 }
956 printImm(MI, O, imm, true);
957 break;
958
959 case X86_INS_AND:
960 case X86_INS_OR:
961 case X86_INS_XOR:
962 // do not print number in negative form
963 if (imm >= 0 && imm <= HEX_THRESHOLD)
964 printImm(MI, O, imm, true);
965 else {
966 imm = arch_masks[opsize? opsize : MI->imm_size] & imm;
967 printImm(MI, O, imm, true);
968 }
969 break;
970
971 case X86_INS_RET:
972 case X86_INS_RETF:
973 // RET imm16
974 if (imm >= 0 && imm <= HEX_THRESHOLD)
975 printImm(MI, O, imm, true);
976 else {
977 imm = 0xffff & imm;
978 printImm(MI, O, imm, true);
979 }
980 break;
981 }
982
983 if (MI->csh->detail) {
984 if (MI->csh->doing_mem) {
985 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
986 } else {
987 #ifndef CAPSTONE_DIET
988 uint8_t access[6];
989 #endif
990
991 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
992 if (opsize > 0) {
993 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
994 MI->flat_insn->detail->x86.encoding.imm_size = encsize;
995 } else if (MI->flat_insn->detail->x86.op_count > 0) {
996 if (MI->flat_insn->id != X86_INS_LCALL && MI->flat_insn->id != X86_INS_LJMP) {
997 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size =
998 MI->flat_insn->detail->x86.operands[0].size;
999 } else
1000 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
1001 } else
1002 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
1003 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
1004
1005 #ifndef CAPSTONE_DIET
1006 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
1007 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
1008 #endif
1009
1010 MI->flat_insn->detail->x86.op_count++;
1011 }
1012 }
1013 }
1014 }
1015
printMemReference(MCInst * MI,unsigned Op,SStream * O)1016 static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
1017 {
1018 bool NeedPlus = false;
1019 MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
1020 uint64_t ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
1021 MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
1022 MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
1023 MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
1024 int reg;
1025
1026 if (MI->csh->detail) {
1027 #ifndef CAPSTONE_DIET
1028 uint8_t access[6];
1029 #endif
1030
1031 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
1032 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
1033 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
1034 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg);
1035 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
1036 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal;
1037 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
1038
1039 #ifndef CAPSTONE_DIET
1040 get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
1041 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
1042 #endif
1043 }
1044
1045 // If this has a segment register, print it.
1046 reg = MCOperand_getReg(SegReg);
1047 if (reg) {
1048 _printOperand(MI, Op + X86_AddrSegmentReg, O);
1049 if (MI->csh->detail) {
1050 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
1051 }
1052 SStream_concat0(O, ":");
1053 }
1054
1055 SStream_concat0(O, "[");
1056
1057 if (MCOperand_getReg(BaseReg)) {
1058 _printOperand(MI, Op + X86_AddrBaseReg, O);
1059 NeedPlus = true;
1060 }
1061
1062 if (MCOperand_getReg(IndexReg)) {
1063 if (NeedPlus) SStream_concat0(O, " + ");
1064 _printOperand(MI, Op + X86_AddrIndexReg, O);
1065 if (ScaleVal != 1)
1066 SStream_concat(O, "*%u", ScaleVal);
1067 NeedPlus = true;
1068 }
1069
1070 if (MCOperand_isImm(DispSpec)) {
1071 int64_t DispVal = MCOperand_getImm(DispSpec);
1072 if (MI->csh->detail)
1073 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal;
1074 if (DispVal) {
1075 if (NeedPlus) {
1076 if (DispVal < 0) {
1077 SStream_concat0(O, " - ");
1078 printImm(MI, O, -DispVal, true);
1079 } else {
1080 SStream_concat0(O, " + ");
1081 printImm(MI, O, DispVal, true);
1082 }
1083 } else {
1084 // memory reference to an immediate address
1085 if (DispVal < 0) {
1086 printImm(MI, O, arch_masks[MI->csh->mode] & DispVal, true);
1087 } else {
1088 printImm(MI, O, DispVal, true);
1089 }
1090 }
1091
1092 } else {
1093 // DispVal = 0
1094 if (!NeedPlus) // [0]
1095 SStream_concat0(O, "0");
1096 }
1097 }
1098
1099 SStream_concat0(O, "]");
1100
1101 if (MI->csh->detail)
1102 MI->flat_insn->detail->x86.op_count++;
1103
1104 if (MI->op1_size == 0)
1105 MI->op1_size = MI->x86opsize;
1106 }
1107
printanymem(MCInst * MI,unsigned OpNo,SStream * O)1108 static void printanymem(MCInst *MI, unsigned OpNo, SStream *O)
1109 {
1110 switch(MI->Opcode) {
1111 default: break;
1112 case X86_LEA16r:
1113 MI->x86opsize = 2;
1114 break;
1115 case X86_LEA32r:
1116 case X86_LEA64_32r:
1117 MI->x86opsize = 4;
1118 break;
1119 case X86_LEA64r:
1120 MI->x86opsize = 8;
1121 break;
1122 }
1123 printMemReference(MI, OpNo, O);
1124 }
1125
1126 #define GET_REGINFO_ENUM
1127 #include "X86GenRegisterInfo.inc"
1128
1129 #define PRINT_ALIAS_INSTR
1130 #ifdef CAPSTONE_X86_REDUCE
1131 #include "X86GenAsmWriter1_reduce.inc"
1132 #else
1133 #include "X86GenAsmWriter1.inc"
1134 #endif
1135
1136 #endif
1137