Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: runtime/vm/disassembler_x64.cc

Issue 1898173005: vm: x64 disassembler fix (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/disassembler.h" 5 #include "vm/disassembler.h"
6 6
7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
8 #if defined(TARGET_ARCH_X64) 8 #if defined(TARGET_ARCH_X64)
9 #include "platform/utils.h" 9 #include "platform/utils.h"
10 #include "vm/allocation.h" 10 #include "vm/allocation.h"
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 367
368 const char* NameOfByteCPURegister(int reg) const { 368 const char* NameOfByteCPURegister(int reg) const {
369 return NameOfCPURegister(reg); 369 return NameOfCPURegister(reg);
370 } 370 }
371 371
372 const char* NameOfXMMRegister(int reg) const { 372 const char* NameOfXMMRegister(int reg) const {
373 ASSERT((0 <= reg) && (reg < kMaxXmmRegisters)); 373 ASSERT((0 <= reg) && (reg < kMaxXmmRegisters));
374 return xmm_regs[reg]; 374 return xmm_regs[reg];
375 } 375 }
376 376
377 void AppendToBuffer(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); 377 void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
378 void AppendAddressToBuffer(uint8_t* addr); 378 void PrintAddress(uint8_t* addr);
379 379
380 int PrintOperands(const char* mnem, 380 int PrintOperands(const char* mnem,
381 OperandType op_order, 381 OperandType op_order,
382 uint8_t* data); 382 uint8_t* data);
383 383
384 typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const; 384 typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
385 385
386 int PrintRightOperandHelper(uint8_t* modrmp, 386 int PrintRightOperandHelper(uint8_t* modrmp,
387 RegisterNameMapping register_name); 387 RegisterNameMapping register_name);
388 int PrintRightOperand(uint8_t* modrmp); 388 int PrintRightOperand(uint8_t* modrmp);
389 int PrintRightByteOperand(uint8_t* modrmp); 389 int PrintRightByteOperand(uint8_t* modrmp);
390 int PrintRightXMMOperand(uint8_t* modrmp); 390 int PrintRightXMMOperand(uint8_t* modrmp);
391 void PrintDisp(int disp, const char* after);
391 int PrintImmediate(uint8_t* data, OperandSize size); 392 int PrintImmediate(uint8_t* data, OperandSize size);
393 void PrintImmediateValue(int64_t value);
392 int PrintImmediateOp(uint8_t* data); 394 int PrintImmediateOp(uint8_t* data);
393 const char* TwoByteMnemonic(uint8_t opcode); 395 const char* TwoByteMnemonic(uint8_t opcode);
394 int TwoByteOpcodeInstruction(uint8_t* data); 396 int TwoByteOpcodeInstruction(uint8_t* data);
395 397
396 int F6F7Instruction(uint8_t* data); 398 int F6F7Instruction(uint8_t* data);
397 int ShiftInstruction(uint8_t* data); 399 int ShiftInstruction(uint8_t* data);
398 int JumpShort(uint8_t* data); 400 int JumpShort(uint8_t* data);
399 int JumpConditional(uint8_t* data); 401 int JumpConditional(uint8_t* data);
400 int JumpConditionalShort(uint8_t* data); 402 int JumpConditionalShort(uint8_t* data);
401 int SetCC(uint8_t* data); 403 int SetCC(uint8_t* data);
402 int FPUInstruction(uint8_t* data); 404 int FPUInstruction(uint8_t* data);
403 int MemoryFPUInstruction(int escape_opcode, int regop, uint8_t* modrm_start); 405 int MemoryFPUInstruction(int escape_opcode, int regop, uint8_t* modrm_start);
404 int RegisterFPUInstruction(int escape_opcode, uint8_t modrm_byte); 406 int RegisterFPUInstruction(int escape_opcode, uint8_t modrm_byte);
405 407
406 bool DecodeInstructionType(uint8_t** data); 408 bool DecodeInstructionType(uint8_t** data);
407 409
408 void UnimplementedInstruction() { 410 void UnimplementedInstruction() {
409 AppendToBuffer("'Unimplemented Instruction'"); 411 Print("'Unimplemented Instruction'");
410 } 412 }
411 413
412 char* buffer_; // Decode instructions into this buffer. 414 char* buffer_; // Decode instructions into this buffer.
413 intptr_t buffer_size_; // The size of the buffer_. 415 intptr_t buffer_size_; // The size of the buffer_.
414 intptr_t buffer_pos_; // Current character position in the buffer_. 416 intptr_t buffer_pos_; // Current character position in the buffer_.
415 417
416 // Prefixes parsed 418 // Prefixes parsed
417 uint8_t rex_; 419 uint8_t rex_;
418 uint8_t operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. 420 uint8_t operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0.
419 // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. 421 // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
420 uint8_t group_1_prefix_; 422 uint8_t group_1_prefix_;
421 // Byte size operand override. 423 // Byte size operand override.
422 bool byte_size_operand_; 424 bool byte_size_operand_;
423 425
424 DISALLOW_COPY_AND_ASSIGN(DisassemblerX64); 426 DISALLOW_COPY_AND_ASSIGN(DisassemblerX64);
425 }; 427 };
426 428
427 429
428 // Append the str to the output buffer. 430 // Append the str to the output buffer.
429 void DisassemblerX64::AppendToBuffer(const char* format, ...) { 431 void DisassemblerX64::Print(const char* format, ...) {
430 intptr_t available = buffer_size_ - buffer_pos_; 432 intptr_t available = buffer_size_ - buffer_pos_;
431 if (available <= 1) { 433 if (available <= 1) {
432 ASSERT(buffer_[buffer_pos_] == '\0'); 434 ASSERT(buffer_[buffer_pos_] == '\0');
433 return; 435 return;
434 } 436 }
435 char* buf = buffer_ + buffer_pos_; 437 char* buf = buffer_ + buffer_pos_;
436 va_list args; 438 va_list args;
437 va_start(args, format); 439 va_start(args, format);
438 int length = OS::VSNPrint(buf, available, format, args); 440 int length = OS::VSNPrint(buf, available, format, args);
439 va_end(args); 441 va_end(args);
440 buffer_pos_ = 442 buffer_pos_ =
441 (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length); 443 (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length);
442 ASSERT(buffer_pos_ < buffer_size_); 444 ASSERT(buffer_pos_ < buffer_size_);
443 } 445 }
444 446
445 447
446 int DisassemblerX64::PrintRightOperandHelper( 448 int DisassemblerX64::PrintRightOperandHelper(
447 uint8_t* modrmp, 449 uint8_t* modrmp,
448 RegisterNameMapping direct_register_name) { 450 RegisterNameMapping direct_register_name) {
449 int mod, regop, rm; 451 int mod, regop, rm;
450 get_modrm(*modrmp, &mod, &regop, &rm); 452 get_modrm(*modrmp, &mod, &regop, &rm);
451 RegisterNameMapping register_name = (mod == 3) ? direct_register_name : 453 RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
452 &DisassemblerX64::NameOfCPURegister; 454 &DisassemblerX64::NameOfCPURegister;
453 switch (mod) { 455 switch (mod) {
454 case 0: 456 case 0:
455 if ((rm & 7) == 5) { 457 if ((rm & 7) == 5) {
456 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); 458 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
457 AppendToBuffer("[rip%s%#x]", disp < 0 ? "-" : "+", Utils::Abs(disp)); 459 Print("[rip");
460 PrintDisp(disp, "]");
458 return 5; 461 return 5;
459 } else if ((rm & 7) == 4) { 462 } else if ((rm & 7) == 4) {
460 // Codes for SIB byte. 463 // Codes for SIB byte.
461 uint8_t sib = *(modrmp + 1); 464 uint8_t sib = *(modrmp + 1);
462 int scale, index, base; 465 int scale, index, base;
463 get_sib(sib, &scale, &index, &base); 466 get_sib(sib, &scale, &index, &base);
464 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { 467 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
465 // index == rsp means no index. Only use sib byte with no index for 468 // index == rsp means no index. Only use sib byte with no index for
466 // rsp and r12 base. 469 // rsp and r12 base.
467 AppendToBuffer("[%s]", NameOfCPURegister(base)); 470 Print("[%s]", NameOfCPURegister(base));
468 return 2; 471 return 2;
469 } else if (base == 5) { 472 } else if (base == 5) {
470 // base == rbp means no base register (when mod == 0). 473 // base == rbp means no base register (when mod == 0).
471 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 474 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
472 AppendToBuffer("[%s*%d+%#x]", 475 Print("[%s*%d", NameOfCPURegister(index), 1 << scale);
473 NameOfCPURegister(index), 476 PrintDisp(disp, "]");
474 1 << scale, disp);
475 return 6; 477 return 6;
476 } else if (index != 4 && base != 5) { 478 } else if (index != 4 && base != 5) {
477 // [base+index*scale] 479 // [base+index*scale]
478 AppendToBuffer("[%s+%s*%d]", 480 Print("[%s+%s*%d]",
479 NameOfCPURegister(base), 481 NameOfCPURegister(base),
480 NameOfCPURegister(index), 482 NameOfCPURegister(index),
481 1 << scale); 483 1 << scale);
482 return 2; 484 return 2;
483 } else { 485 } else {
484 UnimplementedInstruction(); 486 UnimplementedInstruction();
485 return 1; 487 return 1;
486 } 488 }
487 } else { 489 } else {
488 AppendToBuffer("[%s]", NameOfCPURegister(rm)); 490 Print("[%s]", NameOfCPURegister(rm));
489 return 1; 491 return 1;
490 } 492 }
491 break; 493 break;
492 case 1: // fall through 494 case 1: // fall through
493 case 2: 495 case 2:
494 if ((rm & 7) == 4) { 496 if ((rm & 7) == 4) {
495 uint8_t sib = *(modrmp + 1); 497 uint8_t sib = *(modrmp + 1);
496 int scale, index, base; 498 int scale, index, base;
497 get_sib(sib, &scale, &index, &base); 499 get_sib(sib, &scale, &index, &base);
498 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2) 500 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
499 : *reinterpret_cast<char*>(modrmp + 2); 501 : *reinterpret_cast<char*>(modrmp + 2);
500 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { 502 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
501 if (-disp > 0) { 503 Print("[%s", NameOfCPURegister(base));
502 AppendToBuffer("[%s-%#x]", NameOfCPURegister(base), -disp); 504 PrintDisp(disp, "]");
503 } else {
504 AppendToBuffer("[%s+%#x]", NameOfCPURegister(base), disp);
505 }
506 } else { 505 } else {
507 if (-disp > 0) { 506 Print("[%s+%s*%d",
508 AppendToBuffer("[%s+%s*%d-%#x]", 507 NameOfCPURegister(base),
509 NameOfCPURegister(base), 508 NameOfCPURegister(index),
510 NameOfCPURegister(index), 509 1 << scale);
511 1 << scale, 510 PrintDisp(disp, "]");
512 -disp);
513 } else {
514 AppendToBuffer("[%s+%s*%d+%#x]",
515 NameOfCPURegister(base),
516 NameOfCPURegister(index),
517 1 << scale,
518 disp);
519 }
520 } 511 }
521 return mod == 2 ? 6 : 3; 512 return mod == 2 ? 6 : 3;
522 } else { 513 } else {
523 // No sib. 514 // No sib.
524 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1) 515 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
525 : *reinterpret_cast<char*>(modrmp + 1); 516 : *reinterpret_cast<char*>(modrmp + 1);
526 if (-disp > 0) { 517 Print("[%s", NameOfCPURegister(rm));
527 AppendToBuffer("[%s-%#x]", NameOfCPURegister(rm), -disp); 518 PrintDisp(disp, "]");
528 } else {
529 AppendToBuffer("[%s+%#x]", NameOfCPURegister(rm), disp);
530 }
531 return (mod == 2) ? 5 : 2; 519 return (mod == 2) ? 5 : 2;
532 } 520 }
533 break; 521 break;
534 case 3: 522 case 3:
535 AppendToBuffer("%s", (this->*register_name)(rm)); 523 Print("%s", (this->*register_name)(rm));
536 return 1; 524 return 1;
537 default: 525 default:
538 UnimplementedInstruction(); 526 UnimplementedInstruction();
539 return 1; 527 return 1;
540 } 528 }
541 UNREACHABLE(); 529 UNREACHABLE();
542 } 530 }
543 531
544 532
545 int DisassemblerX64::PrintImmediate(uint8_t* data, OperandSize size) { 533 int DisassemblerX64::PrintImmediate(uint8_t* data, OperandSize size) {
(...skipping 14 matching lines...) Expand all
560 break; 548 break;
561 case QUADWORD_SIZE: 549 case QUADWORD_SIZE:
562 value = *reinterpret_cast<int32_t*>(data); 550 value = *reinterpret_cast<int32_t*>(data);
563 count = 4; 551 count = 4;
564 break; 552 break;
565 default: 553 default:
566 UNREACHABLE(); 554 UNREACHABLE();
567 value = 0; // Initialize variables on all paths to satisfy the compiler. 555 value = 0; // Initialize variables on all paths to satisfy the compiler.
568 count = 0; 556 count = 0;
569 } 557 }
570 AppendToBuffer("%#" Px64 "", value); 558 PrintImmediateValue(value);
571 return count; 559 return count;
572 } 560 }
573 561
562 void DisassemblerX64::PrintImmediateValue(int64_t value) {
563 if ((value >= 0) && (value <= 9)) {
564 Print("%" Pd64 "", value);
565 } else {
566 Print("%#" Px64 "", value);
567 }
568 }
569
570 void DisassemblerX64::PrintDisp(int disp, const char* after) {
571 if (-disp > 0) {
572 Print("-%#x", -disp);
573 } else {
574 Print("+%#x", disp);
575 }
576 if (after != NULL) Print("%s", after);
577 }
578
579
580
574 581
575 // Returns number of bytes used by machine instruction, including *data byte. 582 // Returns number of bytes used by machine instruction, including *data byte.
576 // Writes immediate instructions to 'tmp_buffer_'. 583 // Writes immediate instructions to 'tmp_buffer_'.
577 int DisassemblerX64::PrintImmediateOp(uint8_t* data) { 584 int DisassemblerX64::PrintImmediateOp(uint8_t* data) {
578 bool byte_size_immediate = (*data & 0x02) != 0; 585 bool byte_size_immediate = (*data & 0x02) != 0;
579 uint8_t modrm = *(data + 1); 586 uint8_t modrm = *(data + 1);
580 int mod, regop, rm; 587 int mod, regop, rm;
581 get_modrm(modrm, &mod, &regop, &rm); 588 get_modrm(modrm, &mod, &regop, &rm);
582 const char* mnem = "Imm???"; 589 const char* mnem = "Imm???";
583 switch (regop) { 590 switch (regop) {
(...skipping 17 matching lines...) Expand all
601 break; 608 break;
602 case 6: 609 case 6:
603 mnem = "xor"; 610 mnem = "xor";
604 break; 611 break;
605 case 7: 612 case 7:
606 mnem = "cmp"; 613 mnem = "cmp";
607 break; 614 break;
608 default: 615 default:
609 UnimplementedInstruction(); 616 UnimplementedInstruction();
610 } 617 }
611 AppendToBuffer("%s%c ", mnem, operand_size_code()); 618 Print("%s%c ", mnem, operand_size_code());
612 int count = PrintRightOperand(data + 1); 619 int count = PrintRightOperand(data + 1);
613 AppendToBuffer(","); 620 Print(",");
614 OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size(); 621 OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size();
615 count += PrintImmediate(data + 1 + count, immediate_size); 622 count += PrintImmediate(data + 1 + count, immediate_size);
616 return 1 + count; 623 return 1 + count;
617 } 624 }
618 625
619 626
620 // Returns number of bytes used, including *data. 627 // Returns number of bytes used, including *data.
621 int DisassemblerX64::F6F7Instruction(uint8_t* data) { 628 int DisassemblerX64::F6F7Instruction(uint8_t* data) {
622 ASSERT(*data == 0xF7 || *data == 0xF6); 629 ASSERT(*data == 0xF7 || *data == 0xF6);
623 uint8_t modrm = *(data + 1); 630 uint8_t modrm = *(data + 1);
(...skipping 13 matching lines...) Expand all
637 break; 644 break;
638 case 6: 645 case 6:
639 mnem = "div"; 646 mnem = "div";
640 break; 647 break;
641 case 7: 648 case 7:
642 mnem = "idiv"; 649 mnem = "idiv";
643 break; 650 break;
644 default: 651 default:
645 UnimplementedInstruction(); 652 UnimplementedInstruction();
646 } 653 }
647 AppendToBuffer("%s%c %s", 654 Print("%s%c %s",
648 mnem, 655 mnem,
649 operand_size_code(), 656 operand_size_code(),
650 NameOfCPURegister(rm)); 657 NameOfCPURegister(rm));
651 return 2; 658 return 2;
652 } else if (regop == 0) { 659 } else if (regop == 0) {
653 AppendToBuffer("test%c ", operand_size_code()); 660 Print("test%c ", operand_size_code());
654 int count = PrintRightOperand(data + 1); // Use name of 64-bit register. 661 int count = PrintRightOperand(data + 1); // Use name of 64-bit register.
655 AppendToBuffer(",0x"); 662 Print(",");
656 count += PrintImmediate(data + 1 + count, operand_size()); 663 count += PrintImmediate(data + 1 + count, operand_size());
657 return 1 + count; 664 return 1 + count;
658 } else { 665 } else {
659 UnimplementedInstruction(); 666 UnimplementedInstruction();
660 return 2; 667 return 2;
661 } 668 }
662 } 669 }
663 670
664 671
665 int DisassemblerX64::ShiftInstruction(uint8_t* data) { 672 int DisassemblerX64::ShiftInstruction(uint8_t* data) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 UnimplementedInstruction(); 712 UnimplementedInstruction();
706 return num_bytes; 713 return num_bytes;
707 } 714 }
708 ASSERT(NULL != mnem); 715 ASSERT(NULL != mnem);
709 if (op == 0xD0) { 716 if (op == 0xD0) {
710 imm8 = 1; 717 imm8 = 1;
711 } else if (op == 0xC0) { 718 } else if (op == 0xC0) {
712 imm8 = *(data + 2); 719 imm8 = *(data + 2);
713 num_bytes = 3; 720 num_bytes = 3;
714 } 721 }
715 AppendToBuffer("%s%c %s,", 722 Print("%s%c %s,",
716 mnem, 723 mnem,
717 operand_size_code(), 724 operand_size_code(),
718 byte_size_operand_ ? NameOfByteCPURegister(rm) 725 byte_size_operand_ ? NameOfByteCPURegister(rm)
719 : NameOfCPURegister(rm)); 726 : NameOfCPURegister(rm));
720 if (op == 0xD2) { 727 if (op == 0xD2) {
721 AppendToBuffer("cl"); 728 Print("cl");
722 } else { 729 } else {
723 AppendToBuffer("%d", imm8); 730 Print("%d", imm8);
724 } 731 }
725 return num_bytes; 732 return num_bytes;
726 } 733 }
727 734
728 735
729 int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) { 736 int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) {
730 return PrintRightOperandHelper(modrmp, 737 return PrintRightOperandHelper(modrmp,
731 &DisassemblerX64::NameOfCPURegister); 738 &DisassemblerX64::NameOfCPURegister);
732 } 739 }
733 740
(...skipping 17 matching lines...) Expand all
751 uint8_t* data) { 758 uint8_t* data) {
752 uint8_t modrm = *data; 759 uint8_t modrm = *data;
753 int mod, regop, rm; 760 int mod, regop, rm;
754 get_modrm(modrm, &mod, &regop, &rm); 761 get_modrm(modrm, &mod, &regop, &rm);
755 int advance = 0; 762 int advance = 0;
756 const char* register_name = 763 const char* register_name =
757 byte_size_operand_ ? NameOfByteCPURegister(regop) 764 byte_size_operand_ ? NameOfByteCPURegister(regop)
758 : NameOfCPURegister(regop); 765 : NameOfCPURegister(regop);
759 switch (op_order) { 766 switch (op_order) {
760 case REG_OPER_OP_ORDER: { 767 case REG_OPER_OP_ORDER: {
761 AppendToBuffer("%s%c %s,", 768 Print("%s%c %s,", mnem, operand_size_code(), register_name);
762 mnem,
763 operand_size_code(),
764 register_name);
765 advance = byte_size_operand_ ? PrintRightByteOperand(data) 769 advance = byte_size_operand_ ? PrintRightByteOperand(data)
766 : PrintRightOperand(data); 770 : PrintRightOperand(data);
767 break; 771 break;
768 } 772 }
769 case OPER_REG_OP_ORDER: { 773 case OPER_REG_OP_ORDER: {
770 AppendToBuffer("%s%c ", mnem, operand_size_code()); 774 Print("%s%c ", mnem, operand_size_code());
771 advance = byte_size_operand_ ? PrintRightByteOperand(data) 775 advance = byte_size_operand_ ? PrintRightByteOperand(data)
772 : PrintRightOperand(data); 776 : PrintRightOperand(data);
773 AppendToBuffer(",%s", register_name); 777 Print(",%s", register_name);
774 break; 778 break;
775 } 779 }
776 default: 780 default:
777 UNREACHABLE(); 781 UNREACHABLE();
778 break; 782 break;
779 } 783 }
780 return advance; 784 return advance;
781 } 785 }
782 786
783 787
(...skipping 12 matching lines...) Expand all
796 return obj.ToCString(); 800 return obj.ToCString();
797 } 801 }
798 802
799 const Class& clazz = Class::Handle(obj.clazz()); 803 const Class& clazz = Class::Handle(obj.clazz());
800 const char* full_class_name = clazz.ToCString(); 804 const char* full_class_name = clazz.ToCString();
801 return OS::SCreate(Thread::Current()->zone(), 805 return OS::SCreate(Thread::Current()->zone(),
802 "instance of %s", full_class_name); 806 "instance of %s", full_class_name);
803 } 807 }
804 808
805 809
806 void DisassemblerX64::AppendAddressToBuffer(uint8_t* addr_byte_ptr) { 810 void DisassemblerX64::PrintAddress(uint8_t* addr_byte_ptr) {
807 uword addr = reinterpret_cast<uword>(addr_byte_ptr); 811 uword addr = reinterpret_cast<uword>(addr_byte_ptr);
808 AppendToBuffer("%#" Px "", addr); 812 Print("%#" Px "", addr);
809 // Try to print as heap object or stub name 813 // Try to print as heap object or stub name
810 if (((addr & kSmiTagMask) == kHeapObjectTag) && 814 if (((addr & kSmiTagMask) == kHeapObjectTag) &&
811 reinterpret_cast<RawObject*>(addr)->IsWellFormed() && 815 reinterpret_cast<RawObject*>(addr)->IsWellFormed() &&
812 reinterpret_cast<RawObject*>(addr)->IsOldObject() && 816 reinterpret_cast<RawObject*>(addr)->IsOldObject() &&
813 !Dart::vm_isolate()->heap()->CodeContains(addr) && 817 !Dart::vm_isolate()->heap()->CodeContains(addr) &&
814 !Isolate::Current()->heap()->CodeContains(addr) && 818 !Isolate::Current()->heap()->CodeContains(addr) &&
815 Disassembler::CanFindOldObject(addr)) { 819 Disassembler::CanFindOldObject(addr)) {
816 NoSafepointScope no_safepoint; 820 NoSafepointScope no_safepoint;
817 const Object& obj = Object::Handle(reinterpret_cast<RawObject*>(addr)); 821 const Object& obj = Object::Handle(reinterpret_cast<RawObject*>(addr));
818 if (obj.IsArray()) { 822 if (obj.IsArray()) {
819 const Array& arr = Array::Cast(obj); 823 const Array& arr = Array::Cast(obj);
820 intptr_t len = arr.Length(); 824 intptr_t len = arr.Length();
821 if (len > 5) len = 5; // Print a max of 5 elements. 825 if (len > 5) len = 5; // Print a max of 5 elements.
822 AppendToBuffer(" Array["); 826 Print(" Array[");
823 int i = 0; 827 int i = 0;
824 Object& element = Object::Handle(); 828 Object& element = Object::Handle();
825 while (i < len) { 829 while (i < len) {
826 element = arr.At(i); 830 element = arr.At(i);
827 if (i > 0) AppendToBuffer(", "); 831 if (i > 0) Print(", ");
828 AppendToBuffer("%s", ObjectToCStringNoGC(element)); 832 Print("%s", ObjectToCStringNoGC(element));
829 i++; 833 i++;
830 } 834 }
831 if (i < arr.Length()) AppendToBuffer(", ..."); 835 if (i < arr.Length()) Print(", ...");
832 AppendToBuffer("]"); 836 Print("]");
833 return; 837 return;
834 } 838 }
835 AppendToBuffer(" '%s'", ObjectToCStringNoGC(obj)); 839 Print(" '%s'", ObjectToCStringNoGC(obj));
836 } else { 840 } else {
837 // 'addr' is not an object, but probably a code address. 841 // 'addr' is not an object, but probably a code address.
838 const char* name_of_stub = StubCode::NameOfStub(addr); 842 const char* name_of_stub = StubCode::NameOfStub(addr);
839 if (name_of_stub != NULL) { 843 if (name_of_stub != NULL) {
840 AppendToBuffer(" [stub: %s]", name_of_stub); 844 Print(" [stub: %s]", name_of_stub);
841 } 845 }
842 } 846 }
843 } 847 }
844 848
845 849
846 // Returns number of bytes used, including *data. 850 // Returns number of bytes used, including *data.
847 int DisassemblerX64::JumpShort(uint8_t* data) { 851 int DisassemblerX64::JumpShort(uint8_t* data) {
848 ASSERT(0xEB == *data); 852 ASSERT(0xEB == *data);
849 uint8_t b = *(data + 1); 853 uint8_t b = *(data + 1);
850 uint8_t* dest = data + static_cast<int8_t>(b) + 2; 854 uint8_t* dest = data + static_cast<int8_t>(b) + 2;
851 AppendToBuffer("jmp "); 855 Print("jmp ");
852 AppendAddressToBuffer(dest); 856 PrintAddress(dest);
853 return 2; 857 return 2;
854 } 858 }
855 859
856 860
857 // Returns number of bytes used, including *data. 861 // Returns number of bytes used, including *data.
858 int DisassemblerX64::JumpConditional(uint8_t* data) { 862 int DisassemblerX64::JumpConditional(uint8_t* data) {
859 ASSERT(0x0F == *data); 863 ASSERT(0x0F == *data);
860 uint8_t cond = *(data + 1) & 0x0F; 864 uint8_t cond = *(data + 1) & 0x0F;
861 uint8_t* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6; 865 uint8_t* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
862 const char* mnem = conditional_code_suffix[cond]; 866 const char* mnem = conditional_code_suffix[cond];
863 AppendToBuffer("j%s ", mnem); 867 Print("j%s ", mnem);
864 AppendAddressToBuffer(dest); 868 PrintAddress(dest);
865 return 6; // includes 0x0F 869 return 6; // includes 0x0F
866 } 870 }
867 871
868 872
869 // Returns number of bytes used, including *data. 873 // Returns number of bytes used, including *data.
870 int DisassemblerX64::JumpConditionalShort(uint8_t* data) { 874 int DisassemblerX64::JumpConditionalShort(uint8_t* data) {
871 uint8_t cond = *data & 0x0F; 875 uint8_t cond = *data & 0x0F;
872 uint8_t b = *(data + 1); 876 uint8_t b = *(data + 1);
873 uint8_t* dest = data + static_cast<int8_t>(b) + 2; 877 uint8_t* dest = data + static_cast<int8_t>(b) + 2;
874 const char* mnem = conditional_code_suffix[cond]; 878 const char* mnem = conditional_code_suffix[cond];
875 AppendToBuffer("j%s ", mnem); 879 Print("j%s ", mnem);
876 AppendAddressToBuffer(dest); 880 PrintAddress(dest);
877 return 2; 881 return 2;
878 } 882 }
879 883
880 884
881 // Returns number of bytes used, including *data. 885 // Returns number of bytes used, including *data.
882 int DisassemblerX64::SetCC(uint8_t* data) { 886 int DisassemblerX64::SetCC(uint8_t* data) {
883 ASSERT(0x0F == *data); 887 ASSERT(0x0F == *data);
884 uint8_t cond = *(data + 1) & 0x0F; 888 uint8_t cond = *(data + 1) & 0x0F;
885 const char* mnem = conditional_code_suffix[cond]; 889 const char* mnem = conditional_code_suffix[cond];
886 AppendToBuffer("set%s%c ", mnem, operand_size_code()); 890 Print("set%s%c ", mnem, operand_size_code());
887 PrintRightByteOperand(data + 2); 891 PrintRightByteOperand(data + 2);
888 return 3; // includes 0x0F 892 return 3; // includes 0x0F
889 } 893 }
890 894
891 895
892 // Returns number of bytes used, including *data. 896 // Returns number of bytes used, including *data.
893 int DisassemblerX64::FPUInstruction(uint8_t* data) { 897 int DisassemblerX64::FPUInstruction(uint8_t* data) {
894 uint8_t escape_opcode = *data; 898 uint8_t escape_opcode = *data;
895 ASSERT(0xD8 == (escape_opcode & 0xF8)); 899 ASSERT(0xD8 == (escape_opcode & 0xF8));
896 uint8_t modrm_byte = *(data+1); 900 uint8_t modrm_byte = *(data+1);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 939
936 case 0xDF: switch (regop) { 940 case 0xDF: switch (regop) {
937 case 5: mnem = "fild_d"; break; 941 case 5: mnem = "fild_d"; break;
938 case 7: mnem = "fistp_d"; break; 942 case 7: mnem = "fistp_d"; break;
939 default: UnimplementedInstruction(); 943 default: UnimplementedInstruction();
940 } 944 }
941 break; 945 break;
942 946
943 default: UnimplementedInstruction(); 947 default: UnimplementedInstruction();
944 } 948 }
945 AppendToBuffer("%s ", mnem); 949 Print("%s ", mnem);
946 int count = PrintRightOperand(modrm_start); 950 int count = PrintRightOperand(modrm_start);
947 return count + 1; 951 return count + 1;
948 } 952 }
949 953
950 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode, 954 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
951 uint8_t modrm_byte) { 955 uint8_t modrm_byte) {
952 bool has_register = false; // Is the FPU register encoded in modrm_byte? 956 bool has_register = false; // Is the FPU register encoded in modrm_byte?
953 const char* mnem = "?"; 957 const char* mnem = "?";
954 958
955 switch (escape_opcode) { 959 switch (escape_opcode) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 } else if ((modrm_byte & 0xF8) == 0xE8) { 1055 } else if ((modrm_byte & 0xF8) == 0xE8) {
1052 mnem = "fucomip"; 1056 mnem = "fucomip";
1053 has_register = true; 1057 has_register = true;
1054 } 1058 }
1055 break; 1059 break;
1056 1060
1057 default: UnimplementedInstruction(); 1061 default: UnimplementedInstruction();
1058 } 1062 }
1059 1063
1060 if (has_register) { 1064 if (has_register) {
1061 AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); 1065 Print("%s st%d", mnem, modrm_byte & 0x7);
1062 } else { 1066 } else {
1063 AppendToBuffer("%s", mnem); 1067 Print("%s", mnem);
1064 } 1068 }
1065 return 2; 1069 return 2;
1066 } 1070 }
1067 1071
1068 1072
1069 // TODO(srdjan): Should we add a branch hint argument? 1073 // TODO(srdjan): Should we add a branch hint argument?
1070 bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { 1074 bool DisassemblerX64::DecodeInstructionType(uint8_t** data) {
1071 uint8_t current; 1075 uint8_t current;
1072 1076
1073 // Scan for prefixes. 1077 // Scan for prefixes.
1074 while (true) { 1078 while (true) {
1075 current = **data; 1079 current = **data;
1076 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix. 1080 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix.
1077 operand_size_ = current; 1081 operand_size_ = current;
1078 } else if ((current & 0xF0) == 0x40) { // REX prefix. 1082 } else if ((current & 0xF0) == 0x40) { // REX prefix.
1079 setRex(current); 1083 setRex(current);
1080 // TODO(srdjan): Should we enable printing of REX.W? 1084 // TODO(srdjan): Should we enable printing of REX.W?
1081 // if (rex_w()) AppendToBuffer("REX.W "); 1085 // if (rex_w()) Print("REX.W ");
1082 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3). 1086 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3).
1083 group_1_prefix_ = current; 1087 group_1_prefix_ = current;
1084 } else if (current == 0xF0) { 1088 } else if (current == 0xF0) {
1085 AppendToBuffer("lock "); 1089 Print("lock ");
1086 } else { // Not a prefix - an opcode. 1090 } else { // Not a prefix - an opcode.
1087 break; 1091 break;
1088 } 1092 }
1089 (*data)++; 1093 (*data)++;
1090 } 1094 }
1091 1095
1092 const InstructionDesc& idesc = instruction_table.Get(current); 1096 const InstructionDesc& idesc = instruction_table.Get(current);
1093 byte_size_operand_ = idesc.byte_size_operation; 1097 byte_size_operand_ = idesc.byte_size_operation;
1094 1098
1095 switch (idesc.type) { 1099 switch (idesc.type) {
1096 case ZERO_OPERANDS_INSTR: 1100 case ZERO_OPERANDS_INSTR:
1097 if (current >= 0xA4 && current <= 0xA7) { 1101 if (current >= 0xA4 && current <= 0xA7) {
1098 // String move or compare operations. 1102 // String move or compare operations.
1099 if (group_1_prefix_ == REP_PREFIX) { 1103 if (group_1_prefix_ == REP_PREFIX) {
1100 // REP. 1104 // REP.
1101 AppendToBuffer("rep "); 1105 Print("rep ");
1102 } 1106 }
1103 // TODO(srdjan): Should we enable printing of REX.W? 1107 // TODO(srdjan): Should we enable printing of REX.W?
1104 // if (rex_w()) AppendToBuffer("REX.W "); 1108 // if (rex_w()) Print("REX.W ");
1105 AppendToBuffer("%s%c", idesc.mnem, operand_size_code()); 1109 Print("%s%c", idesc.mnem, operand_size_code());
1106 } else { 1110 } else {
1107 AppendToBuffer("%s%c", idesc.mnem, operand_size_code()); 1111 Print("%s%c", idesc.mnem, operand_size_code());
1108 } 1112 }
1109 (*data)++; 1113 (*data)++;
1110 break; 1114 break;
1111 1115
1112 case TWO_OPERANDS_INSTR: 1116 case TWO_OPERANDS_INSTR:
1113 (*data)++; 1117 (*data)++;
1114 (*data) += PrintOperands(idesc.mnem, idesc.op_order_, *data); 1118 (*data) += PrintOperands(idesc.mnem, idesc.op_order_, *data);
1115 break; 1119 break;
1116 1120
1117 case JUMP_CONDITIONAL_SHORT_INSTR: 1121 case JUMP_CONDITIONAL_SHORT_INSTR:
1118 (*data) += JumpConditionalShort(*data); 1122 (*data) += JumpConditionalShort(*data);
1119 break; 1123 break;
1120 1124
1121 case REGISTER_INSTR: 1125 case REGISTER_INSTR:
1122 AppendToBuffer("%s%c %s", 1126 Print("%s%c %s",
1123 idesc.mnem, 1127 idesc.mnem,
1124 operand_size_code(), 1128 operand_size_code(),
1125 NameOfCPURegister(base_reg(current & 0x07))); 1129 NameOfCPURegister(base_reg(current & 0x07)));
1126 (*data)++; 1130 (*data)++;
1127 break; 1131 break;
1128 case PUSHPOP_INSTR: 1132 case PUSHPOP_INSTR:
1129 AppendToBuffer("%s %s", 1133 Print("%s %s",
1130 idesc.mnem, 1134 idesc.mnem,
1131 NameOfCPURegister(base_reg(current & 0x07))); 1135 NameOfCPURegister(base_reg(current & 0x07)));
1132 (*data)++; 1136 (*data)++;
1133 break; 1137 break;
1134 case MOVE_REG_INSTR: { 1138 case MOVE_REG_INSTR: {
1135 uint8_t* addr = NULL; 1139 uint8_t* addr = NULL;
1136 switch (operand_size()) { 1140 switch (operand_size()) {
1137 case WORD_SIZE: 1141 case WORD_SIZE:
1138 addr = reinterpret_cast<uint8_t*>( 1142 addr = reinterpret_cast<uint8_t*>(
1139 *reinterpret_cast<int16_t*>(*data + 1)); 1143 *reinterpret_cast<int16_t*>(*data + 1));
1140 (*data) += 3; 1144 (*data) += 3;
1141 break; 1145 break;
1142 case DOUBLEWORD_SIZE: 1146 case DOUBLEWORD_SIZE:
1143 addr = reinterpret_cast<uint8_t*>( 1147 addr = reinterpret_cast<uint8_t*>(
1144 *reinterpret_cast<int32_t*>(*data + 1)); 1148 *reinterpret_cast<int32_t*>(*data + 1));
1145 (*data) += 5; 1149 (*data) += 5;
1146 break; 1150 break;
1147 case QUADWORD_SIZE: 1151 case QUADWORD_SIZE:
1148 addr = reinterpret_cast<uint8_t*>( 1152 addr = reinterpret_cast<uint8_t*>(
1149 *reinterpret_cast<int64_t*>(*data + 1)); 1153 *reinterpret_cast<int64_t*>(*data + 1));
1150 (*data) += 9; 1154 (*data) += 9;
1151 break; 1155 break;
1152 default: 1156 default:
1153 UNREACHABLE(); 1157 UNREACHABLE();
1154 } 1158 }
1155 AppendToBuffer("mov%c %s,", 1159 Print("mov%c %s,",
1156 operand_size_code(), 1160 operand_size_code(),
1157 NameOfCPURegister(base_reg(current & 0x07))); 1161 NameOfCPURegister(base_reg(current & 0x07)));
1158 AppendAddressToBuffer(addr); 1162 PrintAddress(addr);
1159 break; 1163 break;
1160 } 1164 }
1161 1165
1162 case CALL_JUMP_INSTR: { 1166 case CALL_JUMP_INSTR: {
1163 uint8_t* addr = *data + *reinterpret_cast<int32_t*>(*data + 1) + 5; 1167 uint8_t* addr = *data + *reinterpret_cast<int32_t*>(*data + 1) + 5;
1164 AppendToBuffer("%s ", idesc.mnem); 1168 Print("%s ", idesc.mnem);
1165 AppendAddressToBuffer(addr); 1169 PrintAddress(addr);
1166 (*data) += 5; 1170 (*data) += 5;
1167 break; 1171 break;
1168 } 1172 }
1169 1173
1170 case SHORT_IMMEDIATE_INSTR: { 1174 case SHORT_IMMEDIATE_INSTR: {
1171 uint8_t* addr = 1175 uint8_t* addr =
1172 reinterpret_cast<uint8_t*>(*reinterpret_cast<int32_t*>(*data + 1)); 1176 reinterpret_cast<uint8_t*>(*reinterpret_cast<int32_t*>(*data + 1));
1173 AppendToBuffer("%s rax, ", idesc.mnem); 1177 Print("%s rax, ", idesc.mnem);
1174 AppendAddressToBuffer(addr); 1178 PrintAddress(addr);
1175 (*data) += 5; 1179 (*data) += 5;
1176 break; 1180 break;
1177 } 1181 }
1178 1182
1179 case NO_INSTR: 1183 case NO_INSTR:
1180 return false; 1184 return false;
1181 1185
1182 default: 1186 default:
1183 UNIMPLEMENTED(); // This type is not implemented. 1187 UNIMPLEMENTED(); // This type is not implemented.
1184 } 1188 }
1185 return true; 1189 return true;
1186 } 1190 }
1187 1191
1188 1192
1189 // Handle all two-byte opcodes, which start with 0x0F. 1193 // Handle all two-byte opcodes, which start with 0x0F.
1190 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix. 1194 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
1191 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A. 1195 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
1192 int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { 1196 int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
1193 uint8_t opcode = *(data + 1); 1197 uint8_t opcode = *(data + 1);
1194 uint8_t* current = data + 2; 1198 uint8_t* current = data + 2;
1195 // At return, "current" points to the start of the next instruction. 1199 // At return, "current" points to the start of the next instruction.
1196 const char* mnemonic = TwoByteMnemonic(opcode); 1200 const char* mnemonic = TwoByteMnemonic(opcode);
1197 if (operand_size_ == 0x66) { 1201 if (operand_size_ == 0x66) {
1198 // 0x66 0x0F prefix. 1202 // 0x66 0x0F prefix.
1199 int mod, regop, rm; 1203 int mod, regop, rm;
1200 if (opcode == 0xC6) { 1204 if (opcode == 0xC6) {
1201 int mod, regop, rm; 1205 int mod, regop, rm;
1202 get_modrm(*current, &mod, &regop, &rm); 1206 get_modrm(*current, &mod, &regop, &rm);
1203 AppendToBuffer("shufpd %s, ", NameOfXMMRegister(regop)); 1207 Print("shufpd %s, ", NameOfXMMRegister(regop));
1204 current += PrintRightXMMOperand(current); 1208 current += PrintRightXMMOperand(current);
1205 AppendToBuffer(" [%x]", *current); 1209 Print(" [%x]", *current);
1206 current++; 1210 current++;
1207 } else if (opcode == 0x3A) { 1211 } else if (opcode == 0x3A) {
1208 uint8_t third_byte = *current; 1212 uint8_t third_byte = *current;
1209 current = data + 3; 1213 current = data + 3;
1210 if (third_byte == 0x17) { 1214 if (third_byte == 0x17) {
1211 get_modrm(*current, &mod, &regop, &rm); 1215 get_modrm(*current, &mod, &regop, &rm);
1212 AppendToBuffer("extractps "); // reg/m32, xmm, imm8 1216 Print("extractps "); // reg/m32, xmm, imm8
1213 current += PrintRightOperand(current); 1217 current += PrintRightOperand(current);
1214 AppendToBuffer(", %s, %d", NameOfCPURegister(regop), (*current) & 3); 1218 Print(", %s, %d", NameOfCPURegister(regop), (*current) & 3);
1215 current += 1; 1219 current += 1;
1216 } else if (third_byte == 0x0b) { 1220 } else if (third_byte == 0x0b) {
1217 get_modrm(*current, &mod, &regop, &rm); 1221 get_modrm(*current, &mod, &regop, &rm);
1218 // roundsd xmm, xmm/m64, imm8 1222 // roundsd xmm, xmm/m64, imm8
1219 AppendToBuffer("roundsd %s, ", NameOfCPURegister(regop)); 1223 Print("roundsd %s, ", NameOfCPURegister(regop));
1220 current += PrintRightOperand(current); 1224 current += PrintRightOperand(current);
1221 AppendToBuffer(", %d", (*current) & 3); 1225 Print(", %d", (*current) & 3);
1222 current += 1; 1226 current += 1;
1223 } else { 1227 } else {
1224 UnimplementedInstruction(); 1228 UnimplementedInstruction();
1225 } 1229 }
1226 } else { 1230 } else {
1227 get_modrm(*current, &mod, &regop, &rm); 1231 get_modrm(*current, &mod, &regop, &rm);
1228 if (opcode == 0x1f) { 1232 if (opcode == 0x1f) {
1229 current++; 1233 current++;
1230 if (rm == 4) { // SIB byte present. 1234 if (rm == 4) { // SIB byte present.
1231 current++; 1235 current++;
1232 } 1236 }
1233 if (mod == 1) { // Byte displacement. 1237 if (mod == 1) { // Byte displacement.
1234 current += 1; 1238 current += 1;
1235 } else if (mod == 2) { // 32-bit displacement. 1239 } else if (mod == 2) { // 32-bit displacement.
1236 current += 4; 1240 current += 4;
1237 } // else no immediate displacement. 1241 } // else no immediate displacement.
1238 AppendToBuffer("nop"); 1242 Print("nop");
1239 } else if (opcode == 0x28) { 1243 } else if (opcode == 0x28) {
1240 AppendToBuffer("movapd %s, ", NameOfXMMRegister(regop)); 1244 Print("movapd %s, ", NameOfXMMRegister(regop));
1241 current += PrintRightXMMOperand(current); 1245 current += PrintRightXMMOperand(current);
1242 } else if (opcode == 0x29) { 1246 } else if (opcode == 0x29) {
1243 AppendToBuffer("movapd "); 1247 Print("movapd ");
1244 current += PrintRightXMMOperand(current); 1248 current += PrintRightXMMOperand(current);
1245 AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1249 Print(", %s", NameOfXMMRegister(regop));
1246 } else if (opcode == 0x6E) { 1250 } else if (opcode == 0x6E) {
1247 AppendToBuffer("mov%c %s,", 1251 Print("mov%c %s,",
1248 rex_w() ? 'q' : 'd', 1252 rex_w() ? 'q' : 'd',
1249 NameOfXMMRegister(regop)); 1253 NameOfXMMRegister(regop));
1250 current += PrintRightOperand(current); 1254 current += PrintRightOperand(current);
1251 } else if (opcode == 0x6F) { 1255 } else if (opcode == 0x6F) {
1252 AppendToBuffer("movdqa %s,", 1256 Print("movdqa %s,",
1253 NameOfXMMRegister(regop)); 1257 NameOfXMMRegister(regop));
1254 current += PrintRightXMMOperand(current); 1258 current += PrintRightXMMOperand(current);
1255 } else if (opcode == 0x7E) { 1259 } else if (opcode == 0x7E) {
1256 AppendToBuffer("mov%c ", 1260 Print("mov%c ",
1257 rex_w() ? 'q' : 'd'); 1261 rex_w() ? 'q' : 'd');
1258 current += PrintRightOperand(current); 1262 current += PrintRightOperand(current);
1259 AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1263 Print(", %s", NameOfXMMRegister(regop));
1260 } else if (opcode == 0x7F) { 1264 } else if (opcode == 0x7F) {
1261 AppendToBuffer("movdqa "); 1265 Print("movdqa ");
1262 current += PrintRightXMMOperand(current); 1266 current += PrintRightXMMOperand(current);
1263 AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1267 Print(", %s", NameOfXMMRegister(regop));
1264 } else if (opcode == 0xD6) { 1268 } else if (opcode == 0xD6) {
1265 AppendToBuffer("movq "); 1269 Print("movq ");
1266 current += PrintRightXMMOperand(current); 1270 current += PrintRightXMMOperand(current);
1267 AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1271 Print(", %s", NameOfXMMRegister(regop));
1268 } else if (opcode == 0x50) { 1272 } else if (opcode == 0x50) {
1269 AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop)); 1273 Print("movmskpd %s,", NameOfCPURegister(regop));
1270 current += PrintRightXMMOperand(current); 1274 current += PrintRightXMMOperand(current);
1271 } else { 1275 } else {
1272 const char* mnemonic = "?"; 1276 const char* mnemonic = "?";
1273 if (opcode == 0x14) { 1277 if (opcode == 0x14) {
1274 mnemonic = "unpcklpd"; 1278 mnemonic = "unpcklpd";
1275 } else if (opcode == 0x15) { 1279 } else if (opcode == 0x15) {
1276 mnemonic = "unpckhpd"; 1280 mnemonic = "unpckhpd";
1277 } else if (opcode == 0x54) { 1281 } else if (opcode == 0x54) {
1278 mnemonic = "andpd"; 1282 mnemonic = "andpd";
1279 } else if (opcode == 0x56) { 1283 } else if (opcode == 0x56) {
(...skipping 20 matching lines...) Expand all
1300 mnemonic = "minpd"; 1304 mnemonic = "minpd";
1301 } else if (opcode == 0x5F) { 1305 } else if (opcode == 0x5F) {
1302 mnemonic = "maxpd"; 1306 mnemonic = "maxpd";
1303 } else if (opcode == 0x51) { 1307 } else if (opcode == 0x51) {
1304 mnemonic = "sqrtpd"; 1308 mnemonic = "sqrtpd";
1305 } else if (opcode == 0x5A) { 1309 } else if (opcode == 0x5A) {
1306 mnemonic = "cvtpd2ps"; 1310 mnemonic = "cvtpd2ps";
1307 } else { 1311 } else {
1308 UnimplementedInstruction(); 1312 UnimplementedInstruction();
1309 } 1313 }
1310 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); 1314 Print("%s %s,", mnemonic, NameOfXMMRegister(regop));
1311 current += PrintRightXMMOperand(current); 1315 current += PrintRightXMMOperand(current);
1312 } 1316 }
1313 } 1317 }
1314 } else if (group_1_prefix_ == 0xF2) { 1318 } else if (group_1_prefix_ == 0xF2) {
1315 // Beginning of instructions with prefix 0xF2. 1319 // Beginning of instructions with prefix 0xF2.
1316 1320
1317 if (opcode == 0x11 || opcode == 0x10) { 1321 if (opcode == 0x11 || opcode == 0x10) {
1318 // MOVSD: Move scalar double-precision fp to/from/between XMM registers. 1322 // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
1319 AppendToBuffer("movsd "); 1323 Print("movsd ");
1320 int mod, regop, rm; 1324 int mod, regop, rm;
1321 get_modrm(*current, &mod, &regop, &rm); 1325 get_modrm(*current, &mod, &regop, &rm);
1322 if (opcode == 0x11) { 1326 if (opcode == 0x11) {
1323 current += PrintRightXMMOperand(current); 1327 current += PrintRightXMMOperand(current);
1324 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1328 Print(",%s", NameOfXMMRegister(regop));
1325 } else { 1329 } else {
1326 AppendToBuffer("%s,", NameOfXMMRegister(regop)); 1330 Print("%s,", NameOfXMMRegister(regop));
1327 current += PrintRightXMMOperand(current); 1331 current += PrintRightXMMOperand(current);
1328 } 1332 }
1329 } else if (opcode == 0x2A) { 1333 } else if (opcode == 0x2A) {
1330 // CVTSI2SD: integer to XMM double conversion. 1334 // CVTSI2SD: integer to XMM double conversion.
1331 int mod, regop, rm; 1335 int mod, regop, rm;
1332 get_modrm(*current, &mod, &regop, &rm); 1336 get_modrm(*current, &mod, &regop, &rm);
1333 AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop)); 1337 Print("%sd %s,", mnemonic, NameOfXMMRegister(regop));
1334 current += PrintRightOperand(current); 1338 current += PrintRightOperand(current);
1335 } else if (opcode == 0x2C) { 1339 } else if (opcode == 0x2C) {
1336 // CVTTSD2SI: 1340 // CVTTSD2SI:
1337 // Convert with truncation scalar double-precision FP to integer. 1341 // Convert with truncation scalar double-precision FP to integer.
1338 int mod, regop, rm; 1342 int mod, regop, rm;
1339 get_modrm(*current, &mod, &regop, &rm); 1343 get_modrm(*current, &mod, &regop, &rm);
1340 AppendToBuffer("cvttsd2si%c %s,", 1344 Print("cvttsd2si%c %s,",
1341 operand_size_code(), NameOfCPURegister(regop)); 1345 operand_size_code(), NameOfCPURegister(regop));
1342 current += PrintRightXMMOperand(current); 1346 current += PrintRightXMMOperand(current);
1343 } else if (opcode == 0x2D) { 1347 } else if (opcode == 0x2D) {
1344 // CVTSD2SI: Convert scalar double-precision FP to integer. 1348 // CVTSD2SI: Convert scalar double-precision FP to integer.
1345 int mod, regop, rm; 1349 int mod, regop, rm;
1346 get_modrm(*current, &mod, &regop, &rm); 1350 get_modrm(*current, &mod, &regop, &rm);
1347 AppendToBuffer("cvtsd2si%c %s,", 1351 Print("cvtsd2si%c %s,",
1348 operand_size_code(), NameOfCPURegister(regop)); 1352 operand_size_code(), NameOfCPURegister(regop));
1349 current += PrintRightXMMOperand(current); 1353 current += PrintRightXMMOperand(current);
1350 } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { 1354 } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1351 // XMM arithmetic. Mnemonic was retrieved at the start of this function. 1355 // XMM arithmetic. Mnemonic was retrieved at the start of this function.
1352 int mod, regop, rm; 1356 int mod, regop, rm;
1353 get_modrm(*current, &mod, &regop, &rm); 1357 get_modrm(*current, &mod, &regop, &rm);
1354 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); 1358 Print("%s %s,", mnemonic, NameOfXMMRegister(regop));
1355 current += PrintRightXMMOperand(current); 1359 current += PrintRightXMMOperand(current);
1356 } else { 1360 } else {
1357 UnimplementedInstruction(); 1361 UnimplementedInstruction();
1358 } 1362 }
1359 } else if (group_1_prefix_ == 0xF3) { 1363 } else if (group_1_prefix_ == 0xF3) {
1360 // Instructions with prefix 0xF3. 1364 // Instructions with prefix 0xF3.
1361 if (opcode == 0x11 || opcode == 0x10) { 1365 if (opcode == 0x11 || opcode == 0x10) {
1362 // MOVSS: Move scalar double-precision fp to/from/between XMM registers. 1366 // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
1363 AppendToBuffer("movss "); 1367 Print("movss ");
1364 int mod, regop, rm; 1368 int mod, regop, rm;
1365 get_modrm(*current, &mod, &regop, &rm); 1369 get_modrm(*current, &mod, &regop, &rm);
1366 if (opcode == 0x11) { 1370 if (opcode == 0x11) {
1367 current += PrintRightOperand(current); 1371 current += PrintRightOperand(current);
1368 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1372 Print(",%s", NameOfXMMRegister(regop));
1369 } else { 1373 } else {
1370 AppendToBuffer("%s,", NameOfXMMRegister(regop)); 1374 Print("%s,", NameOfXMMRegister(regop));
1371 current += PrintRightOperand(current); 1375 current += PrintRightOperand(current);
1372 } 1376 }
1373 } else if (opcode == 0x2A) { 1377 } else if (opcode == 0x2A) {
1374 // CVTSI2SS: integer to XMM single conversion. 1378 // CVTSI2SS: integer to XMM single conversion.
1375 int mod, regop, rm; 1379 int mod, regop, rm;
1376 get_modrm(*current, &mod, &regop, &rm); 1380 get_modrm(*current, &mod, &regop, &rm);
1377 AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop)); 1381 Print("%ss %s,", mnemonic, NameOfXMMRegister(regop));
1378 current += PrintRightOperand(current); 1382 current += PrintRightOperand(current);
1379 } else if (opcode == 0x2C) { 1383 } else if (opcode == 0x2C) {
1380 // CVTTSS2SI: 1384 // CVTTSS2SI:
1381 // Convert with truncation scalar single-precision FP to dword integer. 1385 // Convert with truncation scalar single-precision FP to dword integer.
1382 int mod, regop, rm; 1386 int mod, regop, rm;
1383 get_modrm(*current, &mod, &regop, &rm); 1387 get_modrm(*current, &mod, &regop, &rm);
1384 AppendToBuffer("cvttss2si%c %s,", 1388 Print("cvttss2si%c %s,",
1385 operand_size_code(), NameOfCPURegister(regop)); 1389 operand_size_code(), NameOfCPURegister(regop));
1386 current += PrintRightXMMOperand(current); 1390 current += PrintRightXMMOperand(current);
1387 } else if (opcode == 0x5A) { 1391 } else if (opcode == 0x5A) {
1388 // CVTSS2SD: 1392 // CVTSS2SD:
1389 // Convert scalar single-precision FP to scalar double-precision FP. 1393 // Convert scalar single-precision FP to scalar double-precision FP.
1390 int mod, regop, rm; 1394 int mod, regop, rm;
1391 get_modrm(*current, &mod, &regop, &rm); 1395 get_modrm(*current, &mod, &regop, &rm);
1392 AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); 1396 Print("cvtss2sd %s,", NameOfXMMRegister(regop));
1393 current += PrintRightXMMOperand(current); 1397 current += PrintRightXMMOperand(current);
1394 } else if (opcode == 0x7E) { 1398 } else if (opcode == 0x7E) {
1395 int mod, regop, rm; 1399 int mod, regop, rm;
1396 get_modrm(*current, &mod, &regop, &rm); 1400 get_modrm(*current, &mod, &regop, &rm);
1397 AppendToBuffer("movq %s, ", NameOfXMMRegister(regop)); 1401 Print("movq %s, ", NameOfXMMRegister(regop));
1398 current += PrintRightXMMOperand(current); 1402 current += PrintRightXMMOperand(current);
1399 } else if (opcode == 0x58) { 1403 } else if (opcode == 0x58) {
1400 int mod, regop, rm; 1404 int mod, regop, rm;
1401 get_modrm(*current, &mod, &regop, &rm); 1405 get_modrm(*current, &mod, &regop, &rm);
1402 AppendToBuffer("addss %s,", NameOfXMMRegister(regop)); 1406 Print("addss %s,", NameOfXMMRegister(regop));
1403 current += PrintRightXMMOperand(current); 1407 current += PrintRightXMMOperand(current);
1404 } else { 1408 } else {
1405 UnimplementedInstruction(); 1409 UnimplementedInstruction();
1406 } 1410 }
1407 } else if (opcode == 0x1F) { 1411 } else if (opcode == 0x1F) {
1408 // NOP 1412 // NOP
1409 int mod, regop, rm; 1413 int mod, regop, rm;
1410 get_modrm(*current, &mod, &regop, &rm); 1414 get_modrm(*current, &mod, &regop, &rm);
1411 current++; 1415 current++;
1412 if (rm == 4) { // SIB byte present. 1416 if (rm == 4) { // SIB byte present.
1413 current++; 1417 current++;
1414 } 1418 }
1415 if (mod == 1) { // Byte displacement. 1419 if (mod == 1) { // Byte displacement.
1416 current += 1; 1420 current += 1;
1417 } else if (mod == 2) { // 32-bit displacement. 1421 } else if (mod == 2) { // 32-bit displacement.
1418 current += 4; 1422 current += 4;
1419 } // else no immediate displacement. 1423 } // else no immediate displacement.
1420 AppendToBuffer("nop"); 1424 Print("nop");
1421 1425
1422 } else if (opcode == 0x28) { 1426 } else if (opcode == 0x28) {
1423 // movaps xmm, xmm/m128 1427 // movaps xmm, xmm/m128
1424 int mod, regop, rm; 1428 int mod, regop, rm;
1425 get_modrm(*current, &mod, &regop, &rm); 1429 get_modrm(*current, &mod, &regop, &rm);
1426 AppendToBuffer("movaps %s, ", NameOfXMMRegister(regop)); 1430 Print("movaps %s, ", NameOfXMMRegister(regop));
1427 current += PrintRightXMMOperand(current); 1431 current += PrintRightXMMOperand(current);
1428 } else if (opcode == 0x29) { 1432 } else if (opcode == 0x29) {
1429 // movaps xmm/m128, xmm 1433 // movaps xmm/m128, xmm
1430 int mod, regop, rm; 1434 int mod, regop, rm;
1431 get_modrm(*current, &mod, &regop, &rm); 1435 get_modrm(*current, &mod, &regop, &rm);
1432 AppendToBuffer("movaps "); 1436 Print("movaps ");
1433 current += PrintRightXMMOperand(current); 1437 current += PrintRightXMMOperand(current);
1434 AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1438 Print(", %s", NameOfXMMRegister(regop));
1435 } else if (opcode == 0x11) { 1439 } else if (opcode == 0x11) {
1436 // movups xmm/m128, xmm 1440 // movups xmm/m128, xmm
1437 int mod, regop, rm; 1441 int mod, regop, rm;
1438 get_modrm(*current, &mod, &regop, &rm); 1442 get_modrm(*current, &mod, &regop, &rm);
1439 AppendToBuffer("movups "); 1443 Print("movups ");
1440 current += PrintRightXMMOperand(current); 1444 current += PrintRightXMMOperand(current);
1441 AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1445 Print(", %s", NameOfXMMRegister(regop));
1442 } else if (opcode == 0x10) { 1446 } else if (opcode == 0x10) {
1443 // movups xmm, xmm/m128 1447 // movups xmm, xmm/m128
1444 int mod, regop, rm; 1448 int mod, regop, rm;
1445 get_modrm(*current, &mod, &regop, &rm); 1449 get_modrm(*current, &mod, &regop, &rm);
1446 AppendToBuffer("movups %s, ", NameOfXMMRegister(regop)); 1450 Print("movups %s, ", NameOfXMMRegister(regop));
1447 current += PrintRightXMMOperand(current); 1451 current += PrintRightXMMOperand(current);
1448 } else if (opcode == 0x50) { 1452 } else if (opcode == 0x50) {
1449 int mod, regop, rm; 1453 int mod, regop, rm;
1450 get_modrm(*current, &mod, &regop, &rm); 1454 get_modrm(*current, &mod, &regop, &rm);
1451 AppendToBuffer("movmskps %s,", NameOfCPURegister(regop)); 1455 Print("movmskps %s,", NameOfCPURegister(regop));
1452 current += PrintRightXMMOperand(current); 1456 current += PrintRightXMMOperand(current);
1453 } else if (opcode == 0xA2 || opcode == 0x31) { 1457 } else if (opcode == 0xA2 || opcode == 0x31) {
1454 // RDTSC or CPUID 1458 // RDTSC or CPUID
1455 AppendToBuffer("%s", mnemonic); 1459 Print("%s", mnemonic);
1456 1460
1457 } else if ((opcode & 0xF0) == 0x40) { 1461 } else if ((opcode & 0xF0) == 0x40) {
1458 // CMOVcc: conditional move. 1462 // CMOVcc: conditional move.
1459 int condition = opcode & 0x0F; 1463 int condition = opcode & 0x0F;
1460 const InstructionDesc& idesc = cmov_instructions[condition]; 1464 const InstructionDesc& idesc = cmov_instructions[condition];
1461 byte_size_operand_ = idesc.byte_size_operation; 1465 byte_size_operand_ = idesc.byte_size_operation;
1462 current += PrintOperands(idesc.mnem, idesc.op_order_, current); 1466 current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1463 1467
1464 } else if (opcode == 0x12 || opcode == 0x14 || opcode == 0x15 || 1468 } else if (opcode == 0x12 || opcode == 0x14 || opcode == 0x15 ||
1465 opcode == 0x16 || opcode == 0x51 || opcode == 0x52 || 1469 opcode == 0x16 || opcode == 0x51 || opcode == 0x52 ||
(...skipping 17 matching lines...) Expand all
1483 case 0x59: mnemonic = "mulps"; break; 1487 case 0x59: mnemonic = "mulps"; break;
1484 case 0x5A: mnemonic = "cvtsd2ss"; break; 1488 case 0x5A: mnemonic = "cvtsd2ss"; break;
1485 case 0x5C: mnemonic = "subps"; break; 1489 case 0x5C: mnemonic = "subps"; break;
1486 case 0x5D: mnemonic = "minps"; break; 1490 case 0x5D: mnemonic = "minps"; break;
1487 case 0x5E: mnemonic = "divps"; break; 1491 case 0x5E: mnemonic = "divps"; break;
1488 case 0x5F: mnemonic = "maxps"; break; 1492 case 0x5F: mnemonic = "maxps"; break;
1489 default: UNREACHABLE(); 1493 default: UNREACHABLE();
1490 } 1494 }
1491 int mod, regop, rm; 1495 int mod, regop, rm;
1492 get_modrm(*current, &mod, &regop, &rm); 1496 get_modrm(*current, &mod, &regop, &rm);
1493 AppendToBuffer("%s %s, ", mnemonic, NameOfXMMRegister(regop)); 1497 Print("%s %s, ", mnemonic, NameOfXMMRegister(regop));
1494 current += PrintRightXMMOperand(current); 1498 current += PrintRightXMMOperand(current);
1495 } else if (opcode == 0xC2 || opcode == 0xC6) { 1499 } else if (opcode == 0xC2 || opcode == 0xC6) {
1496 int mod, regop, rm; 1500 int mod, regop, rm;
1497 get_modrm(*current, &mod, &regop, &rm); 1501 get_modrm(*current, &mod, &regop, &rm);
1498 if (opcode == 0xC2) { 1502 if (opcode == 0xC2) {
1499 AppendToBuffer("cmpps %s, ", NameOfXMMRegister(regop)); 1503 Print("cmpps %s, ", NameOfXMMRegister(regop));
1500 } else { 1504 } else {
1501 ASSERT(opcode == 0xC6); 1505 ASSERT(opcode == 0xC6);
1502 AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop)); 1506 Print("shufps %s, ", NameOfXMMRegister(regop));
1503 } 1507 }
1504 current += PrintRightXMMOperand(current); 1508 current += PrintRightXMMOperand(current);
1505 AppendToBuffer(" [%x]", *current); 1509 Print(" [%x]", *current);
1506 current++; 1510 current++;
1507 } else if ((opcode & 0xF0) == 0x80) { 1511 } else if ((opcode & 0xF0) == 0x80) {
1508 // Jcc: Conditional jump (branch). 1512 // Jcc: Conditional jump (branch).
1509 current = data + JumpConditional(data); 1513 current = data + JumpConditional(data);
1510 1514
1511 } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 || 1515 } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
1512 opcode == 0xB7 || opcode == 0xAF || opcode == 0xB0 || 1516 opcode == 0xB7 || opcode == 0xAF || opcode == 0xB0 ||
1513 opcode == 0xB1) { 1517 opcode == 0xB1) {
1514 // Size-extending moves, IMUL, cmpxchg. 1518 // Size-extending moves, IMUL, cmpxchg.
1515 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current); 1519 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
1516 1520
1517 } else if ((opcode & 0xF0) == 0x90) { 1521 } else if ((opcode & 0xF0) == 0x90) {
1518 // SETcc: Set byte on condition. Needs pointer to beginning of instruction. 1522 // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
1519 current = data + SetCC(data); 1523 current = data + SetCC(data);
1520 1524
1521 } else if (((opcode & 0xFE) == 0xA4) || ((opcode & 0xFE) == 0xAC) || 1525 } else if (((opcode & 0xFE) == 0xA4) || ((opcode & 0xFE) == 0xAC) ||
1522 (opcode == 0xAB) || (opcode == 0xA3) || (opcode == 0xBD)) { 1526 (opcode == 0xAB) || (opcode == 0xA3) || (opcode == 0xBD)) {
1523 // SHLD, SHRD (double-prec. shift), BTS (bit test and set), BT (bit test). 1527 // SHLD, SHRD (double-prec. shift), BTS (bit test and set), BT (bit test).
1524 AppendToBuffer("%s%c ", mnemonic, operand_size_code()); 1528 Print("%s%c ", mnemonic, operand_size_code());
1525 int mod, regop, rm; 1529 int mod, regop, rm;
1526 get_modrm(*current, &mod, &regop, &rm); 1530 get_modrm(*current, &mod, &regop, &rm);
1527 current += PrintRightOperand(current); 1531 current += PrintRightOperand(current);
1528 AppendToBuffer(",%s", NameOfCPURegister(regop)); 1532 Print(",%s", NameOfCPURegister(regop));
1529 if ((opcode == 0xAB) || (opcode == 0xA3) || (opcode == 0xBD)) { 1533 if ((opcode == 0xAB) || (opcode == 0xA3) || (opcode == 0xBD)) {
1530 // Done. 1534 // Done.
1531 } else if ((opcode == 0xA5) || (opcode == 0xAD)) { 1535 } else if ((opcode == 0xA5) || (opcode == 0xAD)) {
1532 AppendToBuffer(",cl"); 1536 Print(",cl");
1533 } else { 1537 } else {
1534 AppendToBuffer(","); 1538 Print(",");
1535 current += PrintImmediate(current, BYTE_SIZE); 1539 current += PrintImmediate(current, BYTE_SIZE);
1536 } 1540 }
1537 } else { 1541 } else {
1538 UnimplementedInstruction(); 1542 UnimplementedInstruction();
1539 } 1543 }
1540 return static_cast<int>(current - data); 1544 return static_cast<int>(current - data);
1541 } 1545 }
1542 1546
1543 1547
1544 // Mnemonics for two-byte opcode instructions starting with 0x0F. 1548 // Mnemonics for two-byte opcode instructions starting with 0x0F.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1600 1604
1601 1605
1602 int DisassemblerX64::InstructionDecode(uword pc) { 1606 int DisassemblerX64::InstructionDecode(uword pc) {
1603 uint8_t* data = reinterpret_cast<uint8_t*>(pc); 1607 uint8_t* data = reinterpret_cast<uint8_t*>(pc);
1604 1608
1605 const bool processed = DecodeInstructionType(&data); 1609 const bool processed = DecodeInstructionType(&data);
1606 1610
1607 if (!processed) { 1611 if (!processed) {
1608 switch (*data) { 1612 switch (*data) {
1609 case 0xC2: 1613 case 0xC2:
1610 AppendToBuffer("ret %#x", *reinterpret_cast<uint16_t*>(data + 1)); 1614 Print("ret ");
1615 PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1));
1611 data += 3; 1616 data += 3;
1612 break; 1617 break;
1613 1618
1614 case 0xC8: 1619 case 0xC8:
1615 AppendToBuffer("enter %d, %d", 1620 Print("enter %d, %d",
1616 *reinterpret_cast<uint16_t*>(data + 1), 1621 *reinterpret_cast<uint16_t*>(data + 1),
1617 data[3]); 1622 data[3]);
1618 data += 4; 1623 data += 4;
1619 break; 1624 break;
1620 1625
1621 case 0x69: // fall through 1626 case 0x69: // fall through
1622 case 0x6B: { 1627 case 0x6B: {
1623 int mod, regop, rm; 1628 int mod, regop, rm;
1624 get_modrm(*(data + 1), &mod, &regop, &rm); 1629 get_modrm(*(data + 1), &mod, &regop, &rm);
1625 int32_t imm = *data == 0x6B ? *(data + 2) 1630 int32_t imm = *data == 0x6B ? *(data + 2)
1626 : *reinterpret_cast<int32_t*>(data + 2); 1631 : *reinterpret_cast<int32_t*>(data + 2);
1627 AppendToBuffer("imul%c %s,%s,%#x", 1632 Print("imul%c %s,%s,",
1628 operand_size_code(), 1633 operand_size_code(),
1629 NameOfCPURegister(regop), 1634 NameOfCPURegister(regop),
1630 NameOfCPURegister(rm), imm); 1635 NameOfCPURegister(rm));
1636 PrintImmediateValue(imm);
1631 data += 2 + (*data == 0x6B ? 1 : 4); 1637 data += 2 + (*data == 0x6B ? 1 : 4);
1632 break; 1638 break;
1633 } 1639 }
1634 1640
1635 case 0x81: // fall through 1641 case 0x81: // fall through
1636 case 0x83: // 0x81 with sign extension bit set 1642 case 0x83: // 0x81 with sign extension bit set
1637 data += PrintImmediateOp(data); 1643 data += PrintImmediateOp(data);
1638 break; 1644 break;
1639 1645
1640 case 0x0F: 1646 case 0x0F:
1641 data += TwoByteOpcodeInstruction(data); 1647 data += TwoByteOpcodeInstruction(data);
1642 break; 1648 break;
1643 1649
1644 case 0x8F: { 1650 case 0x8F: {
1645 data++; 1651 data++;
1646 int mod, regop, rm; 1652 int mod, regop, rm;
1647 get_modrm(*data, &mod, &regop, &rm); 1653 get_modrm(*data, &mod, &regop, &rm);
1648 if (regop == 0) { 1654 if (regop == 0) {
1649 AppendToBuffer("pop "); 1655 Print("pop ");
1650 data += PrintRightOperand(data); 1656 data += PrintRightOperand(data);
1651 } 1657 }
1652 } 1658 }
1653 break; 1659 break;
1654 1660
1655 case 0xFF: { 1661 case 0xFF: {
1656 data++; 1662 data++;
1657 int mod, regop, rm; 1663 int mod, regop, rm;
1658 get_modrm(*data, &mod, &regop, &rm); 1664 get_modrm(*data, &mod, &regop, &rm);
1659 const char* mnem = NULL; 1665 const char* mnem = NULL;
(...skipping 10 matching lines...) Expand all
1670 case 4: 1676 case 4:
1671 mnem = "jmp"; 1677 mnem = "jmp";
1672 break; 1678 break;
1673 case 6: 1679 case 6:
1674 mnem = "push"; 1680 mnem = "push";
1675 break; 1681 break;
1676 default: 1682 default:
1677 mnem = "???"; 1683 mnem = "???";
1678 } 1684 }
1679 if (regop <= 1) { 1685 if (regop <= 1) {
1680 AppendToBuffer("%s%c ", mnem, operand_size_code()); 1686 Print("%s%c ", mnem, operand_size_code());
1681 } else { 1687 } else {
1682 AppendToBuffer("%s ", mnem); 1688 Print("%s ", mnem);
1683 } 1689 }
1684 data += PrintRightOperand(data); 1690 data += PrintRightOperand(data);
1685 } 1691 }
1686 break; 1692 break;
1687 1693
1688 case 0xC7: // imm32, fall through 1694 case 0xC7: // imm32, fall through
1689 case 0xC6: // imm8 1695 case 0xC6: // imm8
1690 { 1696 {
1691 bool is_byte = *data == 0xC6; 1697 bool is_byte = *data == 0xC6;
1692 data++; 1698 data++;
1693 if (is_byte) { 1699 if (is_byte) {
1694 AppendToBuffer("movb "); 1700 Print("movb ");
1695 data += PrintRightByteOperand(data); 1701 data += PrintRightByteOperand(data);
1696 int32_t imm = *data; 1702 int32_t imm = *data;
1697 AppendToBuffer(",%#x", imm); 1703 Print(",");
1704 PrintImmediateValue(imm);
1698 data++; 1705 data++;
1699 } else { 1706 } else {
1700 AppendToBuffer("mov%c ", operand_size_code()); 1707 Print("mov%c ", operand_size_code());
1701 data += PrintRightOperand(data); 1708 data += PrintRightOperand(data);
1702 int32_t imm = *reinterpret_cast<int32_t*>(data); 1709 int32_t imm = *reinterpret_cast<int32_t*>(data);
1703 AppendToBuffer(",%#x", imm); 1710 Print(",");
1711 PrintImmediateValue(imm);
1704 data += 4; 1712 data += 4;
1705 } 1713 }
1706 } 1714 }
1707 break; 1715 break;
1708 1716
1709 case 0x80: { 1717 case 0x80: {
1710 data++; 1718 data++;
1711 AppendToBuffer("cmpb "); 1719 Print("cmpb ");
1712 data += PrintRightByteOperand(data); 1720 data += PrintRightByteOperand(data);
1713 int32_t imm = *data; 1721 int32_t imm = *data;
1714 AppendToBuffer(",%#x", imm); 1722 Print(",");
1723 PrintImmediateValue(imm);
1715 data++; 1724 data++;
1716 } 1725 }
1717 break; 1726 break;
1718 1727
1719 case 0x88: // 8bit, fall through 1728 case 0x88: // 8bit, fall through
1720 case 0x89: // 32bit 1729 case 0x89: // 32bit
1721 { 1730 {
1722 bool is_byte = *data == 0x88; 1731 bool is_byte = *data == 0x88;
1723 int mod, regop, rm; 1732 int mod, regop, rm;
1724 data++; 1733 data++;
1725 get_modrm(*data, &mod, &regop, &rm); 1734 get_modrm(*data, &mod, &regop, &rm);
1726 if (is_byte) { 1735 if (is_byte) {
1727 AppendToBuffer("movb "); 1736 Print("movb ");
1728 data += PrintRightByteOperand(data); 1737 data += PrintRightByteOperand(data);
1729 AppendToBuffer(",%s", NameOfByteCPURegister(regop)); 1738 Print(",%s", NameOfByteCPURegister(regop));
1730 } else { 1739 } else {
1731 AppendToBuffer("mov%c ", operand_size_code()); 1740 Print("mov%c ", operand_size_code());
1732 data += PrintRightOperand(data); 1741 data += PrintRightOperand(data);
1733 AppendToBuffer(",%s", NameOfCPURegister(regop)); 1742 Print(",%s", NameOfCPURegister(regop));
1734 } 1743 }
1735 } 1744 }
1736 break; 1745 break;
1737 1746
1738 case 0x90: 1747 case 0x90:
1739 case 0x91: 1748 case 0x91:
1740 case 0x92: 1749 case 0x92:
1741 case 0x93: 1750 case 0x93:
1742 case 0x94: 1751 case 0x94:
1743 case 0x95: 1752 case 0x95:
1744 case 0x96: 1753 case 0x96:
1745 case 0x97: { 1754 case 0x97: {
1746 int reg = (*data & 0x7) | (rex_b() ? 8 : 0); 1755 int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
1747 if (reg == 0) { 1756 if (reg == 0) {
1748 AppendToBuffer("nop"); // Common name for xchg rax,rax. 1757 Print("nop"); // Common name for xchg rax,rax.
1749 } else { 1758 } else {
1750 AppendToBuffer("xchg%c rax, %s", 1759 Print("xchg%c rax, %s", operand_size_code(), NameOfCPURegister(reg));
1751 operand_size_code(),
1752 NameOfCPURegister(reg));
1753 } 1760 }
1754 data++; 1761 data++;
1755 } 1762 }
1756 break; 1763 break;
1757 case 0xB0: 1764 case 0xB0:
1758 case 0xB1: 1765 case 0xB1:
1759 case 0xB2: 1766 case 0xB2:
1760 case 0xB3: 1767 case 0xB3:
1761 case 0xB4: 1768 case 0xB4:
1762 case 0xB5: 1769 case 0xB5:
1763 case 0xB6: 1770 case 0xB6:
1764 case 0xB7: 1771 case 0xB7:
1765 case 0xB8: 1772 case 0xB8:
1766 case 0xB9: 1773 case 0xB9:
1767 case 0xBA: 1774 case 0xBA:
1768 case 0xBB: 1775 case 0xBB:
1769 case 0xBC: 1776 case 0xBC:
1770 case 0xBD: 1777 case 0xBD:
1771 case 0xBE: 1778 case 0xBE:
1772 case 0xBF: { 1779 case 0xBF: {
1773 // mov reg8,imm8 or mov reg32,imm32 1780 // mov reg8,imm8 or mov reg32,imm32
1774 uint8_t opcode = *data; 1781 uint8_t opcode = *data;
1775 data++; 1782 data++;
1776 uint8_t is_32bit = (opcode >= 0xB8); 1783 uint8_t is_32bit = (opcode >= 0xB8);
1777 int reg = (opcode & 0x7) | (rex_b() ? 8 : 0); 1784 int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
1778 if (is_32bit) { 1785 if (is_32bit) {
1779 AppendToBuffer("mov%c %s, ", 1786 Print("mov%c %s,", operand_size_code(), NameOfCPURegister(reg));
1780 operand_size_code(),
1781 NameOfCPURegister(reg));
1782 data += PrintImmediate(data, DOUBLEWORD_SIZE); 1787 data += PrintImmediate(data, DOUBLEWORD_SIZE);
1783 } else { 1788 } else {
1784 AppendToBuffer("movb %s, ", 1789 Print("movb %s,", NameOfByteCPURegister(reg));
1785 NameOfByteCPURegister(reg));
1786 data += PrintImmediate(data, BYTE_SIZE); 1790 data += PrintImmediate(data, BYTE_SIZE);
1787 } 1791 }
1788 break; 1792 break;
1789 } 1793 }
1790 case 0xFE: { 1794 case 0xFE: {
1791 data++; 1795 data++;
1792 int mod, regop, rm; 1796 int mod, regop, rm;
1793 get_modrm(*data, &mod, &regop, &rm); 1797 get_modrm(*data, &mod, &regop, &rm);
1794 if (regop == 1) { 1798 if (regop == 1) {
1795 AppendToBuffer("decb "); 1799 Print("decb ");
1796 data += PrintRightByteOperand(data); 1800 data += PrintRightByteOperand(data);
1797 } else { 1801 } else {
1798 UnimplementedInstruction(); 1802 UnimplementedInstruction();
1799 } 1803 }
1800 break; 1804 break;
1801 } 1805 }
1802 case 0x68: 1806 case 0x68:
1803 AppendToBuffer("push %#x", *reinterpret_cast<int32_t*>(data + 1)); 1807 Print("push ");
1808 PrintImmediateValue(*reinterpret_cast<int32_t*>(data + 1));
1804 data += 5; 1809 data += 5;
1805 break; 1810 break;
1806 1811
1807 case 0x6A: 1812 case 0x6A:
1808 AppendToBuffer("push %#x", *reinterpret_cast<int8_t*>(data + 1)); 1813 Print("push ");
1814 PrintImmediateValue(*reinterpret_cast<int8_t*>(data + 1));
1809 data += 2; 1815 data += 2;
1810 break; 1816 break;
1811 1817
1812 case 0xA1: // Fall through. 1818 case 0xA1: // Fall through.
1813 case 0xA3: 1819 case 0xA3:
1814 switch (operand_size()) { 1820 switch (operand_size()) {
1815 case DOUBLEWORD_SIZE: { 1821 case DOUBLEWORD_SIZE: {
1816 AppendAddressToBuffer( 1822 PrintAddress(
1817 reinterpret_cast<uint8_t*>( 1823 reinterpret_cast<uint8_t*>(
1818 *reinterpret_cast<int32_t*>(data + 1))); 1824 *reinterpret_cast<int32_t*>(data + 1)));
1819 if (*data == 0xA1) { // Opcode 0xA1 1825 if (*data == 0xA1) { // Opcode 0xA1
1820 AppendToBuffer("movzxlq rax,("); 1826 Print("movzxlq rax,(");
1821 AppendAddressToBuffer( 1827 PrintAddress(
1822 reinterpret_cast<uint8_t*>( 1828 reinterpret_cast<uint8_t*>(
1823 *reinterpret_cast<int32_t*>(data + 1))); 1829 *reinterpret_cast<int32_t*>(data + 1)));
1824 AppendToBuffer(")"); 1830 Print(")");
1825 } else { // Opcode 0xA3 1831 } else { // Opcode 0xA3
1826 AppendToBuffer("movzxlq ("); 1832 Print("movzxlq (");
1827 AppendAddressToBuffer( 1833 PrintAddress(
1828 reinterpret_cast<uint8_t*>( 1834 reinterpret_cast<uint8_t*>(
1829 *reinterpret_cast<int32_t*>(data + 1))); 1835 *reinterpret_cast<int32_t*>(data + 1)));
1830 AppendToBuffer("),rax"); 1836 Print("),rax");
1831 } 1837 }
1832 data += 5; 1838 data += 5;
1833 break; 1839 break;
1834 } 1840 }
1835 case QUADWORD_SIZE: { 1841 case QUADWORD_SIZE: {
1836 // New x64 instruction mov rax,(imm_64). 1842 // New x64 instruction mov rax,(imm_64).
1837 if (*data == 0xA1) { // Opcode 0xA1 1843 if (*data == 0xA1) { // Opcode 0xA1
1838 AppendToBuffer("movq rax,("); 1844 Print("movq rax,(");
1839 AppendAddressToBuffer(*reinterpret_cast<uint8_t**>(data + 1)); 1845 PrintAddress(*reinterpret_cast<uint8_t**>(data + 1));
1840 AppendToBuffer(")"); 1846 Print(")");
1841 } else { // Opcode 0xA3 1847 } else { // Opcode 0xA3
1842 AppendToBuffer("movq ("); 1848 Print("movq (");
1843 AppendAddressToBuffer(*reinterpret_cast<uint8_t**>(data + 1)); 1849 PrintAddress(*reinterpret_cast<uint8_t**>(data + 1));
1844 AppendToBuffer("),rax"); 1850 Print("),rax");
1845 } 1851 }
1846 data += 9; 1852 data += 9;
1847 break; 1853 break;
1848 } 1854 }
1849 default: 1855 default:
1850 UnimplementedInstruction(); 1856 UnimplementedInstruction();
1851 data += 2; 1857 data += 2;
1852 } 1858 }
1853 break; 1859 break;
1854 1860
1855 case 0xA8: 1861 case 0xA8:
1856 AppendToBuffer("test al,%#x", *reinterpret_cast<uint8_t*>(data + 1)); 1862 Print("test al,");
1863 PrintImmediateValue(*reinterpret_cast<uint8_t*>(data + 1));
1857 data += 2; 1864 data += 2;
1858 break; 1865 break;
1859 1866
1860 case 0xA9: { 1867 case 0xA9: {
1861 int64_t value = 0; 1868 int64_t value = 0;
1862 switch (operand_size()) { 1869 switch (operand_size()) {
1863 case WORD_SIZE: 1870 case WORD_SIZE:
1864 value = *reinterpret_cast<uint16_t*>(data + 1); 1871 value = *reinterpret_cast<uint16_t*>(data + 1);
1865 data += 3; 1872 data += 3;
1866 break; 1873 break;
1867 case DOUBLEWORD_SIZE: 1874 case DOUBLEWORD_SIZE:
1868 value = *reinterpret_cast<uint32_t*>(data + 1); 1875 value = *reinterpret_cast<uint32_t*>(data + 1);
1869 data += 5; 1876 data += 5;
1870 break; 1877 break;
1871 case QUADWORD_SIZE: 1878 case QUADWORD_SIZE:
1872 value = *reinterpret_cast<int32_t*>(data + 1); 1879 value = *reinterpret_cast<int32_t*>(data + 1);
1873 data += 5; 1880 data += 5;
1874 break; 1881 break;
1875 default: 1882 default:
1876 UNREACHABLE(); 1883 UNREACHABLE();
1877 } 1884 }
1878 AppendToBuffer("test%c rax,%#" Px64 "", 1885 Print("test%c rax,", operand_size_code());
1879 operand_size_code(), 1886 PrintImmediateValue(value);
1880 value);
1881 break; 1887 break;
1882 } 1888 }
1883 case 0xD1: // fall through 1889 case 0xD1: // fall through
1884 case 0xD3: // fall through 1890 case 0xD3: // fall through
1885 case 0xC1: 1891 case 0xC1:
1886 data += ShiftInstruction(data); 1892 data += ShiftInstruction(data);
1887 break; 1893 break;
1888 case 0xD0: // fall through 1894 case 0xD0: // fall through
1889 case 0xD2: // fall through 1895 case 0xD2: // fall through
1890 case 0xC0: 1896 case 0xC0:
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1946 if (out_instr_len) { 1952 if (out_instr_len) {
1947 *out_instr_len = instruction_length; 1953 *out_instr_len = instruction_length;
1948 } 1954 }
1949 } 1955 }
1950 1956
1951 #endif // !PRODUCT 1957 #endif // !PRODUCT
1952 1958
1953 } // namespace dart 1959 } // namespace dart
1954 1960
1955 #endif // defined TARGET_ARCH_X64 1961 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698