1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "disassembler_x86.h" 18 19 #include <inttypes.h> 20 21 #include <ostream> 22 #include <sstream> 23 24 #include "base/logging.h" 25 #include "base/stringprintf.h" 26 #include "thread.h" 27 28 namespace art { 29 namespace x86 { 30 31 size_t DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin) { 32 return DumpInstruction(os, begin); 33 } 34 35 void DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) { 36 size_t length = 0; 37 for (const uint8_t* cur = begin; cur < end; cur += length) { 38 length = DumpInstruction(os, cur); 39 } 40 } 41 42 static const char* gReg8Names[] = { 43 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" 44 }; 45 static const char* gExtReg8Names[] = { 46 "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", 47 "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l" 48 }; 49 static const char* gReg16Names[] = { 50 "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", 51 "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" 52 }; 53 static const char* gReg32Names[] = { 54 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", 55 "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" 56 }; 57 static const char* gReg64Names[] = { 58 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 59 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 60 }; 61 62 // 64-bit opcode REX modifier. 63 constexpr uint8_t REX_W = 8U /* 0b1000 */; 64 constexpr uint8_t REX_R = 4U /* 0b0100 */; 65 constexpr uint8_t REX_X = 2U /* 0b0010 */; 66 constexpr uint8_t REX_B = 1U /* 0b0001 */; 67 68 static void DumpReg0(std::ostream& os, uint8_t rex, size_t reg, 69 bool byte_operand, uint8_t size_override) { 70 DCHECK_LT(reg, (rex == 0) ? 8u : 16u); 71 bool rex_w = (rex & REX_W) != 0; 72 if (byte_operand) { 73 os << ((rex == 0) ? gReg8Names[reg] : gExtReg8Names[reg]); 74 } else if (rex_w) { 75 os << gReg64Names[reg]; 76 } else if (size_override == 0x66) { 77 os << gReg16Names[reg]; 78 } else { 79 os << gReg32Names[reg]; 80 } 81 } 82 83 static void DumpAnyReg(std::ostream& os, uint8_t rex, size_t reg, 84 bool byte_operand, uint8_t size_override, RegFile reg_file) { 85 if (reg_file == GPR) { 86 DumpReg0(os, rex, reg, byte_operand, size_override); 87 } else if (reg_file == SSE) { 88 os << "xmm" << reg; 89 } else { 90 os << "mm" << reg; 91 } 92 } 93 94 static void DumpReg(std::ostream& os, uint8_t rex, uint8_t reg, 95 bool byte_operand, uint8_t size_override, RegFile reg_file) { 96 bool rex_r = (rex & REX_R) != 0; 97 size_t reg_num = rex_r ? (reg + 8) : reg; 98 DumpAnyReg(os, rex, reg_num, byte_operand, size_override, reg_file); 99 } 100 101 static void DumpRmReg(std::ostream& os, uint8_t rex, uint8_t reg, 102 bool byte_operand, uint8_t size_override, RegFile reg_file) { 103 bool rex_b = (rex & REX_B) != 0; 104 size_t reg_num = rex_b ? (reg + 8) : reg; 105 DumpAnyReg(os, rex, reg_num, byte_operand, size_override, reg_file); 106 } 107 108 static void DumpAddrReg(std::ostream& os, uint8_t rex, uint8_t reg) { 109 if (rex != 0) { 110 os << gReg64Names[reg]; 111 } else { 112 os << gReg32Names[reg]; 113 } 114 } 115 116 static void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg) { 117 bool rex_b = (rex & REX_B) != 0; 118 size_t reg_num = rex_b ? (reg + 8) : reg; 119 DumpAddrReg(os, rex, reg_num); 120 } 121 122 static void DumpOpcodeReg(std::ostream& os, uint8_t rex, uint8_t reg, 123 bool byte_operand, uint8_t size_override) { 124 bool rex_b = (rex & REX_B) != 0; 125 size_t reg_num = rex_b ? (reg + 8) : reg; 126 DumpReg0(os, rex, reg_num, byte_operand, size_override); 127 } 128 129 enum SegmentPrefix { 130 kCs = 0x2e, 131 kSs = 0x36, 132 kDs = 0x3e, 133 kEs = 0x26, 134 kFs = 0x64, 135 kGs = 0x65, 136 }; 137 138 static void DumpSegmentOverride(std::ostream& os, uint8_t segment_prefix) { 139 switch (segment_prefix) { 140 case kCs: os << "cs:"; break; 141 case kSs: os << "ss:"; break; 142 case kDs: os << "ds:"; break; 143 case kEs: os << "es:"; break; 144 case kFs: os << "fs:"; break; 145 case kGs: os << "gs:"; break; 146 default: break; 147 } 148 } 149 150 // Do not inline to avoid Clang stack frame problems. b/18733806 151 NO_INLINE 152 static std::string DumpCodeHex(const uint8_t* begin, const uint8_t* end) { 153 std::stringstream hex; 154 for (size_t i = 0; begin + i < end; ++i) { 155 hex << StringPrintf("%02X", begin[i]); 156 } 157 return hex.str(); 158 } 159 160 std::string DisassemblerX86::DumpAddress(uint8_t mod, uint8_t rm, uint8_t rex64, uint8_t rex_w, 161 bool no_ops, bool byte_operand, bool byte_second_operand, 162 uint8_t* prefix, bool load, RegFile src_reg_file, 163 RegFile dst_reg_file, const uint8_t** instr, 164 uint32_t* address_bits) { 165 std::ostringstream address; 166 if (mod == 0 && rm == 5) { 167 if (!supports_rex_) { // Absolute address. 168 *address_bits = *reinterpret_cast<const uint32_t*>(*instr); 169 address << StringPrintf("[0x%x]", *address_bits); 170 } else { // 64-bit RIP relative addressing. 171 address << StringPrintf("[RIP + 0x%x]", *reinterpret_cast<const uint32_t*>(*instr)); 172 } 173 (*instr) += 4; 174 } else if (rm == 4 && mod != 3) { // SIB 175 uint8_t sib = **instr; 176 (*instr)++; 177 uint8_t scale = (sib >> 6) & 3; 178 uint8_t index = (sib >> 3) & 7; 179 uint8_t base = sib & 7; 180 address << "["; 181 182 // REX.x is bit 3 of index. 183 if ((rex64 & REX_X) != 0) { 184 index += 8; 185 } 186 187 // Mod = 0 && base = 5 (ebp): no base (ignores REX.b). 188 bool has_base = false; 189 if (base != 5 || mod != 0) { 190 has_base = true; 191 DumpBaseReg(address, rex64, base); 192 } 193 194 // Index = 4 (esp/rsp) is disallowed. 195 if (index != 4) { 196 if (has_base) { 197 address << " + "; 198 } 199 DumpAddrReg(address, rex64, index); 200 if (scale != 0) { 201 address << StringPrintf(" * %d", 1 << scale); 202 } 203 } 204 205 if (mod == 0) { 206 if (base == 5) { 207 if (index != 4) { 208 address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr)); 209 } else { 210 // 64-bit low 32-bit absolute address, redundant absolute address encoding on 32-bit. 211 *address_bits = *reinterpret_cast<const uint32_t*>(*instr); 212 address << StringPrintf("%d", *address_bits); 213 } 214 (*instr) += 4; 215 } 216 } else if (mod == 1) { 217 address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(*instr)); 218 (*instr)++; 219 } else if (mod == 2) { 220 address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr)); 221 (*instr) += 4; 222 } 223 address << "]"; 224 } else { 225 if (mod == 3) { 226 if (!no_ops) { 227 DumpRmReg(address, rex_w, rm, byte_operand || byte_second_operand, 228 prefix[2], load ? src_reg_file : dst_reg_file); 229 } 230 } else { 231 address << "["; 232 DumpBaseReg(address, rex64, rm); 233 if (mod == 1) { 234 address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(*instr)); 235 (*instr)++; 236 } else if (mod == 2) { 237 address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr)); 238 (*instr) += 4; 239 } 240 address << "]"; 241 } 242 } 243 return address.str(); 244 } 245 246 size_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) { 247 const uint8_t* begin_instr = instr; 248 bool have_prefixes = true; 249 uint8_t prefix[4] = {0, 0, 0, 0}; 250 do { 251 switch (*instr) { 252 // Group 1 - lock and repeat prefixes: 253 case 0xF0: 254 case 0xF2: 255 case 0xF3: 256 prefix[0] = *instr; 257 break; 258 // Group 2 - segment override prefixes: 259 case kCs: 260 case kSs: 261 case kDs: 262 case kEs: 263 case kFs: 264 case kGs: 265 prefix[1] = *instr; 266 break; 267 // Group 3 - operand size override: 268 case 0x66: 269 prefix[2] = *instr; 270 break; 271 // Group 4 - address size override: 272 case 0x67: 273 prefix[3] = *instr; 274 break; 275 default: 276 have_prefixes = false; 277 break; 278 } 279 if (have_prefixes) { 280 instr++; 281 } 282 } while (have_prefixes); 283 uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0; 284 if (rex != 0) { 285 instr++; 286 } 287 const char** modrm_opcodes = nullptr; 288 bool has_modrm = false; 289 bool reg_is_opcode = false; 290 size_t immediate_bytes = 0; 291 size_t branch_bytes = 0; 292 std::string opcode_tmp; // Storage to keep StringPrintf result alive. 293 const char* opcode0 = ""; // Prefix part. 294 const char* opcode1 = ""; // Main opcode. 295 const char* opcode2 = ""; // Sub-opcode. E.g., jump type. 296 const char* opcode3 = ""; // Mod-rm part. 297 const char* opcode4 = ""; // Suffix part. 298 bool store = false; // stores to memory (ie rm is on the left) 299 bool load = false; // loads from memory (ie rm is on the right) 300 bool byte_operand = false; // true when the opcode is dealing with byte operands 301 // true when the source operand is a byte register but the target register isn't 302 // (ie movsxb/movzxb). 303 bool byte_second_operand = false; 304 bool target_specific = false; // register name depends on target (64 vs 32 bits). 305 bool ax = false; // implicit use of ax 306 bool cx = false; // implicit use of cx 307 bool reg_in_opcode = false; // low 3-bits of opcode encode register parameter 308 bool no_ops = false; 309 RegFile src_reg_file = GPR; 310 RegFile dst_reg_file = GPR; 311 switch (*instr) { 312 #define DISASSEMBLER_ENTRY(opname, \ 313 rm8_r8, rm32_r32, \ 314 r8_rm8, r32_rm32, \ 315 ax8_i8, ax32_i32) \ 316 case rm8_r8: opcode1 = #opname; store = true; has_modrm = true; byte_operand = true; break; \ 317 case rm32_r32: opcode1 = #opname; store = true; has_modrm = true; break; \ 318 case r8_rm8: opcode1 = #opname; load = true; has_modrm = true; byte_operand = true; break; \ 319 case r32_rm32: opcode1 = #opname; load = true; has_modrm = true; break; \ 320 case ax8_i8: opcode1 = #opname; ax = true; immediate_bytes = 1; byte_operand = true; break; \ 321 case ax32_i32: opcode1 = #opname; ax = true; immediate_bytes = 4; break; 322 323 DISASSEMBLER_ENTRY(add, 324 0x00 /* RegMem8/Reg8 */, 0x01 /* RegMem32/Reg32 */, 325 0x02 /* Reg8/RegMem8 */, 0x03 /* Reg32/RegMem32 */, 326 0x04 /* Rax8/imm8 opcode */, 0x05 /* Rax32/imm32 */) 327 DISASSEMBLER_ENTRY(or, 328 0x08 /* RegMem8/Reg8 */, 0x09 /* RegMem32/Reg32 */, 329 0x0A /* Reg8/RegMem8 */, 0x0B /* Reg32/RegMem32 */, 330 0x0C /* Rax8/imm8 opcode */, 0x0D /* Rax32/imm32 */) 331 DISASSEMBLER_ENTRY(adc, 332 0x10 /* RegMem8/Reg8 */, 0x11 /* RegMem32/Reg32 */, 333 0x12 /* Reg8/RegMem8 */, 0x13 /* Reg32/RegMem32 */, 334 0x14 /* Rax8/imm8 opcode */, 0x15 /* Rax32/imm32 */) 335 DISASSEMBLER_ENTRY(sbb, 336 0x18 /* RegMem8/Reg8 */, 0x19 /* RegMem32/Reg32 */, 337 0x1A /* Reg8/RegMem8 */, 0x1B /* Reg32/RegMem32 */, 338 0x1C /* Rax8/imm8 opcode */, 0x1D /* Rax32/imm32 */) 339 DISASSEMBLER_ENTRY(and, 340 0x20 /* RegMem8/Reg8 */, 0x21 /* RegMem32/Reg32 */, 341 0x22 /* Reg8/RegMem8 */, 0x23 /* Reg32/RegMem32 */, 342 0x24 /* Rax8/imm8 opcode */, 0x25 /* Rax32/imm32 */) 343 DISASSEMBLER_ENTRY(sub, 344 0x28 /* RegMem8/Reg8 */, 0x29 /* RegMem32/Reg32 */, 345 0x2A /* Reg8/RegMem8 */, 0x2B /* Reg32/RegMem32 */, 346 0x2C /* Rax8/imm8 opcode */, 0x2D /* Rax32/imm32 */) 347 DISASSEMBLER_ENTRY(xor, 348 0x30 /* RegMem8/Reg8 */, 0x31 /* RegMem32/Reg32 */, 349 0x32 /* Reg8/RegMem8 */, 0x33 /* Reg32/RegMem32 */, 350 0x34 /* Rax8/imm8 opcode */, 0x35 /* Rax32/imm32 */) 351 DISASSEMBLER_ENTRY(cmp, 352 0x38 /* RegMem8/Reg8 */, 0x39 /* RegMem32/Reg32 */, 353 0x3A /* Reg8/RegMem8 */, 0x3B /* Reg32/RegMem32 */, 354 0x3C /* Rax8/imm8 opcode */, 0x3D /* Rax32/imm32 */) 355 356 #undef DISASSEMBLER_ENTRY 357 case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: 358 opcode1 = "push"; 359 reg_in_opcode = true; 360 target_specific = true; 361 break; 362 case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: 363 opcode1 = "pop"; 364 reg_in_opcode = true; 365 target_specific = true; 366 break; 367 case 0x63: 368 if ((rex & REX_W) != 0) { 369 opcode1 = "movsxd"; 370 has_modrm = true; 371 load = true; 372 } else { 373 // In 32-bit mode (!supports_rex_) this is ARPL, with no REX prefix the functionality is the 374 // same as 'mov' but the use of the instruction is discouraged. 375 opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr); 376 opcode1 = opcode_tmp.c_str(); 377 } 378 break; 379 case 0x68: opcode1 = "push"; immediate_bytes = 4; break; 380 case 0x69: opcode1 = "imul"; load = true; has_modrm = true; immediate_bytes = 4; break; 381 case 0x6A: opcode1 = "push"; immediate_bytes = 1; break; 382 case 0x6B: opcode1 = "imul"; load = true; has_modrm = true; immediate_bytes = 1; break; 383 case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: 384 case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: 385 static const char* condition_codes[] = 386 {"o", "no", "b/nae/c", "nb/ae/nc", "z/eq", "nz/ne", "be/na", "nbe/a", 387 "s", "ns", "p/pe", "np/po", "l/nge", "nl/ge", "le/ng", "nle/g" 388 }; 389 opcode1 = "j"; 390 opcode2 = condition_codes[*instr & 0xF]; 391 branch_bytes = 1; 392 break; 393 case 0x86: case 0x87: 394 opcode1 = "xchg"; 395 store = true; 396 has_modrm = true; 397 byte_operand = (*instr == 0x86); 398 break; 399 case 0x88: opcode1 = "mov"; store = true; has_modrm = true; byte_operand = true; break; 400 case 0x89: opcode1 = "mov"; store = true; has_modrm = true; break; 401 case 0x8A: opcode1 = "mov"; load = true; has_modrm = true; byte_operand = true; break; 402 case 0x8B: opcode1 = "mov"; load = true; has_modrm = true; break; 403 404 case 0x0F: // 2 byte extended opcode 405 instr++; 406 switch (*instr) { 407 case 0x10: case 0x11: 408 if (prefix[0] == 0xF2) { 409 opcode1 = "movsd"; 410 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 411 } else if (prefix[0] == 0xF3) { 412 opcode1 = "movss"; 413 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 414 } else if (prefix[2] == 0x66) { 415 opcode1 = "movupd"; 416 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 417 } else { 418 opcode1 = "movups"; 419 } 420 has_modrm = true; 421 src_reg_file = dst_reg_file = SSE; 422 load = *instr == 0x10; 423 store = !load; 424 break; 425 case 0x12: case 0x13: 426 if (prefix[2] == 0x66) { 427 opcode1 = "movlpd"; 428 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 429 } else if (prefix[0] == 0) { 430 opcode1 = "movlps"; 431 } 432 has_modrm = true; 433 src_reg_file = dst_reg_file = SSE; 434 load = *instr == 0x12; 435 store = !load; 436 break; 437 case 0x16: case 0x17: 438 if (prefix[2] == 0x66) { 439 opcode1 = "movhpd"; 440 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 441 } else if (prefix[0] == 0) { 442 opcode1 = "movhps"; 443 } 444 has_modrm = true; 445 src_reg_file = dst_reg_file = SSE; 446 load = *instr == 0x16; 447 store = !load; 448 break; 449 case 0x28: case 0x29: 450 if (prefix[2] == 0x66) { 451 opcode1 = "movapd"; 452 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 453 } else if (prefix[0] == 0) { 454 opcode1 = "movaps"; 455 } 456 has_modrm = true; 457 src_reg_file = dst_reg_file = SSE; 458 load = *instr == 0x28; 459 store = !load; 460 break; 461 case 0x2A: 462 if (prefix[2] == 0x66) { 463 opcode1 = "cvtpi2pd"; 464 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 465 } else if (prefix[0] == 0xF2) { 466 opcode1 = "cvtsi2sd"; 467 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 468 } else if (prefix[0] == 0xF3) { 469 opcode1 = "cvtsi2ss"; 470 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 471 } else { 472 opcode1 = "cvtpi2ps"; 473 } 474 load = true; 475 has_modrm = true; 476 dst_reg_file = SSE; 477 break; 478 case 0x2C: 479 if (prefix[2] == 0x66) { 480 opcode1 = "cvttpd2pi"; 481 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 482 } else if (prefix[0] == 0xF2) { 483 opcode1 = "cvttsd2si"; 484 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 485 } else if (prefix[0] == 0xF3) { 486 opcode1 = "cvttss2si"; 487 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 488 } else { 489 opcode1 = "cvttps2pi"; 490 } 491 load = true; 492 has_modrm = true; 493 src_reg_file = SSE; 494 break; 495 case 0x2D: 496 if (prefix[2] == 0x66) { 497 opcode1 = "cvtpd2pi"; 498 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 499 } else if (prefix[0] == 0xF2) { 500 opcode1 = "cvtsd2si"; 501 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 502 } else if (prefix[0] == 0xF3) { 503 opcode1 = "cvtss2si"; 504 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 505 } else { 506 opcode1 = "cvtps2pi"; 507 } 508 load = true; 509 has_modrm = true; 510 src_reg_file = SSE; 511 break; 512 case 0x2E: 513 opcode0 = "u"; 514 FALLTHROUGH_INTENDED; 515 case 0x2F: 516 if (prefix[2] == 0x66) { 517 opcode1 = "comisd"; 518 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 519 } else { 520 opcode1 = "comiss"; 521 } 522 has_modrm = true; 523 load = true; 524 src_reg_file = dst_reg_file = SSE; 525 break; 526 case 0x38: // 3 byte extended opcode 527 instr++; 528 if (prefix[2] == 0x66) { 529 switch (*instr) { 530 case 0x01: 531 opcode1 = "phaddw"; 532 prefix[2] = 0; 533 has_modrm = true; 534 load = true; 535 src_reg_file = dst_reg_file = SSE; 536 break; 537 case 0x02: 538 opcode1 = "phaddd"; 539 prefix[2] = 0; 540 has_modrm = true; 541 load = true; 542 src_reg_file = dst_reg_file = SSE; 543 break; 544 case 0x40: 545 opcode1 = "pmulld"; 546 prefix[2] = 0; 547 has_modrm = true; 548 load = true; 549 src_reg_file = dst_reg_file = SSE; 550 break; 551 default: 552 opcode_tmp = StringPrintf("unknown opcode '0F 38 %02X'", *instr); 553 opcode1 = opcode_tmp.c_str(); 554 } 555 } else { 556 opcode_tmp = StringPrintf("unknown opcode '0F 38 %02X'", *instr); 557 opcode1 = opcode_tmp.c_str(); 558 } 559 break; 560 case 0x3A: // 3 byte extended opcode 561 instr++; 562 if (prefix[2] == 0x66) { 563 switch (*instr) { 564 case 0x0A: 565 opcode1 = "roundss"; 566 prefix[2] = 0; 567 has_modrm = true; 568 store = true; 569 src_reg_file = SSE; 570 dst_reg_file = SSE; 571 immediate_bytes = 1; 572 break; 573 case 0x0B: 574 opcode1 = "roundsd"; 575 prefix[2] = 0; 576 has_modrm = true; 577 store = true; 578 src_reg_file = SSE; 579 dst_reg_file = SSE; 580 immediate_bytes = 1; 581 break; 582 case 0x14: 583 opcode1 = "pextrb"; 584 prefix[2] = 0; 585 has_modrm = true; 586 store = true; 587 src_reg_file = SSE; 588 immediate_bytes = 1; 589 break; 590 case 0x15: 591 opcode1 = "pextrw"; 592 prefix[2] = 0; 593 has_modrm = true; 594 store = true; 595 src_reg_file = SSE; 596 immediate_bytes = 1; 597 break; 598 case 0x16: 599 opcode1 = "pextrd"; 600 prefix[2] = 0; 601 has_modrm = true; 602 store = true; 603 src_reg_file = SSE; 604 immediate_bytes = 1; 605 break; 606 default: 607 opcode_tmp = StringPrintf("unknown opcode '0F 3A %02X'", *instr); 608 opcode1 = opcode_tmp.c_str(); 609 } 610 } else { 611 opcode_tmp = StringPrintf("unknown opcode '0F 3A %02X'", *instr); 612 opcode1 = opcode_tmp.c_str(); 613 } 614 break; 615 case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: 616 case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F: 617 opcode1 = "cmov"; 618 opcode2 = condition_codes[*instr & 0xF]; 619 has_modrm = true; 620 load = true; 621 break; 622 case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: 623 case 0x58: case 0x59: case 0x5C: case 0x5D: case 0x5E: case 0x5F: { 624 switch (*instr) { 625 case 0x50: opcode1 = "movmsk"; break; 626 case 0x51: opcode1 = "sqrt"; break; 627 case 0x52: opcode1 = "rsqrt"; break; 628 case 0x53: opcode1 = "rcp"; break; 629 case 0x54: opcode1 = "and"; break; 630 case 0x55: opcode1 = "andn"; break; 631 case 0x56: opcode1 = "or"; break; 632 case 0x57: opcode1 = "xor"; break; 633 case 0x58: opcode1 = "add"; break; 634 case 0x59: opcode1 = "mul"; break; 635 case 0x5C: opcode1 = "sub"; break; 636 case 0x5D: opcode1 = "min"; break; 637 case 0x5E: opcode1 = "div"; break; 638 case 0x5F: opcode1 = "max"; break; 639 default: LOG(FATAL) << "Unreachable"; UNREACHABLE(); 640 } 641 if (prefix[2] == 0x66) { 642 opcode2 = "pd"; 643 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 644 } else if (prefix[0] == 0xF2) { 645 opcode2 = "sd"; 646 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 647 } else if (prefix[0] == 0xF3) { 648 opcode2 = "ss"; 649 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 650 } else { 651 opcode2 = "ps"; 652 } 653 load = true; 654 has_modrm = true; 655 src_reg_file = dst_reg_file = SSE; 656 break; 657 } 658 case 0x5A: 659 if (prefix[2] == 0x66) { 660 opcode1 = "cvtpd2ps"; 661 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 662 } else if (prefix[0] == 0xF2) { 663 opcode1 = "cvtsd2ss"; 664 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 665 } else if (prefix[0] == 0xF3) { 666 opcode1 = "cvtss2sd"; 667 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 668 } else { 669 opcode1 = "cvtps2pd"; 670 } 671 load = true; 672 has_modrm = true; 673 src_reg_file = dst_reg_file = SSE; 674 break; 675 case 0x5B: 676 if (prefix[2] == 0x66) { 677 opcode1 = "cvtps2dq"; 678 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 679 } else if (prefix[0] == 0xF2) { 680 opcode1 = "bad opcode F2 0F 5B"; 681 } else if (prefix[0] == 0xF3) { 682 opcode1 = "cvttps2dq"; 683 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 684 } else { 685 opcode1 = "cvtdq2ps"; 686 } 687 load = true; 688 has_modrm = true; 689 src_reg_file = dst_reg_file = SSE; 690 break; 691 case 0x60: case 0x61: case 0x62: case 0x6C: 692 if (prefix[2] == 0x66) { 693 src_reg_file = dst_reg_file = SSE; 694 prefix[2] = 0; // Clear prefix now. It has served its purpose as part of the opcode. 695 } else { 696 src_reg_file = dst_reg_file = MMX; 697 } 698 switch (*instr) { 699 case 0x60: opcode1 = "punpcklbw"; break; 700 case 0x61: opcode1 = "punpcklwd"; break; 701 case 0x62: opcode1 = "punpckldq"; break; 702 case 0x6c: opcode1 = "punpcklqdq"; break; 703 } 704 load = true; 705 has_modrm = true; 706 break; 707 case 0x6E: 708 if (prefix[2] == 0x66) { 709 dst_reg_file = SSE; 710 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 711 } else { 712 dst_reg_file = MMX; 713 } 714 opcode1 = "movd"; 715 load = true; 716 has_modrm = true; 717 break; 718 case 0x6F: 719 if (prefix[2] == 0x66) { 720 src_reg_file = dst_reg_file = SSE; 721 opcode1 = "movdqa"; 722 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 723 } else if (prefix[0] == 0xF3) { 724 src_reg_file = dst_reg_file = SSE; 725 opcode1 = "movdqu"; 726 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 727 } else { 728 dst_reg_file = MMX; 729 opcode1 = "movq"; 730 } 731 load = true; 732 has_modrm = true; 733 break; 734 case 0x70: 735 if (prefix[2] == 0x66) { 736 opcode1 = "pshufd"; 737 prefix[2] = 0; 738 has_modrm = true; 739 store = true; 740 src_reg_file = dst_reg_file = SSE; 741 immediate_bytes = 1; 742 } else if (prefix[0] == 0xF2) { 743 opcode1 = "pshuflw"; 744 prefix[0] = 0; 745 has_modrm = true; 746 store = true; 747 src_reg_file = dst_reg_file = SSE; 748 immediate_bytes = 1; 749 } else { 750 opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 751 opcode1 = opcode_tmp.c_str(); 752 } 753 break; 754 case 0x71: 755 if (prefix[2] == 0x66) { 756 dst_reg_file = SSE; 757 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 758 } else { 759 dst_reg_file = MMX; 760 } 761 static const char* x71_opcodes[] = { 762 "unknown-71", "unknown-71", "psrlw", "unknown-71", 763 "psraw", "unknown-71", "psllw", "unknown-71"}; 764 modrm_opcodes = x71_opcodes; 765 reg_is_opcode = true; 766 has_modrm = true; 767 store = true; 768 immediate_bytes = 1; 769 break; 770 case 0x72: 771 if (prefix[2] == 0x66) { 772 dst_reg_file = SSE; 773 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 774 } else { 775 dst_reg_file = MMX; 776 } 777 static const char* x72_opcodes[] = { 778 "unknown-72", "unknown-72", "psrld", "unknown-72", 779 "psrad", "unknown-72", "pslld", "unknown-72"}; 780 modrm_opcodes = x72_opcodes; 781 reg_is_opcode = true; 782 has_modrm = true; 783 store = true; 784 immediate_bytes = 1; 785 break; 786 case 0x73: 787 if (prefix[2] == 0x66) { 788 dst_reg_file = SSE; 789 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 790 } else { 791 dst_reg_file = MMX; 792 } 793 static const char* x73_opcodes[] = { 794 "unknown-73", "unknown-73", "psrlq", "psrldq", 795 "unknown-73", "unknown-73", "psllq", "unknown-73"}; 796 modrm_opcodes = x73_opcodes; 797 reg_is_opcode = true; 798 has_modrm = true; 799 store = true; 800 immediate_bytes = 1; 801 break; 802 case 0x7C: 803 if (prefix[0] == 0xF2) { 804 opcode1 = "haddps"; 805 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 806 } else if (prefix[2] == 0x66) { 807 opcode1 = "haddpd"; 808 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 809 } else { 810 opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 811 opcode1 = opcode_tmp.c_str(); 812 break; 813 } 814 src_reg_file = dst_reg_file = SSE; 815 has_modrm = true; 816 load = true; 817 break; 818 case 0x7E: 819 if (prefix[2] == 0x66) { 820 src_reg_file = SSE; 821 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 822 } else { 823 src_reg_file = MMX; 824 } 825 opcode1 = "movd"; 826 has_modrm = true; 827 store = true; 828 break; 829 case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: 830 case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F: 831 opcode1 = "j"; 832 opcode2 = condition_codes[*instr & 0xF]; 833 branch_bytes = 4; 834 break; 835 case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: 836 case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F: 837 opcode1 = "set"; 838 opcode2 = condition_codes[*instr & 0xF]; 839 modrm_opcodes = nullptr; 840 reg_is_opcode = true; 841 has_modrm = true; 842 store = true; 843 break; 844 case 0xA4: 845 opcode1 = "shld"; 846 has_modrm = true; 847 load = true; 848 immediate_bytes = 1; 849 break; 850 case 0xA5: 851 opcode1 = "shld"; 852 has_modrm = true; 853 load = true; 854 cx = true; 855 break; 856 case 0xAC: 857 opcode1 = "shrd"; 858 has_modrm = true; 859 load = true; 860 immediate_bytes = 1; 861 break; 862 case 0xAD: 863 opcode1 = "shrd"; 864 has_modrm = true; 865 load = true; 866 cx = true; 867 break; 868 case 0xAE: 869 if (prefix[0] == 0xF3) { 870 prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 871 static const char* xAE_opcodes[] = { 872 "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", 873 "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"}; 874 modrm_opcodes = xAE_opcodes; 875 reg_is_opcode = true; 876 has_modrm = true; 877 uint8_t reg_or_opcode = (instr[1] >> 3) & 7; 878 switch (reg_or_opcode) { 879 case 0: 880 prefix[1] = kFs; 881 load = true; 882 break; 883 case 1: 884 prefix[1] = kGs; 885 load = true; 886 break; 887 case 2: 888 prefix[1] = kFs; 889 store = true; 890 break; 891 case 3: 892 prefix[1] = kGs; 893 store = true; 894 break; 895 default: 896 load = true; 897 break; 898 } 899 } else { 900 static const char* xAE_opcodes[] = { 901 "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", 902 "unknown-AE", "lfence", "mfence", "sfence"}; 903 modrm_opcodes = xAE_opcodes; 904 reg_is_opcode = true; 905 has_modrm = true; 906 load = true; 907 no_ops = true; 908 } 909 break; 910 case 0xAF: 911 opcode1 = "imul"; 912 has_modrm = true; 913 load = true; 914 break; 915 case 0xB1: 916 opcode1 = "cmpxchg"; 917 has_modrm = true; 918 store = true; 919 break; 920 case 0xB6: 921 opcode1 = "movzxb"; 922 has_modrm = true; 923 load = true; 924 byte_second_operand = true; 925 break; 926 case 0xB7: 927 opcode1 = "movzxw"; 928 has_modrm = true; 929 load = true; 930 break; 931 case 0xBC: 932 opcode1 = "bsf"; 933 has_modrm = true; 934 load = true; 935 break; 936 case 0xBD: 937 opcode1 = "bsr"; 938 has_modrm = true; 939 load = true; 940 break; 941 case 0xB8: 942 opcode1 = "popcnt"; 943 has_modrm = true; 944 load = true; 945 break; 946 case 0xBE: 947 opcode1 = "movsxb"; 948 has_modrm = true; 949 load = true; 950 byte_second_operand = true; 951 rex |= (rex == 0 ? 0 : REX_W); 952 break; 953 case 0xBF: 954 opcode1 = "movsxw"; 955 has_modrm = true; 956 load = true; 957 break; 958 case 0xC3: 959 opcode1 = "movnti"; 960 store = true; 961 has_modrm = true; 962 break; 963 case 0xC5: 964 if (prefix[2] == 0x66) { 965 opcode1 = "pextrw"; 966 prefix[2] = 0; 967 has_modrm = true; 968 load = true; 969 src_reg_file = SSE; 970 immediate_bytes = 1; 971 } else { 972 opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 973 opcode1 = opcode_tmp.c_str(); 974 } 975 break; 976 case 0xC6: 977 if (prefix[2] == 0x66) { 978 opcode1 = "shufpd"; 979 prefix[2] = 0; 980 } else { 981 opcode1 = "shufps"; 982 } 983 has_modrm = true; 984 store = true; 985 src_reg_file = dst_reg_file = SSE; 986 immediate_bytes = 1; 987 break; 988 case 0xC7: 989 static const char* x0FxC7_opcodes[] = { 990 "unknown-0f-c7", "cmpxchg8b", "unknown-0f-c7", "unknown-0f-c7", 991 "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7"}; 992 modrm_opcodes = x0FxC7_opcodes; 993 has_modrm = true; 994 reg_is_opcode = true; 995 store = true; 996 break; 997 case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: 998 opcode1 = "bswap"; 999 reg_in_opcode = true; 1000 break; 1001 case 0xD4: 1002 if (prefix[2] == 0x66) { 1003 src_reg_file = dst_reg_file = SSE; 1004 prefix[2] = 0; 1005 } else { 1006 src_reg_file = dst_reg_file = MMX; 1007 } 1008 opcode1 = "paddq"; 1009 prefix[2] = 0; 1010 has_modrm = true; 1011 load = true; 1012 break; 1013 case 0xDB: 1014 if (prefix[2] == 0x66) { 1015 src_reg_file = dst_reg_file = SSE; 1016 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 1017 } else { 1018 src_reg_file = dst_reg_file = MMX; 1019 } 1020 opcode1 = "pand"; 1021 prefix[2] = 0; 1022 has_modrm = true; 1023 load = true; 1024 break; 1025 case 0xD5: 1026 if (prefix[2] == 0x66) { 1027 opcode1 = "pmullw"; 1028 prefix[2] = 0; 1029 has_modrm = true; 1030 load = true; 1031 src_reg_file = dst_reg_file = SSE; 1032 } else { 1033 opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 1034 opcode1 = opcode_tmp.c_str(); 1035 } 1036 break; 1037 case 0xEB: 1038 if (prefix[2] == 0x66) { 1039 src_reg_file = dst_reg_file = SSE; 1040 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 1041 } else { 1042 src_reg_file = dst_reg_file = MMX; 1043 } 1044 opcode1 = "por"; 1045 prefix[2] = 0; 1046 has_modrm = true; 1047 load = true; 1048 break; 1049 case 0xEF: 1050 if (prefix[2] == 0x66) { 1051 src_reg_file = dst_reg_file = SSE; 1052 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 1053 } else { 1054 src_reg_file = dst_reg_file = MMX; 1055 } 1056 opcode1 = "pxor"; 1057 prefix[2] = 0; 1058 has_modrm = true; 1059 load = true; 1060 break; 1061 case 0xF4: 1062 case 0xF6: 1063 case 0xF8: 1064 case 0xF9: 1065 case 0xFA: 1066 case 0xFB: 1067 case 0xFC: 1068 case 0xFD: 1069 case 0xFE: 1070 if (prefix[2] == 0x66) { 1071 src_reg_file = dst_reg_file = SSE; 1072 prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 1073 } else { 1074 src_reg_file = dst_reg_file = MMX; 1075 } 1076 switch (*instr) { 1077 case 0xF4: opcode1 = "pmuludq"; break; 1078 case 0xF6: opcode1 = "psadbw"; break; 1079 case 0xF8: opcode1 = "psubb"; break; 1080 case 0xF9: opcode1 = "psubw"; break; 1081 case 0xFA: opcode1 = "psubd"; break; 1082 case 0xFB: opcode1 = "psubq"; break; 1083 case 0xFC: opcode1 = "paddb"; break; 1084 case 0xFD: opcode1 = "paddw"; break; 1085 case 0xFE: opcode1 = "paddd"; break; 1086 } 1087 prefix[2] = 0; 1088 has_modrm = true; 1089 load = true; 1090 break; 1091 default: 1092 opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 1093 opcode1 = opcode_tmp.c_str(); 1094 break; 1095 } 1096 break; 1097 case 0x80: case 0x81: case 0x82: case 0x83: 1098 static const char* x80_opcodes[] = {"add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"}; 1099 modrm_opcodes = x80_opcodes; 1100 has_modrm = true; 1101 reg_is_opcode = true; 1102 store = true; 1103 byte_operand = (*instr & 1) == 0; 1104 immediate_bytes = *instr == 0x81 ? 4 : 1; 1105 break; 1106 case 0x84: case 0x85: 1107 opcode1 = "test"; 1108 has_modrm = true; 1109 load = true; 1110 byte_operand = (*instr & 1) == 0; 1111 break; 1112 case 0x8D: 1113 opcode1 = "lea"; 1114 has_modrm = true; 1115 load = true; 1116 break; 1117 case 0x8F: 1118 opcode1 = "pop"; 1119 has_modrm = true; 1120 reg_is_opcode = true; 1121 store = true; 1122 break; 1123 case 0x99: 1124 opcode1 = "cdq"; 1125 break; 1126 case 0x9B: 1127 if (instr[1] == 0xDF && instr[2] == 0xE0) { 1128 opcode1 = "fstsw\tax"; 1129 instr += 2; 1130 } else { 1131 opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr); 1132 opcode1 = opcode_tmp.c_str(); 1133 } 1134 break; 1135 case 0xA5: 1136 opcode1 = (prefix[2] == 0x66 ? "movsw" : "movsl"); 1137 break; 1138 case 0xA7: 1139 opcode1 = (prefix[2] == 0x66 ? "cmpsw" : "cmpsl"); 1140 break; 1141 case 0xAF: 1142 opcode1 = (prefix[2] == 0x66 ? "scasw" : "scasl"); 1143 break; 1144 case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: 1145 opcode1 = "mov"; 1146 immediate_bytes = 1; 1147 byte_operand = true; 1148 reg_in_opcode = true; 1149 byte_operand = true; 1150 break; 1151 case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: 1152 if ((rex & REX_W) != 0) { 1153 opcode1 = "movabsq"; 1154 immediate_bytes = 8; 1155 reg_in_opcode = true; 1156 break; 1157 } 1158 opcode1 = "mov"; 1159 immediate_bytes = 4; 1160 reg_in_opcode = true; 1161 break; 1162 case 0xC0: case 0xC1: 1163 case 0xD0: case 0xD1: case 0xD2: case 0xD3: 1164 static const char* shift_opcodes[] = 1165 {"rol", "ror", "rcl", "rcr", "shl", "shr", "unknown-shift", "sar"}; 1166 modrm_opcodes = shift_opcodes; 1167 has_modrm = true; 1168 reg_is_opcode = true; 1169 store = true; 1170 immediate_bytes = ((*instr & 0xf0) == 0xc0) ? 1 : 0; 1171 cx = (*instr == 0xD2) || (*instr == 0xD3); 1172 byte_operand = (*instr == 0xC0); 1173 break; 1174 case 0xC3: opcode1 = "ret"; break; 1175 case 0xC6: 1176 static const char* c6_opcodes[] = {"mov", "unknown-c6", "unknown-c6", 1177 "unknown-c6", "unknown-c6", "unknown-c6", 1178 "unknown-c6", "unknown-c6"}; 1179 modrm_opcodes = c6_opcodes; 1180 store = true; 1181 immediate_bytes = 1; 1182 has_modrm = true; 1183 reg_is_opcode = true; 1184 byte_operand = true; 1185 break; 1186 case 0xC7: 1187 static const char* c7_opcodes[] = {"mov", "unknown-c7", "unknown-c7", 1188 "unknown-c7", "unknown-c7", "unknown-c7", 1189 "unknown-c7", "unknown-c7"}; 1190 modrm_opcodes = c7_opcodes; 1191 store = true; 1192 immediate_bytes = 4; 1193 has_modrm = true; 1194 reg_is_opcode = true; 1195 break; 1196 case 0xCC: opcode1 = "int 3"; break; 1197 case 0xD9: 1198 if (instr[1] == 0xF8) { 1199 opcode1 = "fprem"; 1200 instr++; 1201 } else { 1202 static const char* d9_opcodes[] = {"flds", "unknown-d9", "fsts", "fstps", "fldenv", "fldcw", 1203 "fnstenv", "fnstcw"}; 1204 modrm_opcodes = d9_opcodes; 1205 store = true; 1206 has_modrm = true; 1207 reg_is_opcode = true; 1208 } 1209 break; 1210 case 0xDA: 1211 if (instr[1] == 0xE9) { 1212 opcode1 = "fucompp"; 1213 instr++; 1214 } else { 1215 opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr); 1216 opcode1 = opcode_tmp.c_str(); 1217 } 1218 break; 1219 case 0xDB: 1220 static const char* db_opcodes[] = {"fildl", "unknown-db", "unknown-db", 1221 "unknown-db", "unknown-db", "unknown-db", 1222 "unknown-db", "unknown-db"}; 1223 modrm_opcodes = db_opcodes; 1224 load = true; 1225 has_modrm = true; 1226 reg_is_opcode = true; 1227 break; 1228 case 0xDD: 1229 static const char* dd_opcodes[] = {"fldl", "fisttp", "fstl", 1230 "fstpl", "frstor", "unknown-dd", 1231 "fnsave", "fnstsw"}; 1232 modrm_opcodes = dd_opcodes; 1233 store = true; 1234 has_modrm = true; 1235 reg_is_opcode = true; 1236 break; 1237 case 0xDF: 1238 static const char* df_opcodes[] = {"fild", "unknown-df", "unknown-df", 1239 "unknown-df", "unknown-df", "fildll", 1240 "unknown-df", "unknown-df"}; 1241 modrm_opcodes = df_opcodes; 1242 load = true; 1243 has_modrm = true; 1244 reg_is_opcode = true; 1245 break; 1246 case 0xE3: opcode1 = "jecxz"; branch_bytes = 1; break; 1247 case 0xE8: opcode1 = "call"; branch_bytes = 4; break; 1248 case 0xE9: opcode1 = "jmp"; branch_bytes = 4; break; 1249 case 0xEB: opcode1 = "jmp"; branch_bytes = 1; break; 1250 case 0xF5: opcode1 = "cmc"; break; 1251 case 0xF6: case 0xF7: 1252 static const char* f7_opcodes[] = { 1253 "test", "unknown-f7", "not", "neg", "mul edx:eax, eax *", 1254 "imul edx:eax, eax *", "div edx:eax, edx:eax /", 1255 "idiv edx:eax, edx:eax /"}; 1256 modrm_opcodes = f7_opcodes; 1257 has_modrm = true; 1258 reg_is_opcode = true; 1259 store = true; 1260 immediate_bytes = ((instr[1] & 0x38) == 0) ? 1 : 0; 1261 break; 1262 case 0xFF: 1263 { 1264 static const char* ff_opcodes[] = { 1265 "inc", "dec", "call", "call", 1266 "jmp", "jmp", "push", "unknown-ff"}; 1267 modrm_opcodes = ff_opcodes; 1268 has_modrm = true; 1269 reg_is_opcode = true; 1270 load = true; 1271 const uint8_t opcode_digit = (instr[1] >> 3) & 7; 1272 // 'call', 'jmp' and 'push' are target specific instructions 1273 if (opcode_digit == 2 || opcode_digit == 4 || opcode_digit == 6) { 1274 target_specific = true; 1275 } 1276 } 1277 break; 1278 default: 1279 opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr); 1280 opcode1 = opcode_tmp.c_str(); 1281 break; 1282 } 1283 std::ostringstream args; 1284 // We force the REX prefix to be available for 64-bit target 1285 // in order to dump addr (base/index) registers correctly. 1286 uint8_t rex64 = supports_rex_ ? (rex | 0x40) : rex; 1287 // REX.W should be forced for 64-target and target-specific instructions (i.e., push or pop). 1288 uint8_t rex_w = (supports_rex_ && target_specific) ? (rex | 0x48) : rex; 1289 if (reg_in_opcode) { 1290 DCHECK(!has_modrm); 1291 DumpOpcodeReg(args, rex_w, *instr & 0x7, byte_operand, prefix[2]); 1292 } 1293 instr++; 1294 uint32_t address_bits = 0; 1295 if (has_modrm) { 1296 uint8_t modrm = *instr; 1297 instr++; 1298 uint8_t mod = modrm >> 6; 1299 uint8_t reg_or_opcode = (modrm >> 3) & 7; 1300 uint8_t rm = modrm & 7; 1301 std::string address = DumpAddress(mod, rm, rex64, rex_w, no_ops, byte_operand, 1302 byte_second_operand, prefix, load, src_reg_file, dst_reg_file, 1303 &instr, &address_bits); 1304 1305 if (reg_is_opcode && modrm_opcodes != nullptr) { 1306 opcode3 = modrm_opcodes[reg_or_opcode]; 1307 } 1308 1309 // Add opcode suffixes to indicate size. 1310 if (byte_operand) { 1311 opcode4 = "b"; 1312 } else if ((rex & REX_W) != 0) { 1313 opcode4 = "q"; 1314 } else if (prefix[2] == 0x66) { 1315 opcode4 = "w"; 1316 } 1317 1318 if (load) { 1319 if (!reg_is_opcode) { 1320 DumpReg(args, rex, reg_or_opcode, byte_operand, prefix[2], dst_reg_file); 1321 args << ", "; 1322 } 1323 DumpSegmentOverride(args, prefix[1]); 1324 args << address; 1325 } else { 1326 DCHECK(store); 1327 DumpSegmentOverride(args, prefix[1]); 1328 args << address; 1329 if (!reg_is_opcode) { 1330 args << ", "; 1331 DumpReg(args, rex, reg_or_opcode, byte_operand, prefix[2], src_reg_file); 1332 } 1333 } 1334 } 1335 if (ax) { 1336 // If this opcode implicitly uses ax, ax is always the first arg. 1337 DumpReg(args, rex, 0 /* EAX */, byte_operand, prefix[2], GPR); 1338 } 1339 if (cx) { 1340 args << ", "; 1341 DumpReg(args, rex, 1 /* ECX */, true, prefix[2], GPR); 1342 } 1343 if (immediate_bytes > 0) { 1344 if (has_modrm || reg_in_opcode || ax || cx) { 1345 args << ", "; 1346 } 1347 if (immediate_bytes == 1) { 1348 args << StringPrintf("%d", *reinterpret_cast<const int8_t*>(instr)); 1349 instr++; 1350 } else if (immediate_bytes == 4) { 1351 if (prefix[2] == 0x66) { // Operand size override from 32-bit to 16-bit. 1352 args << StringPrintf("%d", *reinterpret_cast<const int16_t*>(instr)); 1353 instr += 2; 1354 } else { 1355 args << StringPrintf("%d", *reinterpret_cast<const int32_t*>(instr)); 1356 instr += 4; 1357 } 1358 } else { 1359 CHECK_EQ(immediate_bytes, 8u); 1360 args << StringPrintf("%" PRId64, *reinterpret_cast<const int64_t*>(instr)); 1361 instr += 8; 1362 } 1363 } else if (branch_bytes > 0) { 1364 DCHECK(!has_modrm); 1365 int32_t displacement; 1366 if (branch_bytes == 1) { 1367 displacement = *reinterpret_cast<const int8_t*>(instr); 1368 instr++; 1369 } else { 1370 CHECK_EQ(branch_bytes, 4u); 1371 displacement = *reinterpret_cast<const int32_t*>(instr); 1372 instr += 4; 1373 } 1374 args << StringPrintf("%+d (", displacement) 1375 << FormatInstructionPointer(instr + displacement) 1376 << ")"; 1377 } 1378 if (prefix[1] == kFs && !supports_rex_) { 1379 args << " ; "; 1380 Thread::DumpThreadOffset<4>(args, address_bits); 1381 } 1382 if (prefix[1] == kGs && supports_rex_) { 1383 args << " ; "; 1384 Thread::DumpThreadOffset<8>(args, address_bits); 1385 } 1386 const char* prefix_str; 1387 switch (prefix[0]) { 1388 case 0xF0: prefix_str = "lock "; break; 1389 case 0xF2: prefix_str = "repne "; break; 1390 case 0xF3: prefix_str = "repe "; break; 1391 case 0: prefix_str = ""; break; 1392 default: LOG(FATAL) << "Unreachable"; UNREACHABLE(); 1393 } 1394 os << FormatInstructionPointer(begin_instr) 1395 << StringPrintf(": %22s \t%-7s%s%s%s%s%s ", DumpCodeHex(begin_instr, instr).c_str(), 1396 prefix_str, opcode0, opcode1, opcode2, opcode3, opcode4) 1397 << args.str() << '\n'; 1398 return instr - begin_instr; 1399 } // NOLINT(readability/fn_size) 1400 1401 } // namespace x86 1402 } // namespace art 1403