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