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