| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 8 #if defined(TARGET_ARCH_MIPS) | 8 #if defined(TARGET_ARCH_MIPS) |
| 9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
| 10 | 10 |
| 11 namespace dart { | 11 namespace dart { |
| 12 | 12 |
| 13 class MIPSDecoder : public ValueObject { | 13 class MIPSDecoder : public ValueObject { |
| 14 public: | 14 public: |
| 15 MIPSDecoder(char* buffer, size_t buffer_size) | 15 MIPSDecoder(char* buffer, size_t buffer_size) |
| 16 : buffer_(buffer), | 16 : buffer_(buffer), |
| 17 buffer_size_(buffer_size), | 17 buffer_size_(buffer_size), |
| 18 buffer_pos_(0), | 18 buffer_pos_(0) { |
| 19 decode_failure_(false) { | |
| 20 buffer_[buffer_pos_] = '\0'; | 19 buffer_[buffer_pos_] = '\0'; |
| 21 } | 20 } |
| 22 | 21 |
| 23 ~MIPSDecoder() {} | 22 ~MIPSDecoder() {} |
| 24 | 23 |
| 25 // Writes one disassembled instruction into 'buffer' (0-terminated). | 24 // Writes one disassembled instruction into 'buffer' (0-terminated). |
| 26 // Returns true if the instruction was successfully decoded, false otherwise. | 25 // Returns true if the instruction was successfully decoded, false otherwise. |
| 27 void InstructionDecode(Instr* instr); | 26 void InstructionDecode(Instr* instr); |
| 28 | 27 |
| 29 void set_decode_failure(bool b) { decode_failure_ = b; } | |
| 30 bool decode_failure() const { return decode_failure_; } | |
| 31 | |
| 32 private: | 28 private: |
| 33 // Bottleneck functions to print into the out_buffer. | 29 // Bottleneck functions to print into the out_buffer. |
| 34 void Print(const char* str); | 30 void Print(const char* str); |
| 35 | 31 |
| 36 // Printing of common values. | 32 // Printing of common values. |
| 37 void PrintRegister(Register reg); | 33 void PrintRegister(Register reg); |
| 38 | 34 |
| 39 int FormatRegister(Instr* instr, const char* format); | 35 int FormatRegister(Instr* instr, const char* format); |
| 40 int FormatOption(Instr* instr, const char* format); | 36 int FormatOption(Instr* instr, const char* format); |
| 41 void Format(Instr* instr, const char* format); | 37 void Format(Instr* instr, const char* format); |
| 42 void Unknown(Instr* instr); | 38 void Unknown(Instr* instr); |
| 43 | 39 |
| 44 void DecodeSpecial(Instr* instr); | 40 void DecodeSpecial(Instr* instr); |
| 45 void DecodeSpecial2(Instr* instr); | 41 void DecodeSpecial2(Instr* instr); |
| 46 | 42 |
| 47 // Convenience functions. | 43 // Convenience functions. |
| 48 char* get_buffer() const { return buffer_; } | 44 char* get_buffer() const { return buffer_; } |
| 49 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } | 45 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } |
| 50 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } | 46 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } |
| 51 | 47 |
| 52 char* buffer_; // Decode instructions into this buffer. | 48 char* buffer_; // Decode instructions into this buffer. |
| 53 size_t buffer_size_; // The size of the character buffer. | 49 size_t buffer_size_; // The size of the character buffer. |
| 54 size_t buffer_pos_; // Current character position in buffer. | 50 size_t buffer_pos_; // Current character position in buffer. |
| 55 | 51 |
| 56 bool decode_failure_; // Set to true when a failure to decode is detected. | |
| 57 | |
| 58 DISALLOW_ALLOCATION(); | 52 DISALLOW_ALLOCATION(); |
| 59 DISALLOW_COPY_AND_ASSIGN(MIPSDecoder); | 53 DISALLOW_COPY_AND_ASSIGN(MIPSDecoder); |
| 60 }; | 54 }; |
| 61 | 55 |
| 62 | 56 |
| 63 // Support for assertions in the MIPSDecoder formatting functions. | 57 // Support for assertions in the MIPSDecoder formatting functions. |
| 64 #define STRING_STARTS_WITH(string, compare_string) \ | 58 #define STRING_STARTS_WITH(string, compare_string) \ |
| 65 (strncmp(string, compare_string, strlen(compare_string)) == 0) | 59 (strncmp(string, compare_string, strlen(compare_string)) == 0) |
| 66 | 60 |
| 67 | 61 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 cur = *format++; | 189 cur = *format++; |
| 196 } | 190 } |
| 197 buffer_[buffer_pos_] = '\0'; | 191 buffer_[buffer_pos_] = '\0'; |
| 198 } | 192 } |
| 199 | 193 |
| 200 | 194 |
| 201 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 195 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 202 // which will just print "unknown" of the instruction bits. | 196 // which will just print "unknown" of the instruction bits. |
| 203 void MIPSDecoder::Unknown(Instr* instr) { | 197 void MIPSDecoder::Unknown(Instr* instr) { |
| 204 Format(instr, "unknown"); | 198 Format(instr, "unknown"); |
| 205 set_decode_failure(true); | |
| 206 } | 199 } |
| 207 | 200 |
| 208 | 201 |
| 209 void MIPSDecoder::DecodeSpecial(Instr* instr) { | 202 void MIPSDecoder::DecodeSpecial(Instr* instr) { |
| 210 ASSERT(instr->OpcodeField() == SPECIAL); | 203 ASSERT(instr->OpcodeField() == SPECIAL); |
| 211 switch (instr->FunctionField()) { | 204 switch (instr->FunctionField()) { |
| 212 case ADDU: { | 205 case ADDU: { |
| 213 Format(instr, "addu 'rd, 'rs, 'rt"); | 206 Format(instr, "addu 'rd, 'rs, 'rt"); |
| 214 break; | 207 break; |
| 215 } | 208 } |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 break; | 414 break; |
| 422 } | 415 } |
| 423 default: { | 416 default: { |
| 424 Unknown(instr); | 417 Unknown(instr); |
| 425 break; | 418 break; |
| 426 } | 419 } |
| 427 } | 420 } |
| 428 } | 421 } |
| 429 | 422 |
| 430 | 423 |
| 431 bool Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, | 424 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, |
| 432 char* human_buffer, intptr_t human_size, | 425 char* human_buffer, intptr_t human_size, |
| 433 int *out_instr_len, uword pc) { | 426 int* out_instr_len, uword pc) { |
| 434 MIPSDecoder decoder(human_buffer, human_size); | 427 MIPSDecoder decoder(human_buffer, human_size); |
| 435 Instr* instr = Instr::At(pc); | 428 Instr* instr = Instr::At(pc); |
| 436 decoder.InstructionDecode(instr); | 429 decoder.InstructionDecode(instr); |
| 437 OS::SNPrint(hex_buffer, hex_size, "%08x", instr->InstructionBits()); | 430 OS::SNPrint(hex_buffer, hex_size, "%08x", instr->InstructionBits()); |
| 438 if (out_instr_len) { | 431 if (out_instr_len) { |
| 439 *out_instr_len = Instr::kInstrSize; | 432 *out_instr_len = Instr::kInstrSize; |
| 440 } | 433 } |
| 441 return !decoder.decode_failure(); | |
| 442 } | 434 } |
| 443 | 435 |
| 444 | 436 |
| 445 bool Disassembler::Disassemble(uword start, | 437 void Disassembler::Disassemble(uword start, |
| 446 uword end, | 438 uword end, |
| 447 DisassemblyFormatter* formatter, | 439 DisassemblyFormatter* formatter, |
| 448 const Code::Comments& comments) { | 440 const Code::Comments& comments) { |
| 449 ASSERT(formatter != NULL); | 441 ASSERT(formatter != NULL); |
| 450 bool success = true; | |
| 451 char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form. | 442 char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form. |
| 452 char human_buffer[kUserReadableBufferSize]; // Human-readable instruction. | 443 char human_buffer[kUserReadableBufferSize]; // Human-readable instruction. |
| 453 uword pc = start; | 444 uword pc = start; |
| 454 intptr_t comment_finger = 0; | 445 intptr_t comment_finger = 0; |
| 455 while (pc < end) { | 446 while (pc < end) { |
| 456 const intptr_t offset = pc - start; | 447 const intptr_t offset = pc - start; |
| 457 while (comment_finger < comments.Length() && | 448 while (comment_finger < comments.Length() && |
| 458 comments.PCOffsetAt(comment_finger) <= offset) { | 449 comments.PCOffsetAt(comment_finger) <= offset) { |
| 459 formatter->Print( | 450 formatter->Print( |
| 460 " ;; %s\n", | 451 " ;; %s\n", |
| 461 String::Handle(comments.CommentAt(comment_finger)).ToCString()); | 452 String::Handle(comments.CommentAt(comment_finger)).ToCString()); |
| 462 comment_finger++; | 453 comment_finger++; |
| 463 } | 454 } |
| 464 int instruction_length; | 455 int instruction_length; |
| 465 bool res = DecodeInstruction(hex_buffer, sizeof(hex_buffer), | 456 DecodeInstruction(hex_buffer, sizeof(hex_buffer), |
| 466 human_buffer, sizeof(human_buffer), | 457 human_buffer, sizeof(human_buffer), |
| 467 &instruction_length, pc); | 458 &instruction_length, pc); |
| 468 if (!res) { | 459 |
| 469 success = false; | |
| 470 } | |
| 471 formatter->ConsumeInstruction(hex_buffer, | 460 formatter->ConsumeInstruction(hex_buffer, |
| 472 sizeof(hex_buffer), | 461 sizeof(hex_buffer), |
| 473 human_buffer, | 462 human_buffer, |
| 474 sizeof(human_buffer), | 463 sizeof(human_buffer), |
| 475 pc); | 464 pc); |
| 476 pc += instruction_length; | 465 pc += instruction_length; |
| 477 } | 466 } |
| 478 | 467 |
| 479 return success; | 468 return; |
| 480 } | 469 } |
| 481 | 470 |
| 482 } // namespace dart | 471 } // namespace dart |
| 483 | 472 |
| 484 #endif // defined TARGET_ARCH_MIPS | 473 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |