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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 {
14 public:
15 MIPSDecoder(char* buffer, size_t buffer_size)
16 : buffer_(buffer),
17 buffer_size_(buffer_size),
18 buffer_pos_(0),
19 delay_slot_(false) {
20 buffer_[buffer_pos_] = '\0';
21 }
22
23 ~MIPSDecoder() {}
24
25 // Writes one disassembled instruction into 'buffer' (0-terminated).
26 void InstructionDecode(Instr* instr);
27
28 private:
29 // Bottleneck functions to print into the out_buffer.
30 void Print(const char* str);
31
32 // Printing of common values.
33 void PrintRegister(Register reg);
34
35 int FormatRegister(Instr* instr, const char* format);
36 int FormatOption(Instr* instr, const char* format);
37 void Format(Instr* instr, const char* format);
38
39 void DecodeSpecial(Instr* instr);
40
41 // Convenience functions.
42 char* get_buffer() const { return buffer_; }
43 char* current_position_in_buffer() { return buffer_ + buffer_pos_; }
44 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; }
45
46 char* buffer_; // Decode instructions into this buffer.
47 size_t buffer_size_; // The size of the character buffer.
48 size_t buffer_pos_; // Current character position in buffer.
49
50 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
51
52 DISALLOW_ALLOCATION();
53 DISALLOW_COPY_AND_ASSIGN(MIPSDecoder);
54 };
55
56
57 // Support for assertions in the MIPSDecoder formatting functions.
58 #define STRING_STARTS_WITH(string, compare_string) \
59 (strncmp(string, compare_string, strlen(compare_string)) == 0)
60
61
62 // Append the str to the output buffer.
63 void MIPSDecoder::Print(const char* str) {
64 char cur = *str++;
65 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) {
66 buffer_[buffer_pos_++] = cur;
67 cur = *str++;
68 }
69 buffer_[buffer_pos_] = '\0';
70 }
71
72
73 static const char* reg_names[kNumberOfCpuRegisters] = {
74 "r0" , "r1" , "r2" , "r3" , "r4" , "r5" , "r6" , "r7" ,
75 "r8" , "r9" , "r10", "r11", "r12", "r13", "r14", "r15",
76 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
77 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
78 };
regis 2013/03/06 21:18:42 For better readability of disassembly, we should u
79
80
81 void MIPSDecoder::PrintRegister(Register reg) {
82 ASSERT(0 <= reg);
83 ASSERT(reg < kNumberOfCpuRegisters);
84 Print(reg_names[reg]);
85 }
86
87
88 // Handle all register based formatting in these functions to reduce the
89 // complexity of FormatOption.
90 int MIPSDecoder::FormatRegister(Instr* instr, const char* format) {
91 ASSERT(format[0] == 'r');
92 switch (format[1]) {
93 case 's': { // 'rs: Rs register
94 PrintRegister(instr->RsField());
95 return 2;
96 }
97 case 't': { // 'rt: Rt register
98 PrintRegister(instr->RtField());
99 return 2;
100 }
101 case 'd': { // 'rd: Rd register
102 PrintRegister(instr->RdField());
103 return 2;
104 }
105 }
106 UNREACHABLE();
107 return -1;
108 }
109
110
111 // FormatOption takes a formatting string and interprets it based on
112 // the current instructions. The format string points to the first
113 // character of the option string (the option escape has already been
114 // consumed by the caller.) FormatOption returns the number of
115 // characters that were consumed from the formatting string.
116 int MIPSDecoder::FormatOption(Instr* instr, const char* format) {
117 switch (format[0]) {
118 case 'h': {
119 ASSERT(STRING_STARTS_WITH(format, "hint"));
120 if (instr->SaField() != 0) {
121 UNIMPLEMENTED();
122 }
123 return 4;
124 }
125 case 'i': {
126 ASSERT(STRING_STARTS_WITH(format, "imm"));
127 int32_t imm = instr->ImmField();
128 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
129 remaining_size_in_buffer(),
130 "0x%x",
131 imm);
132 return 3;
133 }
134 case 'r': {
135 return FormatRegister(instr, format);
136 }
137 case 's': {
138 ASSERT(STRING_STARTS_WITH(format, "sa"));
139 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
140 remaining_size_in_buffer(),
141 "%d",
142 instr->SaField());
143 return 2;
144 }
145 default: {
146 UNREACHABLE();
147 }
148 }
149 UNREACHABLE();
150 return -1;
151 }
152
153
154 // Format takes a formatting string for a whole instruction and prints it into
155 // the output buffer. All escaped options are handed to FormatOption to be
156 // parsed further.
157 void MIPSDecoder::Format(Instr* instr, const char* format) {
158 if (delay_slot_) {
159 delay_slot_ = false;
160 // 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
161 buffer_[buffer_pos_++] = '*';
162 // }
163 }
164 char cur = *format++;
165 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) {
166 if (cur == '\'') { // Single quote is used as the formatting escape.
167 format += FormatOption(instr, format);
168 } else {
169 buffer_[buffer_pos_++] = cur;
170 }
171 cur = *format++;
172 }
173 buffer_[buffer_pos_] = '\0';
174 }
175
176
177 void MIPSDecoder::DecodeSpecial(Instr* instr) {
178 switch (instr->FunctionField()) {
179 case SLL: {
180 if ((instr->RdField() == R0) &&
181 (instr->RtField() == R0) &&
182 (instr->SaField() == 0)) {
183 Format(instr, "nop");
184 } else {
185 Format(instr, "sll 'rd, 'rt, 'sa");
186 }
187 break;
188 }
189 case JR: {
190 ASSERT(instr->RtField() == R0);
191 ASSERT(instr->RdField() == R0);
192 Format(instr, "jr'hint 'rs");
193 delay_slot_ = true;
194 break;
195 }
196 default: {
197 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits());
198 UNREACHABLE();
199 break;
200 }
201 }
202 }
203
204
205 void MIPSDecoder::InstructionDecode(Instr* instr) {
206 switch (instr->OpcodeField()) {
207 case SPECIAL: {
208 DecodeSpecial(instr);
209 break;
210 }
211 case ORI: {
212 Format(instr, "ori 'rt, 'rs, 'imm");
213 break;
214 }
215 default: {
216 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits());
217 UNREACHABLE();
218 break;
219 }
220 }
221 }
222
223
13 int Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, 224 int Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
14 char* human_buffer, intptr_t human_size, 225 char* human_buffer, intptr_t human_size,
15 uword pc) { 226 uword pc) {
16 UNIMPLEMENTED(); 227 MIPSDecoder decoder(human_buffer, human_size);
17 return 0; 228 Instr* instr = Instr::At(pc);
18 } 229 decoder.InstructionDecode(instr);
19 230 OS::SNPrint(hex_buffer, hex_size, "%08x", instr->InstructionBits());
20 231 return Instr::kInstrSize;
232 }
233
234
21 void Disassembler::Disassemble(uword start, 235 void Disassembler::Disassemble(uword start,
22 uword end, 236 uword end,
23 DisassemblyFormatter* formatter, 237 DisassemblyFormatter* formatter,
24 const Code::Comments& comments) { 238 const Code::Comments& comments) {
25 UNIMPLEMENTED(); 239 ASSERT(formatter != NULL);
240 char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form.
241 char human_buffer[kUserReadableBufferSize]; // Human-readable instruction.
242 uword pc = start;
243 intptr_t comment_finger = 0;
244 while (pc < end) {
245 const intptr_t offset = pc - start;
246 while (comment_finger < comments.Length() &&
247 comments.PCOffsetAt(comment_finger) <= offset) {
248 formatter->Print(
249 " ;; %s\n",
250 String::Handle(comments.CommentAt(comment_finger)).ToCString());
251 comment_finger++;
252 }
253 int instruction_length = DecodeInstruction(hex_buffer,
254 sizeof(hex_buffer),
255 human_buffer,
256 sizeof(human_buffer),
257 pc);
258 formatter->ConsumeInstruction(hex_buffer,
259 sizeof(hex_buffer),
260 human_buffer,
261 sizeof(human_buffer),
262 pc);
263 pc += instruction_length;
264 }
26 } 265 }
27 266
28 } // namespace dart 267 } // namespace dart
29 268
30 #endif // defined TARGET_ARCH_MIPS 269 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698