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