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
66namespace v8 {
67namespace 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.
74class 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.
144void Decoder::PrintChar(const char ch) {
145  out_buffer_[out_buffer_pos_++] = ch;
146}
147
148
149// Append the str to the output buffer.
150void 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.
161void Decoder::PrintRegister(int reg) {
162  Print(converter_.NameOfCPURegister(reg));
163}
164
165
166void Decoder::PrintRs(Instruction* instr) {
167  int reg = instr->RsValue();
168  PrintRegister(reg);
169}
170
171
172void Decoder::PrintRt(Instruction* instr) {
173  int reg = instr->RtValue();
174  PrintRegister(reg);
175}
176
177
178void 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.
185void Decoder::PrintFPURegister(int freg) {
186  Print(converter_.NameOfXMMRegister(freg));
187}
188
189
190void Decoder::PrintFs(Instruction* instr) {
191  int freg = instr->RsValue();
192  PrintFPURegister(freg);
193}
194
195
196void Decoder::PrintFt(Instruction* instr) {
197  int freg = instr->RtValue();
198  PrintFPURegister(freg);
199}
200
201
202void Decoder::PrintFd(Instruction* instr) {
203  int freg = instr->RdValue();
204  PrintFPURegister(freg);
205}
206
207
208// Print the integer value of the sa field.
209void 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).
216void 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.
223void 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.
230void 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.
237void 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.
244void 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.
251void 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.
258void 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.
265void 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.
293void Decoder::PrintInstructionName(Instruction* instr) {
294}
295
296
297// Handle all register based formatting in this function to reduce the
298// complexity of FormatOption.
299int 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.
321int 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.
346int 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.
412void 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.
428void Decoder::Unknown(Instruction* instr) {
429  Format(instr, "unknown");
430}
431
432
433void 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
769void 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
897void 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.
912int 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
945namespace disasm {
946
947using v8::internal::byte_;
948
949const char* NameConverter::NameOfAddress(byte_* addr) const {
950  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
951  return tmp_buffer_.start();
952}
953
954
955const char* NameConverter::NameOfConstant(byte_* addr) const {
956  return NameOfAddress(addr);
957}
958
959
960const char* NameConverter::NameOfCPURegister(int reg) const {
961  return v8::internal::Registers::Name(reg);
962}
963
964
965const char* NameConverter::NameOfXMMRegister(int reg) const {
966  return v8::internal::FPURegisters::Name(reg);
967}
968
969
970const char* NameConverter::NameOfByteCPURegister(int reg) const {
971  UNREACHABLE();  // MIPS does not have the concept of a byte register
972  return "nobytereg";
973}
974
975
976const 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
985Disassembler::Disassembler(const NameConverter& converter)
986    : converter_(converter) {}
987
988
989Disassembler::~Disassembler() {}
990
991
992int 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.
1000int Disassembler::ConstantPoolSizeAt(byte_* instruction) {
1001  return -1;
1002}
1003
1004
1005void 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