| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 8 #if defined(TARGET_ARCH_ARM64) | 8 #if defined(TARGET_ARCH_ARM64) |
| 9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
| 10 | 10 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 buffer_[buffer_pos_] = '\0'; | 78 buffer_[buffer_pos_] = '\0'; |
| 79 } | 79 } |
| 80 | 80 |
| 81 | 81 |
| 82 // These register names are defined in a way to match the native disassembler | 82 // These register names are defined in a way to match the native disassembler |
| 83 // formatting, except for register aliases ctx (r9) and pp (r10). | 83 // formatting, except for register aliases ctx (r9) and pp (r10). |
| 84 // See for example the command "objdump -d <binary file>". | 84 // See for example the command "objdump -d <binary file>". |
| 85 static const char* reg_names[kNumberOfCpuRegisters] = { | 85 static const char* reg_names[kNumberOfCpuRegisters] = { |
| 86 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 86 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
| 87 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | 87 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
| 88 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", | 88 "ip0", "ip1", "r18", "r19", "r20", "r21", "r22", "r23", |
| 89 "r24", "ip0", "ip1", "pp", "ctx", "fp", "lr", "r31", | 89 "r24", "r25", "r26", "pp", "ctx", "fp", "lr", "r31", |
| 90 }; | 90 }; |
| 91 | 91 |
| 92 | 92 |
| 93 // Print the register name according to the active name converter. | 93 // Print the register name according to the active name converter. |
| 94 void ARM64Decoder::PrintRegister(int reg, R31Type r31t) { | 94 void ARM64Decoder::PrintRegister(int reg, R31Type r31t) { |
| 95 ASSERT(0 <= reg); | 95 ASSERT(0 <= reg); |
| 96 ASSERT(reg < kNumberOfCpuRegisters); | 96 ASSERT(reg < kNumberOfCpuRegisters); |
| 97 if (reg == 31) { | 97 if (reg == 31) { |
| 98 const char* rstr = (r31t == R31IsZR) ? "zr" : "sp"; | 98 const char* rstr = (r31t == R31IsZR) ? "zr" : "sp"; |
| 99 Print(rstr); | 99 Print(rstr); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 "0x%"Px64, | 371 "0x%"Px64, |
| 372 imm); | 372 imm); |
| 373 return ret; | 373 return ret; |
| 374 } | 374 } |
| 375 case 'm': { | 375 case 'm': { |
| 376 ASSERT(STRING_STARTS_WITH(format, "memop")); | 376 ASSERT(STRING_STARTS_WITH(format, "memop")); |
| 377 PrintMemOperand(instr); | 377 PrintMemOperand(instr); |
| 378 return 5; | 378 return 5; |
| 379 } | 379 } |
| 380 case 'p': { | 380 case 'p': { |
| 381 ASSERT(STRING_STARTS_WITH(format, "pcrel")); | 381 if (format[2] == 'a') { |
| 382 const int64_t immhi = instr->SImm19Field(); | 382 ASSERT(STRING_STARTS_WITH(format, "pcadr")); |
| 383 const int64_t immlo = instr->Bits(29, 2); | 383 const int64_t immhi = instr->SImm19Field(); |
| 384 const int64_t off = (immhi << 2) | immlo; | 384 const int64_t immlo = instr->Bits(29, 2); |
| 385 const int64_t pc = reinterpret_cast<int64_t>(instr); | 385 const int64_t off = (immhi << 2) | immlo; |
| 386 const int64_t dest = pc + off; | 386 const int64_t pc = reinterpret_cast<int64_t>(instr); |
| 387 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 387 const int64_t dest = pc + off; |
| 388 remaining_size_in_buffer(), | 388 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 389 "0x%"Px64, | 389 remaining_size_in_buffer(), |
| 390 dest); | 390 "0x%"Px64, |
| 391 dest); |
| 392 } else { |
| 393 ASSERT(STRING_STARTS_WITH(format, "pcldr")); |
| 394 const int64_t off = instr->SImm19Field() << 2; |
| 395 const int64_t pc = reinterpret_cast<int64_t>(instr); |
| 396 const int64_t dest = pc + off; |
| 397 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 398 remaining_size_in_buffer(), |
| 399 "0x%"Px64, |
| 400 dest); |
| 401 } |
| 391 return 5; | 402 return 5; |
| 392 } | 403 } |
| 393 case 'r': { | 404 case 'r': { |
| 394 return FormatRegister(instr, format); | 405 return FormatRegister(instr, format); |
| 395 } | 406 } |
| 396 case 's': { // 's: S flag. | 407 case 's': { // 's: S flag. |
| 397 if (format[1] == 'h') { | 408 if (format[1] == 'h') { |
| 398 ASSERT(STRING_STARTS_WITH(format, "shift_op")); | 409 ASSERT(STRING_STARTS_WITH(format, "shift_op")); |
| 399 PrintShiftExtendRm(instr); | 410 PrintShiftExtendRm(instr); |
| 400 return 8; | 411 return 8; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 return; | 502 return; |
| 492 } | 503 } |
| 493 if (instr->Bit(22) == 1) { | 504 if (instr->Bit(22) == 1) { |
| 494 Format(instr, "ldr'sz 'rt, 'memop"); | 505 Format(instr, "ldr'sz 'rt, 'memop"); |
| 495 } else { | 506 } else { |
| 496 Format(instr, "str'sz 'rt, 'memop"); | 507 Format(instr, "str'sz 'rt, 'memop"); |
| 497 } | 508 } |
| 498 } | 509 } |
| 499 | 510 |
| 500 | 511 |
| 512 void ARM64Decoder::DecodeLoadRegLiteral(Instr* instr) { |
| 513 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || |
| 514 (instr->Bits(24, 3) != 0)) { |
| 515 Unknown(instr); |
| 516 } |
| 517 if (instr->Bit(30)) { |
| 518 Format(instr, "ldrx 'rt, 'pcldr"); |
| 519 } else { |
| 520 Format(instr, "ldrw 'rt, 'pcldr"); |
| 521 } |
| 522 } |
| 523 |
| 524 |
| 501 void ARM64Decoder::DecodeAddSubImm(Instr* instr) { | 525 void ARM64Decoder::DecodeAddSubImm(Instr* instr) { |
| 502 switch (instr->Bit(30)) { | 526 switch (instr->Bit(30)) { |
| 503 case 0: { | 527 case 0: { |
| 504 if ((instr->RdField() == R31) && (instr->SFField())) { | 528 if ((instr->RdField() == R31) && (instr->SFField())) { |
| 505 Format(instr, "cmni'sf 'rn, 'imm12s"); | 529 Format(instr, "cmni'sf 'rn, 'imm12s"); |
| 506 } else { | 530 } else { |
| 507 if (((instr->RdField() == R31) || (instr->RnField() == R31)) && | 531 if (((instr->RdField() == R31) || (instr->RnField() == R31)) && |
| 508 (instr->Imm12Field() == 0) && (instr->Bit(29) == 0)) { | 532 (instr->Imm12Field() == 0) && (instr->Bit(29) == 0)) { |
| 509 Format(instr, "mov'sf 'rd, 'rn"); | 533 Format(instr, "mov'sf 'rd, 'rn"); |
| 510 } else { | 534 } else { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 default: | 575 default: |
| 552 Unknown(instr); | 576 Unknown(instr); |
| 553 break; | 577 break; |
| 554 } | 578 } |
| 555 } | 579 } |
| 556 | 580 |
| 557 | 581 |
| 558 void ARM64Decoder::DecodePCRel(Instr* instr) { | 582 void ARM64Decoder::DecodePCRel(Instr* instr) { |
| 559 const int op = instr->Bit(31); | 583 const int op = instr->Bit(31); |
| 560 if (op == 0) { | 584 if (op == 0) { |
| 561 Format(instr, "adr 'rd, 'pcrel"); | 585 Format(instr, "adr 'rd, 'pcadr"); |
| 562 } else { | 586 } else { |
| 563 Unknown(instr); | 587 Unknown(instr); |
| 564 } | 588 } |
| 565 } | 589 } |
| 566 | 590 |
| 567 | 591 |
| 568 void ARM64Decoder::DecodeDPImmediate(Instr* instr) { | 592 void ARM64Decoder::DecodeDPImmediate(Instr* instr) { |
| 569 if (instr->IsMoveWideOp()) { | 593 if (instr->IsMoveWideOp()) { |
| 570 DecodeMoveWide(instr); | 594 DecodeMoveWide(instr); |
| 571 } else if (instr->IsAddSubImmOp()) { | 595 } else if (instr->IsAddSubImmOp()) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 DecodeUnconditionalBranch(instr); | 709 DecodeUnconditionalBranch(instr); |
| 686 } else { | 710 } else { |
| 687 Unknown(instr); | 711 Unknown(instr); |
| 688 } | 712 } |
| 689 } | 713 } |
| 690 | 714 |
| 691 | 715 |
| 692 void ARM64Decoder::DecodeLoadStore(Instr* instr) { | 716 void ARM64Decoder::DecodeLoadStore(Instr* instr) { |
| 693 if (instr->IsLoadStoreRegOp()) { | 717 if (instr->IsLoadStoreRegOp()) { |
| 694 DecodeLoadStoreReg(instr); | 718 DecodeLoadStoreReg(instr); |
| 719 } else if (instr->IsLoadRegLiteralOp()) { |
| 720 DecodeLoadRegLiteral(instr); |
| 695 } else { | 721 } else { |
| 696 Unknown(instr); | 722 Unknown(instr); |
| 697 } | 723 } |
| 698 } | 724 } |
| 699 | 725 |
| 700 | 726 |
| 701 void ARM64Decoder::DecodeAddSubShiftExt(Instr* instr) { | 727 void ARM64Decoder::DecodeAddSubShiftExt(Instr* instr) { |
| 702 switch (instr->Bit(30)) { | 728 switch (instr->Bit(30)) { |
| 703 case 0: { | 729 case 0: { |
| 704 if ((instr->RdField() == R31) && (instr->SFField())) { | 730 if ((instr->RdField() == R31) && (instr->SFField())) { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 human_buffer, | 918 human_buffer, |
| 893 sizeof(human_buffer), | 919 sizeof(human_buffer), |
| 894 pc); | 920 pc); |
| 895 pc += instruction_length; | 921 pc += instruction_length; |
| 896 } | 922 } |
| 897 } | 923 } |
| 898 | 924 |
| 899 } // namespace dart | 925 } // namespace dart |
| 900 | 926 |
| 901 #endif // defined TARGET_ARCH_ARM | 927 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |