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