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