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