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

Unified Diff: runtime/vm/disassembler_mips.cc

Issue 12541003: - Add a skeleton MIPS assembler, disassembler and simulator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/disassembler_mips.cc
===================================================================
--- runtime/vm/disassembler_mips.cc (revision 19556)
+++ runtime/vm/disassembler_mips.cc (working copy)
@@ -10,11 +10,225 @@
namespace dart {
+class MIPSDecoder : public ValueObject {
+ public:
+ MIPSDecoder(char* buffer, size_t buffer_size)
+ : buffer_(buffer),
+ buffer_size_(buffer_size),
+ buffer_pos_(0),
+ delay_slot_(false) {
+ buffer_[buffer_pos_] = '\0';
+ }
+
+ ~MIPSDecoder() {}
+
+ // Writes one disassembled instruction into 'buffer' (0-terminated).
+ void InstructionDecode(Instr* instr);
+
+ private:
+ // Bottleneck functions to print into the out_buffer.
+ void Print(const char* str);
+
+ // Printing of common values.
+ void PrintRegister(Register reg);
+
+ int FormatRegister(Instr* instr, const char* format);
+ int FormatOption(Instr* instr, const char* format);
+ void Format(Instr* instr, const char* format);
+
+ void DecodeSpecial(Instr* instr);
+
+ // Convenience functions.
+ char* get_buffer() const { return buffer_; }
+ char* current_position_in_buffer() { return buffer_ + buffer_pos_; }
+ size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; }
+
+ char* buffer_; // Decode instructions into this buffer.
+ size_t buffer_size_; // The size of the character buffer.
+ size_t buffer_pos_; // Current character position in buffer.
+
+ bool delay_slot_; // Previous instruction uses a delay slot.
regis 2013/03/06 21:18:42 How will you use this info in the disassembler? I
Ivan Posva 2013/03/07 11:03:22 I was toying with the idea of not creating an inst
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_COPY_AND_ASSIGN(MIPSDecoder);
+};
+
+
+// Support for assertions in the MIPSDecoder formatting functions.
+#define STRING_STARTS_WITH(string, compare_string) \
+ (strncmp(string, compare_string, strlen(compare_string)) == 0)
+
+
+// Append the str to the output buffer.
+void MIPSDecoder::Print(const char* str) {
+ char cur = *str++;
+ while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) {
+ buffer_[buffer_pos_++] = cur;
+ cur = *str++;
+ }
+ buffer_[buffer_pos_] = '\0';
+}
+
+
+static const char* reg_names[kNumberOfCpuRegisters] = {
+ "r0" , "r1" , "r2" , "r3" , "r4" , "r5" , "r6" , "r7" ,
+ "r8" , "r9" , "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+};
regis 2013/03/06 21:18:42 For better readability of disassembly, we should u
+
+
+void MIPSDecoder::PrintRegister(Register reg) {
+ ASSERT(0 <= reg);
+ ASSERT(reg < kNumberOfCpuRegisters);
+ Print(reg_names[reg]);
+}
+
+
+// Handle all register based formatting in these functions to reduce the
+// complexity of FormatOption.
+int MIPSDecoder::FormatRegister(Instr* instr, const char* format) {
+ ASSERT(format[0] == 'r');
+ switch (format[1]) {
+ case 's': { // 'rs: Rs register
+ PrintRegister(instr->RsField());
+ return 2;
+ }
+ case 't': { // 'rt: Rt register
+ PrintRegister(instr->RtField());
+ return 2;
+ }
+ case 'd': { // 'rd: Rd register
+ PrintRegister(instr->RdField());
+ return 2;
+ }
+ }
+ UNREACHABLE();
+ return -1;
+}
+
+
+// FormatOption takes a formatting string and interprets it based on
+// the current instructions. The format string points to the first
+// character of the option string (the option escape has already been
+// consumed by the caller.) FormatOption returns the number of
+// characters that were consumed from the formatting string.
+int MIPSDecoder::FormatOption(Instr* instr, const char* format) {
+ switch (format[0]) {
+ case 'h': {
+ ASSERT(STRING_STARTS_WITH(format, "hint"));
+ if (instr->SaField() != 0) {
+ UNIMPLEMENTED();
+ }
+ return 4;
+ }
+ case 'i': {
+ ASSERT(STRING_STARTS_WITH(format, "imm"));
+ int32_t imm = instr->ImmField();
+ buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(),
+ "0x%x",
+ imm);
+ return 3;
+ }
+ case 'r': {
+ return FormatRegister(instr, format);
+ }
+ case 's': {
+ ASSERT(STRING_STARTS_WITH(format, "sa"));
+ buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(),
+ "%d",
+ instr->SaField());
+ return 2;
+ }
+ default: {
+ UNREACHABLE();
+ }
+ }
+ UNREACHABLE();
+ return -1;
+}
+
+
+// Format takes a formatting string for a whole instruction and prints it into
+// the output buffer. All escaped options are handed to FormatOption to be
+// parsed further.
+void MIPSDecoder::Format(Instr* instr, const char* format) {
+ if (delay_slot_) {
+ delay_slot_ = false;
+ // if (buffer_pos_ < (buffer_size_ - 1)) {
regis 2013/03/06 21:18:42 Commented out code?
Ivan Posva 2013/03/07 11:03:22 Yes, another left over from the experiment with pr
+ buffer_[buffer_pos_++] = '*';
+ // }
+ }
+ char cur = *format++;
+ while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) {
+ if (cur == '\'') { // Single quote is used as the formatting escape.
+ format += FormatOption(instr, format);
+ } else {
+ buffer_[buffer_pos_++] = cur;
+ }
+ cur = *format++;
+ }
+ buffer_[buffer_pos_] = '\0';
+}
+
+
+void MIPSDecoder::DecodeSpecial(Instr* instr) {
+ switch (instr->FunctionField()) {
+ case SLL: {
+ if ((instr->RdField() == R0) &&
+ (instr->RtField() == R0) &&
+ (instr->SaField() == 0)) {
+ Format(instr, "nop");
+ } else {
+ Format(instr, "sll 'rd, 'rt, 'sa");
+ }
+ break;
+ }
+ case JR: {
+ ASSERT(instr->RtField() == R0);
+ ASSERT(instr->RdField() == R0);
+ Format(instr, "jr'hint 'rs");
+ delay_slot_ = true;
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits());
+ UNREACHABLE();
+ break;
+ }
+ }
+}
+
+
+void MIPSDecoder::InstructionDecode(Instr* instr) {
+ switch (instr->OpcodeField()) {
+ case SPECIAL: {
+ DecodeSpecial(instr);
+ break;
+ }
+ case ORI: {
+ Format(instr, "ori 'rt, 'rs, 'imm");
+ break;
+ }
+ default: {
+ OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits());
+ UNREACHABLE();
+ break;
+ }
+ }
+}
+
+
int Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
char* human_buffer, intptr_t human_size,
uword pc) {
- UNIMPLEMENTED();
- return 0;
+ MIPSDecoder decoder(human_buffer, human_size);
+ Instr* instr = Instr::At(pc);
+ decoder.InstructionDecode(instr);
+ OS::SNPrint(hex_buffer, hex_size, "%08x", instr->InstructionBits());
+ return Instr::kInstrSize;
}
@@ -22,7 +236,32 @@
uword end,
DisassemblyFormatter* formatter,
const Code::Comments& comments) {
- UNIMPLEMENTED();
+ ASSERT(formatter != NULL);
+ char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form.
+ char human_buffer[kUserReadableBufferSize]; // Human-readable instruction.
+ uword pc = start;
+ intptr_t comment_finger = 0;
+ while (pc < end) {
+ const intptr_t offset = pc - start;
+ while (comment_finger < comments.Length() &&
+ comments.PCOffsetAt(comment_finger) <= offset) {
+ formatter->Print(
+ " ;; %s\n",
+ String::Handle(comments.CommentAt(comment_finger)).ToCString());
+ comment_finger++;
+ }
+ int instruction_length = DecodeInstruction(hex_buffer,
+ sizeof(hex_buffer),
+ human_buffer,
+ sizeof(human_buffer),
+ pc);
+ formatter->ConsumeInstruction(hex_buffer,
+ sizeof(hex_buffer),
+ human_buffer,
+ sizeof(human_buffer),
+ pc);
+ pc += instruction_length;
+ }
}
} // namespace dart

Powered by Google App Engine
This is Rietveld 408576698