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

Side by Side Diff: src/mips/disasm-mips.cc

Issue 549079: Support for MIPS in architecture independent files.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 11 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
(Empty)
1 // A Disassembler object is used to disassemble a block of code instruction by
2 // instruction. The default implementation of the NameConverter object can be
3 // overriden to modify register names or to do symbol lookup on addresses.
4 //
5 // The example below will disassemble a block of code and print it to stdout.
6 //
7 // NameConverter converter;
8 // Disassembler d(converter);
9 // for (byte* pc = begin; pc < end;) {
10 // char buffer[128];
11 // buffer[0] = '\0';
12 // byte* prev_pc = pc;
13 // pc += d.InstructionDecode(buffer, sizeof buffer, pc);
14 // printf("%p %08x %s\n",
15 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
16 // }
17 //
18 // The Disassembler class also has a convenience method to disassemble a block
19 // of code into a FILE*, meaning that the above functionality could also be
20 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
21
22
23 #include <assert.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #ifndef WIN32
28 #include <stdint.h>
29 #endif
30
31 #include "v8.h"
32
33 #include "constants-mips.h"
34 #include "disasm.h"
35 #include "macro-assembler.h"
36 #include "platform.h"
37
38
39 namespace assembler {
40 namespace mips {
41
42 namespace v8i = v8::internal;
43
44
45 //------------------------------------------------------------------------------
46
47 // Decoder decodes and disassembles instructions into an output buffer.
48 // It uses the converter to convert register names and call destinations into
49 // more informative description.
50 class Decoder {
51 public:
52 Decoder(const disasm::NameConverter& converter,
53 v8::internal::Vector<char> out_buffer)
54 : converter_(converter),
55 out_buffer_(out_buffer),
56 out_buffer_pos_(0) {
57 out_buffer_[out_buffer_pos_] = '\0';
58 }
59
60 ~Decoder() {}
61
62 // Writes one disassembled instruction into 'buffer' (0-terminated).
63 // Returns the length of the disassembled machine instruction in bytes.
64 int InstructionDecode(byte* instruction);
65
66 private:
67 // Bottleneck functions to print into the out_buffer.
68 void PrintChar(const char ch);
69 void Print(const char* str);
70
71 // Printing of common values.
72 void PrintRegister(int reg);
73 void PrintCRegister(int creg);
74 void PrintRs(Instruction* instr);
75 void PrintRt(Instruction* instr);
76 void PrintRd(Instruction* instr);
77 void PrintFs(Instruction* instr);
78 void PrintFt(Instruction* instr);
79 void PrintFd(Instruction* instr);
80 void PrintSa(Instruction* instr);
81 void PrintFunction(Instruction* instr);
82 void PrintSecondaryField(Instruction* instr);
83 void PrintUImm16(Instruction* instr);
84 void PrintSImm16(Instruction* instr);
85 void PrintXImm16(Instruction* instr);
86 void PrintImm26(Instruction* instr);
87 // Printing of instruction name
88 void PrintInstructionName(Instruction* instr);
89
90 // Handle formatting of instructions and their options.
91 int FormatRegister(Instruction* instr, const char* option);
92 int FormatCRegister(Instruction* instr, const char* option);
93 int FormatOption(Instruction* instr, const char* option);
94 void Format(Instruction* instr, const char* format);
95 void Unknown(Instruction* instr);
96
97 // Each of these functions decodes one particular instruction type.
98 void DecodeType1(Instruction* instr);
99 void DecodeType2(Instruction* instr);
100 void DecodeType3(Instruction* instr);
101
102 const disasm::NameConverter& converter_;
103 v8::internal::Vector<char> out_buffer_;
104 int out_buffer_pos_;
105
106 DISALLOW_COPY_AND_ASSIGN(Decoder);
107 };
108
109
110 // Support for assertions in the Decoder formatting functions.
111 #define STRING_STARTS_WITH(string, compare_string) \
112 (strncmp(string, compare_string, strlen(compare_string)) == 0)
113
114
115 // Append the ch to the output buffer.
116 void Decoder::PrintChar(const char ch) {
117 out_buffer_[out_buffer_pos_++] = ch;
118 }
119
120
121 // Append the str to the output buffer.
122 void Decoder::Print(const char* str) {
123 char cur = *str++;
124 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
125 PrintChar(cur);
126 cur = *str++;
127 }
128 out_buffer_[out_buffer_pos_] = 0;
129 }
130
131
132 // Print the register name according to the active name converter.
133 void Decoder::PrintRegister(int reg) {
134 Print(converter_.NameOfCPURegister(reg));
135 }
136
137 void Decoder::PrintRs(Instruction* instr) {
138 int reg = instr->rsField();
139 PrintRegister(reg);
140 }
141 void Decoder::PrintRt(Instruction* instr) {
142 int reg = instr->rtField();
143 PrintRegister(reg);
144 }
145 void Decoder::PrintRd(Instruction* instr) {
146 int reg = instr->rdField();
147 PrintRegister(reg);
148 }
149
150 // Print the Cregister name according to the active name converter.
151 void Decoder::PrintCRegister(int creg) {
152 Print(converter_.NameOfCOP1Register(creg));
153 }
154
155 void Decoder::PrintFs(Instruction* instr) {
156 int creg = instr->rsField();
157 PrintCRegister(creg);
158 }
159 void Decoder::PrintFt(Instruction* instr) {
160 int creg = instr->rtField();
161 PrintCRegister(creg);
162 }
163 void Decoder::PrintFd(Instruction* instr) {
164 int creg = instr->rdField();
165 PrintCRegister(creg);
166 }
167
168 // Print the integer value of the sa field.
169 void Decoder::PrintSa(Instruction* instr) {
170 int sa = instr->saField();
171 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
172 "%d", sa);
173 }
174
175 // Print 16-bit unsigned immediate value.
176 void Decoder::PrintUImm16(Instruction* instr) {
177 int32_t imm = instr->Imm16Field();
178 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
179 "%u", imm);
180 }
181 // Print 16-bit signed immediate value.
182 void Decoder::PrintSImm16(Instruction* instr) {
183 int32_t imm = ((instr->Imm16Field())<<16)>>16;
184 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
185 "%d", imm);
186 }
187 // Print 16-bit hexa immediate value.
188 void Decoder::PrintXImm16(Instruction* instr) {
189 int32_t imm = instr->Imm16Field();
190 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
191 "0x%x", imm);
192 }
193 // Print 26-bit immediate value.
194 void Decoder::PrintImm26(Instruction* instr) {
195 int32_t imm = instr->Imm26Field();
196 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
197 "%d", imm);
198 }
199
200 // Printing of instruction name
201 void Decoder::PrintInstructionName(Instruction* instr) {
202
203 }
204
205
206 // Handle all register based formatting in this function to reduce the
207 // complexity of FormatOption.
208 int Decoder::FormatRegister(Instruction* instr, const char* format) {
209 ASSERT(format[0] == 'r');
210 if (format[1] == 's') { // 'rs: Rs register
211 int reg = instr->rsField();
212 PrintRegister(reg);
213 return 2;
214 } else if (format[1] == 't') { // 'rt: rt register
215 int reg = instr->rtField();
216 PrintRegister(reg);
217 return 2;
218 } else if (format[1] == 'd') { // 'rd: rd register
219 int reg = instr->rdField();
220 PrintRegister(reg);
221 return 2;
222 }
223 UNREACHABLE();
224 return -1;
225 }
226
227
228 // Handle all Cregister based formatting in this function to reduce the
229 // complexity of FormatOption.
230 int Decoder::FormatCRegister(Instruction* instr, const char* format) {
231 ASSERT(format[0] == 'f');
232 if (format[1] == 's') { // 'fs: fs register
233 int reg = instr->rsField();
234 PrintCRegister(reg);
235 return 2;
236 } else if (format[1] == 't') { // 'ft: ft register
237 int reg = instr->rtField();
238 PrintCRegister(reg);
239 return 2;
240 } else if (format[1] == 'd') { // 'fd: fd register
241 int reg = instr->rdField();
242 PrintCRegister(reg);
243 return 2;
244 }
245 UNREACHABLE();
246 return -1;
247 }
248
249
250 // FormatOption takes a formatting string and interprets it based on
251 // the current instructions. The format string points to the first
252 // character of the option string (the option escape has already been
253 // consumed by the caller.) FormatOption returns the number of
254 // characters that were consumed from the formatting string.
255 int Decoder::FormatOption(Instruction* instr, const char* format) {
256 switch (format[0]) {
257 case 'c': { // 'code for break or trap instructions
258 UNIMPLEMENTED();
259 return -1;
260 }
261 case 'i': { // 'imm16u or 'imm26
262 if(format[3] == '1') {
263 ASSERT(STRING_STARTS_WITH(format, "imm16"));
264 if(format[5] == 's') {
265 ASSERT(STRING_STARTS_WITH(format, "imm16s"));
266 PrintSImm16(instr);
267 }
268 else if(format[5] == 'u'){
269 ASSERT(STRING_STARTS_WITH(format, "imm16u"));
270 PrintSImm16(instr);
271 } else {
272 ASSERT(STRING_STARTS_WITH(format, "imm16x"));
273 PrintXImm16(instr);
274 }
275 return 6;
276 } else {
277 ASSERT(STRING_STARTS_WITH(format, "imm26"));
278 PrintImm26(instr);
279 return 5;
280 }
281 }
282 case 'r': { // 'r: registers
283 return FormatRegister(instr, format);
284 }
285 case 's': { // 'sa
286 ASSERT(STRING_STARTS_WITH(format, "sa"));
287 PrintSa(instr);
288 return 2;
289 }
290 };
291 UNREACHABLE();
292 return -1;
293 }
294
295
296 // Format takes a formatting string for a whole instruction and prints it into
297 // the output buffer. All escaped options are handed to FormatOption to be
298 // parsed further.
299 void Decoder::Format(Instruction* instr, const char* format) {
300 char cur = *format++;
301 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
302 if (cur == '\'') { // Single quote is used as the formatting escape.
303 format += FormatOption(instr, format);
304 } else {
305 out_buffer_[out_buffer_pos_++] = cur;
306 }
307 cur = *format++;
308 }
309 out_buffer_[out_buffer_pos_] = '\0';
310 }
311
312
313 // For currently unimplemented decodings the disassembler calls Unknown(instr)
314 // which will just print "unknown" of the instruction bits.
315 void Decoder::Unknown(Instruction* instr) {
316 Format(instr, "unknown");
317 }
318
319
320 void Decoder::DecodeType1(Instruction* instr) {
321 switch(instr->OpcodeFieldRaw()) {
322 case COP1: // Coprocessor instructions
323 switch(instr->rsFieldRaw()) {
324 case BC1: // branch on coprocessor condition
325 UNREACHABLE();
326 break;
327 case MFC1:
328 Format(instr, "mfc1 'rt, 'fs");
329 break;
330 case MFHC1:
331 Format(instr, "mfhc1 rt, 'fs");
332 break;
333 case MTC1:
334 Format(instr, "mtc1 'rt, 'fs");
335 break;
336 case MTHC1:
337 Format(instr, "mthc1 rt, 'fs");
338 break;
339 case S:
340 case D:
341 UNIMPLEMENTED();
342 break;
343 case W:
344 switch(instr->functionFieldRaw()) {
345 case CVT_S_W:
346 UNIMPLEMENTED();
347 break;
348 case CVT_D_W: // Convert word to double.
349 Format(instr, "cvt.d.w 'fd, 'fs");
350 break;
351 default:
352 UNREACHABLE();
353 };
354 break;
355 case L:
356 case PS:
357 UNIMPLEMENTED();
358 break;
359 break;
360 default:
361 UNREACHABLE();
362 break;
363 };
364 break;
365 case SPECIAL:
366 switch(instr->functionFieldRaw()) {
367 case SLL:
368 if( 0x0 == (int)instr->InstructionBits())
369 Format(instr, "nop");
370 else
371 Format(instr, "sll 'rd, 'rt, 'sa");
372 break;
373 case SRL:
374 Format(instr, "srl 'rd, 'rt, 'sa");
375 break;
376 case SRA:
377 Format(instr, "sra 'rd, 'rt, 'sa");
378 break;
379 case SLLV:
380 Format(instr, "sllv 'rd, 'rt, 'rs");
381 break;
382 case SRLV:
383 Format(instr, "srlv 'rd, 'rt, 'rs");
384 break;
385 case SRAV:
386 Format(instr, "srav 'rd, 'rt, 'rs");
387 break;
388 case MFHI:
389 Format(instr, "mfhi 'rd");
390 break;
391 case MFLO:
392 Format(instr, "mflo 'rd");
393 break;
394 case MULT:
395 Format(instr, "mult 'rs, 'rt");
396 break;
397 case MULTU:
398 Format(instr, "multu 'rs, 'rt");
399 break;
400 case DIV:
401 Format(instr, "div 'rs, 'rt");
402 break;
403 case DIVU:
404 Format(instr, "divu 'rs, 'rt");
405 break;
406 case ADD:
407 Format(instr, "add 'rd, 'rs, 'rt");
408 break;
409 case ADDU:
410 Format(instr, "addu 'rd, 'rs, 'rt");
411 break;
412 case SUB:
413 Format(instr, "sub 'rd, 'rs, 'rt");
414 break;
415 case SUBU:
416 Format(instr, "sub 'rd, 'rs, 'rt");
417 break;
418 case AND:
419 Format(instr, "and 'rd, 'rs, 'rt");
420 break;
421 case OR:
422 if(0 == instr->rsField()) {
423 Format(instr, "mov 'rd, 'rt");
424 } else if(0 == instr->rtField()) {
425 Format(instr, "mov 'rd, 'rs");
426 } else {
427 Format(instr, "or 'rd, 'rs, 'rt");
428 }
429 break;
430 case XOR:
431 Format(instr, "xor 'rd, 'rs, 'rt");
432 break;
433 case NOR:
434 Format(instr, "nor 'rd, 'rs, 'rt");
435 break;
436 case SLT:
437 Format(instr, "slt 'rd, 'rs, 'rt");
438 break;
439 case SLTU:
440 Format(instr, "sltu 'rd, 'rs, 'rt");
441 break;
442 case TGE:
443 Format(instr, "tge 'rs, 'rt");
444 break;
445 case TGEU:
446 Format(instr, "tgeu 'rs, 'rt");
447 break;
448 case TLT:
449 Format(instr, "tlt 'rs, 'rt");
450 break;
451 case TLTU:
452 Format(instr, "tltu 'rs, 'rt");
453 break;
454 case TEQ:
455 Format(instr, "teq 'rs, 'rt");
456 break;
457 case TNE:
458 Format(instr, "tne 'rs, 'rt");
459 break;
460 default:
461 UNREACHABLE();
462 break;
463 };
464 break;
465 case SPECIAL2:
466 switch(instr->functionFieldRaw()) {
467 case MUL:
468 break;
469 default:
470 UNREACHABLE();
471 break;
472 };
473 break;
474 default:
475 UNREACHABLE();
476 break;
477 };
478 }
479
480
481 void Decoder::DecodeType2(Instruction* instr) {
482 switch(instr->OpcodeFieldRaw()) {
483 //////////////// REGIMM class
484 case REGIMM:
485 switch(instr->rtFieldRaw()) {
486 case BLTZ:
487 Format(instr, "bltz 'rs, 'imm16u");
488 break;
489 case BLTZAL:
490 Format(instr, "bltzal 'rs, 'imm16u");
491 break;
492 case BGEZ:
493 Format(instr, "bgez 'rs, 'imm16u");
494 break;
495 case BGEZAL:
496 Format(instr, "bgezal 'rs, 'imm16u");
497 break;
498 // case TGEI:
499 // Format(instr, "tgei 'rs, 'imm16s");
500 // break;
501 // case TGEIU:
502 // Format(instr, "tgeiu 'rs, 'imm16u");
503 // break;
504 default:
505 UNREACHABLE();
506 break;
507 };
508 break; // case REGIMM
509 //////////////// Branch instructions
510 case BEQ:
511 Format(instr, "beq 'rs, 'rt, 'imm16u");
512 break;
513 case BNE:
514 Format(instr, "bne 'rs, 'rt, 'imm16u");
515 break;
516 case BLEZ:
517 Format(instr, "blez 'rs, 'imm16u");
518 break;
519 case BGTZ:
520 Format(instr, "bgtz 'rs, 'imm16u");
521 break;
522 //////////////// Arithmetic instructions
523 case ADDI:
524 Format(instr, "addi 'rt, 'rs, 'imm16s");
525 break;
526 case ADDIU:
527 Format(instr, "addiu 'rt, 'rs, 'imm16s");
528 break;
529 case SLTI:
530 Format(instr, "slti 'rt, 'rs, 'imm16s");
531 break;
532 case SLTIU:
533 Format(instr, "sltiu 'rt, 'rs, 'imm16u");
534 break;
535 case ANDI:
536 Format(instr, "andi 'rt, 'rs, 'imm16x");
537 break;
538 case ORI:
539 Format(instr, "ori 'rt, 'rs, 'imm16x");
540 break;
541 case XORI:
542 Format(instr, "xori 'rt, 'rs, 'imm16x");
543 break;
544 case LUI:
545 Format(instr, "lui 'rt, 'imm16x");
546 break;
547 //////////////// Memory instructions
548 case LB:
549 Format(instr, "lb 'rt, 'imm16s('rs)");
550 break;
551 case LW:
552 Format(instr, "lw 'rt, 'imm16s('rs)");
553 break;
554 case LBU:
555 Format(instr, "lbu 'rt, 'imm16s('rs)");
556 break;
557 case SB:
558 Format(instr, "sb 'rt, 'imm16s('rs)");
559 break;
560 case SW:
561 Format(instr, "sw 'rt, 'imm16s('rs)");
562 break;
563 default:
564 UNREACHABLE();
565 break;
566 };
567 }
568
569
570 void Decoder::DecodeType3(Instruction* instr) {
571 switch(instr->OpcodeFieldRaw()) {
572 case SPECIAL:
573 switch(instr->functionFieldRaw()) {
574 case JR:
575 Format(instr, "jr 'rs");
576 break;
577 case JALR:
578 Format(instr, "jalr 'rs");
579 break;
580 default:
581 UNREACHABLE();
582 break;
583 }
584 break;
585 case J:
586 Format(instr, "j 'imm26");
587 break;
588 case JAL:
589 Format(instr, "jal 'imm26");
590 break;
591 default:
592 UNREACHABLE();
593 break;
594 }
595 }
596
597
598 // Disassemble the instruction at *instr_ptr into the output buffer.
599 int Decoder::InstructionDecode(byte* instr_ptr) {
600 Instruction* instr = Instruction::At(instr_ptr);
601 // Print raw instruction bytes.
602 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
603 "%08x ",
604 instr->InstructionBits());
605 switch (instr->instrType()) {
606 case 1: {
607 DecodeType1(instr);
608 break;
609 }
610 case 2: {
611 DecodeType2(instr);
612 break;
613 }
614 case 3: {
615 DecodeType3(instr);
616 break;
617 }
618 default: {
619 UNREACHABLE();
620 break;
621 }
622 }
623 return Instruction::kInstructionSize;
624 }
625
626
627 } } // namespace assembler::mips
628
629
630
631 //------------------------------------------------------------------------------
632
633 namespace disasm {
634
635 namespace v8i = v8::internal;
636
637
638 const char* NameConverter::NameOfAddress(byte* addr) const {
639 static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
640 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
641 return tmp_buffer.start();
642 }
643
644
645 const char* NameConverter::NameOfConstant(byte* addr) const {
646 return NameOfAddress(addr);
647 }
648
649
650 const char* NameConverter::NameOfCPURegister(int reg) const {
651 return assembler::mips::Registers::Name(reg);
652 }
653
654
655 const char* NameConverter::NameOfCOP1Register(int reg) const {
656 return assembler::mips::CRegisters::Name(reg);
657 }
658
659
660 const char* NameConverter::NameOfByteCPURegister(int reg) const {
661 UNREACHABLE(); // MIPS does not have the concept of a byte register
662 return "nobytereg";
663 }
664
665
666 const char* NameConverter::NameOfXMMRegister(int reg) const {
667 UNREACHABLE(); // MIPS does not have any XMM registers
668 return "noxmmreg";
669 }
670
671
672 const char* NameConverter::NameInCode(byte* addr) const {
673 // The default name converter is called for unknown code. So we will not try
674 // to access any memory.
675 return "";
676 }
677
678
679 //------------------------------------------------------------------------------
680
681 Disassembler::Disassembler(const NameConverter& converter)
682 : converter_(converter) {}
683
684
685 Disassembler::~Disassembler() {}
686
687
688 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
689 byte* instruction) {
690 assembler::mips::Decoder d(converter_, buffer);
691 return d.InstructionDecode(instruction);
692 }
693
694
695 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
696 // int instruction_bits = *(reinterpret_cast<int*>(instruction));
697 // if ((instruction_bits & 0xfff00000) == 0x03000000) {
698 // return instruction_bits & 0x0000ffff;
699 // } else {
700 // return -1;
701 // }
702 UNIMPLEMENTED();
703 return -1;
704 }
705
706
707 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
708 NameConverter converter;
709 Disassembler d(converter);
710 for (byte* pc = begin; pc < end;) {
711 v8::internal::EmbeddedVector<char, 128> buffer;
712 buffer[0] = '\0';
713 byte* prev_pc = pc;
714 pc += d.InstructionDecode(buffer, pc);
715 fprintf(f, "%p %08x %s\n",
716 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
717 }
718 }
719
720
721 } // namespace disasm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698