Home | History | Annotate | Download | only in mips
      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 <stdarg.h>
     28 #include <stdio.h>
     29 #include <string.h>
     30 
     31 #include "src/v8.h"
     32 
     33 #if V8_TARGET_ARCH_MIPS
     34 
     35 #include "src/base/platform/platform.h"
     36 #include "src/disasm.h"
     37 #include "src/macro-assembler.h"
     38 #include "src/mips/constants-mips.h"
     39 
     40 namespace v8 {
     41 namespace 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.
     48 class 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 PrintXImm21(Instruction* instr);
     90   void PrintXImm26(Instruction* instr);
     91   void PrintCode(Instruction* instr);   // For break and trap instructions.
     92   // Printing of instruction name.
     93   void PrintInstructionName(Instruction* instr);
     94 
     95   // Handle formatting of instructions and their options.
     96   int FormatRegister(Instruction* instr, const char* option);
     97   int FormatFPURegister(Instruction* instr, const char* option);
     98   int FormatOption(Instruction* instr, const char* option);
     99   void Format(Instruction* instr, const char* format);
    100   void Unknown(Instruction* instr);
    101 
    102   // Each of these functions decodes one particular instruction type.
    103   void DecodeTypeRegister(Instruction* instr);
    104   void DecodeTypeImmediate(Instruction* instr);
    105   void DecodeTypeJump(Instruction* instr);
    106 
    107   const disasm::NameConverter& converter_;
    108   v8::internal::Vector<char> out_buffer_;
    109   int out_buffer_pos_;
    110 
    111   DISALLOW_COPY_AND_ASSIGN(Decoder);
    112 };
    113 
    114 
    115 // Support for assertions in the Decoder formatting functions.
    116 #define STRING_STARTS_WITH(string, compare_string) \
    117   (strncmp(string, compare_string, strlen(compare_string)) == 0)
    118 
    119 
    120 // Append the ch to the output buffer.
    121 void Decoder::PrintChar(const char ch) {
    122   out_buffer_[out_buffer_pos_++] = ch;
    123 }
    124 
    125 
    126 // Append the str to the output buffer.
    127 void Decoder::Print(const char* str) {
    128   char cur = *str++;
    129   while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
    130     PrintChar(cur);
    131     cur = *str++;
    132   }
    133   out_buffer_[out_buffer_pos_] = 0;
    134 }
    135 
    136 
    137 // Print the register name according to the active name converter.
    138 void Decoder::PrintRegister(int reg) {
    139   Print(converter_.NameOfCPURegister(reg));
    140 }
    141 
    142 
    143 void Decoder::PrintRs(Instruction* instr) {
    144   int reg = instr->RsValue();
    145   PrintRegister(reg);
    146 }
    147 
    148 
    149 void Decoder::PrintRt(Instruction* instr) {
    150   int reg = instr->RtValue();
    151   PrintRegister(reg);
    152 }
    153 
    154 
    155 void Decoder::PrintRd(Instruction* instr) {
    156   int reg = instr->RdValue();
    157   PrintRegister(reg);
    158 }
    159 
    160 
    161 // Print the FPUregister name according to the active name converter.
    162 void Decoder::PrintFPURegister(int freg) {
    163   Print(converter_.NameOfXMMRegister(freg));
    164 }
    165 
    166 
    167 void Decoder::PrintFs(Instruction* instr) {
    168   int freg = instr->RsValue();
    169   PrintFPURegister(freg);
    170 }
    171 
    172 
    173 void Decoder::PrintFt(Instruction* instr) {
    174   int freg = instr->RtValue();
    175   PrintFPURegister(freg);
    176 }
    177 
    178 
    179 void Decoder::PrintFd(Instruction* instr) {
    180   int freg = instr->RdValue();
    181   PrintFPURegister(freg);
    182 }
    183 
    184 
    185 // Print the integer value of the sa field.
    186 void Decoder::PrintSa(Instruction* instr) {
    187   int sa = instr->SaValue();
    188   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
    189 }
    190 
    191 
    192 // Print the integer value of the rd field, when it is not used as reg.
    193 void Decoder::PrintSd(Instruction* instr) {
    194   int sd = instr->RdValue();
    195   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd);
    196 }
    197 
    198 
    199 // Print the integer value of the rd field, when used as 'ext' size.
    200 void Decoder::PrintSs1(Instruction* instr) {
    201   int ss = instr->RdValue();
    202   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1);
    203 }
    204 
    205 
    206 // Print the integer value of the rd field, when used as 'ins' size.
    207 void Decoder::PrintSs2(Instruction* instr) {
    208   int ss = instr->RdValue();
    209   int pos = instr->SaValue();
    210   out_buffer_pos_ +=
    211       SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1);
    212 }
    213 
    214 
    215 // Print the integer value of the cc field for the bc1t/f instructions.
    216 void Decoder::PrintBc(Instruction* instr) {
    217   int cc = instr->FBccValue();
    218   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc);
    219 }
    220 
    221 
    222 // Print the integer value of the cc field for the FP compare instructions.
    223 void Decoder::PrintCc(Instruction* instr) {
    224   int cc = instr->FCccValue();
    225   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc);
    226 }
    227 
    228 
    229 // Print 16-bit unsigned immediate value.
    230 void Decoder::PrintUImm16(Instruction* instr) {
    231   int32_t imm = instr->Imm16Value();
    232   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
    233 }
    234 
    235 
    236 // Print 16-bit signed immediate value.
    237 void Decoder::PrintSImm16(Instruction* instr) {
    238   int32_t imm = ((instr->Imm16Value()) << 16) >> 16;
    239   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
    240 }
    241 
    242 
    243 // Print 16-bit hexa immediate value.
    244 void Decoder::PrintXImm16(Instruction* instr) {
    245   int32_t imm = instr->Imm16Value();
    246   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
    247 }
    248 
    249 
    250 // Print 21-bit immediate value.
    251 void Decoder::PrintXImm21(Instruction* instr) {
    252   uint32_t imm = instr->Imm21Value();
    253   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
    254 }
    255 
    256 
    257 // Print 26-bit immediate value.
    258 void Decoder::PrintXImm26(Instruction* instr) {
    259   uint32_t imm = instr->Imm26Value() << kImmFieldShift;
    260   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
    261 }
    262 
    263 
    264 // Print 26-bit immediate value.
    265 void Decoder::PrintCode(Instruction* instr) {
    266   if (instr->OpcodeFieldRaw() != SPECIAL)
    267     return;  // Not a break or trap instruction.
    268   switch (instr->FunctionFieldRaw()) {
    269     case BREAK: {
    270       int32_t code = instr->Bits(25, 6);
    271       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
    272                                   "0x%05x (%d)", code, code);
    273       break;
    274                 }
    275     case TGE:
    276     case TGEU:
    277     case TLT:
    278     case TLTU:
    279     case TEQ:
    280     case TNE: {
    281       int32_t code = instr->Bits(15, 6);
    282       out_buffer_pos_ +=
    283           SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
    284       break;
    285     }
    286     default:  // Not a break or trap instruction.
    287     break;
    288   }
    289 }
    290 
    291 
    292 // Printing of instruction name.
    293 void Decoder::PrintInstructionName(Instruction* instr) {
    294 }
    295 
    296 
    297 // Handle all register based formatting in this function to reduce the
    298 // complexity of FormatOption.
    299 int Decoder::FormatRegister(Instruction* instr, const char* format) {
    300   DCHECK(format[0] == 'r');
    301   if (format[1] == 's') {  // 'rs: Rs register.
    302     int reg = instr->RsValue();
    303     PrintRegister(reg);
    304     return 2;
    305   } else if (format[1] == 't') {  // 'rt: rt register.
    306     int reg = instr->RtValue();
    307     PrintRegister(reg);
    308     return 2;
    309   } else if (format[1] == 'd') {  // 'rd: rd register.
    310     int reg = instr->RdValue();
    311     PrintRegister(reg);
    312     return 2;
    313   }
    314   UNREACHABLE();
    315   return -1;
    316 }
    317 
    318 
    319 // Handle all FPUregister based formatting in this function to reduce the
    320 // complexity of FormatOption.
    321 int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
    322   DCHECK(format[0] == 'f');
    323   if (format[1] == 's') {  // 'fs: fs register.
    324     int reg = instr->FsValue();
    325     PrintFPURegister(reg);
    326     return 2;
    327   } else if (format[1] == 't') {  // 'ft: ft register.
    328     int reg = instr->FtValue();
    329     PrintFPURegister(reg);
    330     return 2;
    331   } else if (format[1] == 'd') {  // 'fd: fd register.
    332     int reg = instr->FdValue();
    333     PrintFPURegister(reg);
    334     return 2;
    335   } else if (format[1] == 'r') {  // 'fr: fr register.
    336     int reg = instr->FrValue();
    337     PrintFPURegister(reg);
    338     return 2;
    339   }
    340   UNREACHABLE();
    341   return -1;
    342 }
    343 
    344 
    345 // FormatOption takes a formatting string and interprets it based on
    346 // the current instructions. The format string points to the first
    347 // character of the option string (the option escape has already been
    348 // consumed by the caller.)  FormatOption returns the number of
    349 // characters that were consumed from the formatting string.
    350 int Decoder::FormatOption(Instruction* instr, const char* format) {
    351   switch (format[0]) {
    352     case 'c': {   // 'code for break or trap instructions.
    353       DCHECK(STRING_STARTS_WITH(format, "code"));
    354       PrintCode(instr);
    355       return 4;
    356     }
    357     case 'i': {   // 'imm16u or 'imm26.
    358       if (format[3] == '1') {
    359         DCHECK(STRING_STARTS_WITH(format, "imm16"));
    360         if (format[5] == 's') {
    361           DCHECK(STRING_STARTS_WITH(format, "imm16s"));
    362           PrintSImm16(instr);
    363         } else if (format[5] == 'u') {
    364           DCHECK(STRING_STARTS_WITH(format, "imm16u"));
    365           PrintSImm16(instr);
    366         } else {
    367           DCHECK(STRING_STARTS_WITH(format, "imm16x"));
    368           PrintXImm16(instr);
    369         }
    370         return 6;
    371       } else if (format[3] == '2' && format[4] == '1') {
    372         DCHECK(STRING_STARTS_WITH(format, "imm21x"));
    373         PrintXImm21(instr);
    374         return 6;
    375       } else if (format[3] == '2' && format[4] == '6') {
    376         DCHECK(STRING_STARTS_WITH(format, "imm26x"));
    377         PrintXImm26(instr);
    378         return 6;
    379       }
    380     }
    381     case 'r': {   // 'r: registers.
    382       return FormatRegister(instr, format);
    383     }
    384     case 'f': {   // 'f: FPUregisters.
    385       return FormatFPURegister(instr, format);
    386     }
    387     case 's': {   // 'sa.
    388       switch (format[1]) {
    389         case 'a': {
    390           DCHECK(STRING_STARTS_WITH(format, "sa"));
    391           PrintSa(instr);
    392           return 2;
    393         }
    394         case 'd': {
    395           DCHECK(STRING_STARTS_WITH(format, "sd"));
    396           PrintSd(instr);
    397           return 2;
    398         }
    399         case 's': {
    400           if (format[2] == '1') {
    401               DCHECK(STRING_STARTS_WITH(format, "ss1"));  /* ext size */
    402               PrintSs1(instr);
    403               return 3;
    404           } else {
    405               DCHECK(STRING_STARTS_WITH(format, "ss2"));  /* ins size */
    406               PrintSs2(instr);
    407               return 3;
    408           }
    409         }
    410       }
    411     }
    412     case 'b': {   // 'bc - Special for bc1 cc field.
    413       DCHECK(STRING_STARTS_WITH(format, "bc"));
    414       PrintBc(instr);
    415       return 2;
    416     }
    417     case 'C': {   // 'Cc - Special for c.xx.d cc field.
    418       DCHECK(STRING_STARTS_WITH(format, "Cc"));
    419       PrintCc(instr);
    420       return 2;
    421     }
    422   }
    423   UNREACHABLE();
    424   return -1;
    425 }
    426 
    427 
    428 // Format takes a formatting string for a whole instruction and prints it into
    429 // the output buffer. All escaped options are handed to FormatOption to be
    430 // parsed further.
    431 void Decoder::Format(Instruction* instr, const char* format) {
    432   char cur = *format++;
    433   while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
    434     if (cur == '\'') {  // Single quote is used as the formatting escape.
    435       format += FormatOption(instr, format);
    436     } else {
    437       out_buffer_[out_buffer_pos_++] = cur;
    438     }
    439     cur = *format++;
    440   }
    441   out_buffer_[out_buffer_pos_]  = '\0';
    442 }
    443 
    444 
    445 // For currently unimplemented decodings the disassembler calls Unknown(instr)
    446 // which will just print "unknown" of the instruction bits.
    447 void Decoder::Unknown(Instruction* instr) {
    448   Format(instr, "unknown");
    449 }
    450 
    451 
    452 void Decoder::DecodeTypeRegister(Instruction* instr) {
    453   switch (instr->OpcodeFieldRaw()) {
    454     case COP1:    // Coprocessor instructions.
    455       switch (instr->RsFieldRaw()) {
    456         case BC1:   // bc1 handled in DecodeTypeImmediate.
    457           UNREACHABLE();
    458           break;
    459         case MFC1:
    460           Format(instr, "mfc1    'rt, 'fs");
    461           break;
    462         case MFHC1:
    463           Format(instr, "mfhc1   'rt, 'fs");
    464           break;
    465         case MTC1:
    466           Format(instr, "mtc1    'rt, 'fs");
    467           break;
    468         // These are called "fs" too, although they are not FPU registers.
    469         case CTC1:
    470           Format(instr, "ctc1    'rt, 'fs");
    471           break;
    472         case CFC1:
    473           Format(instr, "cfc1    'rt, 'fs");
    474           break;
    475         case MTHC1:
    476           Format(instr, "mthc1   'rt, 'fs");
    477           break;
    478         case D:
    479           switch (instr->FunctionFieldRaw()) {
    480             case ADD_D:
    481               Format(instr, "add.d   'fd, 'fs, 'ft");
    482               break;
    483             case SUB_D:
    484               Format(instr, "sub.d   'fd, 'fs, 'ft");
    485               break;
    486             case MUL_D:
    487               Format(instr, "mul.d   'fd, 'fs, 'ft");
    488               break;
    489             case DIV_D:
    490               Format(instr, "div.d   'fd, 'fs, 'ft");
    491               break;
    492             case ABS_D:
    493               Format(instr, "abs.d   'fd, 'fs");
    494               break;
    495             case MOV_D:
    496               Format(instr, "mov.d   'fd, 'fs");
    497               break;
    498             case NEG_D:
    499               Format(instr, "neg.d   'fd, 'fs");
    500               break;
    501             case SQRT_D:
    502               Format(instr, "sqrt.d  'fd, 'fs");
    503               break;
    504             case CVT_W_D:
    505               Format(instr, "cvt.w.d 'fd, 'fs");
    506               break;
    507             case CVT_L_D:
    508               Format(instr, "cvt.l.d 'fd, 'fs");
    509               break;
    510             case TRUNC_W_D:
    511               Format(instr, "trunc.w.d 'fd, 'fs");
    512               break;
    513             case TRUNC_L_D:
    514               Format(instr, "trunc.l.d 'fd, 'fs");
    515               break;
    516             case ROUND_W_D:
    517               Format(instr, "round.w.d 'fd, 'fs");
    518               break;
    519             case FLOOR_W_D:
    520               Format(instr, "floor.w.d 'fd, 'fs");
    521               break;
    522             case CEIL_W_D:
    523               Format(instr, "ceil.w.d 'fd, 'fs");
    524               break;
    525             case CVT_S_D:
    526               Format(instr, "cvt.s.d 'fd, 'fs");
    527               break;
    528             case C_F_D:
    529               Format(instr, "c.f.d   'fs, 'ft, 'Cc");
    530               break;
    531             case C_UN_D:
    532               Format(instr, "c.un.d  'fs, 'ft, 'Cc");
    533               break;
    534             case C_EQ_D:
    535               Format(instr, "c.eq.d  'fs, 'ft, 'Cc");
    536               break;
    537             case C_UEQ_D:
    538               Format(instr, "c.ueq.d 'fs, 'ft, 'Cc");
    539               break;
    540             case C_OLT_D:
    541               Format(instr, "c.olt.d 'fs, 'ft, 'Cc");
    542               break;
    543             case C_ULT_D:
    544               Format(instr, "c.ult.d 'fs, 'ft, 'Cc");
    545               break;
    546             case C_OLE_D:
    547               Format(instr, "c.ole.d 'fs, 'ft, 'Cc");
    548               break;
    549             case C_ULE_D:
    550               Format(instr, "c.ule.d 'fs, 'ft, 'Cc");
    551               break;
    552             default:
    553               Format(instr, "unknown.cop1.d");
    554               break;
    555           }
    556           break;
    557         case S:
    558           UNIMPLEMENTED_MIPS();
    559           break;
    560         case W:
    561           switch (instr->FunctionFieldRaw()) {
    562             case CVT_S_W:   // Convert word to float (single).
    563               Format(instr, "cvt.s.w 'fd, 'fs");
    564               break;
    565             case CVT_D_W:   // Convert word to double.
    566               Format(instr, "cvt.d.w 'fd, 'fs");
    567               break;
    568             default:
    569               UNREACHABLE();
    570           }
    571           break;
    572         case L:
    573           switch (instr->FunctionFieldRaw()) {
    574             case CVT_D_L:
    575               Format(instr, "cvt.d.l 'fd, 'fs");
    576               break;
    577             case CVT_S_L:
    578               Format(instr, "cvt.s.l 'fd, 'fs");
    579               break;
    580             case CMP_UN:
    581               Format(instr, "cmp.un.d  'fd,  'fs, 'ft");
    582               break;
    583             case CMP_EQ:
    584               Format(instr, "cmp.eq.d  'fd,  'fs, 'ft");
    585               break;
    586             case CMP_UEQ:
    587               Format(instr, "cmp.ueq.d  'fd,  'fs, 'ft");
    588               break;
    589             case CMP_LT:
    590               Format(instr, "cmp.lt.d  'fd,  'fs, 'ft");
    591               break;
    592             case CMP_ULT:
    593               Format(instr, "cmp.ult.d  'fd,  'fs, 'ft");
    594               break;
    595             case CMP_LE:
    596               Format(instr, "cmp.le.d  'fd,  'fs, 'ft");
    597               break;
    598             case CMP_ULE:
    599               Format(instr, "cmp.ule.d  'fd,  'fs, 'ft");
    600               break;
    601             case CMP_OR:
    602               Format(instr, "cmp.or.d  'fd,  'fs, 'ft");
    603               break;
    604             case CMP_UNE:
    605               Format(instr, "cmp.une.d  'fd,  'fs, 'ft");
    606               break;
    607             case CMP_NE:
    608               Format(instr, "cmp.ne.d  'fd,  'fs, 'ft");
    609               break;
    610             default:
    611               UNREACHABLE();
    612           }
    613           break;
    614         case PS:
    615           UNIMPLEMENTED_MIPS();
    616           break;
    617         default:
    618           UNREACHABLE();
    619       }
    620       break;
    621     case COP1X:
    622       switch (instr->FunctionFieldRaw()) {
    623         case MADD_D:
    624           Format(instr, "madd.d  'fd, 'fr, 'fs, 'ft");
    625           break;
    626         default:
    627           UNREACHABLE();
    628       }
    629       break;
    630     case SPECIAL:
    631       switch (instr->FunctionFieldRaw()) {
    632         case JR:
    633           Format(instr, "jr      'rs");
    634           break;
    635         case JALR:
    636           Format(instr, "jalr    'rs");
    637           break;
    638         case SLL:
    639           if ( 0x0 == static_cast<int>(instr->InstructionBits()))
    640             Format(instr, "nop");
    641           else
    642             Format(instr, "sll     'rd, 'rt, 'sa");
    643           break;
    644         case SRL:
    645           if (instr->RsValue() == 0) {
    646             Format(instr, "srl     'rd, 'rt, 'sa");
    647           } else {
    648             if (IsMipsArchVariant(kMips32r2)) {
    649               Format(instr, "rotr    'rd, 'rt, 'sa");
    650             } else {
    651               Unknown(instr);
    652             }
    653           }
    654           break;
    655         case SRA:
    656           Format(instr, "sra     'rd, 'rt, 'sa");
    657           break;
    658         case SLLV:
    659           Format(instr, "sllv    'rd, 'rt, 'rs");
    660           break;
    661         case SRLV:
    662           if (instr->SaValue() == 0) {
    663             Format(instr, "srlv    'rd, 'rt, 'rs");
    664           } else {
    665             if (IsMipsArchVariant(kMips32r2)) {
    666               Format(instr, "rotrv   'rd, 'rt, 'rs");
    667             } else {
    668               Unknown(instr);
    669             }
    670           }
    671           break;
    672         case SRAV:
    673           Format(instr, "srav    'rd, 'rt, 'rs");
    674           break;
    675         case MFHI:
    676           if (instr->Bits(25, 16) == 0) {
    677             Format(instr, "mfhi    'rd");
    678           } else {
    679             if ((instr->FunctionFieldRaw() == CLZ_R6)
    680                 && (instr->FdValue() == 1)) {
    681               Format(instr, "clz     'rd, 'rs");
    682             } else if ((instr->FunctionFieldRaw() == CLO_R6)
    683                 && (instr->FdValue() == 1)) {
    684               Format(instr, "clo     'rd, 'rs");
    685             }
    686           }
    687           break;
    688         case MFLO:
    689           Format(instr, "mflo    'rd");
    690           break;
    691         case MULT:  // @Mips32r6 == MUL_MUH.
    692           if (!IsMipsArchVariant(kMips32r6)) {
    693             Format(instr, "mult    'rs, 'rt");
    694           } else {
    695             if (instr->SaValue() == MUL_OP) {
    696               Format(instr, "mul    'rd, 'rs, 'rt");
    697             } else {
    698               Format(instr, "muh    'rd, 'rs, 'rt");
    699             }
    700           }
    701           break;
    702         case MULTU:  // @Mips32r6 == MUL_MUH_U.
    703           if (!IsMipsArchVariant(kMips32r6)) {
    704             Format(instr, "multu   'rs, 'rt");
    705           } else {
    706             if (instr->SaValue() == MUL_OP) {
    707               Format(instr, "mulu   'rd, 'rs, 'rt");
    708             } else {
    709               Format(instr, "muhu   'rd, 'rs, 'rt");
    710             }
    711           }
    712           break;
    713         case DIV:  // @Mips32r6 == DIV_MOD.
    714           if (!IsMipsArchVariant(kMips32r6)) {
    715             Format(instr, "div     'rs, 'rt");
    716           } else {
    717             if (instr->SaValue() == DIV_OP) {
    718               Format(instr, "div    'rd, 'rs, 'rt");
    719             } else {
    720               Format(instr, "mod    'rd, 'rs, 'rt");
    721             }
    722           }
    723           break;
    724         case DIVU:  // @Mips32r6 == DIV_MOD_U.
    725           if (!IsMipsArchVariant(kMips32r6)) {
    726             Format(instr, "divu    'rs, 'rt");
    727           } else {
    728             if (instr->SaValue() == DIV_OP) {
    729               Format(instr, "divu   'rd, 'rs, 'rt");
    730             } else {
    731               Format(instr, "modu   'rd, 'rs, 'rt");
    732             }
    733           }
    734           break;
    735         case ADD:
    736           Format(instr, "add     'rd, 'rs, 'rt");
    737           break;
    738         case ADDU:
    739           Format(instr, "addu    'rd, 'rs, 'rt");
    740           break;
    741         case SUB:
    742           Format(instr, "sub     'rd, 'rs, 'rt");
    743           break;
    744         case SUBU:
    745           Format(instr, "subu    'rd, 'rs, 'rt");
    746           break;
    747         case AND:
    748           Format(instr, "and     'rd, 'rs, 'rt");
    749           break;
    750         case OR:
    751           if (0 == instr->RsValue()) {
    752             Format(instr, "mov     'rd, 'rt");
    753           } else if (0 == instr->RtValue()) {
    754             Format(instr, "mov     'rd, 'rs");
    755           } else {
    756             Format(instr, "or      'rd, 'rs, 'rt");
    757           }
    758           break;
    759         case XOR:
    760           Format(instr, "xor     'rd, 'rs, 'rt");
    761           break;
    762         case NOR:
    763           Format(instr, "nor     'rd, 'rs, 'rt");
    764           break;
    765         case SLT:
    766           Format(instr, "slt     'rd, 'rs, 'rt");
    767           break;
    768         case SLTU:
    769           Format(instr, "sltu    'rd, 'rs, 'rt");
    770           break;
    771         case BREAK:
    772           Format(instr, "break, code: 'code");
    773           break;
    774         case TGE:
    775           Format(instr, "tge     'rs, 'rt, code: 'code");
    776           break;
    777         case TGEU:
    778           Format(instr, "tgeu    'rs, 'rt, code: 'code");
    779           break;
    780         case TLT:
    781           Format(instr, "tlt     'rs, 'rt, code: 'code");
    782           break;
    783         case TLTU:
    784           Format(instr, "tltu    'rs, 'rt, code: 'code");
    785           break;
    786         case TEQ:
    787           Format(instr, "teq     'rs, 'rt, code: 'code");
    788           break;
    789         case TNE:
    790           Format(instr, "tne     'rs, 'rt, code: 'code");
    791           break;
    792         case MOVZ:
    793           Format(instr, "movz    'rd, 'rs, 'rt");
    794           break;
    795         case MOVN:
    796           Format(instr, "movn    'rd, 'rs, 'rt");
    797           break;
    798         case MOVCI:
    799           if (instr->Bit(16)) {
    800             Format(instr, "movt    'rd, 'rs, 'bc");
    801           } else {
    802             Format(instr, "movf    'rd, 'rs, 'bc");
    803           }
    804           break;
    805         case SELEQZ_S:
    806           Format(instr, "seleqz    'rd, 'rs, 'rt");
    807           break;
    808         case SELNEZ_S:
    809           Format(instr, "selnez    'rd, 'rs, 'rt");
    810           break;
    811         default:
    812           UNREACHABLE();
    813       }
    814       break;
    815     case SPECIAL2:
    816       switch (instr->FunctionFieldRaw()) {
    817         case MUL:
    818           Format(instr, "mul     'rd, 'rs, 'rt");
    819           break;
    820         case CLZ:
    821           if (!IsMipsArchVariant(kMips32r6)) {
    822             Format(instr, "clz     'rd, 'rs");
    823           }
    824           break;
    825         default:
    826           UNREACHABLE();
    827       }
    828       break;
    829     case SPECIAL3:
    830       switch (instr->FunctionFieldRaw()) {
    831         case INS: {
    832           if (IsMipsArchVariant(kMips32r2)) {
    833             Format(instr, "ins     'rt, 'rs, 'sa, 'ss2");
    834           } else {
    835             Unknown(instr);
    836           }
    837           break;
    838         }
    839         case EXT: {
    840           if (IsMipsArchVariant(kMips32r2)) {
    841             Format(instr, "ext     'rt, 'rs, 'sa, 'ss1");
    842           } else {
    843             Unknown(instr);
    844           }
    845           break;
    846         }
    847         default:
    848           UNREACHABLE();
    849       }
    850       break;
    851     default:
    852       UNREACHABLE();
    853   }
    854 }
    855 
    856 
    857 void Decoder::DecodeTypeImmediate(Instruction* instr) {
    858   switch (instr->OpcodeFieldRaw()) {
    859     case COP1:
    860       switch (instr->RsFieldRaw()) {
    861         case BC1:
    862           if (instr->FBtrueValue()) {
    863             Format(instr, "bc1t    'bc, 'imm16u");
    864           } else {
    865             Format(instr, "bc1f    'bc, 'imm16u");
    866           }
    867           break;
    868         case BC1EQZ:
    869           Format(instr, "bc1eqz    'ft, 'imm16u");
    870           break;
    871         case BC1NEZ:
    872           Format(instr, "bc1nez    'ft, 'imm16u");
    873           break;
    874         case W:  // CMP.S instruction.
    875           switch (instr->FunctionValue()) {
    876             case CMP_AF:
    877               Format(instr, "cmp.af.S    'ft, 'fs, 'fd");
    878               break;
    879             case CMP_UN:
    880               Format(instr, "cmp.un.S    'ft, 'fs, 'fd");
    881               break;
    882             case CMP_EQ:
    883               Format(instr, "cmp.eq.S    'ft, 'fs, 'fd");
    884               break;
    885             case CMP_UEQ:
    886               Format(instr, "cmp.ueq.S   'ft, 'fs, 'fd");
    887               break;
    888             case CMP_LT:
    889               Format(instr, "cmp.lt.S    'ft, 'fs, 'fd");
    890               break;
    891             case CMP_ULT:
    892               Format(instr, "cmp.ult.S   'ft, 'fs, 'fd");
    893               break;
    894             case CMP_LE:
    895               Format(instr, "cmp.le.S    'ft, 'fs, 'fd");
    896               break;
    897             case CMP_ULE:
    898               Format(instr, "cmp.ule.S   'ft, 'fs, 'fd");
    899               break;
    900             case CMP_OR:
    901               Format(instr, "cmp.or.S    'ft, 'fs, 'fd");
    902               break;
    903             case CMP_UNE:
    904               Format(instr, "cmp.une.S   'ft, 'fs, 'fd");
    905               break;
    906             case CMP_NE:
    907               Format(instr, "cmp.ne.S    'ft, 'fs, 'fd");
    908               break;
    909             default:
    910               UNREACHABLE();
    911           }
    912           break;
    913         case L:  // CMP.D instruction.
    914           switch (instr->FunctionValue()) {
    915             case CMP_AF:
    916               Format(instr, "cmp.af.D    'ft, 'fs, 'fd");
    917               break;
    918             case CMP_UN:
    919               Format(instr, "cmp.un.D    'ft, 'fs, 'fd");
    920               break;
    921             case CMP_EQ:
    922               Format(instr, "cmp.eq.D    'ft, 'fs, 'fd");
    923               break;
    924             case CMP_UEQ:
    925               Format(instr, "cmp.ueq.D   'ft, 'fs, 'fd");
    926               break;
    927             case CMP_LT:
    928               Format(instr, "cmp.lt.D    'ft, 'fs, 'fd");
    929               break;
    930             case CMP_ULT:
    931               Format(instr, "cmp.ult.D   'ft, 'fs, 'fd");
    932               break;
    933             case CMP_LE:
    934               Format(instr, "cmp.le.D    'ft, 'fs, 'fd");
    935               break;
    936             case CMP_ULE:
    937               Format(instr, "cmp.ule.D   'ft, 'fs, 'fd");
    938               break;
    939             case CMP_OR:
    940               Format(instr, "cmp.or.D    'ft, 'fs, 'fd");
    941               break;
    942             case CMP_UNE:
    943               Format(instr, "cmp.une.D   'ft, 'fs, 'fd");
    944               break;
    945             case CMP_NE:
    946               Format(instr, "cmp.ne.D    'ft, 'fs, 'fd");
    947               break;
    948             default:
    949               UNREACHABLE();
    950           }
    951           break;
    952         case S:
    953           switch (instr->FunctionValue()) {
    954             case SEL:
    955               Format(instr, "sel.S    'ft, 'fs, 'fd");
    956               break;
    957             case SELEQZ_C:
    958               Format(instr, "seleqz.S 'ft, 'fs, 'fd");
    959               break;
    960             case SELNEZ_C:
    961               Format(instr, "selnez.S 'ft, 'fs, 'fd");
    962               break;
    963             case MIN:
    964               Format(instr, "min.S    'ft, 'fs, 'fd");
    965               break;
    966             case MINA:
    967               Format(instr, "mina.S   'ft, 'fs, 'fd");
    968               break;
    969             case MAX:
    970               Format(instr, "max.S    'ft, 'fs, 'fd");
    971               break;
    972             case MAXA:
    973               Format(instr, "maxa.S   'ft, 'fs, 'fd");
    974               break;
    975             default:
    976               UNREACHABLE();
    977           }
    978           break;
    979         case D:
    980           switch (instr->FunctionValue()) {
    981             case SEL:
    982               Format(instr, "sel.D    'ft, 'fs, 'fd");
    983               break;
    984             case SELEQZ_C:
    985               Format(instr, "seleqz.D 'ft, 'fs, 'fd");
    986               break;
    987             case SELNEZ_C:
    988               Format(instr, "selnez.D 'ft, 'fs, 'fd");
    989               break;
    990             case MIN:
    991               Format(instr, "min.D    'ft, 'fs, 'fd");
    992               break;
    993             case MINA:
    994               Format(instr, "mina.D   'ft, 'fs, 'fd");
    995               break;
    996             case MAX:
    997               Format(instr, "max.D    'ft, 'fs, 'fd");
    998               break;
    999             case MAXA:
   1000               Format(instr, "maxa.D   'ft, 'fs, 'fd");
   1001               break;
   1002             default:
   1003               UNREACHABLE();
   1004           }
   1005           break;
   1006         default:
   1007           UNREACHABLE();
   1008       }
   1009 
   1010       break;  // Case COP1.
   1011     // ------------- REGIMM class.
   1012     case REGIMM:
   1013       switch (instr->RtFieldRaw()) {
   1014         case BLTZ:
   1015           Format(instr, "bltz    'rs, 'imm16u");
   1016           break;
   1017         case BLTZAL:
   1018           Format(instr, "bltzal  'rs, 'imm16u");
   1019           break;
   1020         case BGEZ:
   1021           Format(instr, "bgez    'rs, 'imm16u");
   1022           break;
   1023         case BGEZAL:
   1024           Format(instr, "bgezal  'rs, 'imm16u");
   1025           break;
   1026         case BGEZALL:
   1027           Format(instr, "bgezall 'rs, 'imm16u");
   1028           break;
   1029         default:
   1030           UNREACHABLE();
   1031       }
   1032     break;  // Case REGIMM.
   1033     // ------------- Branch instructions.
   1034     case BEQ:
   1035       Format(instr, "beq     'rs, 'rt, 'imm16u");
   1036       break;
   1037     case BNE:
   1038       Format(instr, "bne     'rs, 'rt, 'imm16u");
   1039       break;
   1040     case BLEZ:
   1041       if ((instr->RtFieldRaw() == 0)
   1042           && (instr->RsFieldRaw() != 0)) {
   1043         Format(instr, "blez    'rs, 'imm16u");
   1044       } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
   1045           && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
   1046         Format(instr, "bgeuc    'rs, 'rt, 'imm16u");
   1047       } else if ((instr->RtFieldRaw() == instr->RsFieldRaw())
   1048           && (instr->RtFieldRaw() != 0)) {
   1049         Format(instr, "bgezalc  'rs, 'imm16u");
   1050       } else if ((instr->RsFieldRaw() == 0)
   1051           && (instr->RtFieldRaw() != 0)) {
   1052         Format(instr, "blezalc  'rs, 'imm16u");
   1053       } else {
   1054         UNREACHABLE();
   1055       }
   1056       break;
   1057     case BGTZ:
   1058       if ((instr->RtFieldRaw() == 0)
   1059           && (instr->RsFieldRaw() != 0)) {
   1060         Format(instr, "bgtz    'rs, 'imm16u");
   1061       } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
   1062           && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
   1063         Format(instr, "bltuc   'rs, 'rt, 'imm16u");
   1064       } else if ((instr->RtFieldRaw() == instr->RsFieldRaw())
   1065           && (instr->RtFieldRaw() != 0)) {
   1066         Format(instr, "bltzalc 'rt, 'imm16u");
   1067       } else if ((instr->RsFieldRaw() == 0)
   1068           && (instr->RtFieldRaw() != 0)) {
   1069         Format(instr, "bgtzalc 'rt, 'imm16u");
   1070       } else {
   1071         UNREACHABLE();
   1072       }
   1073       break;
   1074     case BLEZL:
   1075       if ((instr->RtFieldRaw() == instr->RsFieldRaw())
   1076           && (instr->RtFieldRaw() != 0)) {
   1077         Format(instr, "bgezc    'rt, 'imm16u");
   1078       } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
   1079           && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
   1080         Format(instr, "bgec     'rs, 'rt, 'imm16u");
   1081       } else if ((instr->RsFieldRaw() == 0)
   1082           && (instr->RtFieldRaw() != 0)) {
   1083         Format(instr, "blezc    'rt, 'imm16u");
   1084       } else {
   1085         UNREACHABLE();
   1086       }
   1087       break;
   1088     case BGTZL:
   1089       if ((instr->RtFieldRaw() == instr->RsFieldRaw())
   1090           && (instr->RtFieldRaw() != 0)) {
   1091         Format(instr, "bltzc    'rt, 'imm16u");
   1092       } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
   1093           && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
   1094         Format(instr, "bltc     'rs, 'rt, 'imm16u");
   1095       } else if ((instr->RsFieldRaw() == 0)
   1096           && (instr->RtFieldRaw() != 0)) {
   1097         Format(instr, "bgtzc    'rt, 'imm16u");
   1098       } else {
   1099         UNREACHABLE();
   1100       }
   1101       break;
   1102     case BEQZC:
   1103       if (instr->RsFieldRaw() != 0) {
   1104         Format(instr, "beqzc   'rs, 'imm21x");
   1105       }
   1106       break;
   1107     case BNEZC:
   1108       if (instr->RsFieldRaw() != 0) {
   1109         Format(instr, "bnezc   'rs, 'imm21x");
   1110       }
   1111       break;
   1112     // ------------- Arithmetic instructions.
   1113     case ADDI:
   1114       if (!IsMipsArchVariant(kMips32r6)) {
   1115         Format(instr, "addi    'rt, 'rs, 'imm16s");
   1116       } else {
   1117         // Check if BOVC or BEQC instruction.
   1118         if (instr->RsFieldRaw() >= instr->RtFieldRaw()) {
   1119           Format(instr, "bovc  'rs, 'rt, 'imm16s");
   1120         } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) {
   1121           Format(instr, "beqc  'rs, 'rt, 'imm16s");
   1122         } else {
   1123           UNREACHABLE();
   1124         }
   1125       }
   1126       break;
   1127     case DADDI:
   1128       if (IsMipsArchVariant(kMips32r6)) {
   1129         // Check if BNVC or BNEC instruction.
   1130         if (instr->RsFieldRaw() >= instr->RtFieldRaw()) {
   1131           Format(instr, "bnvc  'rs, 'rt, 'imm16s");
   1132         } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) {
   1133           Format(instr, "bnec  'rs, 'rt, 'imm16s");
   1134         } else {
   1135           UNREACHABLE();
   1136         }
   1137       }
   1138       break;
   1139     case ADDIU:
   1140       Format(instr, "addiu   'rt, 'rs, 'imm16s");
   1141       break;
   1142     case SLTI:
   1143       Format(instr, "slti    'rt, 'rs, 'imm16s");
   1144       break;
   1145     case SLTIU:
   1146       Format(instr, "sltiu   'rt, 'rs, 'imm16u");
   1147       break;
   1148     case ANDI:
   1149       Format(instr, "andi    'rt, 'rs, 'imm16x");
   1150       break;
   1151     case ORI:
   1152       Format(instr, "ori     'rt, 'rs, 'imm16x");
   1153       break;
   1154     case XORI:
   1155       Format(instr, "xori    'rt, 'rs, 'imm16x");
   1156       break;
   1157     case LUI:
   1158       if (!IsMipsArchVariant(kMips32r6)) {
   1159         Format(instr, "lui     'rt, 'imm16x");
   1160       } else {
   1161         if (instr->RsValue() != 0) {
   1162           Format(instr, "aui     'rt, 'imm16x");
   1163         } else {
   1164           Format(instr, "lui     'rt, 'imm16x");
   1165         }
   1166       }
   1167       break;
   1168     // ------------- Memory instructions.
   1169     case LB:
   1170       Format(instr, "lb      'rt, 'imm16s('rs)");
   1171       break;
   1172     case LH:
   1173       Format(instr, "lh      'rt, 'imm16s('rs)");
   1174       break;
   1175     case LWL:
   1176       Format(instr, "lwl     'rt, 'imm16s('rs)");
   1177       break;
   1178     case LW:
   1179       Format(instr, "lw      'rt, 'imm16s('rs)");
   1180       break;
   1181     case LBU:
   1182       Format(instr, "lbu     'rt, 'imm16s('rs)");
   1183       break;
   1184     case LHU:
   1185       Format(instr, "lhu     'rt, 'imm16s('rs)");
   1186       break;
   1187     case LWR:
   1188       Format(instr, "lwr     'rt, 'imm16s('rs)");
   1189       break;
   1190     case PREF:
   1191       Format(instr, "pref    'rt, 'imm16s('rs)");
   1192       break;
   1193     case SB:
   1194       Format(instr, "sb      'rt, 'imm16s('rs)");
   1195       break;
   1196     case SH:
   1197       Format(instr, "sh      'rt, 'imm16s('rs)");
   1198       break;
   1199     case SWL:
   1200       Format(instr, "swl     'rt, 'imm16s('rs)");
   1201       break;
   1202     case SW:
   1203       Format(instr, "sw      'rt, 'imm16s('rs)");
   1204       break;
   1205     case SWR:
   1206       Format(instr, "swr     'rt, 'imm16s('rs)");
   1207       break;
   1208     case LWC1:
   1209       Format(instr, "lwc1    'ft, 'imm16s('rs)");
   1210       break;
   1211     case LDC1:
   1212       Format(instr, "ldc1    'ft, 'imm16s('rs)");
   1213       break;
   1214     case SWC1:
   1215       Format(instr, "swc1    'ft, 'imm16s('rs)");
   1216       break;
   1217     case SDC1:
   1218       Format(instr, "sdc1    'ft, 'imm16s('rs)");
   1219       break;
   1220     default:
   1221       printf("a 0x%x \n", instr->OpcodeFieldRaw());
   1222       UNREACHABLE();
   1223       break;
   1224   }
   1225 }
   1226 
   1227 
   1228 void Decoder::DecodeTypeJump(Instruction* instr) {
   1229   switch (instr->OpcodeFieldRaw()) {
   1230     case J:
   1231       Format(instr, "j       'imm26x");
   1232       break;
   1233     case JAL:
   1234       Format(instr, "jal     'imm26x");
   1235       break;
   1236     default:
   1237       UNREACHABLE();
   1238   }
   1239 }
   1240 
   1241 
   1242 // Disassemble the instruction at *instr_ptr into the output buffer.
   1243 int Decoder::InstructionDecode(byte* instr_ptr) {
   1244   Instruction* instr = Instruction::At(instr_ptr);
   1245   // Print raw instruction bytes.
   1246   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
   1247                                    "%08x       ",
   1248                                    instr->InstructionBits());
   1249   switch (instr->InstructionType()) {
   1250     case Instruction::kRegisterType: {
   1251       DecodeTypeRegister(instr);
   1252       break;
   1253     }
   1254     case Instruction::kImmediateType: {
   1255       DecodeTypeImmediate(instr);
   1256       break;
   1257     }
   1258     case Instruction::kJumpType: {
   1259       DecodeTypeJump(instr);
   1260       break;
   1261     }
   1262     default: {
   1263       Format(instr, "UNSUPPORTED");
   1264       UNSUPPORTED_MIPS();
   1265     }
   1266   }
   1267   return Instruction::kInstrSize;
   1268 }
   1269 
   1270 
   1271 } }  // namespace v8::internal
   1272 
   1273 
   1274 
   1275 //------------------------------------------------------------------------------
   1276 
   1277 namespace disasm {
   1278 
   1279 const char* NameConverter::NameOfAddress(byte* addr) const {
   1280   v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
   1281   return tmp_buffer_.start();
   1282 }
   1283 
   1284 
   1285 const char* NameConverter::NameOfConstant(byte* addr) const {
   1286   return NameOfAddress(addr);
   1287 }
   1288 
   1289 
   1290 const char* NameConverter::NameOfCPURegister(int reg) const {
   1291   return v8::internal::Registers::Name(reg);
   1292 }
   1293 
   1294 
   1295 const char* NameConverter::NameOfXMMRegister(int reg) const {
   1296   return v8::internal::FPURegisters::Name(reg);
   1297 }
   1298 
   1299 
   1300 const char* NameConverter::NameOfByteCPURegister(int reg) const {
   1301   UNREACHABLE();  // MIPS does not have the concept of a byte register.
   1302   return "nobytereg";
   1303 }
   1304 
   1305 
   1306 const char* NameConverter::NameInCode(byte* addr) const {
   1307   // The default name converter is called for unknown code. So we will not try
   1308   // to access any memory.
   1309   return "";
   1310 }
   1311 
   1312 
   1313 //------------------------------------------------------------------------------
   1314 
   1315 Disassembler::Disassembler(const NameConverter& converter)
   1316     : converter_(converter) {}
   1317 
   1318 
   1319 Disassembler::~Disassembler() {}
   1320 
   1321 
   1322 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
   1323                                     byte* instruction) {
   1324   v8::internal::Decoder d(converter_, buffer);
   1325   return d.InstructionDecode(instruction);
   1326 }
   1327 
   1328 
   1329 // The MIPS assembler does not currently use constant pools.
   1330 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
   1331   return -1;
   1332 }
   1333 
   1334 
   1335 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
   1336   NameConverter converter;
   1337   Disassembler d(converter);
   1338   for (byte* pc = begin; pc < end;) {
   1339     v8::internal::EmbeddedVector<char, 128> buffer;
   1340     buffer[0] = '\0';
   1341     byte* prev_pc = pc;
   1342     pc += d.InstructionDecode(buffer, pc);
   1343     v8::internal::PrintF(f, "%p    %08x      %s\n",
   1344         prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
   1345   }
   1346 }
   1347 
   1348 
   1349 #undef UNSUPPORTED
   1350 
   1351 }  // namespace disasm
   1352 
   1353 #endif  // V8_TARGET_ARCH_MIPS
   1354