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