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), ®, ®2)) { 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