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