v8  3.14.5(node0.10.28)
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:156
static Instruction * At(byte *pc)
#define UNREACHABLE()
Definition: checks.h:50
T * start() const
Definition: utils.h:390
virtual const char * NameOfCPURegister(int reg) const
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:307
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()
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments