/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 | 117k | { | 
| 65 | 117k |   if (MI->csh->detail_opt != CS_OPT_ON) | 
| 66 | 0 |     return; | 
| 67 |  |  | 
| 68 | 117k |   MI->csh->doing_mem = status; | 
| 69 | 117k |   if (!status) | 
| 70 |  |     // done, create the next operand slot | 
| 71 | 58.6k |     MI->flat_insn->detail->x86.op_count++; | 
| 72 | 117k | } | 
| 73 |  |  | 
| 74 |  | static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 75 | 10.2k | { | 
| 76 | 10.2k |   switch(MI->csh->mode) { | 
| 77 | 3.45k |     case CS_MODE_16: | 
| 78 | 3.45k |       switch(MI->flat_insn->id) { | 
| 79 | 1.42k |         default: | 
| 80 | 1.42k |           MI->x86opsize = 2; | 
| 81 | 1.42k |           break; | 
| 82 | 352 |         case X86_INS_LJMP: | 
| 83 | 723 |         case X86_INS_LCALL: | 
| 84 | 723 |           MI->x86opsize = 4; | 
| 85 | 723 |           break; | 
| 86 | 335 |         case X86_INS_SGDT: | 
| 87 | 614 |         case X86_INS_SIDT: | 
| 88 | 954 |         case X86_INS_LGDT: | 
| 89 | 1.31k |         case X86_INS_LIDT: | 
| 90 | 1.31k |           MI->x86opsize = 6; | 
| 91 | 1.31k |           break; | 
| 92 | 3.45k |       } | 
| 93 | 3.45k |       break; | 
| 94 | 3.86k |     case CS_MODE_32: | 
| 95 | 3.86k |       switch(MI->flat_insn->id) { | 
| 96 | 680 |         default: | 
| 97 | 680 |           MI->x86opsize = 4; | 
| 98 | 680 |           break; | 
| 99 | 595 |         case X86_INS_LJMP: | 
| 100 | 1.22k |         case X86_INS_JMP: | 
| 101 | 1.65k |         case X86_INS_LCALL: | 
| 102 | 2.02k |         case X86_INS_SGDT: | 
| 103 | 2.40k |         case X86_INS_SIDT: | 
| 104 | 2.71k |         case X86_INS_LGDT: | 
| 105 | 3.18k |         case X86_INS_LIDT: | 
| 106 | 3.18k |           MI->x86opsize = 6; | 
| 107 | 3.18k |           break; | 
| 108 | 3.86k |       } | 
| 109 | 3.86k |       break; | 
| 110 | 3.86k |     case CS_MODE_64: | 
| 111 | 2.98k |       switch(MI->flat_insn->id) { | 
| 112 | 808 |         default: | 
| 113 | 808 |           MI->x86opsize = 8; | 
| 114 | 808 |           break; | 
| 115 | 443 |         case X86_INS_LJMP: | 
| 116 | 706 |         case X86_INS_LCALL: | 
| 117 | 1.02k |         case X86_INS_SGDT: | 
| 118 | 1.54k |         case X86_INS_SIDT: | 
| 119 | 1.79k |         case X86_INS_LGDT: | 
| 120 | 2.17k |         case X86_INS_LIDT: | 
| 121 | 2.17k |           MI->x86opsize = 10; | 
| 122 | 2.17k |           break; | 
| 123 | 2.98k |       } | 
| 124 | 2.98k |       break; | 
| 125 | 2.98k |     default:  // never reach | 
| 126 | 0 |       break; | 
| 127 | 10.2k |   } | 
| 128 |  |  | 
| 129 | 10.2k |   printMemReference(MI, OpNo, O); | 
| 130 | 10.2k | } | 
| 131 |  |  | 
| 132 |  | static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 133 | 90.1k | { | 
| 134 | 90.1k |   MI->x86opsize = 1; | 
| 135 | 90.1k |   printMemReference(MI, OpNo, O); | 
| 136 | 90.1k | } | 
| 137 |  |  | 
| 138 |  | static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 139 | 36.2k | { | 
| 140 | 36.2k |   MI->x86opsize = 2; | 
| 141 |  |  | 
| 142 | 36.2k |   printMemReference(MI, OpNo, O); | 
| 143 | 36.2k | } | 
| 144 |  |  | 
| 145 |  | static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 146 | 33.6k | { | 
| 147 | 33.6k |   MI->x86opsize = 4; | 
| 148 |  |  | 
| 149 | 33.6k |   printMemReference(MI, OpNo, O); | 
| 150 | 33.6k | } | 
| 151 |  |  | 
| 152 |  | static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 153 | 12.1k | { | 
| 154 | 12.1k |   MI->x86opsize = 8; | 
| 155 | 12.1k |   printMemReference(MI, OpNo, O); | 
| 156 | 12.1k | } | 
| 157 |  |  | 
| 158 |  | static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 159 | 6.20k | { | 
| 160 | 6.20k |   MI->x86opsize = 16; | 
| 161 | 6.20k |   printMemReference(MI, OpNo, O); | 
| 162 | 6.20k | } | 
| 163 |  |  | 
| 164 |  | static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 165 | 3.45k | { | 
| 166 | 3.45k |   MI->x86opsize = 64; | 
| 167 | 3.45k |   printMemReference(MI, OpNo, O); | 
| 168 | 3.45k | } | 
| 169 |  |  | 
| 170 |  | #ifndef CAPSTONE_X86_REDUCE | 
| 171 |  | static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 172 | 3.32k | { | 
| 173 | 3.32k |   MI->x86opsize = 32; | 
| 174 | 3.32k |   printMemReference(MI, OpNo, O); | 
| 175 | 3.32k | } | 
| 176 |  |  | 
| 177 |  | static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 178 | 6.98k | { | 
| 179 | 6.98k |   switch(MCInst_getOpcode(MI)) { | 
| 180 | 5.49k |     default: | 
| 181 | 5.49k |       MI->x86opsize = 4; | 
| 182 | 5.49k |       break; | 
| 183 | 427 |     case X86_FSTENVm: | 
| 184 | 1.49k |     case X86_FLDENVm: | 
| 185 |  |       // TODO: fix this in tablegen instead | 
| 186 | 1.49k |       switch(MI->csh->mode) { | 
| 187 | 0 |         default:    // never reach | 
| 188 | 0 |           break; | 
| 189 | 624 |         case CS_MODE_16: | 
| 190 | 624 |           MI->x86opsize = 14; | 
| 191 | 624 |           break; | 
| 192 | 518 |         case CS_MODE_32: | 
| 193 | 869 |         case CS_MODE_64: | 
| 194 | 869 |           MI->x86opsize = 28; | 
| 195 | 869 |           break; | 
| 196 | 1.49k |       } | 
| 197 | 1.49k |       break; | 
| 198 | 6.98k |   } | 
| 199 |  |  | 
| 200 | 6.98k |   printMemReference(MI, OpNo, O); | 
| 201 | 6.98k | } | 
| 202 |  |  | 
| 203 |  | static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 204 | 5.42k | { | 
| 205 | 5.42k |   MI->x86opsize = 8; | 
| 206 | 5.42k |   printMemReference(MI, OpNo, O); | 
| 207 | 5.42k | } | 
| 208 |  |  | 
| 209 |  | static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 210 | 379 | { | 
| 211 | 379 |   MI->x86opsize = 10; | 
| 212 | 379 |   printMemReference(MI, OpNo, O); | 
| 213 | 379 | } | 
| 214 |  |  | 
| 215 |  | static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 216 | 4.56k | { | 
| 217 | 4.56k |   MI->x86opsize = 16; | 
| 218 | 4.56k |   printMemReference(MI, OpNo, O); | 
| 219 | 4.56k | } | 
| 220 |  |  | 
| 221 |  | static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 222 | 3.55k | { | 
| 223 | 3.55k |   MI->x86opsize = 32; | 
| 224 | 3.55k |   printMemReference(MI, OpNo, O); | 
| 225 | 3.55k | } | 
| 226 |  |  | 
| 227 |  | static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 228 | 2.75k | { | 
| 229 | 2.75k |   MI->x86opsize = 64; | 
| 230 | 2.75k |   printMemReference(MI, OpNo, O); | 
| 231 | 2.75k | } | 
| 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 | 317k | { | 
| 240 | 317k |   MCOperand *Op  = MCInst_getOperand(MI, OpNo); | 
| 241 | 317k |   if (MCOperand_isReg(Op)) { | 
| 242 | 317k |     printRegName(O, MCOperand_getReg(Op)); | 
| 243 | 317k |   } 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 | 317k | } | 
| 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 | 1.22M | { | 
| 286 | 1.22M |   uint8_t count, i; | 
| 287 | 1.22M |   const uint8_t *arr = X86_get_op_access(h, id, eflags); | 
| 288 |  |  | 
| 289 | 1.22M |   if (!arr) { | 
| 290 | 0 |     access[0] = 0; | 
| 291 | 0 |     return; | 
| 292 | 0 |   } | 
| 293 |  |  | 
| 294 |  |   // find the non-zero last entry | 
| 295 | 3.52M |   for(count = 0; arr[count]; count++); | 
| 296 |  |  | 
| 297 | 1.22M |   if (count == 0) | 
| 298 | 78.0k |     return; | 
| 299 |  |  | 
| 300 |  |   // copy in reverse order this access array from Intel syntax -> AT&T syntax | 
| 301 | 1.14M |   count--; | 
| 302 | 3.44M |   for(i = 0; i <= count; i++) { | 
| 303 | 2.30M |     if (arr[count - i] != CS_AC_IGNORE) | 
| 304 | 1.99M |       access[i] = arr[count - i]; | 
| 305 | 303k |     else | 
| 306 | 303k |       access[i] = 0; | 
| 307 | 2.30M |   } | 
| 308 | 1.14M | } | 
| 309 |  |  | 
| 310 |  | static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O) | 
| 311 | 26.7k | { | 
| 312 | 26.7k |   MCOperand *SegReg; | 
| 313 | 26.7k |   int reg; | 
| 314 |  |  | 
| 315 | 26.7k |   if (MI->csh->detail_opt) { | 
| 316 | 26.7k |     uint8_t access[6]; | 
| 317 |  |  | 
| 318 | 26.7k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 319 | 26.7k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; | 
| 320 | 26.7k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; | 
| 321 | 26.7k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID; | 
| 322 | 26.7k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID; | 
| 323 | 26.7k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; | 
| 324 | 26.7k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; | 
| 325 |  |  | 
| 326 | 26.7k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 327 | 26.7k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 328 | 26.7k |   } | 
| 329 |  |  | 
| 330 | 26.7k |   SegReg = MCInst_getOperand(MI, Op+1); | 
| 331 | 26.7k |   reg = MCOperand_getReg(SegReg); | 
| 332 |  |   // If this has a segment register, print it. | 
| 333 | 26.7k |   if (reg) { | 
| 334 | 733 |     _printOperand(MI, Op + 1, O); | 
| 335 | 733 |     SStream_concat0(O, ":"); | 
| 336 |  |  | 
| 337 | 733 |     if (MI->csh->detail_opt) { | 
| 338 | 733 |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_register_map(reg); | 
| 339 | 733 |     } | 
| 340 | 733 |   } | 
| 341 |  |  | 
| 342 | 26.7k |   SStream_concat0(O, "("); | 
| 343 | 26.7k |   set_mem_access(MI, true); | 
| 344 |  |  | 
| 345 | 26.7k |   printOperand(MI, Op, O); | 
| 346 |  |  | 
| 347 | 26.7k |   SStream_concat0(O, ")"); | 
| 348 | 26.7k |   set_mem_access(MI, false); | 
| 349 | 26.7k | } | 
| 350 |  |  | 
| 351 |  | static void printDstIdx(MCInst *MI, unsigned Op, SStream *O) | 
| 352 | 31.9k | { | 
| 353 | 31.9k |   if (MI->csh->detail_opt) { | 
| 354 | 31.9k |     uint8_t access[6]; | 
| 355 |  |  | 
| 356 | 31.9k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 357 | 31.9k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; | 
| 358 | 31.9k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; | 
| 359 | 31.9k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID; | 
| 360 | 31.9k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID; | 
| 361 | 31.9k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; | 
| 362 | 31.9k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; | 
| 363 |  |  | 
| 364 | 31.9k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 365 | 31.9k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 366 | 31.9k |   } | 
| 367 |  |  | 
| 368 |  |   // DI accesses are always ES-based on non-64bit mode | 
| 369 | 31.9k |   if (MI->csh->mode != CS_MODE_64) { | 
| 370 | 18.4k |     SStream_concat0(O, "%es:("); | 
| 371 | 18.4k |     if (MI->csh->detail_opt) { | 
| 372 | 18.4k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_ES; | 
| 373 | 18.4k |     } | 
| 374 | 18.4k |   } else | 
| 375 | 13.4k |     SStream_concat0(O, "("); | 
| 376 |  |  | 
| 377 | 31.9k |   set_mem_access(MI, true); | 
| 378 |  |  | 
| 379 | 31.9k |   printOperand(MI, Op, O); | 
| 380 |  |  | 
| 381 | 31.9k |   SStream_concat0(O, ")"); | 
| 382 | 31.9k |   set_mem_access(MI, false); | 
| 383 | 31.9k | } | 
| 384 |  |  | 
| 385 |  | static void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O) | 
| 386 | 11.4k | { | 
| 387 | 11.4k |   MI->x86opsize = 1; | 
| 388 | 11.4k |   printSrcIdx(MI, OpNo, O); | 
| 389 | 11.4k | } | 
| 390 |  |  | 
| 391 |  | static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O) | 
| 392 | 6.40k | { | 
| 393 | 6.40k |   MI->x86opsize = 2; | 
| 394 | 6.40k |   printSrcIdx(MI, OpNo, O); | 
| 395 | 6.40k | } | 
| 396 |  |  | 
| 397 |  | static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O) | 
| 398 | 6.45k | { | 
| 399 | 6.45k |   MI->x86opsize = 4; | 
| 400 | 6.45k |   printSrcIdx(MI, OpNo, O); | 
| 401 | 6.45k | } | 
| 402 |  |  | 
| 403 |  | static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O) | 
| 404 | 2.44k | { | 
| 405 | 2.44k |   MI->x86opsize = 8; | 
| 406 | 2.44k |   printSrcIdx(MI, OpNo, O); | 
| 407 | 2.44k | } | 
| 408 |  |  | 
| 409 |  | static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O) | 
| 410 | 14.8k | { | 
| 411 | 14.8k |   MI->x86opsize = 1; | 
| 412 | 14.8k |   printDstIdx(MI, OpNo, O); | 
| 413 | 14.8k | } | 
| 414 |  |  | 
| 415 |  | static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O) | 
| 416 | 7.36k | { | 
| 417 | 7.36k |   MI->x86opsize = 2; | 
| 418 | 7.36k |   printDstIdx(MI, OpNo, O); | 
| 419 | 7.36k | } | 
| 420 |  |  | 
| 421 |  | static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O) | 
| 422 | 8.11k | { | 
| 423 | 8.11k |   MI->x86opsize = 4; | 
| 424 | 8.11k |   printDstIdx(MI, OpNo, O); | 
| 425 | 8.11k | } | 
| 426 |  |  | 
| 427 |  | static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O) | 
| 428 | 1.63k | { | 
| 429 | 1.63k |   MI->x86opsize = 8; | 
| 430 | 1.63k |   printDstIdx(MI, OpNo, O); | 
| 431 | 1.63k | } | 
| 432 |  |  | 
| 433 |  | static void printMemOffset(MCInst *MI, unsigned Op, SStream *O) | 
| 434 | 5.82k | { | 
| 435 | 5.82k |   MCOperand *DispSpec = MCInst_getOperand(MI, Op); | 
| 436 | 5.82k |   MCOperand *SegReg = MCInst_getOperand(MI, Op+1); | 
| 437 | 5.82k |   int reg; | 
| 438 |  |  | 
| 439 | 5.82k |   if (MI->csh->detail_opt) { | 
| 440 | 5.82k |     uint8_t access[6]; | 
| 441 |  |  | 
| 442 | 5.82k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 443 | 5.82k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; | 
| 444 | 5.82k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; | 
| 445 | 5.82k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID; | 
| 446 | 5.82k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID; | 
| 447 | 5.82k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; | 
| 448 | 5.82k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; | 
| 449 |  |  | 
| 450 | 5.82k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 451 | 5.82k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 452 | 5.82k |   } | 
| 453 |  |  | 
| 454 |  |   // If this has a segment register, print it. | 
| 455 | 5.82k |   reg = MCOperand_getReg(SegReg); | 
| 456 | 5.82k |   if (reg) { | 
| 457 | 242 |     _printOperand(MI, Op + 1, O); | 
| 458 | 242 |     SStream_concat0(O, ":"); | 
| 459 |  |  | 
| 460 | 242 |     if (MI->csh->detail_opt) { | 
| 461 | 242 |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_register_map(reg); | 
| 462 | 242 |     } | 
| 463 | 242 |   } | 
| 464 |  |  | 
| 465 | 5.82k |   if (MCOperand_isImm(DispSpec)) { | 
| 466 | 5.82k |     int64_t imm = MCOperand_getImm(DispSpec); | 
| 467 | 5.82k |     if (MI->csh->detail_opt) | 
| 468 | 5.82k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm; | 
| 469 | 5.82k |     if (imm < 0) { | 
| 470 | 858 |       SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm); | 
| 471 | 4.96k |     } else { | 
| 472 | 4.96k |       if (imm > HEX_THRESHOLD) | 
| 473 | 4.61k |         SStream_concat(O, "0x%"PRIx64, imm); | 
| 474 | 347 |       else | 
| 475 | 347 |         SStream_concat(O, "%"PRIu64, imm); | 
| 476 | 4.96k |     } | 
| 477 | 5.82k |   } | 
| 478 |  |  | 
| 479 | 5.82k |   if (MI->csh->detail_opt) | 
| 480 | 5.82k |     MI->flat_insn->detail->x86.op_count++; | 
| 481 | 5.82k | } | 
| 482 |  |  | 
| 483 |  | static void printU8Imm(MCInst *MI, unsigned Op, SStream *O) | 
| 484 | 28.3k | { | 
| 485 | 28.3k |   uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff; | 
| 486 |  |  | 
| 487 | 28.3k |   if (val > HEX_THRESHOLD) | 
| 488 | 24.3k |     SStream_concat(O, "$0x%x", val); | 
| 489 | 3.99k |   else | 
| 490 | 3.99k |     SStream_concat(O, "$%u", val); | 
| 491 |  |  | 
| 492 | 28.3k |   if (MI->csh->detail_opt) { | 
| 493 | 28.3k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; | 
| 494 | 28.3k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = val; | 
| 495 | 28.3k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = 1; | 
| 496 | 28.3k |     MI->flat_insn->detail->x86.op_count++; | 
| 497 | 28.3k |   } | 
| 498 | 28.3k | } | 
| 499 |  |  | 
| 500 |  | static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O) | 
| 501 | 3.00k | { | 
| 502 | 3.00k |   MI->x86opsize = 1; | 
| 503 | 3.00k |   printMemOffset(MI, OpNo, O); | 
| 504 | 3.00k | } | 
| 505 |  |  | 
| 506 |  | static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O) | 
| 507 | 1.22k | { | 
| 508 | 1.22k |   MI->x86opsize = 2; | 
| 509 | 1.22k |   printMemOffset(MI, OpNo, O); | 
| 510 | 1.22k | } | 
| 511 |  |  | 
| 512 |  | static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O) | 
| 513 | 1.18k | { | 
| 514 | 1.18k |   MI->x86opsize = 4; | 
| 515 | 1.18k |   printMemOffset(MI, OpNo, O); | 
| 516 | 1.18k | } | 
| 517 |  |  | 
| 518 |  | static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O) | 
| 519 | 412 | { | 
| 520 | 412 |   MI->x86opsize = 8; | 
| 521 | 412 |   printMemOffset(MI, OpNo, O); | 
| 522 | 412 | } | 
| 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 | 35.0k | { | 
| 530 | 35.0k |   MCOperand *Op = MCInst_getOperand(MI, OpNo); | 
| 531 | 35.0k |   if (MCOperand_isImm(Op)) { | 
| 532 | 35.0k |     int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + MI->address; | 
| 533 |  |  | 
| 534 |  |     // truncat imm for non-64bit | 
| 535 | 35.0k |     if (MI->csh->mode != CS_MODE_64) { | 
| 536 | 24.4k |       imm = imm & 0xffffffff; | 
| 537 | 24.4k |     } | 
| 538 |  |  | 
| 539 | 35.0k |     if (imm < 0) { | 
| 540 | 621 |       SStream_concat(O, "0x%"PRIx64, imm); | 
| 541 | 34.4k |     } else { | 
| 542 | 34.4k |       if (imm > HEX_THRESHOLD) | 
| 543 | 34.4k |         SStream_concat(O, "0x%"PRIx64, imm); | 
| 544 | 22 |       else | 
| 545 | 22 |         SStream_concat(O, "%"PRIu64, imm); | 
| 546 | 34.4k |     } | 
| 547 | 35.0k |     if (MI->csh->detail_opt) { | 
| 548 | 35.0k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; | 
| 549 | 35.0k |       MI->has_imm = true; | 
| 550 | 35.0k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm; | 
| 551 | 35.0k |       MI->flat_insn->detail->x86.op_count++; | 
| 552 | 35.0k |     } | 
| 553 | 35.0k |   } | 
| 554 | 35.0k | } | 
| 555 |  |  | 
| 556 |  | static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) | 
| 557 | 517k | { | 
| 558 | 517k |   MCOperand *Op  = MCInst_getOperand(MI, OpNo); | 
| 559 | 517k |   if (MCOperand_isReg(Op)) { | 
| 560 | 458k |     unsigned int reg = MCOperand_getReg(Op); | 
| 561 | 458k |     printRegName(O, reg); | 
| 562 | 458k |     if (MI->csh->detail_opt) { | 
| 563 | 458k |       if (MI->csh->doing_mem) { | 
| 564 | 58.6k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_register_map(reg); | 
| 565 | 400k |       } else { | 
| 566 | 400k |         uint8_t access[6]; | 
| 567 |  |  | 
| 568 | 400k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG; | 
| 569 | 400k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = X86_register_map(reg); | 
| 570 | 400k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[X86_register_map(reg)]; | 
| 571 |  |  | 
| 572 | 400k |         get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 573 | 400k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 574 |  |  | 
| 575 | 400k |         MI->flat_insn->detail->x86.op_count++; | 
| 576 | 400k |       } | 
| 577 | 458k |     } | 
| 578 | 458k |   } else if (MCOperand_isImm(Op)) { | 
| 579 |  |     // Print X86 immediates as signed values. | 
| 580 | 58.6k |     uint8_t encsize; | 
| 581 | 58.6k |     int64_t imm = MCOperand_getImm(Op); | 
| 582 | 58.6k |     uint8_t opsize = X86_immediate_size(MCInst_getOpcode(MI), &encsize); | 
| 583 |  |  | 
| 584 | 58.6k |     if (opsize == 1)    // print 1 byte immediate in positive form | 
| 585 | 25.0k |       imm = imm & 0xff; | 
| 586 |  |  | 
| 587 | 58.6k |     switch(MI->flat_insn->id) { | 
| 588 | 25.7k |       default: | 
| 589 | 25.7k |         if (imm >= 0) { | 
| 590 | 22.8k |           if (imm > HEX_THRESHOLD) | 
| 591 | 20.5k |             SStream_concat(O, "$0x%"PRIx64, imm); | 
| 592 | 2.27k |           else | 
| 593 | 2.27k |             SStream_concat(O, "$%"PRIu64, imm); | 
| 594 | 22.8k |         } else { | 
| 595 | 2.94k |           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 | 2.94k |           } else { | 
| 614 | 2.94k |             if (imm == 0x8000000000000000LL)  // imm == -imm | 
| 615 | 0 |               SStream_concat0(O, "$0x8000000000000000"); | 
| 616 | 2.94k |             else if (imm < -HEX_THRESHOLD) | 
| 617 | 2.52k |               SStream_concat(O, "$-0x%"PRIx64, -imm); | 
| 618 | 421 |             else | 
| 619 | 421 |               SStream_concat(O, "$-%"PRIu64, -imm); | 
| 620 | 2.94k |           } | 
| 621 | 2.94k |         } | 
| 622 | 25.7k |         break; | 
| 623 |  |  | 
| 624 | 25.7k |       case X86_INS_MOVABS: | 
| 625 | 10.0k |       case X86_INS_MOV: | 
| 626 |  |         // do not print number in negative form | 
| 627 | 10.0k |         if (imm > HEX_THRESHOLD) | 
| 628 | 9.27k |           SStream_concat(O, "$0x%"PRIx64, imm); | 
| 629 | 796 |         else | 
| 630 | 796 |           SStream_concat(O, "$%"PRIu64, imm); | 
| 631 | 10.0k |         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 | 928 |       case X86_INS_LCALL: | 
| 646 | 2.14k |       case X86_INS_LJMP: | 
| 647 | 2.14k |       case X86_INS_JMP: | 
| 648 |  |         // always print address in positive form | 
| 649 | 2.14k |         if (OpNo == 1) { // selector is ptr16 | 
| 650 | 1.07k |           imm = imm & 0xffff; | 
| 651 | 1.07k |           opsize = 2; | 
| 652 | 1.07k |         } else | 
| 653 | 1.07k |           opsize = 4; | 
| 654 | 2.14k |         SStream_concat(O, "$0x%"PRIx64, imm); | 
| 655 | 2.14k |         break; | 
| 656 |  |  | 
| 657 | 5.03k |       case X86_INS_AND: | 
| 658 | 10.0k |       case X86_INS_OR: | 
| 659 | 13.4k |       case X86_INS_XOR: | 
| 660 |  |         // do not print number in negative form | 
| 661 | 13.4k |         if (imm >= 0 && imm <= HEX_THRESHOLD) | 
| 662 | 1.00k |           SStream_concat(O, "$%u", imm); | 
| 663 | 12.4k |         else { | 
| 664 | 12.4k |           imm = arch_masks[opsize? opsize : MI->imm_size] & imm; | 
| 665 | 12.4k |           SStream_concat(O, "$0x%"PRIx64, imm); | 
| 666 | 12.4k |         } | 
| 667 | 13.4k |         break; | 
| 668 |  |  | 
| 669 | 5.79k |       case X86_INS_RET: | 
| 670 | 7.24k |       case X86_INS_RETF: | 
| 671 |  |         // RET imm16 | 
| 672 | 7.24k |         if (imm >= 0 && imm <= HEX_THRESHOLD) | 
| 673 | 450 |           SStream_concat(O, "$%u", imm); | 
| 674 | 6.79k |         else { | 
| 675 | 6.79k |           imm = 0xffff & imm; | 
| 676 | 6.79k |           SStream_concat(O, "$0x%x", imm); | 
| 677 | 6.79k |         } | 
| 678 | 7.24k |         break; | 
| 679 | 58.6k |     } | 
| 680 |  |  | 
| 681 | 58.6k |     if (MI->csh->detail_opt) { | 
| 682 | 58.6k |       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 | 58.6k |       } else { | 
| 686 | 58.6k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; | 
| 687 | 58.6k |         MI->has_imm = true; | 
| 688 | 58.6k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm; | 
| 689 |  |  | 
| 690 | 58.6k |         if (opsize > 0) { | 
| 691 | 47.4k |           MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize; | 
| 692 | 47.4k |           MI->flat_insn->detail->x86.encoding.imm_size = encsize; | 
| 693 | 47.4k |         } 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 | 11.1k |         else | 
| 696 | 11.1k |           MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size; | 
| 697 |  |  | 
| 698 | 58.6k |         MI->flat_insn->detail->x86.op_count++; | 
| 699 | 58.6k |       } | 
| 700 | 58.6k |     } | 
| 701 | 58.6k |   } | 
| 702 | 517k | } | 
| 703 |  |  | 
| 704 |  | static void printMemReference(MCInst *MI, unsigned Op, SStream *O) | 
| 705 | 224k | { | 
| 706 | 224k |   MCOperand *BaseReg  = MCInst_getOperand(MI, Op + X86_AddrBaseReg); | 
| 707 | 224k |   MCOperand *IndexReg  = MCInst_getOperand(MI, Op + X86_AddrIndexReg); | 
| 708 | 224k |   MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp); | 
| 709 | 224k |   MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg); | 
| 710 | 224k |   uint64_t ScaleVal; | 
| 711 | 224k |   int segreg; | 
| 712 | 224k |   int64_t DispVal = 1; | 
| 713 |  |  | 
| 714 | 224k |   if (MI->csh->detail_opt) { | 
| 715 | 224k |     uint8_t access[6]; | 
| 716 |  |  | 
| 717 | 224k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM; | 
| 718 | 224k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize; | 
| 719 | 224k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID; | 
| 720 | 224k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_register_map(MCOperand_getReg(BaseReg)); | 
| 721 | 224k |         if (MCOperand_getReg(IndexReg) != X86_EIZ) { | 
| 722 | 224k |             MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_register_map(MCOperand_getReg(IndexReg)); | 
| 723 | 224k |         } | 
| 724 | 224k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1; | 
| 725 | 224k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0; | 
| 726 |  |  | 
| 727 | 224k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 728 | 224k |     MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count]; | 
| 729 | 224k |   } | 
| 730 |  |  | 
| 731 |  |   // If this has a segment register, print it. | 
| 732 | 224k |   segreg = MCOperand_getReg(SegReg); | 
| 733 | 224k |   if (segreg) { | 
| 734 | 5.92k |     _printOperand(MI, Op + X86_AddrSegmentReg, O); | 
| 735 | 5.92k |     SStream_concat0(O, ":"); | 
| 736 |  |  | 
| 737 | 5.92k |     if (MI->csh->detail_opt) { | 
| 738 | 5.92k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_register_map(segreg); | 
| 739 | 5.92k |     } | 
| 740 | 5.92k |   } | 
| 741 |  |  | 
| 742 | 224k |   if (MCOperand_isImm(DispSpec)) { | 
| 743 | 224k |     DispVal = MCOperand_getImm(DispSpec); | 
| 744 | 224k |     if (MI->csh->detail_opt) | 
| 745 | 224k |       MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal; | 
| 746 | 224k |     if (DispVal) { | 
| 747 | 73.1k |       if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) { | 
| 748 | 69.8k |         printInt64(O, DispVal); | 
| 749 | 69.8k |       } else { | 
| 750 |  |         // only immediate as address of memory | 
| 751 | 3.33k |         if (DispVal < 0) { | 
| 752 | 1.08k |           SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal); | 
| 753 | 2.24k |         } else { | 
| 754 | 2.24k |           if (DispVal > HEX_THRESHOLD) | 
| 755 | 1.97k |             SStream_concat(O, "0x%"PRIx64, DispVal); | 
| 756 | 274 |           else | 
| 757 | 274 |             SStream_concat(O, "%"PRIu64, DispVal); | 
| 758 | 2.24k |         } | 
| 759 | 3.33k |       } | 
| 760 | 73.1k |     } | 
| 761 | 224k |   } | 
| 762 |  |  | 
| 763 | 224k |   if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) { | 
| 764 | 221k |     SStream_concat0(O, "("); | 
| 765 |  |  | 
| 766 | 221k |     if (MCOperand_getReg(BaseReg)) | 
| 767 | 220k |       _printOperand(MI, Op + X86_AddrBaseReg, O); | 
| 768 |  |  | 
| 769 | 221k |         if (MCOperand_getReg(IndexReg) && MCOperand_getReg(IndexReg) != X86_EIZ) { | 
| 770 | 89.9k |       SStream_concat0(O, ", "); | 
| 771 | 89.9k |       _printOperand(MI, Op + X86_AddrIndexReg, O); | 
| 772 | 89.9k |       ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt)); | 
| 773 | 89.9k |       if (MI->csh->detail_opt) | 
| 774 | 89.9k |         MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal; | 
| 775 | 89.9k |       if (ScaleVal != 1) { | 
| 776 | 4.50k |         SStream_concat(O, ", %u", ScaleVal); | 
| 777 | 4.50k |       } | 
| 778 | 89.9k |     } | 
| 779 |  |  | 
| 780 | 221k |     SStream_concat0(O, ")"); | 
| 781 | 221k |   } else { | 
| 782 | 3.90k |     if (!DispVal) | 
| 783 | 575 |       SStream_concat0(O, "0"); | 
| 784 | 3.90k |   } | 
| 785 |  |  | 
| 786 | 224k |   if (MI->csh->detail_opt) | 
| 787 | 224k |     MI->flat_insn->detail->x86.op_count++; | 
| 788 | 224k | } | 
| 789 |  |  | 
| 790 |  | static void printanymem(MCInst *MI, unsigned OpNo, SStream *O) | 
| 791 | 5.77k | { | 
| 792 | 5.77k |   switch(MI->Opcode) { | 
| 793 | 125 |     default: break; | 
| 794 | 1.09k |     case X86_LEA16r: | 
| 795 | 1.09k |          MI->x86opsize = 2; | 
| 796 | 1.09k |          break; | 
| 797 | 423 |     case X86_LEA32r: | 
| 798 | 846 |     case X86_LEA64_32r: | 
| 799 | 846 |          MI->x86opsize = 4; | 
| 800 | 846 |          break; | 
| 801 | 414 |     case X86_LEA64r: | 
| 802 | 414 |          MI->x86opsize = 8; | 
| 803 | 414 |          break; | 
| 804 | 275 |     case X86_BNDCL32rm: | 
| 805 | 720 |     case X86_BNDCN32rm: | 
| 806 | 1.04k |     case X86_BNDCU32rm: | 
| 807 | 1.52k |     case X86_BNDSTXmr: | 
| 808 | 2.06k |     case X86_BNDLDXrm: | 
| 809 | 2.60k |     case X86_BNDCL64rm: | 
| 810 | 3.09k |     case X86_BNDCN64rm: | 
| 811 | 3.29k |     case X86_BNDCU64rm: | 
| 812 | 3.29k |          MI->x86opsize = 16; | 
| 813 | 3.29k |          break; | 
| 814 | 5.77k |   } | 
| 815 |  |  | 
| 816 | 5.77k |   printMemReference(MI, OpNo, O); | 
| 817 | 5.77k | } | 
| 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 | 775k | { | 
| 832 | 775k |   SStream_concat(OS, "%%%s", getRegisterName(RegNo)); | 
| 833 | 775k | } | 
| 834 |  |  | 
| 835 |  | void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info) | 
| 836 | 534k | { | 
| 837 | 534k |   x86_reg reg, reg2; | 
| 838 | 534k |   enum cs_ac_type access1, access2; | 
| 839 | 534k |   int i; | 
| 840 |  |  | 
| 841 |  |   // perhaps this instruction does not need printer | 
| 842 | 534k |   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 | 534k |   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 | 534k |   X86_lockrep(MI, OS); | 
| 861 | 534k |   printInstruction(MI, OS); | 
| 862 |  |  | 
| 863 | 534k |   if (MI->has_imm) { | 
| 864 |  |     // if op_count > 1, then this operand's size is taken from the destination op | 
| 865 | 91.6k |     if (MI->flat_insn->detail->x86.op_count > 1) { | 
| 866 | 47.0k |       if (MI->flat_insn->id != X86_INS_LCALL && MI->flat_insn->id != X86_INS_LJMP && MI->flat_insn->id != X86_INS_JMP) { | 
| 867 | 140k |         for (i = 0; i < MI->flat_insn->detail->x86.op_count; i++) { | 
| 868 | 94.9k |           if (MI->flat_insn->detail->x86.operands[i].type == X86_OP_IMM) | 
| 869 | 46.8k |             MI->flat_insn->detail->x86.operands[i].size = | 
| 870 | 46.8k |               MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count - 1].size; | 
| 871 | 94.9k |         } | 
| 872 | 45.9k |       } | 
| 873 | 47.0k |     } else | 
| 874 | 44.6k |       MI->flat_insn->detail->x86.operands[0].size = MI->imm_size; | 
| 875 | 91.6k |   } | 
| 876 |  |  | 
| 877 | 534k |   if (MI->csh->detail_opt) { | 
| 878 | 534k |     uint8_t access[6] = {0}; | 
| 879 |  |  | 
| 880 |  |     // some instructions need to supply immediate 1 in the first op | 
| 881 | 534k |     switch(MCInst_getOpcode(MI)) { | 
| 882 | 499k |       default: | 
| 883 | 499k |         break; | 
| 884 | 499k |       case X86_SHL8r1: | 
| 885 | 545 |       case X86_SHL16r1: | 
| 886 | 1.13k |       case X86_SHL32r1: | 
| 887 | 1.57k |       case X86_SHL64r1: | 
| 888 | 1.98k |       case X86_SAL8r1: | 
| 889 | 2.36k |       case X86_SAL16r1: | 
| 890 | 3.16k |       case X86_SAL32r1: | 
| 891 | 3.78k |       case X86_SAL64r1: | 
| 892 | 4.06k |       case X86_SHR8r1: | 
| 893 | 4.77k |       case X86_SHR16r1: | 
| 894 | 5.46k |       case X86_SHR32r1: | 
| 895 | 5.94k |       case X86_SHR64r1: | 
| 896 | 6.53k |       case X86_SAR8r1: | 
| 897 | 7.34k |       case X86_SAR16r1: | 
| 898 | 7.96k |       case X86_SAR32r1: | 
| 899 | 8.54k |       case X86_SAR64r1: | 
| 900 | 10.3k |       case X86_RCL8r1: | 
| 901 | 11.6k |       case X86_RCL16r1: | 
| 902 | 12.8k |       case X86_RCL32r1: | 
| 903 | 13.8k |       case X86_RCL64r1: | 
| 904 | 14.0k |       case X86_RCR8r1: | 
| 905 | 14.3k |       case X86_RCR16r1: | 
| 906 | 14.9k |       case X86_RCR32r1: | 
| 907 | 15.2k |       case X86_RCR64r1: | 
| 908 | 15.5k |       case X86_ROL8r1: | 
| 909 | 15.9k |       case X86_ROL16r1: | 
| 910 | 16.9k |       case X86_ROL32r1: | 
| 911 | 18.2k |       case X86_ROL64r1: | 
| 912 | 18.5k |       case X86_ROR8r1: | 
| 913 | 18.9k |       case X86_ROR16r1: | 
| 914 | 19.4k |       case X86_ROR32r1: | 
| 915 | 19.7k |       case X86_ROR64r1: | 
| 916 | 20.0k |       case X86_SHL8m1: | 
| 917 | 20.8k |       case X86_SHL16m1: | 
| 918 | 21.9k |       case X86_SHL32m1: | 
| 919 | 22.4k |       case X86_SHL64m1: | 
| 920 | 22.8k |       case X86_SAL8m1: | 
| 921 | 23.2k |       case X86_SAL16m1: | 
| 922 | 23.7k |       case X86_SAL32m1: | 
| 923 | 24.0k |       case X86_SAL64m1: | 
| 924 | 24.3k |       case X86_SHR8m1: | 
| 925 | 25.1k |       case X86_SHR16m1: | 
| 926 | 25.7k |       case X86_SHR32m1: | 
| 927 | 26.1k |       case X86_SHR64m1: | 
| 928 | 26.6k |       case X86_SAR8m1: | 
| 929 | 27.0k |       case X86_SAR16m1: | 
| 930 | 27.6k |       case X86_SAR32m1: | 
| 931 | 27.9k |       case X86_SAR64m1: | 
| 932 | 28.2k |       case X86_RCL8m1: | 
| 933 | 28.5k |       case X86_RCL16m1: | 
| 934 | 29.2k |       case X86_RCL32m1: | 
| 935 | 29.6k |       case X86_RCL64m1: | 
| 936 | 29.9k |       case X86_RCR8m1: | 
| 937 | 30.4k |       case X86_RCR16m1: | 
| 938 | 31.0k |       case X86_RCR32m1: | 
| 939 | 31.1k |       case X86_RCR64m1: | 
| 940 | 31.6k |       case X86_ROL8m1: | 
| 941 | 32.1k |       case X86_ROL16m1: | 
| 942 | 32.8k |       case X86_ROL32m1: | 
| 943 | 33.4k |       case X86_ROL64m1: | 
| 944 | 33.8k |       case X86_ROR8m1: | 
| 945 | 34.3k |       case X86_ROR16m1: | 
| 946 | 35.3k |       case X86_ROR32m1: | 
| 947 | 35.9k |       case X86_ROR64m1: | 
| 948 |  |         // shift all the ops right to leave 1st slot for this new register op | 
| 949 | 35.9k |         memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]), | 
| 950 | 35.9k |             sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1)); | 
| 951 | 35.9k |         MI->flat_insn->detail->x86.operands[0].type = X86_OP_IMM; | 
| 952 | 35.9k |         MI->flat_insn->detail->x86.operands[0].imm = 1; | 
| 953 | 35.9k |         MI->flat_insn->detail->x86.operands[0].size = 1; | 
| 954 | 35.9k |         MI->flat_insn->detail->x86.op_count++; | 
| 955 | 534k |     } | 
| 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 | 534k |     reg = X86_insn_reg_att(MCInst_getOpcode(MI), &access1); | 
| 964 | 534k |     if (reg) { | 
| 965 |  |       // shift all the ops right to leave 1st slot for this new register op | 
| 966 | 29.9k |       memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]), | 
| 967 | 29.9k |           sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1)); | 
| 968 | 29.9k |       MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG; | 
| 969 | 29.9k |       MI->flat_insn->detail->x86.operands[0].reg = reg; | 
| 970 | 29.9k |       MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg]; | 
| 971 | 29.9k |       MI->flat_insn->detail->x86.operands[0].access = access1; | 
| 972 |  |  | 
| 973 | 29.9k |       MI->flat_insn->detail->x86.op_count++; | 
| 974 | 504k |     } else { | 
| 975 | 504k |       if (X86_insn_reg_att2(MCInst_getOpcode(MI), ®, &access1, ®2, &access2)) { | 
| 976 |  |  | 
| 977 | 8.64k |         MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG; | 
| 978 | 8.64k |         MI->flat_insn->detail->x86.operands[0].reg = reg; | 
| 979 | 8.64k |         MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg]; | 
| 980 | 8.64k |         MI->flat_insn->detail->x86.operands[0].access = access1; | 
| 981 | 8.64k |         MI->flat_insn->detail->x86.operands[1].type = X86_OP_REG; | 
| 982 | 8.64k |         MI->flat_insn->detail->x86.operands[1].reg = reg2; | 
| 983 | 8.64k |         MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg2]; | 
| 984 | 8.64k |         MI->flat_insn->detail->x86.operands[0].access = access2; | 
| 985 | 8.64k |         MI->flat_insn->detail->x86.op_count = 2; | 
| 986 | 8.64k |       } | 
| 987 | 504k |     } | 
| 988 |  |  | 
| 989 | 534k | #ifndef CAPSTONE_DIET | 
| 990 | 534k |     get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags); | 
| 991 | 534k |     MI->flat_insn->detail->x86.operands[0].access = access[0]; | 
| 992 | 534k |     MI->flat_insn->detail->x86.operands[1].access = access[1]; | 
| 993 | 534k | #endif | 
| 994 | 534k |   } | 
| 995 | 534k | } | 
| 996 |  |  | 
| 997 |  | #endif |