1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// A Disassembler object is used to disassemble a block of code instruction by
6// instruction. The default implementation of the NameConverter object can be
7// overriden to modify register names or to do symbol lookup on addresses.
8//
9// The example below will disassemble a block of code and print it to stdout.
10//
11//   NameConverter converter;
12//   Disassembler d(converter);
13//   for (byte* pc = begin; pc < end;) {
14//     v8::internal::EmbeddedVector<char, 256> buffer;
15//     byte* prev_pc = pc;
16//     pc += d.InstructionDecode(buffer, pc);
17//     printf("%p    %08x      %s\n",
18//            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
19//   }
20//
21// The Disassembler class also has a convenience method to disassemble a block
22// of code into a FILE*, meaning that the above functionality could also be
23// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
24
25
26#include <assert.h>
27#include <stdio.h>
28#include <stdarg.h>
29#include <string.h>
30
31#include "src/v8.h"
32
33#if V8_TARGET_ARCH_MIPS
34
35#include "src/mips/constants-mips.h"
36#include "src/disasm.h"
37#include "src/macro-assembler.h"
38#include "src/platform.h"
39
40namespace v8 {
41namespace internal {
42
43//------------------------------------------------------------------------------
44
45// Decoder decodes and disassembles instructions into an output buffer.
46// It uses the converter to convert register names and call destinations into
47// more informative description.
48class Decoder {
49 public:
50  Decoder(const disasm::NameConverter& converter,
51          v8::internal::Vector<char> out_buffer)
52    : converter_(converter),
53      out_buffer_(out_buffer),
54      out_buffer_pos_(0) {
55    out_buffer_[out_buffer_pos_] = '\0';
56  }
57
58  ~Decoder() {}
59
60  // Writes one disassembled instruction into 'buffer' (0-terminated).
61  // Returns the length of the disassembled machine instruction in bytes.
62  int InstructionDecode(byte* instruction);
63
64 private:
65  // Bottleneck functions to print into the out_buffer.
66  void PrintChar(const char ch);
67  void Print(const char* str);
68
69  // Printing of common values.
70  void PrintRegister(int reg);
71  void PrintFPURegister(int freg);
72  void PrintRs(Instruction* instr);
73  void PrintRt(Instruction* instr);
74  void PrintRd(Instruction* instr);
75  void PrintFs(Instruction* instr);
76  void PrintFt(Instruction* instr);
77  void PrintFd(Instruction* instr);
78  void PrintSa(Instruction* instr);
79  void PrintSd(Instruction* instr);
80  void PrintSs1(Instruction* instr);
81  void PrintSs2(Instruction* instr);
82  void PrintBc(Instruction* instr);
83  void PrintCc(Instruction* instr);
84  void PrintFunction(Instruction* instr);
85  void PrintSecondaryField(Instruction* instr);
86  void PrintUImm16(Instruction* instr);
87  void PrintSImm16(Instruction* instr);
88  void PrintXImm16(Instruction* instr);
89  void PrintXImm26(Instruction* instr);
90  void PrintCode(Instruction* instr);   // For break and trap instructions.
91  // Printing of instruction name.
92  void PrintInstructionName(Instruction* instr);
93
94  // Handle formatting of instructions and their options.
95  int FormatRegister(Instruction* instr, const char* option);
96  int FormatFPURegister(Instruction* instr, const char* option);
97  int FormatOption(Instruction* instr, const char* option);
98  void Format(Instruction* instr, const char* format);
99  void Unknown(Instruction* instr);
100
101  // Each of these functions decodes one particular instruction type.
102  void DecodeTypeRegister(Instruction* instr);
103  void DecodeTypeImmediate(Instruction* instr);
104  void DecodeTypeJump(Instruction* instr);
105
106  const disasm::NameConverter& converter_;
107  v8::internal::Vector<char> out_buffer_;
108  int out_buffer_pos_;
109
110  DISALLOW_COPY_AND_ASSIGN(Decoder);
111};
112
113
114// Support for assertions in the Decoder formatting functions.
115#define STRING_STARTS_WITH(string, compare_string) \
116  (strncmp(string, compare_string, strlen(compare_string)) == 0)
117
118
119// Append the ch to the output buffer.
120void Decoder::PrintChar(const char ch) {
121  out_buffer_[out_buffer_pos_++] = ch;
122}
123
124
125// Append the str to the output buffer.
126void Decoder::Print(const char* str) {
127  char cur = *str++;
128  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
129    PrintChar(cur);
130    cur = *str++;
131  }
132  out_buffer_[out_buffer_pos_] = 0;
133}
134
135
136// Print the register name according to the active name converter.
137void Decoder::PrintRegister(int reg) {
138  Print(converter_.NameOfCPURegister(reg));
139}
140
141
142void Decoder::PrintRs(Instruction* instr) {
143  int reg = instr->RsValue();
144  PrintRegister(reg);
145}
146
147
148void Decoder::PrintRt(Instruction* instr) {
149  int reg = instr->RtValue();
150  PrintRegister(reg);
151}
152
153
154void Decoder::PrintRd(Instruction* instr) {
155  int reg = instr->RdValue();
156  PrintRegister(reg);
157}
158
159
160// Print the FPUregister name according to the active name converter.
161void Decoder::PrintFPURegister(int freg) {
162  Print(converter_.NameOfXMMRegister(freg));
163}
164
165
166void Decoder::PrintFs(Instruction* instr) {
167  int freg = instr->RsValue();
168  PrintFPURegister(freg);
169}
170
171
172void Decoder::PrintFt(Instruction* instr) {
173  int freg = instr->RtValue();
174  PrintFPURegister(freg);
175}
176
177
178void Decoder::PrintFd(Instruction* instr) {
179  int freg = instr->RdValue();
180  PrintFPURegister(freg);
181}
182
183
184// Print the integer value of the sa field.
185void Decoder::PrintSa(Instruction* instr) {
186  int sa = instr->SaValue();
187  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
188}
189
190
191// Print the integer value of the rd field, when it is not used as reg.
192void Decoder::PrintSd(Instruction* instr) {
193  int sd = instr->RdValue();
194  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd);
195}
196
197
198// Print the integer value of the rd field, when used as 'ext' size.
199void Decoder::PrintSs1(Instruction* instr) {
200  int ss = instr->RdValue();
201  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1);
202}
203
204
205// Print the integer value of the rd field, when used as 'ins' size.
206void Decoder::PrintSs2(Instruction* instr) {
207  int ss = instr->RdValue();
208  int pos = instr->SaValue();
209  out_buffer_pos_ +=
210      SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1);
211}
212
213
214// Print the integer value of the cc field for the bc1t/f instructions.
215void Decoder::PrintBc(Instruction* instr) {
216  int cc = instr->FBccValue();
217  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc);
218}
219
220
221// Print the integer value of the cc field for the FP compare instructions.
222void Decoder::PrintCc(Instruction* instr) {
223  int cc = instr->FCccValue();
224  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc);
225}
226
227
228// Print 16-bit unsigned immediate value.
229void Decoder::PrintUImm16(Instruction* instr) {
230  int32_t imm = instr->Imm16Value();
231  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
232}
233
234
235// Print 16-bit signed immediate value.
236void Decoder::PrintSImm16(Instruction* instr) {
237  int32_t imm = ((instr->Imm16Value()) << 16) >> 16;
238  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
239}
240
241
242// Print 16-bit hexa immediate value.
243void Decoder::PrintXImm16(Instruction* instr) {
244  int32_t imm = instr->Imm16Value();
245  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
246}
247
248
249// Print 26-bit immediate value.
250void Decoder::PrintXImm26(Instruction* instr) {
251  uint32_t imm = instr->Imm26Value() << kImmFieldShift;
252  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
253}
254
255
256// Print 26-bit immediate value.
257void Decoder::PrintCode(Instruction* instr) {
258  if (instr->OpcodeFieldRaw() != SPECIAL)
259    return;  // Not a break or trap instruction.
260  switch (instr->FunctionFieldRaw()) {
261    case BREAK: {
262      int32_t code = instr->Bits(25, 6);
263      out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
264                                  "0x%05x (%d)", code, code);
265      break;
266                }
267    case TGE:
268    case TGEU:
269    case TLT:
270    case TLTU:
271    case TEQ:
272    case TNE: {
273      int32_t code = instr->Bits(15, 6);
274      out_buffer_pos_ +=
275          SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
276      break;
277    }
278    default:  // Not a break or trap instruction.
279    break;
280  }
281}
282
283
284// Printing of instruction name.
285void Decoder::PrintInstructionName(Instruction* instr) {
286}
287
288
289// Handle all register based formatting in this function to reduce the
290// complexity of FormatOption.
291int Decoder::FormatRegister(Instruction* instr, const char* format) {
292  ASSERT(format[0] == 'r');
293  if (format[1] == 's') {  // 'rs: Rs register.
294    int reg = instr->RsValue();
295    PrintRegister(reg);
296    return 2;
297  } else if (format[1] == 't') {  // 'rt: rt register.
298    int reg = instr->RtValue();
299    PrintRegister(reg);
300    return 2;
301  } else if (format[1] == 'd') {  // 'rd: rd register.
302    int reg = instr->RdValue();
303    PrintRegister(reg);
304    return 2;
305  }
306  UNREACHABLE();
307  return -1;
308}
309
310
311// Handle all FPUregister based formatting in this function to reduce the
312// complexity of FormatOption.
313int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
314  ASSERT(format[0] == 'f');
315  if (format[1] == 's') {  // 'fs: fs register.
316    int reg = instr->FsValue();
317    PrintFPURegister(reg);
318    return 2;
319  } else if (format[1] == 't') {  // 'ft: ft register.
320    int reg = instr->FtValue();
321    PrintFPURegister(reg);
322    return 2;
323  } else if (format[1] == 'd') {  // 'fd: fd register.
324    int reg = instr->FdValue();
325    PrintFPURegister(reg);
326    return 2;
327  } else if (format[1] == 'r') {  // 'fr: fr register.
328    int reg = instr->FrValue();
329    PrintFPURegister(reg);
330    return 2;
331  }
332  UNREACHABLE();
333  return -1;
334}
335
336
337// FormatOption takes a formatting string and interprets it based on
338// the current instructions. The format string points to the first
339// character of the option string (the option escape has already been
340// consumed by the caller.)  FormatOption returns the number of
341// characters that were consumed from the formatting string.
342int Decoder::FormatOption(Instruction* instr, const char* format) {
343  switch (format[0]) {
344    case 'c': {   // 'code for break or trap instructions.
345      ASSERT(STRING_STARTS_WITH(format, "code"));
346      PrintCode(instr);
347      return 4;
348    }
349    case 'i': {   // 'imm16u or 'imm26.
350      if (format[3] == '1') {
351        ASSERT(STRING_STARTS_WITH(format, "imm16"));
352        if (format[5] == 's') {
353          ASSERT(STRING_STARTS_WITH(format, "imm16s"));
354          PrintSImm16(instr);
355        } else if (format[5] == 'u') {
356          ASSERT(STRING_STARTS_WITH(format, "imm16u"));
357          PrintSImm16(instr);
358        } else {
359          ASSERT(STRING_STARTS_WITH(format, "imm16x"));
360          PrintXImm16(instr);
361        }
362        return 6;
363      } else {
364        ASSERT(STRING_STARTS_WITH(format, "imm26x"));
365        PrintXImm26(instr);
366        return 6;
367      }
368    }
369    case 'r': {   // 'r: registers.
370      return FormatRegister(instr, format);
371    }
372    case 'f': {   // 'f: FPUregisters.
373      return FormatFPURegister(instr, format);
374    }
375    case 's': {   // 'sa.
376      switch (format[1]) {
377        case 'a': {
378          ASSERT(STRING_STARTS_WITH(format, "sa"));
379          PrintSa(instr);
380          return 2;
381        }
382        case 'd': {
383          ASSERT(STRING_STARTS_WITH(format, "sd"));
384          PrintSd(instr);
385          return 2;
386        }
387        case 's': {
388          if (format[2] == '1') {
389              ASSERT(STRING_STARTS_WITH(format, "ss1"));  /* ext size */
390              PrintSs1(instr);
391              return 3;
392          } else {
393              ASSERT(STRING_STARTS_WITH(format, "ss2"));  /* ins size */
394              PrintSs2(instr);
395              return 3;
396          }
397        }
398      }
399    }
400    case 'b': {   // 'bc - Special for bc1 cc field.
401      ASSERT(STRING_STARTS_WITH(format, "bc"));
402      PrintBc(instr);
403      return 2;
404    }
405    case 'C': {   // 'Cc - Special for c.xx.d cc field.
406      ASSERT(STRING_STARTS_WITH(format, "Cc"));
407      PrintCc(instr);
408      return 2;
409    }
410  }
411  UNREACHABLE();
412  return -1;
413}
414
415
416// Format takes a formatting string for a whole instruction and prints it into
417// the output buffer. All escaped options are handed to FormatOption to be
418// parsed further.
419void Decoder::Format(Instruction* instr, const char* format) {
420  char cur = *format++;
421  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
422    if (cur == '\'') {  // Single quote is used as the formatting escape.
423      format += FormatOption(instr, format);
424    } else {
425      out_buffer_[out_buffer_pos_++] = cur;
426    }
427    cur = *format++;
428  }
429  out_buffer_[out_buffer_pos_]  = '\0';
430}
431
432
433// For currently unimplemented decodings the disassembler calls Unknown(instr)
434// which will just print "unknown" of the instruction bits.
435void Decoder::Unknown(Instruction* instr) {
436  Format(instr, "unknown");
437}
438
439
440void Decoder::DecodeTypeRegister(Instruction* instr) {
441  switch (instr->OpcodeFieldRaw()) {
442    case COP1:    // Coprocessor instructions.
443      switch (instr->RsFieldRaw()) {
444        case BC1:   // bc1 handled in DecodeTypeImmediate.
445          UNREACHABLE();
446          break;
447        case MFC1:
448          Format(instr, "mfc1    'rt, 'fs");
449          break;
450        case MFHC1:
451          Format(instr, "mfhc1   'rt, 'fs");
452          break;
453        case MTC1:
454          Format(instr, "mtc1    'rt, 'fs");
455          break;
456        // These are called "fs" too, although they are not FPU registers.
457        case CTC1:
458          Format(instr, "ctc1    'rt, 'fs");
459          break;
460        case CFC1:
461          Format(instr, "cfc1    'rt, 'fs");
462          break;
463        case MTHC1:
464          Format(instr, "mthc1   'rt, 'fs");
465          break;
466        case D:
467          switch (instr->FunctionFieldRaw()) {
468            case ADD_D:
469              Format(instr, "add.d   'fd, 'fs, 'ft");
470              break;
471            case SUB_D:
472              Format(instr, "sub.d   'fd, 'fs, 'ft");
473              break;
474            case MUL_D:
475              Format(instr, "mul.d   'fd, 'fs, 'ft");
476              break;
477            case DIV_D:
478              Format(instr, "div.d   'fd, 'fs, 'ft");
479              break;
480            case ABS_D:
481              Format(instr, "abs.d   'fd, 'fs");
482              break;
483            case MOV_D:
484              Format(instr, "mov.d   'fd, 'fs");
485              break;
486            case NEG_D:
487              Format(instr, "neg.d   'fd, 'fs");
488              break;
489            case SQRT_D:
490              Format(instr, "sqrt.d  'fd, 'fs");
491              break;
492            case CVT_W_D:
493              Format(instr, "cvt.w.d 'fd, 'fs");
494              break;
495            case CVT_L_D: {
496              if (kArchVariant == kMips32r2) {
497                Format(instr, "cvt.l.d 'fd, 'fs");
498              } else {
499                Unknown(instr);
500              }
501              break;
502            }
503            case TRUNC_W_D:
504              Format(instr, "trunc.w.d 'fd, 'fs");
505              break;
506            case TRUNC_L_D: {
507              if (kArchVariant == kMips32r2) {
508                Format(instr, "trunc.l.d 'fd, 'fs");
509              } else {
510                Unknown(instr);
511              }
512              break;
513            }
514            case ROUND_W_D:
515              Format(instr, "round.w.d 'fd, 'fs");
516              break;
517            case FLOOR_W_D:
518              Format(instr, "floor.w.d 'fd, 'fs");
519              break;
520            case CEIL_W_D:
521              Format(instr, "ceil.w.d 'fd, 'fs");
522              break;
523            case CVT_S_D:
524              Format(instr, "cvt.s.d 'fd, 'fs");
525              break;
526            case C_F_D:
527              Format(instr, "c.f.d   'fs, 'ft, 'Cc");
528              break;
529            case C_UN_D:
530              Format(instr, "c.un.d  'fs, 'ft, 'Cc");
531              break;
532            case C_EQ_D:
533              Format(instr, "c.eq.d  'fs, 'ft, 'Cc");
534              break;
535            case C_UEQ_D:
536              Format(instr, "c.ueq.d 'fs, 'ft, 'Cc");
537              break;
538            case C_OLT_D:
539              Format(instr, "c.olt.d 'fs, 'ft, 'Cc");
540              break;
541            case C_ULT_D:
542              Format(instr, "c.ult.d 'fs, 'ft, 'Cc");
543              break;
544            case C_OLE_D:
545              Format(instr, "c.ole.d 'fs, 'ft, 'Cc");
546              break;
547            case C_ULE_D:
548              Format(instr, "c.ule.d 'fs, 'ft, 'Cc");
549              break;
550            default:
551              Format(instr, "unknown.cop1.d");
552              break;
553          }
554          break;
555        case S:
556          UNIMPLEMENTED_MIPS();
557          break;
558        case W:
559          switch (instr->FunctionFieldRaw()) {
560            case CVT_S_W:   // Convert word to float (single).
561              Format(instr, "cvt.s.w 'fd, 'fs");
562              break;
563            case CVT_D_W:   // Convert word to double.
564              Format(instr, "cvt.d.w 'fd, 'fs");
565              break;
566            default:
567              UNREACHABLE();
568          }
569          break;
570        case L:
571          switch (instr->FunctionFieldRaw()) {
572            case CVT_D_L: {
573              if (kArchVariant == kMips32r2) {
574                Format(instr, "cvt.d.l 'fd, 'fs");
575              } else {
576                Unknown(instr);
577              }
578              break;
579            }
580            case CVT_S_L: {
581              if (kArchVariant == kMips32r2) {
582                Format(instr, "cvt.s.l 'fd, 'fs");
583              } else {
584                Unknown(instr);
585              }
586              break;
587            }
588            default:
589              UNREACHABLE();
590          }
591          break;
592        case PS:
593          UNIMPLEMENTED_MIPS();
594          break;
595        default:
596          UNREACHABLE();
597      }
598      break;
599    case COP1X:
600      switch (instr->FunctionFieldRaw()) {
601        case MADD_D:
602          Format(instr, "madd.d  'fd, 'fr, 'fs, 'ft");
603          break;
604        default:
605          UNREACHABLE();
606      }
607      break;
608    case SPECIAL:
609      switch (instr->FunctionFieldRaw()) {
610        case JR:
611          Format(instr, "jr      'rs");
612          break;
613        case JALR:
614          Format(instr, "jalr    'rs");
615          break;
616        case SLL:
617          if ( 0x0 == static_cast<int>(instr->InstructionBits()))
618            Format(instr, "nop");
619          else
620            Format(instr, "sll     'rd, 'rt, 'sa");
621          break;
622        case SRL:
623          if (instr->RsValue() == 0) {
624            Format(instr, "srl     'rd, 'rt, 'sa");
625          } else {
626            if (kArchVariant == kMips32r2) {
627              Format(instr, "rotr    'rd, 'rt, 'sa");
628            } else {
629              Unknown(instr);
630            }
631          }
632          break;
633        case SRA:
634          Format(instr, "sra     'rd, 'rt, 'sa");
635          break;
636        case SLLV:
637          Format(instr, "sllv    'rd, 'rt, 'rs");
638          break;
639        case SRLV:
640          if (instr->SaValue() == 0) {
641            Format(instr, "srlv    'rd, 'rt, 'rs");
642          } else {
643            if (kArchVariant == kMips32r2) {
644              Format(instr, "rotrv   'rd, 'rt, 'rs");
645            } else {
646              Unknown(instr);
647            }
648          }
649          break;
650        case SRAV:
651          Format(instr, "srav    'rd, 'rt, 'rs");
652          break;
653        case MFHI:
654          Format(instr, "mfhi    'rd");
655          break;
656        case MFLO:
657          Format(instr, "mflo    'rd");
658          break;
659        case MULT:
660          Format(instr, "mult    'rs, 'rt");
661          break;
662        case MULTU:
663          Format(instr, "multu   'rs, 'rt");
664          break;
665        case DIV:
666          Format(instr, "div     'rs, 'rt");
667          break;
668        case DIVU:
669          Format(instr, "divu    'rs, 'rt");
670          break;
671        case ADD:
672          Format(instr, "add     'rd, 'rs, 'rt");
673          break;
674        case ADDU:
675          Format(instr, "addu    'rd, 'rs, 'rt");
676          break;
677        case SUB:
678          Format(instr, "sub     'rd, 'rs, 'rt");
679          break;
680        case SUBU:
681          Format(instr, "subu    'rd, 'rs, 'rt");
682          break;
683        case AND:
684          Format(instr, "and     'rd, 'rs, 'rt");
685          break;
686        case OR:
687          if (0 == instr->RsValue()) {
688            Format(instr, "mov     'rd, 'rt");
689          } else if (0 == instr->RtValue()) {
690            Format(instr, "mov     'rd, 'rs");
691          } else {
692            Format(instr, "or      'rd, 'rs, 'rt");
693          }
694          break;
695        case XOR:
696          Format(instr, "xor     'rd, 'rs, 'rt");
697          break;
698        case NOR:
699          Format(instr, "nor     'rd, 'rs, 'rt");
700          break;
701        case SLT:
702          Format(instr, "slt     'rd, 'rs, 'rt");
703          break;
704        case SLTU:
705          Format(instr, "sltu    'rd, 'rs, 'rt");
706          break;
707        case BREAK:
708          Format(instr, "break, code: 'code");
709          break;
710        case TGE:
711          Format(instr, "tge     'rs, 'rt, code: 'code");
712          break;
713        case TGEU:
714          Format(instr, "tgeu    'rs, 'rt, code: 'code");
715          break;
716        case TLT:
717          Format(instr, "tlt     'rs, 'rt, code: 'code");
718          break;
719        case TLTU:
720          Format(instr, "tltu    'rs, 'rt, code: 'code");
721          break;
722        case TEQ:
723          Format(instr, "teq     'rs, 'rt, code: 'code");
724          break;
725        case TNE:
726          Format(instr, "tne     'rs, 'rt, code: 'code");
727          break;
728        case MOVZ:
729          Format(instr, "movz    'rd, 'rs, 'rt");
730          break;
731        case MOVN:
732          Format(instr, "movn    'rd, 'rs, 'rt");
733          break;
734        case MOVCI:
735          if (instr->Bit(16)) {
736            Format(instr, "movt    'rd, 'rs, 'bc");
737          } else {
738            Format(instr, "movf    'rd, 'rs, 'bc");
739          }
740          break;
741        default:
742          UNREACHABLE();
743      }
744      break;
745    case SPECIAL2:
746      switch (instr->FunctionFieldRaw()) {
747        case MUL:
748          Format(instr, "mul     'rd, 'rs, 'rt");
749          break;
750        case CLZ:
751          Format(instr, "clz     'rd, 'rs");
752          break;
753        default:
754          UNREACHABLE();
755      }
756      break;
757    case SPECIAL3:
758      switch (instr->FunctionFieldRaw()) {
759        case INS: {
760          if (kArchVariant == kMips32r2) {
761            Format(instr, "ins     'rt, 'rs, 'sa, 'ss2");
762          } else {
763            Unknown(instr);
764          }
765          break;
766        }
767        case EXT: {
768          if (kArchVariant == kMips32r2) {
769            Format(instr, "ext     'rt, 'rs, 'sa, 'ss1");
770          } else {
771            Unknown(instr);
772          }
773          break;
774        }
775        default:
776          UNREACHABLE();
777      }
778      break;
779    default:
780      UNREACHABLE();
781  }
782}
783
784
785void Decoder::DecodeTypeImmediate(Instruction* instr) {
786  switch (instr->OpcodeFieldRaw()) {
787    // ------------- REGIMM class.
788    case COP1:
789      switch (instr->RsFieldRaw()) {
790        case BC1:
791          if (instr->FBtrueValue()) {
792            Format(instr, "bc1t    'bc, 'imm16u");
793          } else {
794            Format(instr, "bc1f    'bc, 'imm16u");
795          }
796          break;
797        default:
798          UNREACHABLE();
799      }
800      break;  // Case COP1.
801    case REGIMM:
802      switch (instr->RtFieldRaw()) {
803        case BLTZ:
804          Format(instr, "bltz    'rs, 'imm16u");
805          break;
806        case BLTZAL:
807          Format(instr, "bltzal  'rs, 'imm16u");
808          break;
809        case BGEZ:
810          Format(instr, "bgez    'rs, 'imm16u");
811          break;
812        case BGEZAL:
813          Format(instr, "bgezal  'rs, 'imm16u");
814          break;
815        default:
816          UNREACHABLE();
817      }
818    break;  // Case REGIMM.
819    // ------------- Branch instructions.
820    case BEQ:
821      Format(instr, "beq     'rs, 'rt, 'imm16u");
822      break;
823    case BNE:
824      Format(instr, "bne     'rs, 'rt, 'imm16u");
825      break;
826    case BLEZ:
827      Format(instr, "blez    'rs, 'imm16u");
828      break;
829    case BGTZ:
830      Format(instr, "bgtz    'rs, 'imm16u");
831      break;
832    // ------------- Arithmetic instructions.
833    case ADDI:
834      Format(instr, "addi    'rt, 'rs, 'imm16s");
835      break;
836    case ADDIU:
837      Format(instr, "addiu   'rt, 'rs, 'imm16s");
838      break;
839    case SLTI:
840      Format(instr, "slti    'rt, 'rs, 'imm16s");
841      break;
842    case SLTIU:
843      Format(instr, "sltiu   'rt, 'rs, 'imm16u");
844      break;
845    case ANDI:
846      Format(instr, "andi    'rt, 'rs, 'imm16x");
847      break;
848    case ORI:
849      Format(instr, "ori     'rt, 'rs, 'imm16x");
850      break;
851    case XORI:
852      Format(instr, "xori    'rt, 'rs, 'imm16x");
853      break;
854    case LUI:
855      Format(instr, "lui     'rt, 'imm16x");
856      break;
857    // ------------- Memory instructions.
858    case LB:
859      Format(instr, "lb      'rt, 'imm16s('rs)");
860      break;
861    case LH:
862      Format(instr, "lh      'rt, 'imm16s('rs)");
863      break;
864    case LWL:
865      Format(instr, "lwl     'rt, 'imm16s('rs)");
866      break;
867    case LW:
868      Format(instr, "lw      'rt, 'imm16s('rs)");
869      break;
870    case LBU:
871      Format(instr, "lbu     'rt, 'imm16s('rs)");
872      break;
873    case LHU:
874      Format(instr, "lhu     'rt, 'imm16s('rs)");
875      break;
876    case LWR:
877      Format(instr, "lwr     'rt, 'imm16s('rs)");
878      break;
879    case PREF:
880      Format(instr, "pref    'rt, 'imm16s('rs)");
881      break;
882    case SB:
883      Format(instr, "sb      'rt, 'imm16s('rs)");
884      break;
885    case SH:
886      Format(instr, "sh      'rt, 'imm16s('rs)");
887      break;
888    case SWL:
889      Format(instr, "swl     'rt, 'imm16s('rs)");
890      break;
891    case SW:
892      Format(instr, "sw      'rt, 'imm16s('rs)");
893      break;
894    case SWR:
895      Format(instr, "swr     'rt, 'imm16s('rs)");
896      break;
897    case LWC1:
898      Format(instr, "lwc1    'ft, 'imm16s('rs)");
899      break;
900    case LDC1:
901      Format(instr, "ldc1    'ft, 'imm16s('rs)");
902      break;
903    case SWC1:
904      Format(instr, "swc1    'ft, 'imm16s('rs)");
905      break;
906    case SDC1:
907      Format(instr, "sdc1    'ft, 'imm16s('rs)");
908      break;
909    default:
910      UNREACHABLE();
911      break;
912  }
913}
914
915
916void Decoder::DecodeTypeJump(Instruction* instr) {
917  switch (instr->OpcodeFieldRaw()) {
918    case J:
919      Format(instr, "j       'imm26x");
920      break;
921    case JAL:
922      Format(instr, "jal     'imm26x");
923      break;
924    default:
925      UNREACHABLE();
926  }
927}
928
929
930// Disassemble the instruction at *instr_ptr into the output buffer.
931int Decoder::InstructionDecode(byte* instr_ptr) {
932  Instruction* instr = Instruction::At(instr_ptr);
933  // Print raw instruction bytes.
934  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
935                                   "%08x       ",
936                                   instr->InstructionBits());
937  switch (instr->InstructionType()) {
938    case Instruction::kRegisterType: {
939      DecodeTypeRegister(instr);
940      break;
941    }
942    case Instruction::kImmediateType: {
943      DecodeTypeImmediate(instr);
944      break;
945    }
946    case Instruction::kJumpType: {
947      DecodeTypeJump(instr);
948      break;
949    }
950    default: {
951      Format(instr, "UNSUPPORTED");
952      UNSUPPORTED_MIPS();
953    }
954  }
955  return Instruction::kInstrSize;
956}
957
958
959} }  // namespace v8::internal
960
961
962
963//------------------------------------------------------------------------------
964
965namespace disasm {
966
967const char* NameConverter::NameOfAddress(byte* addr) const {
968  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
969  return tmp_buffer_.start();
970}
971
972
973const char* NameConverter::NameOfConstant(byte* addr) const {
974  return NameOfAddress(addr);
975}
976
977
978const char* NameConverter::NameOfCPURegister(int reg) const {
979  return v8::internal::Registers::Name(reg);
980}
981
982
983const char* NameConverter::NameOfXMMRegister(int reg) const {
984  return v8::internal::FPURegisters::Name(reg);
985}
986
987
988const char* NameConverter::NameOfByteCPURegister(int reg) const {
989  UNREACHABLE();  // MIPS does not have the concept of a byte register.
990  return "nobytereg";
991}
992
993
994const char* NameConverter::NameInCode(byte* addr) const {
995  // The default name converter is called for unknown code. So we will not try
996  // to access any memory.
997  return "";
998}
999
1000
1001//------------------------------------------------------------------------------
1002
1003Disassembler::Disassembler(const NameConverter& converter)
1004    : converter_(converter) {}
1005
1006
1007Disassembler::~Disassembler() {}
1008
1009
1010int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1011                                    byte* instruction) {
1012  v8::internal::Decoder d(converter_, buffer);
1013  return d.InstructionDecode(instruction);
1014}
1015
1016
1017// The MIPS assembler does not currently use constant pools.
1018int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1019  return -1;
1020}
1021
1022
1023void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1024  NameConverter converter;
1025  Disassembler d(converter);
1026  for (byte* pc = begin; pc < end;) {
1027    v8::internal::EmbeddedVector<char, 128> buffer;
1028    buffer[0] = '\0';
1029    byte* prev_pc = pc;
1030    pc += d.InstructionDecode(buffer, pc);
1031    v8::internal::PrintF(f, "%p    %08x      %s\n",
1032        prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1033  }
1034}
1035
1036
1037#undef UNSUPPORTED
1038
1039}  // namespace disasm
1040
1041#endif  // V8_TARGET_ARCH_MIPS
1042