/src/capstonenext/arch/X86/X86ATTInstPrinter.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===// | 
| 2 |  | // | 
| 3 |  | //                     The LLVM Compiler Infrastructure | 
| 4 |  | // | 
| 5 |  | // This file is distributed under the University of Illinois Open Source | 
| 6 |  | // License. See LICENSE.TXT for details. | 
| 7 |  | // | 
| 8 |  | //===----------------------------------------------------------------------===// | 
| 9 |  | // | 
| 10 |  | // This file includes code for rendering MCInst instances as AT&T-style | 
| 11 |  | // assembly. | 
| 12 |  | // | 
| 13 |  | //===----------------------------------------------------------------------===// | 
| 14 |  |  | 
| 15 |  | /* Capstone Disassembly Engine */ | 
| 16 |  | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */ | 
| 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 (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64) | 
| 22 |  | #pragma warning(disable:4996)     // disable MSVC's warning on strncpy() | 
| 23 |  | #pragma warning(disable:28719)    // disable MSVC's warning on strncpy() | 
| 24 |  | #endif | 
| 25 |  |  | 
| 26 |  | #if !defined(CAPSTONE_HAS_OSXKERNEL) | 
| 27 |  | #include <ctype.h> | 
| 28 |  | #endif | 
| 29 |  | #include <capstone/platform.h> | 
| 30 |  |  | 
| 31 |  | #if defined(CAPSTONE_HAS_OSXKERNEL) | 
| 32 |  | #include <Availability.h> | 
| 33 |  | #include <libkern/libkern.h> | 
| 34 |  | #else | 
| 35 |  | #include <stdio.h> | 
| 36 |  | #include <stdlib.h> | 
| 37 |  | #endif | 
| 38 |  |  | 
| 39 |  | #include <string.h> | 
| 40 |  |  | 
| 41 |  | #include "../../utils.h" | 
| 42 |  | #include "../../MCInst.h" | 
| 43 |  | #include "../../SStream.h" | 
| 44 |  | #include "../../MCRegisterInfo.h" | 
| 45 |  | #include "X86Mapping.h" | 
| 46 |  | #include "X86BaseInfo.h" | 
| 47 |  | #include "X86InstPrinterCommon.h" | 
| 48 |  |  | 
| 49 |  | #define GET_INSTRINFO_ENUM | 
| 50 |  | #ifdef CAPSTONE_X86_REDUCE | 
| 51 |  | #include "X86GenInstrInfo_reduce.inc" | 
| 52 |  | #else | 
| 53 |  | #include "X86GenInstrInfo.inc" | 
| 54 |  | #endif | 
| 55 |  |  | 
| 56 |  | #define GET_REGINFO_ENUM | 
| 57 |  | #include "X86GenRegisterInfo.inc" | 
| 58 |  |  | 
| 59 |  | static void printMemReference(MCInst *MI, unsigned Op, SStream *O); | 
| 60 |  | static void printOperand(MCInst *MI, unsigned OpNo, SStream *O); | 
| 61 |  |  | 
| 62 |  |  | 
| 63 |  | static void set_mem_access(MCInst *MI, bool status) | 
| 64 | 77.8k | { | 
| 65 | 77.8k |   if (MI->csh->detail_opt != CS_OPT_ON) | 
| 66 | 0 |     return; | 
| 67 |  |  | 
| 68 | 77.8k |   MI->csh->doing_mem = status; | 
| 69 | 77.8k |   if (!status) | 
| 70 |  |     // done, create the next operand slot | 
| 71 | 38.9k |     MI->flat_insn->detail->x86.op_count++; | 
| 72 | 77.8k | } | 
| 73 |  |  | 
| 74 |  | static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 75 | 6.36k | { | 
| 76 | 6.36k |   switch(MI->csh->mode) { | 
| 77 | 2.16k |     case CS_MODE_16: | 
| 78 | 2.16k |       switch(MI->flat_insn->id) { | 
| 79 | 851 |         default: | 
| 80 | 851 |           MI->x86opsize = 2; | 
| 81 | 851 |           break; | 
| 82 | 248 |         case X86_INS_LJMP: | 
| 83 | 459 |         case X86_INS_LCALL: | 
| 84 | 459 |           MI->x86opsize = 4; | 
| 85 | 459 |           break; | 
| 86 | 235 |         case X86_INS_SGDT: | 
| 87 | 437 |         case X86_INS_SIDT: | 
| 88 | 636 |         case X86_INS_LGDT: | 
| 89 | 857 |         case X86_INS_LIDT: | 
| 90 | 857 |           MI->x86opsize = 6; | 
| 91 | 857 |           break; | 
| 92 | 2.16k |       } | 
| 93 | 2.16k |       break; | 
| 94 | 2.34k |     case CS_MODE_32: | 
| 95 | 2.34k |       switch(MI->flat_insn->id) { | 
| 96 | 439 |         default: | 
| 97 | 439 |           MI->x86opsize = 4; | 
| 98 | 439 |           break; | 
| 99 | 247 |         case X86_INS_LJMP: | 
| 100 | 616 |         case X86_INS_JMP: | 
| 101 | 813 |         case X86_INS_LCALL: | 
| 102 | 1.08k |         case X86_INS_SGDT: | 
| 103 | 1.41k |         case X86_INS_SIDT: | 
| 104 | 1.68k |         case X86_INS_LGDT: | 
| 105 | 1.90k |         case X86_INS_LIDT: | 
| 106 | 1.90k |           MI->x86opsize = 6; | 
| 107 | 1.90k |           break; | 
| 108 | 2.34k |       } | 
| 109 | 2.34k |       break; | 
| 110 | 2.34k |     case CS_MODE_64: | 
| 111 | 1.85k |       switch(MI->flat_insn->id) { | 
| 112 | 356 |         default: | 
| 113 | 356 |           MI->x86opsize = 8; | 
| 114 | 356 |           break; | 
| 115 | 239 |         case X86_INS_LJMP: | 
| 116 | 482 |         case X86_INS_LCALL: | 
| 117 | 706 |         case X86_INS_SGDT: | 
| 118 | 1.07k |         case X86_INS_SIDT: | 
| 119 | 1.30k |         case X86_INS_LGDT: | 
| 120 | 1.50k |         case X86_INS_LIDT: | 
| 121 | 1.50k |           MI->x86opsize = 10; | 
| 122 | 1.50k |           break; | 
| 123 | 1.85k |       } | 
| 124 | 1.85k |       break; | 
| 125 | 1.85k |     default:  // never reach | 
| 126 | 0 |       break; | 
| 127 | 6.36k |   } | 
| 128 |  |  | 
| 129 | 6.36k |   printMemReference(MI, OpNo, O); | 
| 130 | 6.36k | } | 
| 131 |  |  | 
| 132 |  | static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 133 | 54.8k | { | 
| 134 | 54.8k |   MI->x86opsize = 1; | 
| 135 | 54.8k |   printMemReference(MI, OpNo, O); | 
| 136 | 54.8k | } | 
| 137 |  |  | 
| 138 |  | static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 139 | 22.5k | { | 
| 140 | 22.5k |   MI->x86opsize = 2; | 
| 141 |  |  | 
| 142 | 22.5k |   printMemReference(MI, OpNo, O); | 
| 143 | 22.5k | } | 
| 144 |  |  | 
| 145 |  | static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 146 | 22.0k | { | 
| 147 | 22.0k |   MI->x86opsize = 4; | 
| 148 |  |  | 
| 149 | 22.0k |   printMemReference(MI, OpNo, O); | 
| 150 | 22.0k | } | 
| 151 |  |  | 
| 152 |  | static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 153 | 8.18k | { | 
| 154 | 8.18k |   MI->x86opsize = 8; | 
| 155 | 8.18k |   printMemReference(MI, OpNo, O); | 
| 156 | 8.18k | } | 
| 157 |  |  | 
| 158 |  | static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 159 | 4.56k | { | 
| 160 | 4.56k |   MI->x86opsize = 16; | 
| 161 | 4.56k |   printMemReference(MI, OpNo, O); | 
| 162 | 4.56k | } | 
| 163 |  |  | 
| 164 |  | static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 165 | 2.58k | { | 
| 166 | 2.58k |   MI->x86opsize = 64; | 
| 167 | 2.58k |   printMemReference(MI, OpNo, O); | 
| 168 | 2.58k | } | 
| 169 |  |  | 
| 170 |  | #ifndef CAPSTONE_X86_REDUCE | 
| 171 |  | static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 172 | 2.51k | { | 
| 173 | 2.51k |   MI->x86opsize = 32; | 
| 174 | 2.51k |   printMemReference(MI, OpNo, O); | 
| 175 | 2.51k | } | 
| 176 |  |  | 
| 177 |  | static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 178 | 4.81k | { | 
| 179 | 4.81k |   switch(MCInst_getOpcode(MI)) { | 
| 180 | 3.63k |     default: | 
| 181 | 3.63k |       MI->x86opsize = 4; | 
| 182 | 3.63k |       break; | 
| 183 | 387 |     case X86_FSTENVm: | 
| 184 | 1.17k |     case X86_FLDENVm: | 
| 185 |  |       // TODO: fix this in tablegen instead | 
| 186 | 1.17k |       switch(MI->csh->mode) { | 
| 187 | 0 |         default:    // never reach | 
| 188 | 0 |           break; | 
| 189 | 446 |         case CS_MODE_16: | 
| 190 | 446 |           MI->x86opsize = 14; | 
| 191 | 446 |           break; | 
| 192 | 454 |         case CS_MODE_32: | 
| 193 | 733 |         case CS_MODE_64: | 
| 194 | 733 |           MI->x86opsize = 28; | 
| 195 | 733 |           break; | 
| 196 | 1.17k |       } | 
| 197 | 1.17k |       break; | 
| 198 | 4.81k |   } | 
| 199 |  |  | 
| 200 | 4.81k |   printMemReference(MI, OpNo, O); | 
| 201 | 4.81k | } | 
| 202 |  |  | 
| 203 |  | static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 204 | 4.62k | { | 
| 205 | 4.62k |   MI->x86opsize = 8; | 
| 206 | 4.62k |   printMemReference(MI, OpNo, O); | 
| 207 | 4.62k | } | 
| 208 |  |  | 
| 209 |  | static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 210 | 222 | { | 
| 211 | 222 |   MI->x86opsize = 10; | 
| 212 | 222 |   printMemReference(MI, OpNo, O); | 
| 213 | 222 | } | 
| 214 |  |  | 
| 215 |  | static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 216 | 3.66k | { | 
| 217 | 3.66k |   MI->x86opsize = 16; | 
| 218 | 3.66k |   printMemReference(MI, OpNo, O); | 
| 219 | 3.66k | } | 
| 220 |  |  | 
| 221 |  | static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 222 | 2.70k | { | 
| 223 | 2.70k |   MI->x86opsize = 32; | 
| 224 | 2.70k |   printMemReference(MI, OpNo, O); | 
| 225 | 2.70k | } | 
| 226 |  |  | 
| 227 |  | static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 228 | 2.28k | { | 
| 229 | 2.28k |   MI->x86opsize = 64; | 
| 230 | 2.28k |   printMemReference(MI, OpNo, O); | 
| 231 | 2.28k | } | 
| 232 |  |  | 
| 233 |  | #endif | 
| 234 |  |  | 
| 235 |  | static void printRegName(SStream *OS, unsigned RegNo); | 
| 236 |  |  | 
| 237 |  | // local printOperand, without updating public operands | 
| 238 |  | static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O) | 
| 239 | 204k | { | 
| 240 | 204k |   MCOperand *Op  = MCInst_getOperand(MI, OpNo); | 
| 241 | 204k |   if (MCOperand_isReg(Op)) { | 
| 242 | 204k |     printRegName(O, MCOperand_getReg(Op)); | 
| 243 | 204k |   } else if (MCOperand_isImm(Op)) { | 
| 244 | 0 |     uint8_t encsize; | 
| 245 | 0 |     uint8_t opsize = X86_immediate_size(MCInst_getOpcode(MI), &encsize); | 
| 246 |  |  | 
| 247 |  |     // Print X86 immediates as signed values. | 
| 248 | 0 |     int64_t imm = MCOperand_getImm(Op); | 
| 249 | 0 |     if (imm < 0) { | 
| 250 | 0 |       if (MI->csh->imm_unsigned) { | 
| 251 | 0 |         if (opsize) { | 
| 252 | 0 |           switch(opsize) { | 
| 253 | 0 |             default: | 
| 254 | 0 |               break; | 
| 255 | 0 |             case 1: | 
| 256 | 0 |               imm &= 0xff; | 
| 257 | 0 |               break; | 
| 258 | 0 |             case 2: | 
| 259 | 0 |               imm &= 0xffff; | 
| 260 | 0 |               break; | 
| 261 | 0 |             case 4: | 
| 262 | 0 |               imm &= 0xffffffff; | 
| 263 | 0 |               break; | 
| 264 | 0 |           } | 
| 265 | 0 |         } | 
| 266 |  |  | 
| 267 | 0 |         SStream_concat(O, "$0x%"PRIx64, imm); | 
| 268 | 0 |       } else { | 
| 269 | 0 |         if (imm < -HEX_THRESHOLD) | 
| 270 | 0 |           SStream_concat(O, "$-0x%"PRIx64, -imm); | 
| 271 | 0 |         else | 
| 272 | 0 |           SStream_concat(O, "$-%"PRIu64, -imm); | 
| 273 | 0 |       } | 
| 274 | 0 |     } else { | 
| 275 | 0 |       if (imm > HEX_THRESHOLD) | 
| 276 | 0 |         SStream_concat(O, "$0x%"PRIx64, imm); | 
| 277 | 0 |       else | 
| 278 | 0 |         SStream_concat(O, "$%"PRIu64, imm); | 
| 279 | 0 |     } | 
| 280 | 0 |   } | 
| 281 | 204k | } | 
| 282 |  |  | 
| 283 |  | // convert Intel access info to AT&T access info | 
| 284 |  | static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64_t *eflags) | 
| 285 | 801k | { | 
| 286 | 801k |   uint8_t count, i; | 
| 287 | 801k |   const uint8_t *arr = X86_get_op_access(h, id, eflags); | 
| 288 |  |  | 
| 289 | 801k |   if (!arr) { | 
| 290 | 0 |     access[0] = 0; | 
| 291 | 0 |     return; | 
| 292 | 0 |   } | 
| 293 |  |  | 
| 294 |  |   // find the non-zero last entry | 
| 295 | 2.32M |   for(count = 0; arr[count]; count++); | 
| 296 |  |  | 
| 297 | 801k |   if (count == 0) | 
| 298 | 53.2k |     return; | 
| 299 |  |  | 
| 300 |  |   // copy in reverse order this access array from Intel syntax -> AT&T syntax | 
| 301 | 748k |   count--; | 
| 302 | 2.27M |   for(i = 0; i <= count; i++) { | 
| 303 | 1.52M |     if (arr[count - i] != CS_AC_IGNORE) | 
| 304 | 1.32M |       access[i] = arr[count - i]; | 
| 305 | 199k |     else | 
| 306 | 199k |       access[i] = 0; | 
| 307 | 1.52M |   } | 
| 308 | 748k | } | 
| 309 |  |  | 
| 310 |  | static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O) | 
| 311 | 17.5k | { | 
| 312 | 17.5k |   MCOperand *SegReg; | 
| 313 | 17.5k |   int reg; | 
| 314 |  |  | 
| 315 | 17.5k |   if (MI->csh->detail_opt) { | 
| 316 | 17.5k |     uint8_t access[6]; | 
| 317 |  |  | 
| 318 | 17.5k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 319 | 17.5k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; | 
| 320 | 17.5k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; | 
| 321 | 17.5k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID; | 
| 322 | 17.5k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID; | 
| 323 | 17.5k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; | 
| 324 | 17.5k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; | 
| 325 |  |  | 
| 326 | 17.5k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 327 | 17.5k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 328 | 17.5k |   } | 
| 329 |  |  | 
| 330 | 17.5k |   SegReg = MCInst_getOperand(MI, Op+1); | 
| 331 | 17.5k |   reg = MCOperand_getReg(SegReg); | 
| 332 |  |   // If this has a segment register, print it. | 
| 333 | 17.5k |   if (reg) { | 
| 334 | 582 |     _printOperand(MI, Op + 1, O); | 
| 335 | 582 |     SStream_concat0(O, ":"); | 
| 336 |  |  | 
| 337 | 582 |     if (MI->csh->detail_opt) { | 
| 338 | 582 |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_register_map(reg); | 
| 339 | 582 |     } | 
| 340 | 582 |   } | 
| 341 |  |  | 
| 342 | 17.5k |   SStream_concat0(O, "("); | 
| 343 | 17.5k |   set_mem_access(MI, true); | 
| 344 |  |  | 
| 345 | 17.5k |   printOperand(MI, Op, O); | 
| 346 |  |  | 
| 347 | 17.5k |   SStream_concat0(O, ")"); | 
| 348 | 17.5k |   set_mem_access(MI, false); | 
| 349 | 17.5k | } | 
| 350 |  |  | 
| 351 |  | static void printDstIdx(MCInst *MI, unsigned Op, SStream *O) | 
| 352 | 21.4k | { | 
| 353 | 21.4k |   if (MI->csh->detail_opt) { | 
| 354 | 21.4k |     uint8_t access[6]; | 
| 355 |  |  | 
| 356 | 21.4k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 357 | 21.4k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; | 
| 358 | 21.4k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; | 
| 359 | 21.4k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID; | 
| 360 | 21.4k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID; | 
| 361 | 21.4k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; | 
| 362 | 21.4k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; | 
| 363 |  |  | 
| 364 | 21.4k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 365 | 21.4k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 366 | 21.4k |   } | 
| 367 |  |  | 
| 368 |  |   // DI accesses are always ES-based on non-64bit mode | 
| 369 | 21.4k |   if (MI->csh->mode != CS_MODE_64) { | 
| 370 | 11.5k |     SStream_concat0(O, "%es:("); | 
| 371 | 11.5k |     if (MI->csh->detail_opt) { | 
| 372 | 11.5k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_ES; | 
| 373 | 11.5k |     } | 
| 374 | 11.5k |   } else | 
| 375 | 9.90k |     SStream_concat0(O, "("); | 
| 376 |  |  | 
| 377 | 21.4k |   set_mem_access(MI, true); | 
| 378 |  |  | 
| 379 | 21.4k |   printOperand(MI, Op, O); | 
| 380 |  |  | 
| 381 | 21.4k |   SStream_concat0(O, ")"); | 
| 382 | 21.4k |   set_mem_access(MI, false); | 
| 383 | 21.4k | } | 
| 384 |  |  | 
| 385 |  | static void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O) | 
| 386 | 8.31k | { | 
| 387 | 8.31k |   MI->x86opsize = 1; | 
| 388 | 8.31k |   printSrcIdx(MI, OpNo, O); | 
| 389 | 8.31k | } | 
| 390 |  |  | 
| 391 |  | static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O) | 
| 392 | 3.48k | { | 
| 393 | 3.48k |   MI->x86opsize = 2; | 
| 394 | 3.48k |   printSrcIdx(MI, OpNo, O); | 
| 395 | 3.48k | } | 
| 396 |  |  | 
| 397 |  | static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O) | 
| 398 | 4.35k | { | 
| 399 | 4.35k |   MI->x86opsize = 4; | 
| 400 | 4.35k |   printSrcIdx(MI, OpNo, O); | 
| 401 | 4.35k | } | 
| 402 |  |  | 
| 403 |  | static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O) | 
| 404 | 1.36k | { | 
| 405 | 1.36k |   MI->x86opsize = 8; | 
| 406 | 1.36k |   printSrcIdx(MI, OpNo, O); | 
| 407 | 1.36k | } | 
| 408 |  |  | 
| 409 |  | static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O) | 
| 410 | 10.7k | { | 
| 411 | 10.7k |   MI->x86opsize = 1; | 
| 412 | 10.7k |   printDstIdx(MI, OpNo, O); | 
| 413 | 10.7k | } | 
| 414 |  |  | 
| 415 |  | static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O) | 
| 416 | 3.81k | { | 
| 417 | 3.81k |   MI->x86opsize = 2; | 
| 418 | 3.81k |   printDstIdx(MI, OpNo, O); | 
| 419 | 3.81k | } | 
| 420 |  |  | 
| 421 |  | static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O) | 
| 422 | 5.44k | { | 
| 423 | 5.44k |   MI->x86opsize = 4; | 
| 424 | 5.44k |   printDstIdx(MI, OpNo, O); | 
| 425 | 5.44k | } | 
| 426 |  |  | 
| 427 |  | static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O) | 
| 428 | 1.36k | { | 
| 429 | 1.36k |   MI->x86opsize = 8; | 
| 430 | 1.36k |   printDstIdx(MI, OpNo, O); | 
| 431 | 1.36k | } | 
| 432 |  |  | 
| 433 |  | static void printMemOffset(MCInst *MI, unsigned Op, SStream *O) | 
| 434 | 3.87k | { | 
| 435 | 3.87k |   MCOperand *DispSpec = MCInst_getOperand(MI, Op); | 
| 436 | 3.87k |   MCOperand *SegReg = MCInst_getOperand(MI, Op+1); | 
| 437 | 3.87k |   int reg; | 
| 438 |  |  | 
| 439 | 3.87k |   if (MI->csh->detail_opt) { | 
| 440 | 3.87k |     uint8_t access[6]; | 
| 441 |  |  | 
| 442 | 3.87k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 443 | 3.87k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; | 
| 444 | 3.87k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; | 
| 445 | 3.87k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID; | 
| 446 | 3.87k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID; | 
| 447 | 3.87k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; | 
| 448 | 3.87k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; | 
| 449 |  |  | 
| 450 | 3.87k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 451 | 3.87k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 452 | 3.87k |   } | 
| 453 |  |  | 
| 454 |  |   // If this has a segment register, print it. | 
| 455 | 3.87k |   reg = MCOperand_getReg(SegReg); | 
| 456 | 3.87k |   if (reg) { | 
| 457 | 215 |     _printOperand(MI, Op + 1, O); | 
| 458 | 215 |     SStream_concat0(O, ":"); | 
| 459 |  |  | 
| 460 | 215 |     if (MI->csh->detail_opt) { | 
| 461 | 215 |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_register_map(reg); | 
| 462 | 215 |     } | 
| 463 | 215 |   } | 
| 464 |  |  | 
| 465 | 3.87k |   if (MCOperand_isImm(DispSpec)) { | 
| 466 | 3.87k |     int64_t imm = MCOperand_getImm(DispSpec); | 
| 467 | 3.87k |     if (MI->csh->detail_opt) | 
| 468 | 3.87k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm; | 
| 469 | 3.87k |     if (imm < 0) { | 
| 470 | 573 |       SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm); | 
| 471 | 3.30k |     } else { | 
| 472 | 3.30k |       if (imm > HEX_THRESHOLD) | 
| 473 | 3.06k |         SStream_concat(O, "0x%"PRIx64, imm); | 
| 474 | 241 |       else | 
| 475 | 241 |         SStream_concat(O, "%"PRIu64, imm); | 
| 476 | 3.30k |     } | 
| 477 | 3.87k |   } | 
| 478 |  |  | 
| 479 | 3.87k |   if (MI->csh->detail_opt) | 
| 480 | 3.87k |     MI->flat_insn->detail->x86.op_count++; | 
| 481 | 3.87k | } | 
| 482 |  |  | 
| 483 |  | static void printU8Imm(MCInst *MI, unsigned Op, SStream *O) | 
| 484 | 20.0k | { | 
| 485 | 20.0k |   uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff; | 
| 486 |  |  | 
| 487 | 20.0k |   if (val > HEX_THRESHOLD) | 
| 488 | 17.1k |     SStream_concat(O, "$0x%x", val); | 
| 489 | 2.84k |   else | 
| 490 | 2.84k |     SStream_concat(O, "$%u", val); | 
| 491 |  |  | 
| 492 | 20.0k |   if (MI->csh->detail_opt) { | 
| 493 | 20.0k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; | 
| 494 | 20.0k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = val; | 
| 495 | 20.0k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = 1; | 
| 496 | 20.0k |     MI->flat_insn->detail->x86.op_count++; | 
| 497 | 20.0k |   } | 
| 498 | 20.0k | } | 
| 499 |  |  | 
| 500 |  | static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O) | 
| 501 | 2.07k | { | 
| 502 | 2.07k |   MI->x86opsize = 1; | 
| 503 | 2.07k |   printMemOffset(MI, OpNo, O); | 
| 504 | 2.07k | } | 
| 505 |  |  | 
| 506 |  | static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O) | 
| 507 | 850 | { | 
| 508 | 850 |   MI->x86opsize = 2; | 
| 509 | 850 |   printMemOffset(MI, OpNo, O); | 
| 510 | 850 | } | 
| 511 |  |  | 
| 512 |  | static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O) | 
| 513 | 719 | { | 
| 514 | 719 |   MI->x86opsize = 4; | 
| 515 | 719 |   printMemOffset(MI, OpNo, O); | 
| 516 | 719 | } | 
| 517 |  |  | 
| 518 |  | static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O) | 
| 519 | 237 | { | 
| 520 | 237 |   MI->x86opsize = 8; | 
| 521 | 237 |   printMemOffset(MI, OpNo, O); | 
| 522 | 237 | } | 
| 523 |  |  | 
| 524 |  | /// printPCRelImm - This is used to print an immediate value that ends up | 
| 525 |  | /// being encoded as a pc-relative value (e.g. for jumps and calls).  These | 
| 526 |  | /// print slightly differently than normal immediates.  For example, a $ is not | 
| 527 |  | /// emitted. | 
| 528 |  | static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O) | 
| 529 | 22.0k | { | 
| 530 | 22.0k |   MCOperand *Op = MCInst_getOperand(MI, OpNo); | 
| 531 | 22.0k |   if (MCOperand_isImm(Op)) { | 
| 532 | 22.0k |     int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + MI->address; | 
| 533 |  |  | 
| 534 |  |     // truncat imm for non-64bit | 
| 535 | 22.0k |     if (MI->csh->mode != CS_MODE_64) { | 
| 536 | 15.0k |       imm = imm & 0xffffffff; | 
| 537 | 15.0k |     } | 
| 538 |  |  | 
| 539 | 22.0k |     if (imm < 0) { | 
| 540 | 359 |       SStream_concat(O, "0x%"PRIx64, imm); | 
| 541 | 21.7k |     } else { | 
| 542 | 21.7k |       if (imm > HEX_THRESHOLD) | 
| 543 | 21.7k |         SStream_concat(O, "0x%"PRIx64, imm); | 
| 544 | 18 |       else | 
| 545 | 18 |         SStream_concat(O, "%"PRIu64, imm); | 
| 546 | 21.7k |     } | 
| 547 | 22.0k |     if (MI->csh->detail_opt) { | 
| 548 | 22.0k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; | 
| 549 | 22.0k |       MI->has_imm = true; | 
| 550 | 22.0k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm; | 
| 551 | 22.0k |       MI->flat_insn->detail->x86.op_count++; | 
| 552 | 22.0k |     } | 
| 553 | 22.0k |   } | 
| 554 | 22.0k | } | 
| 555 |  |  | 
| 556 |  | static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) | 
| 557 | 342k | { | 
| 558 | 342k |   MCOperand *Op  = MCInst_getOperand(MI, OpNo); | 
| 559 | 342k |   if (MCOperand_isReg(Op)) { | 
| 560 | 306k |     unsigned int reg = MCOperand_getReg(Op); | 
| 561 | 306k |     printRegName(O, reg); | 
| 562 | 306k |     if (MI->csh->detail_opt) { | 
| 563 | 306k |       if (MI->csh->doing_mem) { | 
| 564 | 38.9k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_register_map(reg); | 
| 565 | 267k |       } else { | 
| 566 | 267k |         uint8_t access[6]; | 
| 567 |  |  | 
| 568 | 267k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG; | 
| 569 | 267k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = X86_register_map(reg); | 
| 570 | 267k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[X86_register_map(reg)]; | 
| 571 |  |  | 
| 572 | 267k |         get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 573 | 267k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 574 |  |  | 
| 575 | 267k |         MI->flat_insn->detail->x86.op_count++; | 
| 576 | 267k |       } | 
| 577 | 306k |     } | 
| 578 | 306k |   } else if (MCOperand_isImm(Op)) { | 
| 579 |  |     // Print X86 immediates as signed values. | 
| 580 | 35.8k |     uint8_t encsize; | 
| 581 | 35.8k |     int64_t imm = MCOperand_getImm(Op); | 
| 582 | 35.8k |     uint8_t opsize = X86_immediate_size(MCInst_getOpcode(MI), &encsize); | 
| 583 |  |  | 
| 584 | 35.8k |     if (opsize == 1)    // print 1 byte immediate in positive form | 
| 585 | 15.6k |       imm = imm & 0xff; | 
| 586 |  |  | 
| 587 | 35.8k |     switch(MI->flat_insn->id) { | 
| 588 | 16.3k |       default: | 
| 589 | 16.3k |         if (imm >= 0) { | 
| 590 | 14.7k |           if (imm > HEX_THRESHOLD) | 
| 591 | 13.4k |             SStream_concat(O, "$0x%"PRIx64, imm); | 
| 592 | 1.31k |           else | 
| 593 | 1.31k |             SStream_concat(O, "$%"PRIu64, imm); | 
| 594 | 14.7k |         } else { | 
| 595 | 1.58k |           if (MI->csh->imm_unsigned) { | 
| 596 | 0 |             if (opsize) { | 
| 597 | 0 |               switch(opsize) { | 
| 598 | 0 |                 default: | 
| 599 | 0 |                   break; | 
| 600 | 0 |                 case 1: | 
| 601 | 0 |                   imm &= 0xff; | 
| 602 | 0 |                   break; | 
| 603 | 0 |                 case 2: | 
| 604 | 0 |                   imm &= 0xffff; | 
| 605 | 0 |                   break; | 
| 606 | 0 |                 case 4: | 
| 607 | 0 |                   imm &= 0xffffffff; | 
| 608 | 0 |                   break; | 
| 609 | 0 |               } | 
| 610 | 0 |             } | 
| 611 |  |  | 
| 612 | 0 |             SStream_concat(O, "$0x%"PRIx64, imm); | 
| 613 | 1.58k |           } else { | 
| 614 | 1.58k |             if (imm == 0x8000000000000000LL)  // imm == -imm | 
| 615 | 0 |               SStream_concat0(O, "$0x8000000000000000"); | 
| 616 | 1.58k |             else if (imm < -HEX_THRESHOLD) | 
| 617 | 1.26k |               SStream_concat(O, "$-0x%"PRIx64, -imm); | 
| 618 | 315 |             else | 
| 619 | 315 |               SStream_concat(O, "$-%"PRIu64, -imm); | 
| 620 | 1.58k |           } | 
| 621 | 1.58k |         } | 
| 622 | 16.3k |         break; | 
| 623 |  |  | 
| 624 | 16.3k |       case X86_INS_MOVABS: | 
| 625 | 6.00k |       case X86_INS_MOV: | 
| 626 |  |         // do not print number in negative form | 
| 627 | 6.00k |         if (imm > HEX_THRESHOLD) | 
| 628 | 5.51k |           SStream_concat(O, "$0x%"PRIx64, imm); | 
| 629 | 484 |         else | 
| 630 | 484 |           SStream_concat(O, "$%"PRIu64, imm); | 
| 631 | 6.00k |         break; | 
| 632 |  |  | 
| 633 | 0 |       case X86_INS_IN: | 
| 634 | 0 |       case X86_INS_OUT: | 
| 635 | 0 |       case X86_INS_INT: | 
| 636 |  |         // do not print number in negative form | 
| 637 | 0 |         imm = imm & 0xff; | 
| 638 | 0 |         if (imm >= 0 && imm <= HEX_THRESHOLD) | 
| 639 | 0 |           SStream_concat(O, "$%u", imm); | 
| 640 | 0 |         else { | 
| 641 | 0 |           SStream_concat(O, "$0x%x", imm); | 
| 642 | 0 |         } | 
| 643 | 0 |         break; | 
| 644 |  |  | 
| 645 | 624 |       case X86_INS_LCALL: | 
| 646 | 1.39k |       case X86_INS_LJMP: | 
| 647 | 1.39k |       case X86_INS_JMP: | 
| 648 |  |         // always print address in positive form | 
| 649 | 1.39k |         if (OpNo == 1) { // selector is ptr16 | 
| 650 | 697 |           imm = imm & 0xffff; | 
| 651 | 697 |           opsize = 2; | 
| 652 | 697 |         } else | 
| 653 | 697 |           opsize = 4; | 
| 654 | 1.39k |         SStream_concat(O, "$0x%"PRIx64, imm); | 
| 655 | 1.39k |         break; | 
| 656 |  |  | 
| 657 | 2.94k |       case X86_INS_AND: | 
| 658 | 5.39k |       case X86_INS_OR: | 
| 659 | 7.69k |       case X86_INS_XOR: | 
| 660 |  |         // do not print number in negative form | 
| 661 | 7.69k |         if (imm >= 0 && imm <= HEX_THRESHOLD) | 
| 662 | 683 |           SStream_concat(O, "$%u", imm); | 
| 663 | 7.00k |         else { | 
| 664 | 7.00k |           imm = arch_masks[opsize? opsize : MI->imm_size] & imm; | 
| 665 | 7.00k |           SStream_concat(O, "$0x%"PRIx64, imm); | 
| 666 | 7.00k |         } | 
| 667 | 7.69k |         break; | 
| 668 |  |  | 
| 669 | 3.74k |       case X86_INS_RET: | 
| 670 | 4.45k |       case X86_INS_RETF: | 
| 671 |  |         // RET imm16 | 
| 672 | 4.45k |         if (imm >= 0 && imm <= HEX_THRESHOLD) | 
| 673 | 250 |           SStream_concat(O, "$%u", imm); | 
| 674 | 4.20k |         else { | 
| 675 | 4.20k |           imm = 0xffff & imm; | 
| 676 | 4.20k |           SStream_concat(O, "$0x%x", imm); | 
| 677 | 4.20k |         } | 
| 678 | 4.45k |         break; | 
| 679 | 35.8k |     } | 
| 680 |  |  | 
| 681 | 35.8k |     if (MI->csh->detail_opt) { | 
| 682 | 35.8k |       if (MI->csh->doing_mem) { | 
| 683 | 0 |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 684 | 0 |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm; | 
| 685 | 35.8k |       } else { | 
| 686 | 35.8k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; | 
| 687 | 35.8k |         MI->has_imm = true; | 
| 688 | 35.8k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm; | 
| 689 |  |  | 
| 690 | 35.8k |         if (opsize > 0) { | 
| 691 | 29.2k |           MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize; | 
| 692 | 29.2k |           MI->flat_insn->detail->x86.encoding.imm_size = encsize; | 
| 693 | 29.2k |         } else if (MI->op1_size > 0) | 
| 694 | 0 |           MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->op1_size; | 
| 695 | 6.60k |         else | 
| 696 | 6.60k |           MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size; | 
| 697 |  |  | 
| 698 | 35.8k |         MI->flat_insn->detail->x86.op_count++; | 
| 699 | 35.8k |       } | 
| 700 | 35.8k |     } | 
| 701 | 35.8k |   } | 
| 702 | 342k | } | 
| 703 |  |  | 
| 704 |  | static void printMemReference(MCInst *MI, unsigned Op, SStream *O) | 
| 705 | 145k | { | 
| 706 | 145k |   MCOperand *BaseReg  = MCInst_getOperand(MI, Op + X86_AddrBaseReg); | 
| 707 | 145k |   MCOperand *IndexReg  = MCInst_getOperand(MI, Op + X86_AddrIndexReg); | 
| 708 | 145k |   MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp); | 
| 709 | 145k |   MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg); | 
| 710 | 145k |   uint64_t ScaleVal; | 
| 711 | 145k |   int segreg; | 
| 712 | 145k |   int64_t DispVal = 1; | 
| 713 |  |  | 
| 714 | 145k |   if (MI->csh->detail_opt) { | 
| 715 | 145k |     uint8_t access[6]; | 
| 716 |  |  | 
| 717 | 145k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 718 | 145k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; | 
| 719 | 145k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; | 
| 720 | 145k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_register_map(MCOperand_getReg(BaseReg)); | 
| 721 | 145k |         if (MCOperand_getReg(IndexReg) != X86_EIZ) { | 
| 722 | 145k |             MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_register_map(MCOperand_getReg(IndexReg)); | 
| 723 | 145k |         } | 
| 724 | 145k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; | 
| 725 | 145k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; | 
| 726 |  |  | 
| 727 | 145k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 728 | 145k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 729 | 145k |   } | 
| 730 |  |  | 
| 731 |  |   // If this has a segment register, print it. | 
| 732 | 145k |   segreg = MCOperand_getReg(SegReg); | 
| 733 | 145k |   if (segreg) { | 
| 734 | 3.89k |     _printOperand(MI, Op + X86_AddrSegmentReg, O); | 
| 735 | 3.89k |     SStream_concat0(O, ":"); | 
| 736 |  |  | 
| 737 | 3.89k |     if (MI->csh->detail_opt) { | 
| 738 | 3.89k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_register_map(segreg); | 
| 739 | 3.89k |     } | 
| 740 | 3.89k |   } | 
| 741 |  |  | 
| 742 | 145k |   if (MCOperand_isImm(DispSpec)) { | 
| 743 | 145k |     DispVal = MCOperand_getImm(DispSpec); | 
| 744 | 145k |     if (MI->csh->detail_opt) | 
| 745 | 145k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal; | 
| 746 | 145k |     if (DispVal) { | 
| 747 | 47.0k |       if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) { | 
| 748 | 44.6k |         printInt64(O, DispVal); | 
| 749 | 44.6k |       } else { | 
| 750 |  |         // only immediate as address of memory | 
| 751 | 2.47k |         if (DispVal < 0) { | 
| 752 | 766 |           SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal); | 
| 753 | 1.71k |         } else { | 
| 754 | 1.71k |           if (DispVal > HEX_THRESHOLD) | 
| 755 | 1.49k |             SStream_concat(O, "0x%"PRIx64, DispVal); | 
| 756 | 212 |           else | 
| 757 | 212 |             SStream_concat(O, "%"PRIu64, DispVal); | 
| 758 | 1.71k |         } | 
| 759 | 2.47k |       } | 
| 760 | 47.0k |     } | 
| 761 | 145k |   } | 
| 762 |  |  | 
| 763 | 145k |   if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) { | 
| 764 | 142k |     SStream_concat0(O, "("); | 
| 765 |  |  | 
| 766 | 142k |     if (MCOperand_getReg(BaseReg)) | 
| 767 | 142k |       _printOperand(MI, Op + X86_AddrBaseReg, O); | 
| 768 |  |  | 
| 769 | 142k |         if (MCOperand_getReg(IndexReg) && MCOperand_getReg(IndexReg) != X86_EIZ) { | 
| 770 | 57.1k |       SStream_concat0(O, ", "); | 
| 771 | 57.1k |       _printOperand(MI, Op + X86_AddrIndexReg, O); | 
| 772 | 57.1k |       ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt)); | 
| 773 | 57.1k |       if (MI->csh->detail_opt) | 
| 774 | 57.1k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal; | 
| 775 | 57.1k |       if (ScaleVal != 1) { | 
| 776 | 2.94k |         SStream_concat(O, ", %u", ScaleVal); | 
| 777 | 2.94k |       } | 
| 778 | 57.1k |     } | 
| 779 |  |  | 
| 780 | 142k |     SStream_concat0(O, ")"); | 
| 781 | 142k |   } else { | 
| 782 | 2.92k |     if (!DispVal) | 
| 783 | 449 |       SStream_concat0(O, "0"); | 
| 784 | 2.92k |   } | 
| 785 |  |  | 
| 786 | 145k |   if (MI->csh->detail_opt) | 
| 787 | 145k |     MI->flat_insn->detail->x86.op_count++; | 
| 788 | 145k | } | 
| 789 |  |  | 
| 790 |  | static void printanymem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 791 | 3.83k | { | 
| 792 | 3.83k |   switch(MI->Opcode) { | 
| 793 | 72 |     default: break; | 
| 794 | 413 |     case X86_LEA16r: | 
| 795 | 413 |          MI->x86opsize = 2; | 
| 796 | 413 |          break; | 
| 797 | 359 |     case X86_LEA32r: | 
| 798 | 738 |     case X86_LEA64_32r: | 
| 799 | 738 |          MI->x86opsize = 4; | 
| 800 | 738 |          break; | 
| 801 | 378 |     case X86_LEA64r: | 
| 802 | 378 |          MI->x86opsize = 8; | 
| 803 | 378 |          break; | 
| 804 | 196 |     case X86_BNDCL32rm: | 
| 805 | 408 |     case X86_BNDCN32rm: | 
| 806 | 623 |     case X86_BNDCU32rm: | 
| 807 | 894 |     case X86_BNDSTXmr: | 
| 808 | 1.35k |     case X86_BNDLDXrm: | 
| 809 | 1.83k |     case X86_BNDCL64rm: | 
| 810 | 2.03k |     case X86_BNDCN64rm: | 
| 811 | 2.22k |     case X86_BNDCU64rm: | 
| 812 | 2.22k |          MI->x86opsize = 16; | 
| 813 | 2.22k |          break; | 
| 814 | 3.83k |   } | 
| 815 |  |  | 
| 816 | 3.83k |   printMemReference(MI, OpNo, O); | 
| 817 | 3.83k | } | 
| 818 |  |  | 
| 819 |  | #include "X86InstPrinter.h" | 
| 820 |  |  | 
| 821 |  | // Include the auto-generated portion of the assembly writer. | 
| 822 |  | #ifdef CAPSTONE_X86_REDUCE | 
| 823 |  | #include "X86GenAsmWriter_reduce.inc" | 
| 824 |  | #else | 
| 825 |  | #include "X86GenAsmWriter.inc" | 
| 826 |  | #endif | 
| 827 |  |  | 
| 828 |  | #include "X86GenRegisterName.inc" | 
| 829 |  |  | 
| 830 |  | static void printRegName(SStream *OS, unsigned RegNo) | 
| 831 | 511k | { | 
| 832 | 511k |   SStream_concat(OS, "%%%s", getRegisterName(RegNo)); | 
| 833 | 511k | } | 
| 834 |  |  | 
| 835 |  | void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info) | 
| 836 | 344k | { | 
| 837 | 344k |   x86_reg reg, reg2; | 
| 838 | 344k |   enum cs_ac_type access1, access2; | 
| 839 | 344k |   int i; | 
| 840 |  |  | 
| 841 |  |   // perhaps this instruction does not need printer | 
| 842 | 344k |   if (MI->assembly[0]) { | 
| 843 | 0 |     strncpy(OS->buffer, MI->assembly, sizeof(OS->buffer)); | 
| 844 | 0 |     return; | 
| 845 | 0 |   } | 
| 846 |  |  | 
| 847 |  |   // Output CALLpcrel32 as "callq" in 64-bit mode. | 
| 848 |  |   // In Intel annotation it's always emitted as "call". | 
| 849 |  |   // | 
| 850 |  |   // TODO: Probably this hack should be redesigned via InstAlias in | 
| 851 |  |   // InstrInfo.td as soon as Requires clause is supported properly | 
| 852 |  |   // for InstAlias. | 
| 853 | 344k |   if (MI->csh->mode == CS_MODE_64 && MCInst_getOpcode(MI) == X86_CALLpcrel32) { | 
| 854 | 0 |     SStream_concat0(OS, "callq\t"); | 
| 855 | 0 |     MCInst_setOpcodePub(MI, X86_INS_CALL); | 
| 856 | 0 |     printPCRelImm(MI, 0, OS); | 
| 857 | 0 |     return; | 
| 858 | 0 |   } | 
| 859 |  |  | 
| 860 | 344k |   X86_lockrep(MI, OS); | 
| 861 | 344k |   printInstruction(MI, OS); | 
| 862 |  |  | 
| 863 | 344k |   if (MI->has_imm) { | 
| 864 |  |     // if op_count > 1, then this operand's size is taken from the destination op | 
| 865 | 56.9k |     if (MI->flat_insn->detail->x86.op_count > 1) { | 
| 866 | 28.5k |       if (MI->flat_insn->id != X86_INS_LCALL && MI->flat_insn->id != X86_INS_LJMP && MI->flat_insn->id != X86_INS_JMP) { | 
| 867 | 85.6k |         for (i = 0; i < MI->flat_insn->detail->x86.op_count; i++) { | 
| 868 | 57.8k |           if (MI->flat_insn->detail->x86.operands[i].type == X86_OP_IMM) | 
| 869 | 28.2k |             MI->flat_insn->detail->x86.operands[i].size = | 
| 870 | 28.2k |               MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count - 1].size; | 
| 871 | 57.8k |         } | 
| 872 | 27.8k |       } | 
| 873 | 28.5k |     } else | 
| 874 | 28.3k |       MI->flat_insn->detail->x86.operands[0].size = MI->imm_size; | 
| 875 | 56.9k |   } | 
| 876 |  |  | 
| 877 | 344k |   if (MI->csh->detail_opt) { | 
| 878 | 344k |     uint8_t access[6] = {0}; | 
| 879 |  |  | 
| 880 |  |     // some instructions need to supply immediate 1 in the first op | 
| 881 | 344k |     switch(MCInst_getOpcode(MI)) { | 
| 882 | 322k |       default: | 
| 883 | 322k |         break; | 
| 884 | 322k |       case X86_SHL8r1: | 
| 885 | 282 |       case X86_SHL16r1: | 
| 886 | 741 |       case X86_SHL32r1: | 
| 887 | 1.02k |       case X86_SHL64r1: | 
| 888 | 1.34k |       case X86_SAL8r1: | 
| 889 | 1.61k |       case X86_SAL16r1: | 
| 890 | 2.34k |       case X86_SAL32r1: | 
| 891 | 2.65k |       case X86_SAL64r1: | 
| 892 | 2.86k |       case X86_SHR8r1: | 
| 893 | 3.29k |       case X86_SHR16r1: | 
| 894 | 3.69k |       case X86_SHR32r1: | 
| 895 | 4.14k |       case X86_SHR64r1: | 
| 896 | 4.50k |       case X86_SAR8r1: | 
| 897 | 5.18k |       case X86_SAR16r1: | 
| 898 | 5.54k |       case X86_SAR32r1: | 
| 899 | 5.88k |       case X86_SAR64r1: | 
| 900 | 6.73k |       case X86_RCL8r1: | 
| 901 | 7.27k |       case X86_RCL16r1: | 
| 902 | 8.16k |       case X86_RCL32r1: | 
| 903 | 8.78k |       case X86_RCL64r1: | 
| 904 | 9.00k |       case X86_RCR8r1: | 
| 905 | 9.21k |       case X86_RCR16r1: | 
| 906 | 9.53k |       case X86_RCR32r1: | 
| 907 | 9.80k |       case X86_RCR64r1: | 
| 908 | 10.0k |       case X86_ROL8r1: | 
| 909 | 10.3k |       case X86_ROL16r1: | 
| 910 | 10.7k |       case X86_ROL32r1: | 
| 911 | 11.3k |       case X86_ROL64r1: | 
| 912 | 11.5k |       case X86_ROR8r1: | 
| 913 | 11.9k |       case X86_ROR16r1: | 
| 914 | 12.3k |       case X86_ROR32r1: | 
| 915 | 12.5k |       case X86_ROR64r1: | 
| 916 | 12.8k |       case X86_SHL8m1: | 
| 917 | 13.4k |       case X86_SHL16m1: | 
| 918 | 13.8k |       case X86_SHL32m1: | 
| 919 | 14.1k |       case X86_SHL64m1: | 
| 920 | 14.3k |       case X86_SAL8m1: | 
| 921 | 14.6k |       case X86_SAL16m1: | 
| 922 | 14.9k |       case X86_SAL32m1: | 
| 923 | 15.1k |       case X86_SAL64m1: | 
| 924 | 15.4k |       case X86_SHR8m1: | 
| 925 | 15.7k |       case X86_SHR16m1: | 
| 926 | 16.0k |       case X86_SHR32m1: | 
| 927 | 16.3k |       case X86_SHR64m1: | 
| 928 | 16.5k |       case X86_SAR8m1: | 
| 929 | 16.8k |       case X86_SAR16m1: | 
| 930 | 17.4k |       case X86_SAR32m1: | 
| 931 | 17.5k |       case X86_SAR64m1: | 
| 932 | 17.7k |       case X86_RCL8m1: | 
| 933 | 18.0k |       case X86_RCL16m1: | 
| 934 | 18.4k |       case X86_RCL32m1: | 
| 935 | 18.7k |       case X86_RCL64m1: | 
| 936 | 18.9k |       case X86_RCR8m1: | 
| 937 | 19.2k |       case X86_RCR16m1: | 
| 938 | 19.5k |       case X86_RCR32m1: | 
| 939 | 19.6k |       case X86_RCR64m1: | 
| 940 | 19.9k |       case X86_ROL8m1: | 
| 941 | 20.2k |       case X86_ROL16m1: | 
| 942 | 20.7k |       case X86_ROL32m1: | 
| 943 | 21.0k |       case X86_ROL64m1: | 
| 944 | 21.3k |       case X86_ROR8m1: | 
| 945 | 21.7k |       case X86_ROR16m1: | 
| 946 | 22.3k |       case X86_ROR32m1: | 
| 947 | 22.7k |       case X86_ROR64m1: | 
| 948 |  |         // shift all the ops right to leave 1st slot for this new register op | 
| 949 | 22.7k |         memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]), | 
| 950 | 22.7k |             sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1)); | 
| 951 | 22.7k |         MI->flat_insn->detail->x86.operands[0].type = X86_OP_IMM; | 
| 952 | 22.7k |         MI->flat_insn->detail->x86.operands[0].imm = 1; | 
| 953 | 22.7k |         MI->flat_insn->detail->x86.operands[0].size = 1; | 
| 954 | 22.7k |         MI->flat_insn->detail->x86.op_count++; | 
| 955 | 344k |     } | 
| 956 |  |  | 
| 957 |  |     // special instruction needs to supply register op | 
| 958 |  |     // first op can be embedded in the asm by llvm. | 
| 959 |  |     // so we have to add the missing register as the first operand | 
| 960 |  |  | 
| 961 |  |     //printf(">>> opcode = %u\n", MCInst_getOpcode(MI)); | 
| 962 |  |  | 
| 963 | 344k |     reg = X86_insn_reg_att(MCInst_getOpcode(MI), &access1); | 
| 964 | 344k |     if (reg) { | 
| 965 |  |       // shift all the ops right to leave 1st slot for this new register op | 
| 966 | 19.2k |       memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]), | 
| 967 | 19.2k |           sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1)); | 
| 968 | 19.2k |       MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG; | 
| 969 | 19.2k |       MI->flat_insn->detail->x86.operands[0].reg = reg; | 
| 970 | 19.2k |       MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg]; | 
| 971 | 19.2k |       MI->flat_insn->detail->x86.operands[0].access = access1; | 
| 972 |  |  | 
| 973 | 19.2k |       MI->flat_insn->detail->x86.op_count++; | 
| 974 | 325k |     } else { | 
| 975 | 325k |       if (X86_insn_reg_att2(MCInst_getOpcode(MI), ®, &access1, ®2, &access2)) { | 
| 976 |  |  | 
| 977 | 5.74k |         MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG; | 
| 978 | 5.74k |         MI->flat_insn->detail->x86.operands[0].reg = reg; | 
| 979 | 5.74k |         MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg]; | 
| 980 | 5.74k |         MI->flat_insn->detail->x86.operands[0].access = access1; | 
| 981 | 5.74k |         MI->flat_insn->detail->x86.operands[1].type = X86_OP_REG; | 
| 982 | 5.74k |         MI->flat_insn->detail->x86.operands[1].reg = reg2; | 
| 983 | 5.74k |         MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg2]; | 
| 984 | 5.74k |         MI->flat_insn->detail->x86.operands[0].access = access2; | 
| 985 | 5.74k |         MI->flat_insn->detail->x86.op_count = 2; | 
| 986 | 5.74k |       } | 
| 987 | 325k |     } | 
| 988 |  |  | 
| 989 | 344k | #ifndef CAPSTONE_DIET | 
| 990 | 344k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 991 | 344k |     MI->flat_insn->detail->x86.operands[0].access = access[0]; | 
| 992 | 344k |     MI->flat_insn->detail->x86.operands[1].access = access[1]; | 
| 993 | 344k | #endif | 
| 994 | 344k |   } | 
| 995 | 344k | } | 
| 996 |  |  | 
| 997 |  | #endif |