1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <assert.h> 6 #include <stdarg.h> 7 #include <stdio.h> 8 9 #if V8_TARGET_ARCH_IA32 10 11 #include "src/base/compiler-specific.h" 12 #include "src/disasm.h" 13 #include "src/ia32/sse-instr.h" 14 15 namespace disasm { 16 17 enum OperandOrder { 18 UNSET_OP_ORDER = 0, 19 REG_OPER_OP_ORDER, 20 OPER_REG_OP_ORDER 21 }; 22 23 24 //------------------------------------------------------------------ 25 // Tables 26 //------------------------------------------------------------------ 27 struct ByteMnemonic { 28 int b; // -1 terminates, otherwise must be in range (0..255) 29 const char* mnem; 30 OperandOrder op_order_; 31 }; 32 33 static const ByteMnemonic two_operands_instr[] = { 34 {0x01, "add", OPER_REG_OP_ORDER}, {0x03, "add", REG_OPER_OP_ORDER}, 35 {0x09, "or", OPER_REG_OP_ORDER}, {0x0B, "or", REG_OPER_OP_ORDER}, 36 {0x13, "adc", REG_OPER_OP_ORDER}, {0x1B, "sbb", REG_OPER_OP_ORDER}, 37 {0x21, "and", OPER_REG_OP_ORDER}, {0x23, "and", REG_OPER_OP_ORDER}, 38 {0x29, "sub", OPER_REG_OP_ORDER}, {0x2A, "subb", REG_OPER_OP_ORDER}, 39 {0x2B, "sub", REG_OPER_OP_ORDER}, {0x31, "xor", OPER_REG_OP_ORDER}, 40 {0x33, "xor", REG_OPER_OP_ORDER}, {0x38, "cmpb", OPER_REG_OP_ORDER}, 41 {0x39, "cmp", OPER_REG_OP_ORDER}, {0x3A, "cmpb", REG_OPER_OP_ORDER}, 42 {0x3B, "cmp", REG_OPER_OP_ORDER}, {0x84, "test_b", REG_OPER_OP_ORDER}, 43 {0x85, "test", REG_OPER_OP_ORDER}, {0x86, "xchg_b", REG_OPER_OP_ORDER}, 44 {0x87, "xchg", REG_OPER_OP_ORDER}, {0x8A, "mov_b", REG_OPER_OP_ORDER}, 45 {0x8B, "mov", REG_OPER_OP_ORDER}, {0x8D, "lea", REG_OPER_OP_ORDER}, 46 {-1, "", UNSET_OP_ORDER}}; 47 48 static const ByteMnemonic zero_operands_instr[] = { 49 {0xC3, "ret", UNSET_OP_ORDER}, 50 {0xC9, "leave", UNSET_OP_ORDER}, 51 {0x90, "nop", UNSET_OP_ORDER}, 52 {0xF4, "hlt", UNSET_OP_ORDER}, 53 {0xCC, "int3", UNSET_OP_ORDER}, 54 {0x60, "pushad", UNSET_OP_ORDER}, 55 {0x61, "popad", UNSET_OP_ORDER}, 56 {0x9C, "pushfd", UNSET_OP_ORDER}, 57 {0x9D, "popfd", UNSET_OP_ORDER}, 58 {0x9E, "sahf", UNSET_OP_ORDER}, 59 {0x99, "cdq", UNSET_OP_ORDER}, 60 {0x9B, "fwait", UNSET_OP_ORDER}, 61 {0xFC, "cld", UNSET_OP_ORDER}, 62 {0xAB, "stos", UNSET_OP_ORDER}, 63 {-1, "", UNSET_OP_ORDER} 64 }; 65 66 67 static const ByteMnemonic call_jump_instr[] = { 68 {0xE8, "call", UNSET_OP_ORDER}, 69 {0xE9, "jmp", UNSET_OP_ORDER}, 70 {-1, "", UNSET_OP_ORDER} 71 }; 72 73 74 static const ByteMnemonic short_immediate_instr[] = { 75 {0x05, "add", UNSET_OP_ORDER}, 76 {0x0D, "or", UNSET_OP_ORDER}, 77 {0x15, "adc", UNSET_OP_ORDER}, 78 {0x25, "and", UNSET_OP_ORDER}, 79 {0x2D, "sub", UNSET_OP_ORDER}, 80 {0x35, "xor", UNSET_OP_ORDER}, 81 {0x3D, "cmp", UNSET_OP_ORDER}, 82 {-1, "", UNSET_OP_ORDER} 83 }; 84 85 86 // Generally we don't want to generate these because they are subject to partial 87 // register stalls. They are included for completeness and because the cmp 88 // variant is used by the RecordWrite stub. Because it does not update the 89 // register it is not subject to partial register stalls. 90 static ByteMnemonic byte_immediate_instr[] = {{0x0C, "or", UNSET_OP_ORDER}, 91 {0x24, "and", UNSET_OP_ORDER}, 92 {0x34, "xor", UNSET_OP_ORDER}, 93 {0x3C, "cmp", UNSET_OP_ORDER}, 94 {-1, "", UNSET_OP_ORDER}}; 95 96 static const char* const jump_conditional_mnem[] = { 97 /*0*/ "jo", "jno", "jc", "jnc", 98 /*4*/ "jz", "jnz", "jna", "ja", 99 /*8*/ "js", "jns", "jpe", "jpo", 100 /*12*/ "jl", "jnl", "jng", "jg" 101 }; 102 103 104 static const char* const set_conditional_mnem[] = { 105 /*0*/ "seto", "setno", "setc", "setnc", 106 /*4*/ "setz", "setnz", "setna", "seta", 107 /*8*/ "sets", "setns", "setpe", "setpo", 108 /*12*/ "setl", "setnl", "setng", "setg" 109 }; 110 111 112 static const char* const conditional_move_mnem[] = { 113 /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", 114 /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", 115 /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", 116 /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg" 117 }; 118 119 120 enum InstructionType { 121 NO_INSTR, 122 ZERO_OPERANDS_INSTR, 123 TWO_OPERANDS_INSTR, 124 JUMP_CONDITIONAL_SHORT_INSTR, 125 REGISTER_INSTR, 126 MOVE_REG_INSTR, 127 CALL_JUMP_INSTR, 128 SHORT_IMMEDIATE_INSTR, 129 BYTE_IMMEDIATE_INSTR 130 }; 131 132 133 struct InstructionDesc { 134 const char* mnem; 135 InstructionType type; 136 OperandOrder op_order_; 137 }; 138 139 140 class InstructionTable { 141 public: 142 InstructionTable(); 143 const InstructionDesc& Get(byte x) const { return instructions_[x]; } 144 static InstructionTable* get_instance() { 145 static InstructionTable table; 146 return &table; 147 } 148 149 private: 150 InstructionDesc instructions_[256]; 151 void Clear(); 152 void Init(); 153 void CopyTable(const ByteMnemonic bm[], InstructionType type); 154 void SetTableRange(InstructionType type, 155 byte start, 156 byte end, 157 const char* mnem); 158 void AddJumpConditionalShort(); 159 }; 160 161 162 InstructionTable::InstructionTable() { 163 Clear(); 164 Init(); 165 } 166 167 168 void InstructionTable::Clear() { 169 for (int i = 0; i < 256; i++) { 170 instructions_[i].mnem = ""; 171 instructions_[i].type = NO_INSTR; 172 instructions_[i].op_order_ = UNSET_OP_ORDER; 173 } 174 } 175 176 177 void InstructionTable::Init() { 178 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); 179 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); 180 CopyTable(call_jump_instr, CALL_JUMP_INSTR); 181 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); 182 CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR); 183 AddJumpConditionalShort(); 184 SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); 185 SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); 186 SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); 187 SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop"); 188 SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop. 189 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); 190 } 191 192 193 void InstructionTable::CopyTable(const ByteMnemonic bm[], 194 InstructionType type) { 195 for (int i = 0; bm[i].b >= 0; i++) { 196 InstructionDesc* id = &instructions_[bm[i].b]; 197 id->mnem = bm[i].mnem; 198 id->op_order_ = bm[i].op_order_; 199 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. 200 id->type = type; 201 } 202 } 203 204 205 void InstructionTable::SetTableRange(InstructionType type, 206 byte start, 207 byte end, 208 const char* mnem) { 209 for (byte b = start; b <= end; b++) { 210 InstructionDesc* id = &instructions_[b]; 211 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. 212 id->mnem = mnem; 213 id->type = type; 214 } 215 } 216 217 218 void InstructionTable::AddJumpConditionalShort() { 219 for (byte b = 0x70; b <= 0x7F; b++) { 220 InstructionDesc* id = &instructions_[b]; 221 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. 222 id->mnem = jump_conditional_mnem[b & 0x0F]; 223 id->type = JUMP_CONDITIONAL_SHORT_INSTR; 224 } 225 } 226 227 228 // The IA32 disassembler implementation. 229 class DisassemblerIA32 { 230 public: 231 DisassemblerIA32( 232 const NameConverter& converter, 233 Disassembler::UnimplementedOpcodeAction unimplemented_opcode_action) 234 : converter_(converter), 235 vex_byte0_(0), 236 vex_byte1_(0), 237 vex_byte2_(0), 238 instruction_table_(InstructionTable::get_instance()), 239 tmp_buffer_pos_(0), 240 unimplemented_opcode_action_(unimplemented_opcode_action) { 241 tmp_buffer_[0] = '\0'; 242 } 243 244 virtual ~DisassemblerIA32() {} 245 246 // Writes one disassembled instruction into 'buffer' (0-terminated). 247 // Returns the length of the disassembled machine instruction in bytes. 248 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 249 250 private: 251 const NameConverter& converter_; 252 byte vex_byte0_; // 0xC4 or 0xC5 253 byte vex_byte1_; 254 byte vex_byte2_; // only for 3 bytes vex prefix 255 InstructionTable* instruction_table_; 256 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 257 unsigned int tmp_buffer_pos_; 258 Disassembler::UnimplementedOpcodeAction unimplemented_opcode_action_; 259 260 enum { 261 eax = 0, 262 ecx = 1, 263 edx = 2, 264 ebx = 3, 265 esp = 4, 266 ebp = 5, 267 esi = 6, 268 edi = 7 269 }; 270 271 272 enum ShiftOpcodeExtension { 273 kROL = 0, 274 kROR = 1, 275 kRCL = 2, 276 kRCR = 3, 277 kSHL = 4, 278 KSHR = 5, 279 kSAR = 7 280 }; 281 282 bool vex_128() { 283 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5); 284 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_; 285 return (checked & 4) == 0; 286 } 287 288 bool vex_none() { 289 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5); 290 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_; 291 return (checked & 3) == 0; 292 } 293 294 bool vex_66() { 295 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5); 296 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_; 297 return (checked & 3) == 1; 298 } 299 300 bool vex_f3() { 301 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5); 302 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_; 303 return (checked & 3) == 2; 304 } 305 306 bool vex_f2() { 307 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5); 308 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_; 309 return (checked & 3) == 3; 310 } 311 312 bool vex_w() { 313 if (vex_byte0_ == 0xC5) return false; 314 return (vex_byte2_ & 0x80) != 0; 315 } 316 317 bool vex_0f() { 318 if (vex_byte0_ == 0xC5) return true; 319 return (vex_byte1_ & 3) == 1; 320 } 321 322 bool vex_0f38() { 323 if (vex_byte0_ == 0xC5) return false; 324 return (vex_byte1_ & 3) == 2; 325 } 326 327 bool vex_0f3a() { 328 if (vex_byte0_ == 0xC5) return false; 329 return (vex_byte1_ & 3) == 3; 330 } 331 332 int vex_vreg() { 333 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5); 334 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_; 335 return ~(checked >> 3) & 0xF; 336 } 337 338 char float_size_code() { return "sd"[vex_w()]; } 339 340 const char* NameOfCPURegister(int reg) const { 341 return converter_.NameOfCPURegister(reg); 342 } 343 344 345 const char* NameOfByteCPURegister(int reg) const { 346 return converter_.NameOfByteCPURegister(reg); 347 } 348 349 350 const char* NameOfXMMRegister(int reg) const { 351 return converter_.NameOfXMMRegister(reg); 352 } 353 354 355 const char* NameOfAddress(byte* addr) const { 356 return converter_.NameOfAddress(addr); 357 } 358 359 360 // Disassembler helper functions. 361 static void get_modrm(byte data, int* mod, int* regop, int* rm) { 362 *mod = (data >> 6) & 3; 363 *regop = (data & 0x38) >> 3; 364 *rm = data & 7; 365 } 366 367 368 static void get_sib(byte data, int* scale, int* index, int* base) { 369 *scale = (data >> 6) & 3; 370 *index = (data >> 3) & 7; 371 *base = data & 7; 372 } 373 374 typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const; 375 376 int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); 377 int PrintRightOperand(byte* modrmp); 378 int PrintRightByteOperand(byte* modrmp); 379 int PrintRightXMMOperand(byte* modrmp); 380 int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); 381 int PrintImmediateOp(byte* data); 382 int F7Instruction(byte* data); 383 int D1D3C1Instruction(byte* data); 384 int JumpShort(byte* data); 385 int JumpConditional(byte* data, const char* comment); 386 int JumpConditionalShort(byte* data, const char* comment); 387 int SetCC(byte* data); 388 int CMov(byte* data); 389 int FPUInstruction(byte* data); 390 int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); 391 int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); 392 int AVXInstruction(byte* data); 393 PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...); 394 395 void UnimplementedInstruction() { 396 if (unimplemented_opcode_action_ == 397 Disassembler::kAbortOnUnimplementedOpcode) { 398 FATAL("Unimplemented instruction in disassembler"); 399 } else { 400 AppendToBuffer("'Unimplemented Instruction'"); 401 } 402 } 403 }; 404 405 406 void DisassemblerIA32::AppendToBuffer(const char* format, ...) { 407 v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; 408 va_list args; 409 va_start(args, format); 410 int result = v8::internal::VSNPrintF(buf, format, args); 411 va_end(args); 412 tmp_buffer_pos_ += result; 413 } 414 415 int DisassemblerIA32::PrintRightOperandHelper( 416 byte* modrmp, 417 RegisterNameMapping direct_register_name) { 418 int mod, regop, rm; 419 get_modrm(*modrmp, &mod, ®op, &rm); 420 RegisterNameMapping register_name = (mod == 3) ? direct_register_name : 421 &DisassemblerIA32::NameOfCPURegister; 422 switch (mod) { 423 case 0: 424 if (rm == ebp) { 425 int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1); 426 AppendToBuffer("[0x%x]", disp); 427 return 5; 428 } else if (rm == esp) { 429 byte sib = *(modrmp + 1); 430 int scale, index, base; 431 get_sib(sib, &scale, &index, &base); 432 if (index == esp && base == esp && scale == 0 /*times_1*/) { 433 AppendToBuffer("[%s]", (this->*register_name)(rm)); 434 return 2; 435 } else if (base == ebp) { 436 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 437 AppendToBuffer("[%s*%d%s0x%x]", 438 (this->*register_name)(index), 439 1 << scale, 440 disp < 0 ? "-" : "+", 441 disp < 0 ? -disp : disp); 442 return 6; 443 } else if (index != esp && base != ebp) { 444 // [base+index*scale] 445 AppendToBuffer("[%s+%s*%d]", 446 (this->*register_name)(base), 447 (this->*register_name)(index), 448 1 << scale); 449 return 2; 450 } else { 451 UnimplementedInstruction(); 452 return 1; 453 } 454 } else { 455 AppendToBuffer("[%s]", (this->*register_name)(rm)); 456 return 1; 457 } 458 break; 459 case 1: // fall through 460 case 2: 461 if (rm == esp) { 462 byte sib = *(modrmp + 1); 463 int scale, index, base; 464 get_sib(sib, &scale, &index, &base); 465 int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2) 466 : *reinterpret_cast<int8_t*>(modrmp + 2); 467 if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) { 468 AppendToBuffer("[%s%s0x%x]", 469 (this->*register_name)(rm), 470 disp < 0 ? "-" : "+", 471 disp < 0 ? -disp : disp); 472 } else { 473 AppendToBuffer("[%s+%s*%d%s0x%x]", 474 (this->*register_name)(base), 475 (this->*register_name)(index), 476 1 << scale, 477 disp < 0 ? "-" : "+", 478 disp < 0 ? -disp : disp); 479 } 480 return mod == 2 ? 6 : 3; 481 } else { 482 // No sib. 483 int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1) 484 : *reinterpret_cast<int8_t*>(modrmp + 1); 485 AppendToBuffer("[%s%s0x%x]", 486 (this->*register_name)(rm), 487 disp < 0 ? "-" : "+", 488 disp < 0 ? -disp : disp); 489 return mod == 2 ? 5 : 2; 490 } 491 break; 492 case 3: 493 AppendToBuffer("%s", (this->*register_name)(rm)); 494 return 1; 495 default: 496 UnimplementedInstruction(); 497 return 1; 498 } 499 UNREACHABLE(); 500 } 501 502 503 int DisassemblerIA32::PrintRightOperand(byte* modrmp) { 504 return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister); 505 } 506 507 508 int DisassemblerIA32::PrintRightByteOperand(byte* modrmp) { 509 return PrintRightOperandHelper(modrmp, 510 &DisassemblerIA32::NameOfByteCPURegister); 511 } 512 513 514 int DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) { 515 return PrintRightOperandHelper(modrmp, 516 &DisassemblerIA32::NameOfXMMRegister); 517 } 518 519 520 // Returns number of bytes used including the current *data. 521 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 522 int DisassemblerIA32::PrintOperands(const char* mnem, 523 OperandOrder op_order, 524 byte* data) { 525 byte modrm = *data; 526 int mod, regop, rm; 527 get_modrm(modrm, &mod, ®op, &rm); 528 int advance = 0; 529 switch (op_order) { 530 case REG_OPER_OP_ORDER: { 531 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 532 advance = PrintRightOperand(data); 533 break; 534 } 535 case OPER_REG_OP_ORDER: { 536 AppendToBuffer("%s ", mnem); 537 advance = PrintRightOperand(data); 538 AppendToBuffer(",%s", NameOfCPURegister(regop)); 539 break; 540 } 541 default: 542 UNREACHABLE(); 543 break; 544 } 545 return advance; 546 } 547 548 549 // Returns number of bytes used by machine instruction, including *data byte. 550 // Writes immediate instructions to 'tmp_buffer_'. 551 int DisassemblerIA32::PrintImmediateOp(byte* data) { 552 bool sign_extension_bit = (*data & 0x02) != 0; 553 byte modrm = *(data+1); 554 int mod, regop, rm; 555 get_modrm(modrm, &mod, ®op, &rm); 556 const char* mnem = "Imm???"; 557 switch (regop) { 558 case 0: mnem = "add"; break; 559 case 1: mnem = "or"; break; 560 case 2: mnem = "adc"; break; 561 case 4: mnem = "and"; break; 562 case 5: mnem = "sub"; break; 563 case 6: mnem = "xor"; break; 564 case 7: mnem = "cmp"; break; 565 default: UnimplementedInstruction(); 566 } 567 AppendToBuffer("%s ", mnem); 568 int count = PrintRightOperand(data+1); 569 if (sign_extension_bit) { 570 AppendToBuffer(",0x%x", *(data + 1 + count)); 571 return 1 + count + 1 /*int8*/; 572 } else { 573 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); 574 return 1 + count + 4 /*int32_t*/; 575 } 576 } 577 578 579 // Returns number of bytes used, including *data. 580 int DisassemblerIA32::F7Instruction(byte* data) { 581 DCHECK_EQ(0xF7, *data); 582 byte modrm = *++data; 583 int mod, regop, rm; 584 get_modrm(modrm, &mod, ®op, &rm); 585 const char* mnem = nullptr; 586 switch (regop) { 587 case 0: 588 mnem = "test"; 589 break; 590 case 2: 591 mnem = "not"; 592 break; 593 case 3: 594 mnem = "neg"; 595 break; 596 case 4: 597 mnem = "mul"; 598 break; 599 case 5: 600 mnem = "imul"; 601 break; 602 case 6: 603 mnem = "div"; 604 break; 605 case 7: 606 mnem = "idiv"; 607 break; 608 default: 609 UnimplementedInstruction(); 610 } 611 AppendToBuffer("%s ", mnem); 612 int count = PrintRightOperand(data); 613 if (regop == 0) { 614 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count)); 615 count += 4; 616 } 617 return 1 + count; 618 } 619 620 621 int DisassemblerIA32::D1D3C1Instruction(byte* data) { 622 byte op = *data; 623 DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1); 624 byte modrm = *++data; 625 int mod, regop, rm; 626 get_modrm(modrm, &mod, ®op, &rm); 627 int imm8 = -1; 628 const char* mnem = nullptr; 629 switch (regop) { 630 case kROL: 631 mnem = "rol"; 632 break; 633 case kROR: 634 mnem = "ror"; 635 break; 636 case kRCL: 637 mnem = "rcl"; 638 break; 639 case kRCR: 640 mnem = "rcr"; 641 break; 642 case kSHL: 643 mnem = "shl"; 644 break; 645 case KSHR: 646 mnem = "shr"; 647 break; 648 case kSAR: 649 mnem = "sar"; 650 break; 651 default: 652 UnimplementedInstruction(); 653 } 654 AppendToBuffer("%s ", mnem); 655 int count = PrintRightOperand(data); 656 if (op == 0xD1) { 657 imm8 = 1; 658 } else if (op == 0xC1) { 659 imm8 = *(data + 1); 660 count++; 661 } else if (op == 0xD3) { 662 // Shift/rotate by cl. 663 } 664 if (imm8 >= 0) { 665 AppendToBuffer(",%d", imm8); 666 } else { 667 AppendToBuffer(",cl"); 668 } 669 return 1 + count; 670 } 671 672 673 // Returns number of bytes used, including *data. 674 int DisassemblerIA32::JumpShort(byte* data) { 675 DCHECK_EQ(0xEB, *data); 676 byte b = *(data+1); 677 byte* dest = data + static_cast<int8_t>(b) + 2; 678 AppendToBuffer("jmp %s", NameOfAddress(dest)); 679 return 2; 680 } 681 682 683 // Returns number of bytes used, including *data. 684 int DisassemblerIA32::JumpConditional(byte* data, const char* comment) { 685 DCHECK_EQ(0x0F, *data); 686 byte cond = *(data+1) & 0x0F; 687 byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; 688 const char* mnem = jump_conditional_mnem[cond]; 689 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 690 if (comment != nullptr) { 691 AppendToBuffer(", %s", comment); 692 } 693 return 6; // includes 0x0F 694 } 695 696 697 // Returns number of bytes used, including *data. 698 int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { 699 byte cond = *data & 0x0F; 700 byte b = *(data+1); 701 byte* dest = data + static_cast<int8_t>(b) + 2; 702 const char* mnem = jump_conditional_mnem[cond]; 703 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 704 if (comment != nullptr) { 705 AppendToBuffer(", %s", comment); 706 } 707 return 2; 708 } 709 710 711 // Returns number of bytes used, including *data. 712 int DisassemblerIA32::SetCC(byte* data) { 713 DCHECK_EQ(0x0F, *data); 714 byte cond = *(data+1) & 0x0F; 715 const char* mnem = set_conditional_mnem[cond]; 716 AppendToBuffer("%s ", mnem); 717 PrintRightByteOperand(data+2); 718 return 3; // Includes 0x0F. 719 } 720 721 722 // Returns number of bytes used, including *data. 723 int DisassemblerIA32::CMov(byte* data) { 724 DCHECK_EQ(0x0F, *data); 725 byte cond = *(data + 1) & 0x0F; 726 const char* mnem = conditional_move_mnem[cond]; 727 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); 728 return 2 + op_size; // includes 0x0F 729 } 730 731 const char* sf_str[4] = {"", "rl", "ra", "ll"}; 732 733 int DisassemblerIA32::AVXInstruction(byte* data) { 734 byte opcode = *data; 735 byte* current = data + 1; 736 if (vex_66() && vex_0f38()) { 737 int mod, regop, rm, vvvv = vex_vreg(); 738 get_modrm(*current, &mod, ®op, &rm); 739 switch (opcode) { 740 case 0x99: 741 AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(), 742 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 743 current += PrintRightXMMOperand(current); 744 break; 745 case 0xA9: 746 AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(), 747 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 748 current += PrintRightXMMOperand(current); 749 break; 750 case 0xB9: 751 AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(), 752 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 753 current += PrintRightXMMOperand(current); 754 break; 755 case 0x9B: 756 AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(), 757 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 758 current += PrintRightXMMOperand(current); 759 break; 760 case 0xAB: 761 AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(), 762 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 763 current += PrintRightXMMOperand(current); 764 break; 765 case 0xBB: 766 AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(), 767 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 768 current += PrintRightXMMOperand(current); 769 break; 770 case 0x9D: 771 AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(), 772 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 773 current += PrintRightXMMOperand(current); 774 break; 775 case 0xAD: 776 AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(), 777 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 778 current += PrintRightXMMOperand(current); 779 break; 780 case 0xBD: 781 AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(), 782 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 783 current += PrintRightXMMOperand(current); 784 break; 785 case 0x9F: 786 AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(), 787 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 788 current += PrintRightXMMOperand(current); 789 break; 790 case 0xAF: 791 AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(), 792 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 793 current += PrintRightXMMOperand(current); 794 break; 795 case 0xBF: 796 AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(), 797 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 798 current += PrintRightXMMOperand(current); 799 break; 800 case 0xF7: 801 AppendToBuffer("shlx %s,", NameOfCPURegister(regop)); 802 current += PrintRightOperand(current); 803 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); 804 break; 805 #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, \ 806 opcode) \ 807 case 0x##opcode: { \ 808 AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \ 809 NameOfXMMRegister(vvvv)); \ 810 current += PrintRightXMMOperand(current); \ 811 break; \ 812 } 813 814 SSSE3_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE) 815 SSE4_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE) 816 #undef DECLARE_SSE_AVX_DIS_CASE 817 #define DECLARE_SSE_AVX_RM_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, \ 818 opcode) \ 819 case 0x##opcode: { \ 820 AppendToBuffer("v" #instruction " %s,", NameOfXMMRegister(regop)); \ 821 current += PrintRightXMMOperand(current); \ 822 break; \ 823 } 824 825 SSE4_RM_INSTRUCTION_LIST(DECLARE_SSE_AVX_RM_DIS_CASE) 826 #undef DECLARE_SSE_AVX_RM_DIS_CASE 827 default: 828 UnimplementedInstruction(); 829 } 830 } else if (vex_66() && vex_0f3a()) { 831 int mod, regop, rm, vvvv = vex_vreg(); 832 get_modrm(*current, &mod, ®op, &rm); 833 switch (opcode) { 834 case 0x0E: 835 AppendToBuffer("vpblendw %s,%s,", NameOfXMMRegister(regop), 836 NameOfXMMRegister(vvvv)); 837 current += PrintRightXMMOperand(current); 838 AppendToBuffer(",%d", *reinterpret_cast<uint8_t*>(current)); 839 current++; 840 break; 841 case 0x0F: 842 AppendToBuffer("vpalignr %s,%s,", NameOfXMMRegister(regop), 843 NameOfXMMRegister(vvvv)); 844 current += PrintRightXMMOperand(current); 845 AppendToBuffer(",%d", *reinterpret_cast<uint8_t*>(current)); 846 current++; 847 break; 848 case 0x14: 849 AppendToBuffer("vpextrb "); 850 current += PrintRightOperand(current); 851 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), 852 *reinterpret_cast<int8_t*>(current)); 853 current++; 854 break; 855 case 0x15: 856 AppendToBuffer("vpextrw "); 857 current += PrintRightOperand(current); 858 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), 859 *reinterpret_cast<int8_t*>(current)); 860 current++; 861 break; 862 case 0x16: 863 AppendToBuffer("vpextrd "); 864 current += PrintRightOperand(current); 865 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), 866 *reinterpret_cast<int8_t*>(current)); 867 current++; 868 break; 869 case 0x20: 870 AppendToBuffer("vpinsrb %s,%s,", NameOfXMMRegister(regop), 871 NameOfXMMRegister(vvvv)); 872 current += PrintRightOperand(current); 873 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current)); 874 current++; 875 break; 876 case 0x21: 877 AppendToBuffer("vinsertps %s,%s,", NameOfXMMRegister(regop), 878 NameOfXMMRegister(vvvv)); 879 current += PrintRightXMMOperand(current); 880 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current)); 881 current++; 882 break; 883 case 0x22: 884 AppendToBuffer("vpinsrd %s,%s,", NameOfXMMRegister(regop), 885 NameOfXMMRegister(vvvv)); 886 current += PrintRightOperand(current); 887 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current)); 888 current++; 889 break; 890 default: 891 UnimplementedInstruction(); 892 } 893 } else if (vex_f2() && vex_0f()) { 894 int mod, regop, rm, vvvv = vex_vreg(); 895 get_modrm(*current, &mod, ®op, &rm); 896 switch (opcode) { 897 case 0x51: 898 AppendToBuffer("vsqrtsd %s,%s,", NameOfXMMRegister(regop), 899 NameOfXMMRegister(vvvv)); 900 current += PrintRightXMMOperand(current); 901 break; 902 case 0x58: 903 AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop), 904 NameOfXMMRegister(vvvv)); 905 current += PrintRightXMMOperand(current); 906 break; 907 case 0x59: 908 AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop), 909 NameOfXMMRegister(vvvv)); 910 current += PrintRightXMMOperand(current); 911 break; 912 case 0x5C: 913 AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop), 914 NameOfXMMRegister(vvvv)); 915 current += PrintRightXMMOperand(current); 916 break; 917 case 0x5D: 918 AppendToBuffer("vminsd %s,%s,", NameOfXMMRegister(regop), 919 NameOfXMMRegister(vvvv)); 920 current += PrintRightXMMOperand(current); 921 break; 922 case 0x5E: 923 AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop), 924 NameOfXMMRegister(vvvv)); 925 current += PrintRightXMMOperand(current); 926 break; 927 case 0x5F: 928 AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop), 929 NameOfXMMRegister(vvvv)); 930 current += PrintRightXMMOperand(current); 931 break; 932 case 0x70: 933 AppendToBuffer("vpshuflw %s,", NameOfXMMRegister(regop)); 934 current += PrintRightXMMOperand(current); 935 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current)); 936 current++; 937 break; 938 case 0x7C: 939 AppendToBuffer("vhaddps %s,%s,", NameOfXMMRegister(regop), 940 NameOfXMMRegister(vvvv)); 941 current += PrintRightXMMOperand(current); 942 break; 943 default: 944 UnimplementedInstruction(); 945 } 946 } else if (vex_f3() && vex_0f()) { 947 int mod, regop, rm, vvvv = vex_vreg(); 948 get_modrm(*current, &mod, ®op, &rm); 949 switch (opcode) { 950 case 0x51: 951 AppendToBuffer("vsqrtss %s,%s,", NameOfXMMRegister(regop), 952 NameOfXMMRegister(vvvv)); 953 current += PrintRightXMMOperand(current); 954 break; 955 case 0x58: 956 AppendToBuffer("vaddss %s,%s,", NameOfXMMRegister(regop), 957 NameOfXMMRegister(vvvv)); 958 current += PrintRightXMMOperand(current); 959 break; 960 case 0x59: 961 AppendToBuffer("vmulss %s,%s,", NameOfXMMRegister(regop), 962 NameOfXMMRegister(vvvv)); 963 current += PrintRightXMMOperand(current); 964 break; 965 case 0x5B: 966 AppendToBuffer("vcvttps2dq %s,", NameOfXMMRegister(regop)); 967 current += PrintRightXMMOperand(current); 968 break; 969 case 0x5C: 970 AppendToBuffer("vsubss %s,%s,", NameOfXMMRegister(regop), 971 NameOfXMMRegister(vvvv)); 972 current += PrintRightXMMOperand(current); 973 break; 974 case 0x5D: 975 AppendToBuffer("vminss %s,%s,", NameOfXMMRegister(regop), 976 NameOfXMMRegister(vvvv)); 977 current += PrintRightXMMOperand(current); 978 break; 979 case 0x5E: 980 AppendToBuffer("vdivss %s,%s,", NameOfXMMRegister(regop), 981 NameOfXMMRegister(vvvv)); 982 current += PrintRightXMMOperand(current); 983 break; 984 case 0x5F: 985 AppendToBuffer("vmaxss %s,%s,", NameOfXMMRegister(regop), 986 NameOfXMMRegister(vvvv)); 987 current += PrintRightXMMOperand(current); 988 break; 989 case 0x6f: 990 AppendToBuffer("vmovdqu %s,", NameOfXMMRegister(regop)); 991 current += PrintRightOperand(current); 992 break; 993 case 0x70: 994 AppendToBuffer("vpshufhw %s,", NameOfXMMRegister(regop)); 995 current += PrintRightXMMOperand(current); 996 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current)); 997 current++; 998 break; 999 case 0x7f: 1000 AppendToBuffer("vmovdqu "); 1001 current += PrintRightOperand(current); 1002 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1003 break; 1004 default: 1005 UnimplementedInstruction(); 1006 } 1007 } else if (vex_none() && vex_0f38()) { 1008 int mod, regop, rm, vvvv = vex_vreg(); 1009 get_modrm(*current, &mod, ®op, &rm); 1010 const char* mnem = "?"; 1011 switch (opcode) { 1012 case 0xF2: 1013 AppendToBuffer("andn %s,%s,", NameOfCPURegister(regop), 1014 NameOfCPURegister(vvvv)); 1015 current += PrintRightOperand(current); 1016 break; 1017 case 0xF5: 1018 AppendToBuffer("bzhi %s,", NameOfCPURegister(regop)); 1019 current += PrintRightOperand(current); 1020 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); 1021 break; 1022 case 0xF7: 1023 AppendToBuffer("bextr %s,", NameOfCPURegister(regop)); 1024 current += PrintRightOperand(current); 1025 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); 1026 break; 1027 case 0xF3: 1028 switch (regop) { 1029 case 1: 1030 mnem = "blsr"; 1031 break; 1032 case 2: 1033 mnem = "blsmsk"; 1034 break; 1035 case 3: 1036 mnem = "blsi"; 1037 break; 1038 default: 1039 UnimplementedInstruction(); 1040 } 1041 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(vvvv)); 1042 current += PrintRightOperand(current); 1043 mnem = "?"; 1044 break; 1045 default: 1046 UnimplementedInstruction(); 1047 } 1048 } else if (vex_f2() && vex_0f38()) { 1049 int mod, regop, rm, vvvv = vex_vreg(); 1050 get_modrm(*current, &mod, ®op, &rm); 1051 switch (opcode) { 1052 case 0xF5: 1053 AppendToBuffer("pdep %s,%s,", NameOfCPURegister(regop), 1054 NameOfCPURegister(vvvv)); 1055 current += PrintRightOperand(current); 1056 break; 1057 case 0xF6: 1058 AppendToBuffer("mulx %s,%s,", NameOfCPURegister(regop), 1059 NameOfCPURegister(vvvv)); 1060 current += PrintRightOperand(current); 1061 break; 1062 case 0xF7: 1063 AppendToBuffer("shrx %s,", NameOfCPURegister(regop)); 1064 current += PrintRightOperand(current); 1065 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); 1066 break; 1067 default: 1068 UnimplementedInstruction(); 1069 } 1070 } else if (vex_f3() && vex_0f38()) { 1071 int mod, regop, rm, vvvv = vex_vreg(); 1072 get_modrm(*current, &mod, ®op, &rm); 1073 switch (opcode) { 1074 case 0xF5: 1075 AppendToBuffer("pext %s,%s,", NameOfCPURegister(regop), 1076 NameOfCPURegister(vvvv)); 1077 current += PrintRightOperand(current); 1078 break; 1079 case 0xF7: 1080 AppendToBuffer("sarx %s,", NameOfCPURegister(regop)); 1081 current += PrintRightOperand(current); 1082 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); 1083 break; 1084 default: 1085 UnimplementedInstruction(); 1086 } 1087 } else if (vex_f2() && vex_0f3a()) { 1088 int mod, regop, rm; 1089 get_modrm(*current, &mod, ®op, &rm); 1090 switch (opcode) { 1091 case 0xF0: 1092 AppendToBuffer("rorx %s,", NameOfCPURegister(regop)); 1093 current += PrintRightOperand(current); 1094 AppendToBuffer(",%d", *current & 0x1F); 1095 current += 1; 1096 break; 1097 default: 1098 UnimplementedInstruction(); 1099 } 1100 } else if (vex_none() && vex_0f()) { 1101 int mod, regop, rm, vvvv = vex_vreg(); 1102 get_modrm(*current, &mod, ®op, &rm); 1103 switch (opcode) { 1104 case 0x28: 1105 AppendToBuffer("vmovaps %s,", NameOfXMMRegister(regop)); 1106 current += PrintRightXMMOperand(current); 1107 break; 1108 case 0x52: 1109 AppendToBuffer("vrsqrtps %s,", NameOfXMMRegister(regop)); 1110 current += PrintRightXMMOperand(current); 1111 break; 1112 case 0x53: 1113 AppendToBuffer("vrcpps %s,", NameOfXMMRegister(regop)); 1114 current += PrintRightXMMOperand(current); 1115 break; 1116 case 0x54: 1117 AppendToBuffer("vandps %s,%s,", NameOfXMMRegister(regop), 1118 NameOfXMMRegister(vvvv)); 1119 current += PrintRightXMMOperand(current); 1120 break; 1121 case 0x57: 1122 AppendToBuffer("vxorps %s,%s,", NameOfXMMRegister(regop), 1123 NameOfXMMRegister(vvvv)); 1124 current += PrintRightXMMOperand(current); 1125 break; 1126 case 0x58: 1127 AppendToBuffer("vaddps %s,%s,", NameOfXMMRegister(regop), 1128 NameOfXMMRegister(vvvv)); 1129 current += PrintRightXMMOperand(current); 1130 break; 1131 case 0x59: 1132 AppendToBuffer("vmulps %s,%s,", NameOfXMMRegister(regop), 1133 NameOfXMMRegister(vvvv)); 1134 current += PrintRightXMMOperand(current); 1135 break; 1136 case 0x5B: 1137 AppendToBuffer("vcvtdq2ps %s,", NameOfXMMRegister(regop)); 1138 current += PrintRightXMMOperand(current); 1139 break; 1140 case 0x5C: 1141 AppendToBuffer("vsubps %s,%s,", NameOfXMMRegister(regop), 1142 NameOfXMMRegister(vvvv)); 1143 current += PrintRightXMMOperand(current); 1144 break; 1145 case 0x5D: 1146 AppendToBuffer("vminps %s,%s,", NameOfXMMRegister(regop), 1147 NameOfXMMRegister(vvvv)); 1148 current += PrintRightXMMOperand(current); 1149 break; 1150 case 0x5E: 1151 AppendToBuffer("vdivps %s,%s,", NameOfXMMRegister(regop), 1152 NameOfXMMRegister(vvvv)); 1153 current += PrintRightXMMOperand(current); 1154 break; 1155 case 0x5F: 1156 AppendToBuffer("vmaxps %s,%s,", NameOfXMMRegister(regop), 1157 NameOfXMMRegister(vvvv)); 1158 current += PrintRightXMMOperand(current); 1159 break; 1160 case 0xC2: { 1161 const char* const pseudo_op[] = {"eq", "lt", "le", "unord", 1162 "neq", "nlt", "nle", "ord"}; 1163 AppendToBuffer("vcmpps %s,%s,", NameOfXMMRegister(regop), 1164 NameOfXMMRegister(vvvv)); 1165 current += PrintRightXMMOperand(current); 1166 AppendToBuffer(", (%s)", pseudo_op[*current]); 1167 current++; 1168 break; 1169 } 1170 case 0xC6: 1171 AppendToBuffer("vshufps %s,%s,", NameOfXMMRegister(regop), 1172 NameOfXMMRegister(vvvv)); 1173 current += PrintRightXMMOperand(current); 1174 AppendToBuffer(", %d", (*current) & 3); 1175 current += 1; 1176 break; 1177 default: 1178 UnimplementedInstruction(); 1179 } 1180 } else if (vex_66() && vex_0f()) { 1181 int mod, regop, rm, vvvv = vex_vreg(); 1182 get_modrm(*current, &mod, ®op, &rm); 1183 switch (opcode) { 1184 case 0x54: 1185 AppendToBuffer("vandpd %s,%s,", NameOfXMMRegister(regop), 1186 NameOfXMMRegister(vvvv)); 1187 current += PrintRightXMMOperand(current); 1188 break; 1189 case 0x57: 1190 AppendToBuffer("vxorpd %s,%s,", NameOfXMMRegister(regop), 1191 NameOfXMMRegister(vvvv)); 1192 current += PrintRightXMMOperand(current); 1193 break; 1194 case 0x58: 1195 AppendToBuffer("vaddpd %s,%s,", NameOfXMMRegister(regop), 1196 NameOfXMMRegister(vvvv)); 1197 current += PrintRightXMMOperand(current); 1198 break; 1199 case 0x59: 1200 AppendToBuffer("vmulpd %s,%s,", NameOfXMMRegister(regop), 1201 NameOfXMMRegister(vvvv)); 1202 current += PrintRightXMMOperand(current); 1203 break; 1204 case 0x5C: 1205 AppendToBuffer("vsubpd %s,%s,", NameOfXMMRegister(regop), 1206 NameOfXMMRegister(vvvv)); 1207 current += PrintRightXMMOperand(current); 1208 break; 1209 case 0x5D: 1210 AppendToBuffer("vminpd %s,%s,", NameOfXMMRegister(regop), 1211 NameOfXMMRegister(vvvv)); 1212 current += PrintRightXMMOperand(current); 1213 break; 1214 case 0x5E: 1215 AppendToBuffer("vdivpd %s,%s,", NameOfXMMRegister(regop), 1216 NameOfXMMRegister(vvvv)); 1217 current += PrintRightXMMOperand(current); 1218 break; 1219 case 0x5F: 1220 AppendToBuffer("vmaxpd %s,%s,", NameOfXMMRegister(regop), 1221 NameOfXMMRegister(vvvv)); 1222 current += PrintRightXMMOperand(current); 1223 break; 1224 case 0x6E: 1225 AppendToBuffer("vmovd %s,", NameOfXMMRegister(regop)); 1226 current += PrintRightOperand(current); 1227 break; 1228 case 0x70: 1229 AppendToBuffer("vpshufd %s,", NameOfXMMRegister(regop)); 1230 current += PrintRightXMMOperand(current); 1231 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current)); 1232 current++; 1233 break; 1234 case 0x71: 1235 AppendToBuffer("vps%sw %s,%s", sf_str[regop / 2], 1236 NameOfXMMRegister(vvvv), NameOfXMMRegister(rm)); 1237 current++; 1238 AppendToBuffer(",%u", *current++); 1239 break; 1240 case 0x72: 1241 AppendToBuffer("vps%sd %s,%s", sf_str[regop / 2], 1242 NameOfXMMRegister(vvvv), NameOfXMMRegister(rm)); 1243 current++; 1244 AppendToBuffer(",%u", *current++); 1245 break; 1246 case 0x7E: 1247 AppendToBuffer("vmovd "); 1248 current += PrintRightOperand(current); 1249 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1250 break; 1251 case 0xC4: 1252 AppendToBuffer("vpinsrw %s,%s,", NameOfXMMRegister(regop), 1253 NameOfXMMRegister(vvvv)); 1254 current += PrintRightOperand(current); 1255 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current)); 1256 current++; 1257 break; 1258 #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \ 1259 case 0x##opcode: { \ 1260 AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \ 1261 NameOfXMMRegister(vvvv)); \ 1262 current += PrintRightXMMOperand(current); \ 1263 break; \ 1264 } 1265 1266 SSE2_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE) 1267 #undef DECLARE_SSE_AVX_DIS_CASE 1268 default: 1269 UnimplementedInstruction(); 1270 } 1271 } else { 1272 UnimplementedInstruction(); 1273 } 1274 1275 return static_cast<int>(current - data); 1276 } 1277 1278 1279 // Returns number of bytes used, including *data. 1280 int DisassemblerIA32::FPUInstruction(byte* data) { 1281 byte escape_opcode = *data; 1282 DCHECK_EQ(0xD8, escape_opcode & 0xF8); 1283 byte modrm_byte = *(data+1); 1284 1285 if (modrm_byte >= 0xC0) { 1286 return RegisterFPUInstruction(escape_opcode, modrm_byte); 1287 } else { 1288 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 1289 } 1290 } 1291 1292 int DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, 1293 int modrm_byte, 1294 byte* modrm_start) { 1295 const char* mnem = "?"; 1296 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. 1297 switch (escape_opcode) { 1298 case 0xD9: switch (regop) { 1299 case 0: mnem = "fld_s"; break; 1300 case 2: mnem = "fst_s"; break; 1301 case 3: mnem = "fstp_s"; break; 1302 case 7: mnem = "fstcw"; break; 1303 default: UnimplementedInstruction(); 1304 } 1305 break; 1306 1307 case 0xDB: switch (regop) { 1308 case 0: mnem = "fild_s"; break; 1309 case 1: mnem = "fisttp_s"; break; 1310 case 2: mnem = "fist_s"; break; 1311 case 3: mnem = "fistp_s"; break; 1312 default: UnimplementedInstruction(); 1313 } 1314 break; 1315 1316 case 0xDD: switch (regop) { 1317 case 0: mnem = "fld_d"; break; 1318 case 1: mnem = "fisttp_d"; break; 1319 case 2: mnem = "fst_d"; break; 1320 case 3: mnem = "fstp_d"; break; 1321 default: UnimplementedInstruction(); 1322 } 1323 break; 1324 1325 case 0xDF: switch (regop) { 1326 case 5: mnem = "fild_d"; break; 1327 case 7: mnem = "fistp_d"; break; 1328 default: UnimplementedInstruction(); 1329 } 1330 break; 1331 1332 default: UnimplementedInstruction(); 1333 } 1334 AppendToBuffer("%s ", mnem); 1335 int count = PrintRightOperand(modrm_start); 1336 return count + 1; 1337 } 1338 1339 int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode, 1340 byte modrm_byte) { 1341 bool has_register = false; // Is the FPU register encoded in modrm_byte? 1342 const char* mnem = "?"; 1343 1344 switch (escape_opcode) { 1345 case 0xD8: 1346 has_register = true; 1347 switch (modrm_byte & 0xF8) { 1348 case 0xC0: mnem = "fadd_i"; break; 1349 case 0xE0: mnem = "fsub_i"; break; 1350 case 0xC8: mnem = "fmul_i"; break; 1351 case 0xF0: mnem = "fdiv_i"; break; 1352 default: UnimplementedInstruction(); 1353 } 1354 break; 1355 1356 case 0xD9: 1357 switch (modrm_byte & 0xF8) { 1358 case 0xC0: 1359 mnem = "fld"; 1360 has_register = true; 1361 break; 1362 case 0xC8: 1363 mnem = "fxch"; 1364 has_register = true; 1365 break; 1366 default: 1367 switch (modrm_byte) { 1368 case 0xE0: mnem = "fchs"; break; 1369 case 0xE1: mnem = "fabs"; break; 1370 case 0xE4: mnem = "ftst"; break; 1371 case 0xE8: mnem = "fld1"; break; 1372 case 0xEB: mnem = "fldpi"; break; 1373 case 0xED: mnem = "fldln2"; break; 1374 case 0xEE: mnem = "fldz"; break; 1375 case 0xF0: mnem = "f2xm1"; break; 1376 case 0xF1: mnem = "fyl2x"; break; 1377 case 0xF4: mnem = "fxtract"; break; 1378 case 0xF5: mnem = "fprem1"; break; 1379 case 0xF7: mnem = "fincstp"; break; 1380 case 0xF8: mnem = "fprem"; break; 1381 case 0xFC: mnem = "frndint"; break; 1382 case 0xFD: mnem = "fscale"; break; 1383 case 0xFE: mnem = "fsin"; break; 1384 case 0xFF: mnem = "fcos"; break; 1385 default: UnimplementedInstruction(); 1386 } 1387 } 1388 break; 1389 1390 case 0xDA: 1391 if (modrm_byte == 0xE9) { 1392 mnem = "fucompp"; 1393 } else { 1394 UnimplementedInstruction(); 1395 } 1396 break; 1397 1398 case 0xDB: 1399 if ((modrm_byte & 0xF8) == 0xE8) { 1400 mnem = "fucomi"; 1401 has_register = true; 1402 } else if (modrm_byte == 0xE2) { 1403 mnem = "fclex"; 1404 } else if (modrm_byte == 0xE3) { 1405 mnem = "fninit"; 1406 } else { 1407 UnimplementedInstruction(); 1408 } 1409 break; 1410 1411 case 0xDC: 1412 has_register = true; 1413 switch (modrm_byte & 0xF8) { 1414 case 0xC0: mnem = "fadd"; break; 1415 case 0xE8: mnem = "fsub"; break; 1416 case 0xC8: mnem = "fmul"; break; 1417 case 0xF8: mnem = "fdiv"; break; 1418 default: UnimplementedInstruction(); 1419 } 1420 break; 1421 1422 case 0xDD: 1423 has_register = true; 1424 switch (modrm_byte & 0xF8) { 1425 case 0xC0: mnem = "ffree"; break; 1426 case 0xD0: mnem = "fst"; break; 1427 case 0xD8: mnem = "fstp"; break; 1428 default: UnimplementedInstruction(); 1429 } 1430 break; 1431 1432 case 0xDE: 1433 if (modrm_byte == 0xD9) { 1434 mnem = "fcompp"; 1435 } else { 1436 has_register = true; 1437 switch (modrm_byte & 0xF8) { 1438 case 0xC0: mnem = "faddp"; break; 1439 case 0xE8: mnem = "fsubp"; break; 1440 case 0xC8: mnem = "fmulp"; break; 1441 case 0xF8: mnem = "fdivp"; break; 1442 default: UnimplementedInstruction(); 1443 } 1444 } 1445 break; 1446 1447 case 0xDF: 1448 if (modrm_byte == 0xE0) { 1449 mnem = "fnstsw_ax"; 1450 } else if ((modrm_byte & 0xF8) == 0xE8) { 1451 mnem = "fucomip"; 1452 has_register = true; 1453 } 1454 break; 1455 1456 default: UnimplementedInstruction(); 1457 } 1458 1459 if (has_register) { 1460 AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); 1461 } else { 1462 AppendToBuffer("%s", mnem); 1463 } 1464 return 2; 1465 } 1466 1467 // Mnemonics for instructions 0xF0 byte. 1468 // Returns nullptr if the instruction is not handled here. 1469 static const char* F0Mnem(byte f0byte) { 1470 switch (f0byte) { 1471 case 0x0B: 1472 return "ud2"; 1473 case 0x18: 1474 return "prefetch"; 1475 case 0xA2: 1476 return "cpuid"; 1477 case 0xBE: 1478 return "movsx_b"; 1479 case 0xBF: 1480 return "movsx_w"; 1481 case 0xB6: 1482 return "movzx_b"; 1483 case 0xB7: 1484 return "movzx_w"; 1485 case 0xAF: 1486 return "imul"; 1487 case 0xA4: 1488 return "shld"; 1489 case 0xA5: 1490 return "shld"; 1491 case 0xAD: 1492 return "shrd"; 1493 case 0xAC: 1494 return "shrd"; // 3-operand version. 1495 case 0xAB: 1496 return "bts"; 1497 case 0xB0: 1498 return "cmpxchg_b"; 1499 case 0xB1: 1500 return "cmpxchg"; 1501 case 0xBC: 1502 return "bsf"; 1503 case 0xBD: 1504 return "bsr"; 1505 case 0xC7: 1506 return "cmpxchg8b"; 1507 default: 1508 return nullptr; 1509 } 1510 } 1511 1512 1513 // Disassembled instruction '*instr' and writes it into 'out_buffer'. 1514 int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, 1515 byte* instr) { 1516 tmp_buffer_pos_ = 0; // starting to write as position 0 1517 byte* data = instr; 1518 // Check for hints. 1519 const char* branch_hint = nullptr; 1520 // We use these two prefixes only with branch prediction 1521 if (*data == 0x3E /*ds*/) { 1522 branch_hint = "predicted taken"; 1523 data++; 1524 } else if (*data == 0x2E /*cs*/) { 1525 branch_hint = "predicted not taken"; 1526 data++; 1527 } else if (*data == 0xC4 && *(data + 1) >= 0xC0) { 1528 vex_byte0_ = *data; 1529 vex_byte1_ = *(data + 1); 1530 vex_byte2_ = *(data + 2); 1531 data += 3; 1532 } else if (*data == 0xC5 && *(data + 1) >= 0xC0) { 1533 vex_byte0_ = *data; 1534 vex_byte1_ = *(data + 1); 1535 data += 2; 1536 } else if (*data == 0xF0 /*lock*/) { 1537 AppendToBuffer("lock "); 1538 data++; 1539 } 1540 1541 bool processed = true; // Will be set to false if the current instruction 1542 // is not in 'instructions' table. 1543 // Decode AVX instructions. 1544 if (vex_byte0_ != 0) { 1545 data += AVXInstruction(data); 1546 } else { 1547 const InstructionDesc& idesc = instruction_table_->Get(*data); 1548 switch (idesc.type) { 1549 case ZERO_OPERANDS_INSTR: 1550 AppendToBuffer("%s", idesc.mnem); 1551 data++; 1552 break; 1553 1554 case TWO_OPERANDS_INSTR: 1555 data++; 1556 data += PrintOperands(idesc.mnem, idesc.op_order_, data); 1557 break; 1558 1559 case JUMP_CONDITIONAL_SHORT_INSTR: 1560 data += JumpConditionalShort(data, branch_hint); 1561 break; 1562 1563 case REGISTER_INSTR: 1564 AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); 1565 data++; 1566 break; 1567 1568 case MOVE_REG_INSTR: { 1569 byte* addr = 1570 reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1571 AppendToBuffer("mov %s,%s", NameOfCPURegister(*data & 0x07), 1572 NameOfAddress(addr)); 1573 data += 5; 1574 break; 1575 } 1576 1577 case CALL_JUMP_INSTR: { 1578 byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5; 1579 AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); 1580 data += 5; 1581 break; 1582 } 1583 1584 case SHORT_IMMEDIATE_INSTR: { 1585 byte* addr = 1586 reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1587 AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr)); 1588 data += 5; 1589 break; 1590 } 1591 1592 case BYTE_IMMEDIATE_INSTR: { 1593 AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]); 1594 data += 2; 1595 break; 1596 } 1597 1598 case NO_INSTR: 1599 processed = false; 1600 break; 1601 1602 default: 1603 UNIMPLEMENTED(); // This type is not implemented. 1604 } 1605 } 1606 //---------------------------- 1607 if (!processed) { 1608 switch (*data) { 1609 case 0xC2: 1610 AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1)); 1611 data += 3; 1612 break; 1613 1614 case 0x6B: { 1615 data++; 1616 data += PrintOperands("imul", REG_OPER_OP_ORDER, data); 1617 AppendToBuffer(",%d", *data); 1618 data++; 1619 } break; 1620 1621 case 0x69: { 1622 data++; 1623 data += PrintOperands("imul", REG_OPER_OP_ORDER, data); 1624 AppendToBuffer(",%d", *reinterpret_cast<int32_t*>(data)); 1625 data += 4; 1626 } 1627 break; 1628 1629 case 0xF6: 1630 { data++; 1631 int mod, regop, rm; 1632 get_modrm(*data, &mod, ®op, &rm); 1633 if (regop == eax) { 1634 AppendToBuffer("test_b "); 1635 data += PrintRightByteOperand(data); 1636 int32_t imm = *data; 1637 AppendToBuffer(",0x%x", imm); 1638 data++; 1639 } else { 1640 UnimplementedInstruction(); 1641 } 1642 } 1643 break; 1644 1645 case 0x81: // fall through 1646 case 0x83: // 0x81 with sign extension bit set 1647 data += PrintImmediateOp(data); 1648 break; 1649 1650 case 0x0F: 1651 { byte f0byte = data[1]; 1652 const char* f0mnem = F0Mnem(f0byte); 1653 if (f0byte == 0x18) { 1654 data += 2; 1655 int mod, regop, rm; 1656 get_modrm(*data, &mod, ®op, &rm); 1657 const char* suffix[] = {"nta", "1", "2", "3"}; 1658 AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]); 1659 data += PrintRightOperand(data); 1660 } else if (f0byte == 0x1F && data[2] == 0) { 1661 AppendToBuffer("nop"); // 3 byte nop. 1662 data += 3; 1663 } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) { 1664 AppendToBuffer("nop"); // 4 byte nop. 1665 data += 4; 1666 } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 && 1667 data[4] == 0) { 1668 AppendToBuffer("nop"); // 5 byte nop. 1669 data += 5; 1670 } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 && 1671 data[4] == 0 && data[5] == 0 && data[6] == 0) { 1672 AppendToBuffer("nop"); // 7 byte nop. 1673 data += 7; 1674 } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 && 1675 data[4] == 0 && data[5] == 0 && data[6] == 0 && 1676 data[7] == 0) { 1677 AppendToBuffer("nop"); // 8 byte nop. 1678 data += 8; 1679 } else if (f0byte == 0x0B || f0byte == 0xA2 || f0byte == 0x31) { 1680 AppendToBuffer("%s", f0mnem); 1681 data += 2; 1682 } else if (f0byte == 0x28) { 1683 data += 2; 1684 int mod, regop, rm; 1685 get_modrm(*data, &mod, ®op, &rm); 1686 AppendToBuffer("movaps %s,%s", 1687 NameOfXMMRegister(regop), 1688 NameOfXMMRegister(rm)); 1689 data++; 1690 } else if (f0byte == 0x10 || f0byte == 0x11) { 1691 data += 2; 1692 // movups xmm, xmm/m128 1693 // movups xmm/m128, xmm 1694 int mod, regop, rm; 1695 get_modrm(*data, &mod, ®op, &rm); 1696 AppendToBuffer("movups "); 1697 if (f0byte == 0x11) { 1698 data += PrintRightXMMOperand(data); 1699 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1700 } else { 1701 AppendToBuffer("%s,", NameOfXMMRegister(regop)); 1702 data += PrintRightXMMOperand(data); 1703 } 1704 } else if (f0byte == 0x2E) { 1705 data += 2; 1706 int mod, regop, rm; 1707 get_modrm(*data, &mod, ®op, &rm); 1708 AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop)); 1709 data += PrintRightXMMOperand(data); 1710 } else if (f0byte >= 0x52 && f0byte <= 0x5F) { 1711 const char* const pseudo_op[] = { 1712 "rsqrtps", "rcpps", "andps", "andnps", "orps", 1713 "xorps", "addps", "mulps", "cvtps2pd", "cvtdq2ps", 1714 "subps", "minps", "divps", "maxps", 1715 }; 1716 1717 data += 2; 1718 int mod, regop, rm; 1719 get_modrm(*data, &mod, ®op, &rm); 1720 AppendToBuffer("%s %s,", pseudo_op[f0byte - 0x52], 1721 NameOfXMMRegister(regop)); 1722 data += PrintRightXMMOperand(data); 1723 } else if (f0byte == 0x50) { 1724 data += 2; 1725 int mod, regop, rm; 1726 get_modrm(*data, &mod, ®op, &rm); 1727 AppendToBuffer("movmskps %s,%s", 1728 NameOfCPURegister(regop), 1729 NameOfXMMRegister(rm)); 1730 data++; 1731 } else if (f0byte == 0xC2) { 1732 data += 2; 1733 int mod, regop, rm; 1734 get_modrm(*data, &mod, ®op, &rm); 1735 const char* const pseudo_op[] = {"eq", "lt", "le", "unord", 1736 "neq", "nlt", "nle", "ord"}; 1737 AppendToBuffer("cmpps %s, ", NameOfXMMRegister(regop)); 1738 data += PrintRightXMMOperand(data); 1739 AppendToBuffer(", (%s)", pseudo_op[*data]); 1740 data++; 1741 } else if (f0byte== 0xC6) { 1742 // shufps xmm, xmm/m128, imm8 1743 data += 2; 1744 int mod, regop, rm; 1745 get_modrm(*data, &mod, ®op, &rm); 1746 int8_t imm8 = static_cast<int8_t>(data[1]); 1747 AppendToBuffer("shufps %s,%s,%d", 1748 NameOfXMMRegister(rm), 1749 NameOfXMMRegister(regop), 1750 static_cast<int>(imm8)); 1751 data += 2; 1752 } else if (f0byte >= 0xC8 && f0byte <= 0xCF) { 1753 // bswap 1754 data += 2; 1755 int reg = f0byte - 0xC8; 1756 AppendToBuffer("bswap %s", NameOfCPURegister(reg)); 1757 } else if ((f0byte & 0xF0) == 0x80) { 1758 data += JumpConditional(data, branch_hint); 1759 } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 || 1760 f0byte == 0xB7 || f0byte == 0xAF) { 1761 data += 2; 1762 data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data); 1763 } else if ((f0byte & 0xF0) == 0x90) { 1764 data += SetCC(data); 1765 } else if ((f0byte & 0xF0) == 0x40) { 1766 data += CMov(data); 1767 } else if (f0byte == 0xA4 || f0byte == 0xAC) { 1768 // shld, shrd 1769 data += 2; 1770 AppendToBuffer("%s ", f0mnem); 1771 int mod, regop, rm; 1772 get_modrm(*data, &mod, ®op, &rm); 1773 int8_t imm8 = static_cast<int8_t>(data[1]); 1774 data += 2; 1775 AppendToBuffer("%s,%s,%d", NameOfCPURegister(rm), 1776 NameOfCPURegister(regop), static_cast<int>(imm8)); 1777 } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) { 1778 // shrd_cl, shld_cl, bts 1779 data += 2; 1780 AppendToBuffer("%s ", f0mnem); 1781 int mod, regop, rm; 1782 get_modrm(*data, &mod, ®op, &rm); 1783 data += PrintRightOperand(data); 1784 if (f0byte == 0xAB) { 1785 AppendToBuffer(",%s", NameOfCPURegister(regop)); 1786 } else { 1787 AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); 1788 } 1789 } else if (f0byte == 0xB0) { 1790 // cmpxchg_b 1791 data += 2; 1792 AppendToBuffer("%s ", f0mnem); 1793 int mod, regop, rm; 1794 get_modrm(*data, &mod, ®op, &rm); 1795 data += PrintRightOperand(data); 1796 AppendToBuffer(",%s", NameOfByteCPURegister(regop)); 1797 } else if (f0byte == 0xB1) { 1798 // cmpxchg 1799 data += 2; 1800 data += PrintOperands(f0mnem, OPER_REG_OP_ORDER, data); 1801 } else if (f0byte == 0xBC) { 1802 data += 2; 1803 int mod, regop, rm; 1804 get_modrm(*data, &mod, ®op, &rm); 1805 AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop)); 1806 data += PrintRightOperand(data); 1807 } else if (f0byte == 0xBD) { 1808 data += 2; 1809 int mod, regop, rm; 1810 get_modrm(*data, &mod, ®op, &rm); 1811 AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop)); 1812 data += PrintRightOperand(data); 1813 } else if (f0byte == 0xC7) { 1814 // cmpxchg8b 1815 data += 2; 1816 AppendToBuffer("%s ", f0mnem); 1817 int mod, regop, rm; 1818 get_modrm(*data, &mod, ®op, &rm); 1819 data += PrintRightOperand(data); 1820 } else if (f0byte == 0xAE && (data[2] & 0xF8) == 0xE8) { 1821 AppendToBuffer("lfence"); 1822 data += 3; 1823 } else { 1824 UnimplementedInstruction(); 1825 } 1826 } 1827 break; 1828 1829 case 0x8F: 1830 { data++; 1831 int mod, regop, rm; 1832 get_modrm(*data, &mod, ®op, &rm); 1833 if (regop == eax) { 1834 AppendToBuffer("pop "); 1835 data += PrintRightOperand(data); 1836 } 1837 } 1838 break; 1839 1840 case 0xFF: 1841 { data++; 1842 int mod, regop, rm; 1843 get_modrm(*data, &mod, ®op, &rm); 1844 const char* mnem = nullptr; 1845 switch (regop) { 1846 case esi: mnem = "push"; break; 1847 case eax: mnem = "inc"; break; 1848 case ecx: mnem = "dec"; break; 1849 case edx: mnem = "call"; break; 1850 case esp: mnem = "jmp"; break; 1851 default: mnem = "???"; 1852 } 1853 AppendToBuffer("%s ", mnem); 1854 data += PrintRightOperand(data); 1855 } 1856 break; 1857 1858 case 0xC7: // imm32, fall through 1859 case 0xC6: // imm8 1860 { bool is_byte = *data == 0xC6; 1861 data++; 1862 if (is_byte) { 1863 AppendToBuffer("%s ", "mov_b"); 1864 data += PrintRightByteOperand(data); 1865 int32_t imm = *data; 1866 AppendToBuffer(",0x%x", imm); 1867 data++; 1868 } else { 1869 AppendToBuffer("%s ", "mov"); 1870 data += PrintRightOperand(data); 1871 int32_t imm = *reinterpret_cast<int32_t*>(data); 1872 AppendToBuffer(",0x%x", imm); 1873 data += 4; 1874 } 1875 } 1876 break; 1877 1878 case 0x80: 1879 { data++; 1880 int mod, regop, rm; 1881 get_modrm(*data, &mod, ®op, &rm); 1882 const char* mnem = nullptr; 1883 switch (regop) { 1884 case 5: mnem = "subb"; break; 1885 case 7: mnem = "cmpb"; break; 1886 default: UnimplementedInstruction(); 1887 } 1888 AppendToBuffer("%s ", mnem); 1889 data += PrintRightByteOperand(data); 1890 int32_t imm = *data; 1891 AppendToBuffer(",0x%x", imm); 1892 data++; 1893 } 1894 break; 1895 1896 case 0x88: // 8bit, fall through 1897 case 0x89: // 32bit 1898 { bool is_byte = *data == 0x88; 1899 int mod, regop, rm; 1900 data++; 1901 get_modrm(*data, &mod, ®op, &rm); 1902 if (is_byte) { 1903 AppendToBuffer("%s ", "mov_b"); 1904 data += PrintRightByteOperand(data); 1905 AppendToBuffer(",%s", NameOfByteCPURegister(regop)); 1906 } else { 1907 AppendToBuffer("%s ", "mov"); 1908 data += PrintRightOperand(data); 1909 AppendToBuffer(",%s", NameOfCPURegister(regop)); 1910 } 1911 } 1912 break; 1913 1914 case 0x66: // prefix 1915 while (*data == 0x66) data++; 1916 if (*data == 0xF && data[1] == 0x1F) { 1917 AppendToBuffer("nop"); // 0x66 prefix 1918 } else if (*data == 0x39) { 1919 data++; 1920 data += PrintOperands("cmpw", OPER_REG_OP_ORDER, data); 1921 } else if (*data == 0x3B) { 1922 data++; 1923 data += PrintOperands("cmpw", REG_OPER_OP_ORDER, data); 1924 } else if (*data == 0x81) { 1925 data++; 1926 AppendToBuffer("cmpw "); 1927 data += PrintRightOperand(data); 1928 int imm = *reinterpret_cast<int16_t*>(data); 1929 AppendToBuffer(",0x%x", imm); 1930 data += 2; 1931 } else if (*data == 0x87) { 1932 data++; 1933 int mod, regop, rm; 1934 get_modrm(*data, &mod, ®op, &rm); 1935 AppendToBuffer("xchg_w %s,", NameOfCPURegister(regop)); 1936 data += PrintRightOperand(data); 1937 } else if (*data == 0x89) { 1938 data++; 1939 int mod, regop, rm; 1940 get_modrm(*data, &mod, ®op, &rm); 1941 AppendToBuffer("mov_w "); 1942 data += PrintRightOperand(data); 1943 AppendToBuffer(",%s", NameOfCPURegister(regop)); 1944 } else if (*data == 0x8B) { 1945 data++; 1946 data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data); 1947 } else if (*data == 0x90) { 1948 AppendToBuffer("nop"); // 0x66 prefix 1949 } else if (*data == 0xC7) { 1950 data++; 1951 AppendToBuffer("%s ", "mov_w"); 1952 data += PrintRightOperand(data); 1953 int imm = *reinterpret_cast<int16_t*>(data); 1954 AppendToBuffer(",0x%x", imm); 1955 data += 2; 1956 } else if (*data == 0xF7) { 1957 data++; 1958 AppendToBuffer("%s ", "test_w"); 1959 data += PrintRightOperand(data); 1960 int imm = *reinterpret_cast<int16_t*>(data); 1961 AppendToBuffer(",0x%x", imm); 1962 data += 2; 1963 } else if (*data == 0x0F) { 1964 data++; 1965 if (*data == 0x38) { 1966 data++; 1967 byte op = *data; 1968 data++; 1969 int mod, regop, rm; 1970 get_modrm(*data, &mod, ®op, &rm); 1971 switch (op) { 1972 #define SSE34_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, opcode) \ 1973 case 0x##opcode: { \ 1974 AppendToBuffer(#instruction " %s,", NameOfXMMRegister(regop)); \ 1975 data += PrintRightXMMOperand(data); \ 1976 break; \ 1977 } 1978 1979 SSSE3_INSTRUCTION_LIST(SSE34_DIS_CASE) 1980 SSE4_INSTRUCTION_LIST(SSE34_DIS_CASE) 1981 SSE4_RM_INSTRUCTION_LIST(SSE34_DIS_CASE) 1982 #undef SSE34_DIS_CASE 1983 default: 1984 UnimplementedInstruction(); 1985 } 1986 } else if (*data == 0x3A) { 1987 data++; 1988 if (*data == 0x0A) { 1989 data++; 1990 int mod, regop, rm; 1991 get_modrm(*data, &mod, ®op, &rm); 1992 int8_t imm8 = static_cast<int8_t>(data[1]); 1993 AppendToBuffer("roundss %s,%s,%d", NameOfXMMRegister(regop), 1994 NameOfXMMRegister(rm), static_cast<int>(imm8)); 1995 data += 2; 1996 } else if (*data == 0x0B) { 1997 data++; 1998 int mod, regop, rm; 1999 get_modrm(*data, &mod, ®op, &rm); 2000 int8_t imm8 = static_cast<int8_t>(data[1]); 2001 AppendToBuffer("roundsd %s,%s,%d", 2002 NameOfXMMRegister(regop), 2003 NameOfXMMRegister(rm), 2004 static_cast<int>(imm8)); 2005 data += 2; 2006 } else if (*data == 0x0E) { 2007 data++; 2008 int mod, regop, rm; 2009 get_modrm(*data, &mod, ®op, &rm); 2010 AppendToBuffer("pblendw %s,", NameOfXMMRegister(regop)); 2011 data += PrintRightXMMOperand(data); 2012 AppendToBuffer(",%d", *reinterpret_cast<uint8_t*>(data)); 2013 data++; 2014 } else if (*data == 0x0F) { 2015 data++; 2016 int mod, regop, rm; 2017 get_modrm(*data, &mod, ®op, &rm); 2018 AppendToBuffer("palignr %s,", NameOfXMMRegister(regop)); 2019 data += PrintRightXMMOperand(data); 2020 AppendToBuffer(",%d", *reinterpret_cast<uint8_t*>(data)); 2021 data++; 2022 } else if (*data == 0x14) { 2023 data++; 2024 int mod, regop, rm; 2025 get_modrm(*data, &mod, ®op, &rm); 2026 AppendToBuffer("pextrb "); 2027 data += PrintRightOperand(data); 2028 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), 2029 *reinterpret_cast<int8_t*>(data)); 2030 data++; 2031 } else if (*data == 0x15) { 2032 data++; 2033 int mod, regop, rm; 2034 get_modrm(*data, &mod, ®op, &rm); 2035 AppendToBuffer("pextrw "); 2036 data += PrintRightOperand(data); 2037 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), 2038 *reinterpret_cast<int8_t*>(data)); 2039 data++; 2040 } else if (*data == 0x16) { 2041 data++; 2042 int mod, regop, rm; 2043 get_modrm(*data, &mod, ®op, &rm); 2044 AppendToBuffer("pextrd "); 2045 data += PrintRightOperand(data); 2046 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), 2047 *reinterpret_cast<int8_t*>(data)); 2048 data++; 2049 } else if (*data == 0x17) { 2050 data++; 2051 int mod, regop, rm; 2052 get_modrm(*data, &mod, ®op, &rm); 2053 int8_t imm8 = static_cast<int8_t>(data[1]); 2054 AppendToBuffer("extractps %s,%s,%d", 2055 NameOfCPURegister(rm), 2056 NameOfXMMRegister(regop), 2057 static_cast<int>(imm8)); 2058 data += 2; 2059 } else if (*data == 0x20) { 2060 data++; 2061 int mod, regop, rm; 2062 get_modrm(*data, &mod, ®op, &rm); 2063 AppendToBuffer("pinsrb %s,", NameOfXMMRegister(regop)); 2064 data += PrintRightOperand(data); 2065 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data)); 2066 data++; 2067 } else if (*data == 0x21) { 2068 data++; 2069 int mod, regop, rm; 2070 get_modrm(*data, &mod, ®op, &rm); 2071 AppendToBuffer("insertps %s,", NameOfXMMRegister(regop)); 2072 data += PrintRightXMMOperand(data); 2073 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data)); 2074 data++; 2075 } else if (*data == 0x22) { 2076 data++; 2077 int mod, regop, rm; 2078 get_modrm(*data, &mod, ®op, &rm); 2079 AppendToBuffer("pinsrd %s,", NameOfXMMRegister(regop)); 2080 data += PrintRightOperand(data); 2081 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data)); 2082 data++; 2083 } else { 2084 UnimplementedInstruction(); 2085 } 2086 } else if (*data == 0x2E || *data == 0x2F) { 2087 const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd"; 2088 data++; 2089 int mod, regop, rm; 2090 get_modrm(*data, &mod, ®op, &rm); 2091 if (mod == 0x3) { 2092 AppendToBuffer("%s %s,%s", mnem, 2093 NameOfXMMRegister(regop), 2094 NameOfXMMRegister(rm)); 2095 data++; 2096 } else { 2097 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 2098 data += PrintRightOperand(data); 2099 } 2100 } else if (*data == 0x50) { 2101 data++; 2102 int mod, regop, rm; 2103 get_modrm(*data, &mod, ®op, &rm); 2104 AppendToBuffer("movmskpd %s,%s", 2105 NameOfCPURegister(regop), 2106 NameOfXMMRegister(rm)); 2107 data++; 2108 } else if (*data == 0x54) { 2109 data++; 2110 int mod, regop, rm; 2111 get_modrm(*data, &mod, ®op, &rm); 2112 AppendToBuffer("andpd %s,%s", 2113 NameOfXMMRegister(regop), 2114 NameOfXMMRegister(rm)); 2115 data++; 2116 } else if (*data == 0x56) { 2117 data++; 2118 int mod, regop, rm; 2119 get_modrm(*data, &mod, ®op, &rm); 2120 AppendToBuffer("orpd %s,%s", 2121 NameOfXMMRegister(regop), 2122 NameOfXMMRegister(rm)); 2123 data++; 2124 } else if (*data == 0x57) { 2125 data++; 2126 int mod, regop, rm; 2127 get_modrm(*data, &mod, ®op, &rm); 2128 AppendToBuffer("xorpd %s,%s", 2129 NameOfXMMRegister(regop), 2130 NameOfXMMRegister(rm)); 2131 data++; 2132 } else if (*data == 0x6E) { 2133 data++; 2134 int mod, regop, rm; 2135 get_modrm(*data, &mod, ®op, &rm); 2136 AppendToBuffer("movd %s,", NameOfXMMRegister(regop)); 2137 data += PrintRightOperand(data); 2138 } else if (*data == 0x6F) { 2139 data++; 2140 int mod, regop, rm; 2141 get_modrm(*data, &mod, ®op, &rm); 2142 AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop)); 2143 data += PrintRightXMMOperand(data); 2144 } else if (*data == 0x70) { 2145 data++; 2146 int mod, regop, rm; 2147 get_modrm(*data, &mod, ®op, &rm); 2148 AppendToBuffer("pshufd %s,", NameOfXMMRegister(regop)); 2149 data += PrintRightXMMOperand(data); 2150 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data)); 2151 data++; 2152 } else if (*data == 0x90) { 2153 data++; 2154 AppendToBuffer("nop"); // 2 byte nop. 2155 } else if (*data == 0xF3) { 2156 data++; 2157 int mod, regop, rm; 2158 get_modrm(*data, &mod, ®op, &rm); 2159 AppendToBuffer("psllq %s,%s", 2160 NameOfXMMRegister(regop), 2161 NameOfXMMRegister(rm)); 2162 data++; 2163 } else if (*data == 0x71) { 2164 data++; 2165 int mod, regop, rm; 2166 get_modrm(*data, &mod, ®op, &rm); 2167 int8_t imm8 = static_cast<int8_t>(data[1]); 2168 AppendToBuffer("ps%sw %s,%d", sf_str[regop / 2], 2169 NameOfXMMRegister(rm), static_cast<int>(imm8)); 2170 data += 2; 2171 } else if (*data == 0x72) { 2172 data++; 2173 int mod, regop, rm; 2174 get_modrm(*data, &mod, ®op, &rm); 2175 int8_t imm8 = static_cast<int8_t>(data[1]); 2176 AppendToBuffer("ps%sd %s,%d", sf_str[regop / 2], 2177 NameOfXMMRegister(rm), static_cast<int>(imm8)); 2178 data += 2; 2179 } else if (*data == 0x73) { 2180 data++; 2181 int mod, regop, rm; 2182 get_modrm(*data, &mod, ®op, &rm); 2183 int8_t imm8 = static_cast<int8_t>(data[1]); 2184 DCHECK(regop == esi || regop == edx); 2185 AppendToBuffer("ps%sq %s,%d", sf_str[regop / 2], 2186 NameOfXMMRegister(rm), static_cast<int>(imm8)); 2187 data += 2; 2188 } else if (*data == 0xD3) { 2189 data++; 2190 int mod, regop, rm; 2191 get_modrm(*data, &mod, ®op, &rm); 2192 AppendToBuffer("psrlq %s,%s", 2193 NameOfXMMRegister(regop), 2194 NameOfXMMRegister(rm)); 2195 data++; 2196 } else if (*data == 0x7F) { 2197 AppendToBuffer("movdqa "); 2198 data++; 2199 int mod, regop, rm; 2200 get_modrm(*data, &mod, ®op, &rm); 2201 data += PrintRightXMMOperand(data); 2202 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 2203 } else if (*data == 0x7E) { 2204 data++; 2205 int mod, regop, rm; 2206 get_modrm(*data, &mod, ®op, &rm); 2207 AppendToBuffer("movd "); 2208 data += PrintRightOperand(data); 2209 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 2210 } else if (*data == 0xC4) { 2211 data++; 2212 int mod, regop, rm; 2213 get_modrm(*data, &mod, ®op, &rm); 2214 AppendToBuffer("pinsrw %s,", NameOfXMMRegister(regop)); 2215 data += PrintRightOperand(data); 2216 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data)); 2217 data++; 2218 } else if (*data == 0xE7) { 2219 data++; 2220 int mod, regop, rm; 2221 get_modrm(*data, &mod, ®op, &rm); 2222 if (mod == 3) { 2223 // movntdq 2224 UnimplementedInstruction(); 2225 } else { 2226 UnimplementedInstruction(); 2227 } 2228 } else if (*data == 0xB1) { 2229 data++; 2230 data += PrintOperands("cmpxchg_w", OPER_REG_OP_ORDER, data); 2231 } else { 2232 byte op = *data; 2233 data++; 2234 int mod, regop, rm; 2235 get_modrm(*data, &mod, ®op, &rm); 2236 switch (op) { 2237 #define SSE2_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \ 2238 case 0x##opcode: { \ 2239 AppendToBuffer(#instruction " %s,", NameOfXMMRegister(regop)); \ 2240 data += PrintRightXMMOperand(data); \ 2241 break; \ 2242 } 2243 2244 SSE2_INSTRUCTION_LIST(SSE2_DIS_CASE) 2245 #undef SSE2_DIS_CASE 2246 default: 2247 UnimplementedInstruction(); 2248 } 2249 } 2250 } else { 2251 UnimplementedInstruction(); 2252 } 2253 break; 2254 2255 case 0xFE: 2256 { data++; 2257 int mod, regop, rm; 2258 get_modrm(*data, &mod, ®op, &rm); 2259 if (regop == ecx) { 2260 AppendToBuffer("dec_b "); 2261 data += PrintRightOperand(data); 2262 } else { 2263 UnimplementedInstruction(); 2264 } 2265 } 2266 break; 2267 2268 case 0x68: 2269 AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1)); 2270 data += 5; 2271 break; 2272 2273 case 0x6A: 2274 AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 2275 data += 2; 2276 break; 2277 2278 case 0xA8: 2279 AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1)); 2280 data += 2; 2281 break; 2282 2283 case 0xA9: 2284 AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1)); 2285 data += 5; 2286 break; 2287 2288 case 0xD1: // fall through 2289 case 0xD3: // fall through 2290 case 0xC1: 2291 data += D1D3C1Instruction(data); 2292 break; 2293 2294 case 0xD8: // fall through 2295 case 0xD9: // fall through 2296 case 0xDA: // fall through 2297 case 0xDB: // fall through 2298 case 0xDC: // fall through 2299 case 0xDD: // fall through 2300 case 0xDE: // fall through 2301 case 0xDF: 2302 data += FPUInstruction(data); 2303 break; 2304 2305 case 0xEB: 2306 data += JumpShort(data); 2307 break; 2308 2309 case 0xF2: 2310 if (*(data+1) == 0x0F) { 2311 byte b2 = *(data+2); 2312 if (b2 == 0x11) { 2313 AppendToBuffer("movsd "); 2314 data += 3; 2315 int mod, regop, rm; 2316 get_modrm(*data, &mod, ®op, &rm); 2317 data += PrintRightXMMOperand(data); 2318 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 2319 } else if (b2 == 0x10) { 2320 data += 3; 2321 int mod, regop, rm; 2322 get_modrm(*data, &mod, ®op, &rm); 2323 AppendToBuffer("movsd %s,", NameOfXMMRegister(regop)); 2324 data += PrintRightXMMOperand(data); 2325 } else if (b2 == 0x5A) { 2326 data += 3; 2327 int mod, regop, rm; 2328 get_modrm(*data, &mod, ®op, &rm); 2329 AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop)); 2330 data += PrintRightXMMOperand(data); 2331 } else if (b2 == 0x70) { 2332 data += 3; 2333 int mod, regop, rm; 2334 get_modrm(*data, &mod, ®op, &rm); 2335 AppendToBuffer("pshuflw %s,", NameOfXMMRegister(regop)); 2336 data += PrintRightXMMOperand(data); 2337 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data)); 2338 data++; 2339 } else { 2340 const char* mnem = "?"; 2341 switch (b2) { 2342 case 0x2A: 2343 mnem = "cvtsi2sd"; 2344 break; 2345 case 0x2C: 2346 mnem = "cvttsd2si"; 2347 break; 2348 case 0x2D: 2349 mnem = "cvtsd2si"; 2350 break; 2351 case 0x51: 2352 mnem = "sqrtsd"; 2353 break; 2354 case 0x58: 2355 mnem = "addsd"; 2356 break; 2357 case 0x59: 2358 mnem = "mulsd"; 2359 break; 2360 case 0x5C: 2361 mnem = "subsd"; 2362 break; 2363 case 0x5D: 2364 mnem = "minsd"; 2365 break; 2366 case 0x5E: 2367 mnem = "divsd"; 2368 break; 2369 case 0x5F: 2370 mnem = "maxsd"; 2371 break; 2372 case 0x7C: 2373 mnem = "haddps"; 2374 break; 2375 } 2376 data += 3; 2377 int mod, regop, rm; 2378 get_modrm(*data, &mod, ®op, &rm); 2379 if (b2 == 0x2A) { 2380 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 2381 data += PrintRightOperand(data); 2382 } else if (b2 == 0x2C || b2 == 0x2D) { 2383 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 2384 data += PrintRightXMMOperand(data); 2385 } else if (b2 == 0xC2) { 2386 // Intel manual 2A, Table 3-18. 2387 const char* const pseudo_op[] = { 2388 "cmpeqsd", 2389 "cmpltsd", 2390 "cmplesd", 2391 "cmpunordsd", 2392 "cmpneqsd", 2393 "cmpnltsd", 2394 "cmpnlesd", 2395 "cmpordsd" 2396 }; 2397 AppendToBuffer("%s %s,%s", 2398 pseudo_op[data[1]], 2399 NameOfXMMRegister(regop), 2400 NameOfXMMRegister(rm)); 2401 data += 2; 2402 } else { 2403 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 2404 data += PrintRightXMMOperand(data); 2405 } 2406 } 2407 } else { 2408 UnimplementedInstruction(); 2409 } 2410 break; 2411 2412 case 0xF3: 2413 if (*(data+1) == 0x0F) { 2414 byte b2 = *(data+2); 2415 if (b2 == 0x11) { 2416 AppendToBuffer("movss "); 2417 data += 3; 2418 int mod, regop, rm; 2419 get_modrm(*data, &mod, ®op, &rm); 2420 data += PrintRightXMMOperand(data); 2421 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 2422 } else if (b2 == 0x10) { 2423 data += 3; 2424 int mod, regop, rm; 2425 get_modrm(*data, &mod, ®op, &rm); 2426 AppendToBuffer("movss %s,", NameOfXMMRegister(regop)); 2427 data += PrintRightXMMOperand(data); 2428 } else if (b2 == 0x5A) { 2429 data += 3; 2430 int mod, regop, rm; 2431 get_modrm(*data, &mod, ®op, &rm); 2432 AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); 2433 data += PrintRightXMMOperand(data); 2434 } else if (b2 == 0x6F) { 2435 data += 3; 2436 int mod, regop, rm; 2437 get_modrm(*data, &mod, ®op, &rm); 2438 AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop)); 2439 data += PrintRightXMMOperand(data); 2440 } else if (b2 == 0x70) { 2441 data += 3; 2442 int mod, regop, rm; 2443 get_modrm(*data, &mod, ®op, &rm); 2444 AppendToBuffer("pshufhw %s,", NameOfXMMRegister(regop)); 2445 data += PrintRightXMMOperand(data); 2446 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data)); 2447 data++; 2448 } else if (b2 == 0x7F) { 2449 AppendToBuffer("movdqu "); 2450 data += 3; 2451 int mod, regop, rm; 2452 get_modrm(*data, &mod, ®op, &rm); 2453 data += PrintRightXMMOperand(data); 2454 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 2455 } else if (b2 == 0xB8) { 2456 data += 3; 2457 int mod, regop, rm; 2458 get_modrm(*data, &mod, ®op, &rm); 2459 AppendToBuffer("popcnt %s,", NameOfCPURegister(regop)); 2460 data += PrintRightOperand(data); 2461 } else if (b2 == 0xBC) { 2462 data += 3; 2463 int mod, regop, rm; 2464 get_modrm(*data, &mod, ®op, &rm); 2465 AppendToBuffer("tzcnt %s,", NameOfCPURegister(regop)); 2466 data += PrintRightOperand(data); 2467 } else if (b2 == 0xBD) { 2468 data += 3; 2469 int mod, regop, rm; 2470 get_modrm(*data, &mod, ®op, &rm); 2471 AppendToBuffer("lzcnt %s,", NameOfCPURegister(regop)); 2472 data += PrintRightOperand(data); 2473 } else { 2474 const char* mnem = "?"; 2475 switch (b2) { 2476 case 0x2A: 2477 mnem = "cvtsi2ss"; 2478 break; 2479 case 0x2C: 2480 mnem = "cvttss2si"; 2481 break; 2482 case 0x2D: 2483 mnem = "cvtss2si"; 2484 break; 2485 case 0x51: 2486 mnem = "sqrtss"; 2487 break; 2488 case 0x58: 2489 mnem = "addss"; 2490 break; 2491 case 0x59: 2492 mnem = "mulss"; 2493 break; 2494 case 0x5B: 2495 mnem = "cvttps2dq"; 2496 break; 2497 case 0x5C: 2498 mnem = "subss"; 2499 break; 2500 case 0x5D: 2501 mnem = "minss"; 2502 break; 2503 case 0x5E: 2504 mnem = "divss"; 2505 break; 2506 case 0x5F: 2507 mnem = "maxss"; 2508 break; 2509 case 0x7E: 2510 mnem = "movq"; 2511 break; 2512 } 2513 data += 3; 2514 int mod, regop, rm; 2515 get_modrm(*data, &mod, ®op, &rm); 2516 if (b2 == 0x2A) { 2517 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 2518 data += PrintRightOperand(data); 2519 } else if (b2 == 0x2C || b2 == 0x2D) { 2520 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 2521 data += PrintRightXMMOperand(data); 2522 } else if (b2 == 0xC2) { 2523 // Intel manual 2A, Table 3-18. 2524 const char* const pseudo_op[] = { 2525 "cmpeqss", "cmpltss", "cmpless", "cmpunordss", 2526 "cmpneqss", "cmpnltss", "cmpnless", "cmpordss"}; 2527 AppendToBuffer("%s %s,%s", pseudo_op[data[1]], 2528 NameOfXMMRegister(regop), NameOfXMMRegister(rm)); 2529 data += 2; 2530 } else { 2531 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 2532 data += PrintRightXMMOperand(data); 2533 } 2534 } 2535 } else if (*(data+1) == 0xA5) { 2536 data += 2; 2537 AppendToBuffer("rep_movs"); 2538 } else if (*(data+1) == 0xAB) { 2539 data += 2; 2540 AppendToBuffer("rep_stos"); 2541 } else if (*(data + 1) == 0x90) { 2542 data += 2; 2543 AppendToBuffer("pause"); 2544 } else { 2545 UnimplementedInstruction(); 2546 } 2547 break; 2548 2549 case 0xF7: 2550 data += F7Instruction(data); 2551 break; 2552 2553 default: 2554 UnimplementedInstruction(); 2555 } 2556 } 2557 2558 if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 2559 tmp_buffer_[tmp_buffer_pos_] = '\0'; 2560 } 2561 2562 int instr_len = data - instr; 2563 if (instr_len == 0) { 2564 printf("%02x", *data); 2565 } 2566 DCHECK_GT(instr_len, 0); // Ensure progress. 2567 2568 int outp = 0; 2569 // Instruction bytes. 2570 for (byte* bp = instr; bp < data; bp++) { 2571 outp += v8::internal::SNPrintF(out_buffer + outp, 2572 "%02x", 2573 *bp); 2574 } 2575 for (int i = 6 - instr_len; i >= 0; i--) { 2576 outp += v8::internal::SNPrintF(out_buffer + outp, " "); 2577 } 2578 2579 outp += v8::internal::SNPrintF(out_buffer + outp, 2580 " %s", 2581 tmp_buffer_.start()); 2582 return instr_len; 2583 } // NOLINT (function is too long) 2584 2585 2586 //------------------------------------------------------------------------------ 2587 2588 2589 static const char* const cpu_regs[8] = { 2590 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 2591 }; 2592 2593 2594 static const char* const byte_cpu_regs[8] = { 2595 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" 2596 }; 2597 2598 2599 static const char* const xmm_regs[8] = { 2600 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" 2601 }; 2602 2603 2604 const char* NameConverter::NameOfAddress(byte* addr) const { 2605 v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr)); 2606 return tmp_buffer_.start(); 2607 } 2608 2609 2610 const char* NameConverter::NameOfConstant(byte* addr) const { 2611 return NameOfAddress(addr); 2612 } 2613 2614 2615 const char* NameConverter::NameOfCPURegister(int reg) const { 2616 if (0 <= reg && reg < 8) return cpu_regs[reg]; 2617 return "noreg"; 2618 } 2619 2620 2621 const char* NameConverter::NameOfByteCPURegister(int reg) const { 2622 if (0 <= reg && reg < 8) return byte_cpu_regs[reg]; 2623 return "noreg"; 2624 } 2625 2626 2627 const char* NameConverter::NameOfXMMRegister(int reg) const { 2628 if (0 <= reg && reg < 8) return xmm_regs[reg]; 2629 return "noxmmreg"; 2630 } 2631 2632 2633 const char* NameConverter::NameInCode(byte* addr) const { 2634 // IA32 does not embed debug strings at the moment. 2635 UNREACHABLE(); 2636 } 2637 2638 2639 //------------------------------------------------------------------------------ 2640 2641 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 2642 byte* instruction) { 2643 DisassemblerIA32 d(converter_, unimplemented_opcode_action()); 2644 return d.InstructionDecode(buffer, instruction); 2645 } 2646 2647 // The IA-32 assembler does not currently use constant pools. 2648 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } 2649 2650 // static 2651 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end, 2652 UnimplementedOpcodeAction unimplemented_action) { 2653 NameConverter converter; 2654 Disassembler d(converter, unimplemented_action); 2655 for (byte* pc = begin; pc < end;) { 2656 v8::internal::EmbeddedVector<char, 128> buffer; 2657 buffer[0] = '\0'; 2658 byte* prev_pc = pc; 2659 pc += d.InstructionDecode(buffer, pc); 2660 fprintf(f, "%p", static_cast<void*>(prev_pc)); 2661 fprintf(f, " "); 2662 2663 for (byte* bp = prev_pc; bp < pc; bp++) { 2664 fprintf(f, "%02x", *bp); 2665 } 2666 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 2667 fprintf(f, " "); 2668 } 2669 fprintf(f, " %s\n", buffer.start()); 2670 } 2671 } 2672 2673 2674 } // namespace disasm 2675 2676 #endif // V8_TARGET_ARCH_IA32 2677