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