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