V8 Project
disasm-mips64.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // A Disassembler object is used to disassemble a block of code instruction by
6 // instruction. The default implementation of the NameConverter object can be
7 // overriden to modify register names or to do symbol lookup on addresses.
8 //
9 // The example below will disassemble a block of code and print it to stdout.
10 //
11 // NameConverter converter;
12 // Disassembler d(converter);
13 // for (byte* pc = begin; pc < end;) {
14 // v8::internal::EmbeddedVector<char, 256> buffer;
15 // byte* prev_pc = pc;
16 // pc += d.InstructionDecode(buffer, pc);
17 // printf("%p %08x %s\n",
18 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
19 // }
20 //
21 // The Disassembler class also has a convenience method to disassemble a block
22 // of code into a FILE*, meaning that the above functionality could also be
23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
24 
25 
26 #include <assert.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "src/v8.h"
32 
33 #if V8_TARGET_ARCH_MIPS64
34 
36 #include "src/disasm.h"
37 #include "src/macro-assembler.h"
39 
40 namespace v8 {
41 namespace internal {
42 
43 //------------------------------------------------------------------------------
44 
45 // Decoder decodes and disassembles instructions into an output buffer.
46 // It uses the converter to convert register names and call destinations into
47 // more informative description.
48 class Decoder {
49  public:
50  Decoder(const disasm::NameConverter& converter,
51  v8::internal::Vector<char> out_buffer)
52  : converter_(converter),
53  out_buffer_(out_buffer),
54  out_buffer_pos_(0) {
55  out_buffer_[out_buffer_pos_] = '\0';
56  }
57 
58  ~Decoder() {}
59 
60  // Writes one disassembled instruction into 'buffer' (0-terminated).
61  // Returns the length of the disassembled machine instruction in bytes.
62  int InstructionDecode(byte* instruction);
63 
64  private:
65  // Bottleneck functions to print into the out_buffer.
66  void PrintChar(const char ch);
67  void Print(const char* str);
68 
69  // Printing of common values.
70  void PrintRegister(int reg);
71  void PrintFPURegister(int freg);
72  void PrintRs(Instruction* instr);
73  void PrintRt(Instruction* instr);
74  void PrintRd(Instruction* instr);
75  void PrintFs(Instruction* instr);
76  void PrintFt(Instruction* instr);
77  void PrintFd(Instruction* instr);
78  void PrintSa(Instruction* instr);
79  void PrintSd(Instruction* instr);
80  void PrintSs1(Instruction* instr);
81  void PrintSs2(Instruction* instr);
82  void PrintBc(Instruction* instr);
83  void PrintCc(Instruction* instr);
84  void PrintFunction(Instruction* instr);
85  void PrintSecondaryField(Instruction* instr);
86  void PrintUImm16(Instruction* instr);
87  void PrintSImm16(Instruction* instr);
88  void PrintXImm16(Instruction* instr);
89  void PrintXImm21(Instruction* instr);
90  void PrintXImm26(Instruction* instr);
91  void PrintCode(Instruction* instr); // For break and trap instructions.
92  // Printing of instruction name.
93  void PrintInstructionName(Instruction* instr);
94 
95  // Handle formatting of instructions and their options.
96  int FormatRegister(Instruction* instr, const char* option);
97  int FormatFPURegister(Instruction* instr, const char* option);
98  int FormatOption(Instruction* instr, const char* option);
99  void Format(Instruction* instr, const char* format);
100  void Unknown(Instruction* instr);
101  int DecodeBreakInstr(Instruction* instr);
102 
103  // Each of these functions decodes one particular instruction type.
104  int DecodeTypeRegister(Instruction* instr);
105  void DecodeTypeImmediate(Instruction* instr);
106  void DecodeTypeJump(Instruction* instr);
107 
108  const disasm::NameConverter& converter_;
109  v8::internal::Vector<char> out_buffer_;
110  int out_buffer_pos_;
111 
113 };
114 
115 
116 // Support for assertions in the Decoder formatting functions.
117 #define STRING_STARTS_WITH(string, compare_string) \
118  (strncmp(string, compare_string, strlen(compare_string)) == 0)
119 
120 
121 // Append the ch to the output buffer.
122 void Decoder::PrintChar(const char ch) {
123  out_buffer_[out_buffer_pos_++] = ch;
124 }
125 
126 
127 // Append the str to the output buffer.
128 void Decoder::Print(const char* str) {
129  char cur = *str++;
130  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
131  PrintChar(cur);
132  cur = *str++;
133  }
134  out_buffer_[out_buffer_pos_] = 0;
135 }
136 
137 
138 // Print the register name according to the active name converter.
139 void Decoder::PrintRegister(int reg) {
140  Print(converter_.NameOfCPURegister(reg));
141 }
142 
143 
144 void Decoder::PrintRs(Instruction* instr) {
145  int reg = instr->RsValue();
146  PrintRegister(reg);
147 }
148 
149 
150 void Decoder::PrintRt(Instruction* instr) {
151  int reg = instr->RtValue();
152  PrintRegister(reg);
153 }
154 
155 
156 void Decoder::PrintRd(Instruction* instr) {
157  int reg = instr->RdValue();
158  PrintRegister(reg);
159 }
160 
161 
162 // Print the FPUregister name according to the active name converter.
163 void Decoder::PrintFPURegister(int freg) {
164  Print(converter_.NameOfXMMRegister(freg));
165 }
166 
167 
168 void Decoder::PrintFs(Instruction* instr) {
169  int freg = instr->RsValue();
170  PrintFPURegister(freg);
171 }
172 
173 
174 void Decoder::PrintFt(Instruction* instr) {
175  int freg = instr->RtValue();
176  PrintFPURegister(freg);
177 }
178 
179 
180 void Decoder::PrintFd(Instruction* instr) {
181  int freg = instr->RdValue();
182  PrintFPURegister(freg);
183 }
184 
185 
186 // Print the integer value of the sa field.
187 void Decoder::PrintSa(Instruction* instr) {
188  int sa = instr->SaValue();
189  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
190 }
191 
192 
193 // Print the integer value of the rd field, when it is not used as reg.
194 void Decoder::PrintSd(Instruction* instr) {
195  int sd = instr->RdValue();
196  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd);
197 }
198 
199 
200 // Print the integer value of the rd field, when used as 'ext' size.
201 void Decoder::PrintSs1(Instruction* instr) {
202  int ss = instr->RdValue();
203  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1);
204 }
205 
206 
207 // Print the integer value of the rd field, when used as 'ins' size.
208 void Decoder::PrintSs2(Instruction* instr) {
209  int ss = instr->RdValue();
210  int pos = instr->SaValue();
211  out_buffer_pos_ +=
212  SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1);
213 }
214 
215 
216 // Print the integer value of the cc field for the bc1t/f instructions.
217 void Decoder::PrintBc(Instruction* instr) {
218  int cc = instr->FBccValue();
219  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc);
220 }
221 
222 
223 // Print the integer value of the cc field for the FP compare instructions.
224 void Decoder::PrintCc(Instruction* instr) {
225  int cc = instr->FCccValue();
226  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc);
227 }
228 
229 
230 // Print 16-bit unsigned immediate value.
231 void Decoder::PrintUImm16(Instruction* instr) {
232  int32_t imm = instr->Imm16Value();
233  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
234 }
235 
236 
237 // Print 16-bit signed immediate value.
238 void Decoder::PrintSImm16(Instruction* instr) {
239  int32_t imm = ((instr->Imm16Value()) << 16) >> 16;
240  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
241 }
242 
243 
244 // Print 16-bit hexa immediate value.
245 void Decoder::PrintXImm16(Instruction* instr) {
246  int32_t imm = instr->Imm16Value();
247  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
248 }
249 
250 
251 // Print 21-bit immediate value.
252 void Decoder::PrintXImm21(Instruction* instr) {
253  uint32_t imm = instr->Imm21Value();
254  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
255 }
256 
257 
258 // Print 26-bit immediate value.
259 void Decoder::PrintXImm26(Instruction* instr) {
260  uint32_t imm = instr->Imm26Value() << kImmFieldShift;
261  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
262 }
263 
264 
265 // Print 26-bit immediate value.
266 void Decoder::PrintCode(Instruction* instr) {
267  if (instr->OpcodeFieldRaw() != SPECIAL)
268  return; // Not a break or trap instruction.
269  switch (instr->FunctionFieldRaw()) {
270  case BREAK: {
271  int32_t code = instr->Bits(25, 6);
272  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
273  "0x%05x (%d)", code, code);
274  break;
275  }
276  case TGE:
277  case TGEU:
278  case TLT:
279  case TLTU:
280  case TEQ:
281  case TNE: {
282  int32_t code = instr->Bits(15, 6);
283  out_buffer_pos_ +=
284  SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
285  break;
286  }
287  default: // Not a break or trap instruction.
288  break;
289  }
290 }
291 
292 
293 // Printing of instruction name.
294 void Decoder::PrintInstructionName(Instruction* instr) {
295 }
296 
297 
298 // Handle all register based formatting in this function to reduce the
299 // complexity of FormatOption.
300 int Decoder::FormatRegister(Instruction* instr, const char* format) {
301  DCHECK(format[0] == 'r');
302  if (format[1] == 's') { // 'rs: Rs register.
303  int reg = instr->RsValue();
304  PrintRegister(reg);
305  return 2;
306  } else if (format[1] == 't') { // 'rt: rt register.
307  int reg = instr->RtValue();
308  PrintRegister(reg);
309  return 2;
310  } else if (format[1] == 'd') { // 'rd: rd register.
311  int reg = instr->RdValue();
312  PrintRegister(reg);
313  return 2;
314  }
315  UNREACHABLE();
316  return -1;
317 }
318 
319 
320 // Handle all FPUregister based formatting in this function to reduce the
321 // complexity of FormatOption.
322 int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
323  DCHECK(format[0] == 'f');
324  if (format[1] == 's') { // 'fs: fs register.
325  int reg = instr->FsValue();
326  PrintFPURegister(reg);
327  return 2;
328  } else if (format[1] == 't') { // 'ft: ft register.
329  int reg = instr->FtValue();
330  PrintFPURegister(reg);
331  return 2;
332  } else if (format[1] == 'd') { // 'fd: fd register.
333  int reg = instr->FdValue();
334  PrintFPURegister(reg);
335  return 2;
336  } else if (format[1] == 'r') { // 'fr: fr register.
337  int reg = instr->FrValue();
338  PrintFPURegister(reg);
339  return 2;
340  }
341  UNREACHABLE();
342  return -1;
343 }
344 
345 
346 // FormatOption takes a formatting string and interprets it based on
347 // the current instructions. The format string points to the first
348 // character of the option string (the option escape has already been
349 // consumed by the caller.) FormatOption returns the number of
350 // characters that were consumed from the formatting string.
351 int Decoder::FormatOption(Instruction* instr, const char* format) {
352  switch (format[0]) {
353  case 'c': { // 'code for break or trap instructions.
354  DCHECK(STRING_STARTS_WITH(format, "code"));
355  PrintCode(instr);
356  return 4;
357  }
358  case 'i': { // 'imm16u or 'imm26.
359  if (format[3] == '1') {
360  DCHECK(STRING_STARTS_WITH(format, "imm16"));
361  if (format[5] == 's') {
362  DCHECK(STRING_STARTS_WITH(format, "imm16s"));
363  PrintSImm16(instr);
364  } else if (format[5] == 'u') {
365  DCHECK(STRING_STARTS_WITH(format, "imm16u"));
366  PrintSImm16(instr);
367  } else {
368  DCHECK(STRING_STARTS_WITH(format, "imm16x"));
369  PrintXImm16(instr);
370  }
371  return 6;
372  } else if (format[3] == '2' && format[4] == '1') {
373  DCHECK(STRING_STARTS_WITH(format, "imm21x"));
374  PrintXImm21(instr);
375  return 6;
376  } else if (format[3] == '2' && format[4] == '6') {
377  DCHECK(STRING_STARTS_WITH(format, "imm26x"));
378  PrintXImm26(instr);
379  return 6;
380  }
381  }
382  case 'r': { // 'r: registers.
383  return FormatRegister(instr, format);
384  }
385  case 'f': { // 'f: FPUregisters.
386  return FormatFPURegister(instr, format);
387  }
388  case 's': { // 'sa.
389  switch (format[1]) {
390  case 'a': {
391  DCHECK(STRING_STARTS_WITH(format, "sa"));
392  PrintSa(instr);
393  return 2;
394  }
395  case 'd': {
396  DCHECK(STRING_STARTS_WITH(format, "sd"));
397  PrintSd(instr);
398  return 2;
399  }
400  case 's': {
401  if (format[2] == '1') {
402  DCHECK(STRING_STARTS_WITH(format, "ss1")); /* ext size */
403  PrintSs1(instr);
404  return 3;
405  } else {
406  DCHECK(STRING_STARTS_WITH(format, "ss2")); /* ins size */
407  PrintSs2(instr);
408  return 3;
409  }
410  }
411  }
412  }
413  case 'b': { // 'bc - Special for bc1 cc field.
414  DCHECK(STRING_STARTS_WITH(format, "bc"));
415  PrintBc(instr);
416  return 2;
417  }
418  case 'C': { // 'Cc - Special for c.xx.d cc field.
419  DCHECK(STRING_STARTS_WITH(format, "Cc"));
420  PrintCc(instr);
421  return 2;
422  }
423  }
424  UNREACHABLE();
425  return -1;
426 }
427 
428 
429 // Format takes a formatting string for a whole instruction and prints it into
430 // the output buffer. All escaped options are handed to FormatOption to be
431 // parsed further.
432 void Decoder::Format(Instruction* instr, const char* format) {
433  char cur = *format++;
434  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
435  if (cur == '\'') { // Single quote is used as the formatting escape.
436  format += FormatOption(instr, format);
437  } else {
438  out_buffer_[out_buffer_pos_++] = cur;
439  }
440  cur = *format++;
441  }
442  out_buffer_[out_buffer_pos_] = '\0';
443 }
444 
445 
446 // For currently unimplemented decodings the disassembler calls Unknown(instr)
447 // which will just print "unknown" of the instruction bits.
448 void Decoder::Unknown(Instruction* instr) {
449  Format(instr, "unknown");
450 }
451 
452 
453 int Decoder::DecodeBreakInstr(Instruction* instr) {
454  // This is already known to be BREAK instr, just extract the code.
455  if (instr->Bits(25, 6) == static_cast<int>(kMaxStopCode)) {
456  // This is stop(msg).
457  Format(instr, "break, code: 'code");
458  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
459  "\n%p %08lx stop msg: %s",
460  static_cast<void*>
461  (reinterpret_cast<int32_t*>(instr
463  reinterpret_cast<uint64_t>
464  (*reinterpret_cast<char**>(instr
466  *reinterpret_cast<char**>(instr
468  // Size 3: the break_ instr, plus embedded 64-bit char pointer.
469  return 3 * Instruction::kInstrSize;
470  } else {
471  Format(instr, "break, code: 'code");
473  }
474 }
475 
476 
477 int Decoder::DecodeTypeRegister(Instruction* instr) {
478  switch (instr->OpcodeFieldRaw()) {
479  case COP1: // Coprocessor instructions.
480  switch (instr->RsFieldRaw()) {
481  case MFC1:
482  Format(instr, "mfc1 'rt, 'fs");
483  break;
484  case DMFC1:
485  Format(instr, "dmfc1 'rt, 'fs");
486  break;
487  case MFHC1:
488  Format(instr, "mfhc1 'rt, 'fs");
489  break;
490  case MTC1:
491  Format(instr, "mtc1 'rt, 'fs");
492  break;
493  case DMTC1:
494  Format(instr, "dmtc1 'rt, 'fs");
495  break;
496  // These are called "fs" too, although they are not FPU registers.
497  case CTC1:
498  Format(instr, "ctc1 'rt, 'fs");
499  break;
500  case CFC1:
501  Format(instr, "cfc1 'rt, 'fs");
502  break;
503  case MTHC1:
504  Format(instr, "mthc1 'rt, 'fs");
505  break;
506  case D:
507  switch (instr->FunctionFieldRaw()) {
508  case ADD_D:
509  Format(instr, "add.d 'fd, 'fs, 'ft");
510  break;
511  case SUB_D:
512  Format(instr, "sub.d 'fd, 'fs, 'ft");
513  break;
514  case MUL_D:
515  Format(instr, "mul.d 'fd, 'fs, 'ft");
516  break;
517  case DIV_D:
518  Format(instr, "div.d 'fd, 'fs, 'ft");
519  break;
520  case ABS_D:
521  Format(instr, "abs.d 'fd, 'fs");
522  break;
523  case MOV_D:
524  Format(instr, "mov.d 'fd, 'fs");
525  break;
526  case NEG_D:
527  Format(instr, "neg.d 'fd, 'fs");
528  break;
529  case SQRT_D:
530  Format(instr, "sqrt.d 'fd, 'fs");
531  break;
532  case CVT_W_D:
533  Format(instr, "cvt.w.d 'fd, 'fs");
534  break;
535  case CVT_L_D:
536  Format(instr, "cvt.l.d 'fd, 'fs");
537  break;
538  case TRUNC_W_D:
539  Format(instr, "trunc.w.d 'fd, 'fs");
540  break;
541  case TRUNC_L_D:
542  Format(instr, "trunc.l.d 'fd, 'fs");
543  break;
544  case ROUND_W_D:
545  Format(instr, "round.w.d 'fd, 'fs");
546  break;
547  case ROUND_L_D:
548  Format(instr, "round.l.d 'fd, 'fs");
549  break;
550  case FLOOR_W_D:
551  Format(instr, "floor.w.d 'fd, 'fs");
552  break;
553  case FLOOR_L_D:
554  Format(instr, "floor.l.d 'fd, 'fs");
555  break;
556  case CEIL_W_D:
557  Format(instr, "ceil.w.d 'fd, 'fs");
558  break;
559  case CEIL_L_D:
560  Format(instr, "ceil.l.d 'fd, 'fs");
561  break;
562  case CVT_S_D:
563  Format(instr, "cvt.s.d 'fd, 'fs");
564  break;
565  case C_F_D:
566  Format(instr, "c.f.d 'fs, 'ft, 'Cc");
567  break;
568  case C_UN_D:
569  Format(instr, "c.un.d 'fs, 'ft, 'Cc");
570  break;
571  case C_EQ_D:
572  Format(instr, "c.eq.d 'fs, 'ft, 'Cc");
573  break;
574  case C_UEQ_D:
575  Format(instr, "c.ueq.d 'fs, 'ft, 'Cc");
576  break;
577  case C_OLT_D:
578  Format(instr, "c.olt.d 'fs, 'ft, 'Cc");
579  break;
580  case C_ULT_D:
581  Format(instr, "c.ult.d 'fs, 'ft, 'Cc");
582  break;
583  case C_OLE_D:
584  Format(instr, "c.ole.d 'fs, 'ft, 'Cc");
585  break;
586  case C_ULE_D:
587  Format(instr, "c.ule.d 'fs, 'ft, 'Cc");
588  break;
589  default:
590  Format(instr, "unknown.cop1.d");
591  break;
592  }
593  break;
594  case W:
595  switch (instr->FunctionFieldRaw()) {
596  case CVT_D_W: // Convert word to double.
597  Format(instr, "cvt.d.w 'fd, 'fs");
598  break;
599  default:
600  UNREACHABLE();
601  }
602  break;
603  case L:
604  switch (instr->FunctionFieldRaw()) {
605  case CVT_D_L:
606  Format(instr, "cvt.d.l 'fd, 'fs");
607  break;
608  case CVT_S_L:
609  Format(instr, "cvt.s.l 'fd, 'fs");
610  break;
611  case CMP_UN:
612  Format(instr, "cmp.un.d 'fd, 'fs, 'ft");
613  break;
614  case CMP_EQ:
615  Format(instr, "cmp.eq.d 'fd, 'fs, 'ft");
616  break;
617  case CMP_UEQ:
618  Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft");
619  break;
620  case CMP_LT:
621  Format(instr, "cmp.lt.d 'fd, 'fs, 'ft");
622  break;
623  case CMP_ULT:
624  Format(instr, "cmp.ult.d 'fd, 'fs, 'ft");
625  break;
626  case CMP_LE:
627  Format(instr, "cmp.le.d 'fd, 'fs, 'ft");
628  break;
629  case CMP_ULE:
630  Format(instr, "cmp.ule.d 'fd, 'fs, 'ft");
631  break;
632  case CMP_OR:
633  Format(instr, "cmp.or.d 'fd, 'fs, 'ft");
634  break;
635  case CMP_UNE:
636  Format(instr, "cmp.une.d 'fd, 'fs, 'ft");
637  break;
638  case CMP_NE:
639  Format(instr, "cmp.ne.d 'fd, 'fs, 'ft");
640  break;
641  default:
642  UNREACHABLE();
643  }
644  break;
645  default:
646  UNREACHABLE();
647  }
648  break;
649  case COP1X:
650  switch (instr->FunctionFieldRaw()) {
651  case MADD_D:
652  Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
653  break;
654  default:
655  UNREACHABLE();
656  }
657  break;
658  case SPECIAL:
659  switch (instr->FunctionFieldRaw()) {
660  case JR:
661  Format(instr, "jr 'rs");
662  break;
663  case JALR:
664  Format(instr, "jalr 'rs");
665  break;
666  case SLL:
667  if (0x0 == static_cast<int>(instr->InstructionBits()))
668  Format(instr, "nop");
669  else
670  Format(instr, "sll 'rd, 'rt, 'sa");
671  break;
672  case DSLL:
673  Format(instr, "dsll 'rd, 'rt, 'sa");
674  break;
675  case D_MUL_MUH: // Equals to DMUL.
676  if (kArchVariant != kMips64r6) {
677  Format(instr, "dmult 'rs, 'rt");
678  } else {
679  if (instr->SaValue() == MUL_OP) {
680  Format(instr, "dmul 'rd, 'rs, 'rt");
681  } else {
682  Format(instr, "dmuh 'rd, 'rs, 'rt");
683  }
684  }
685  break;
686  case DSLL32:
687  Format(instr, "dsll32 'rd, 'rt, 'sa");
688  break;
689  case SRL:
690  if (instr->RsValue() == 0) {
691  Format(instr, "srl 'rd, 'rt, 'sa");
692  } else {
693  if (kArchVariant == kMips64r2) {
694  Format(instr, "rotr 'rd, 'rt, 'sa");
695  } else {
696  Unknown(instr);
697  }
698  }
699  break;
700  case DSRL:
701  if (instr->RsValue() == 0) {
702  Format(instr, "dsrl 'rd, 'rt, 'sa");
703  } else {
704  if (kArchVariant == kMips64r2) {
705  Format(instr, "drotr 'rd, 'rt, 'sa");
706  } else {
707  Unknown(instr);
708  }
709  }
710  break;
711  case DSRL32:
712  Format(instr, "dsrl32 'rd, 'rt, 'sa");
713  break;
714  case SRA:
715  Format(instr, "sra 'rd, 'rt, 'sa");
716  break;
717  case DSRA:
718  Format(instr, "dsra 'rd, 'rt, 'sa");
719  break;
720  case DSRA32:
721  Format(instr, "dsra32 'rd, 'rt, 'sa");
722  break;
723  case SLLV:
724  Format(instr, "sllv 'rd, 'rt, 'rs");
725  break;
726  case DSLLV:
727  Format(instr, "dsllv 'rd, 'rt, 'rs");
728  break;
729  case SRLV:
730  if (instr->SaValue() == 0) {
731  Format(instr, "srlv 'rd, 'rt, 'rs");
732  } else {
733  if (kArchVariant == kMips64r2) {
734  Format(instr, "rotrv 'rd, 'rt, 'rs");
735  } else {
736  Unknown(instr);
737  }
738  }
739  break;
740  case DSRLV:
741  if (instr->SaValue() == 0) {
742  Format(instr, "dsrlv 'rd, 'rt, 'rs");
743  } else {
744  if (kArchVariant == kMips64r2) {
745  Format(instr, "drotrv 'rd, 'rt, 'rs");
746  } else {
747  Unknown(instr);
748  }
749  }
750  break;
751  case SRAV:
752  Format(instr, "srav 'rd, 'rt, 'rs");
753  break;
754  case DSRAV:
755  Format(instr, "dsrav 'rd, 'rt, 'rs");
756  break;
757  case MFHI:
758  if (instr->Bits(25, 16) == 0) {
759  Format(instr, "mfhi 'rd");
760  } else {
761  if ((instr->FunctionFieldRaw() == CLZ_R6)
762  && (instr->FdValue() == 1)) {
763  Format(instr, "clz 'rd, 'rs");
764  } else if ((instr->FunctionFieldRaw() == CLO_R6)
765  && (instr->FdValue() == 1)) {
766  Format(instr, "clo 'rd, 'rs");
767  }
768  }
769  break;
770  case MFLO:
771  Format(instr, "mflo 'rd");
772  break;
773  case D_MUL_MUH_U: // Equals to DMULTU.
774  if (kArchVariant != kMips64r6) {
775  Format(instr, "dmultu 'rs, 'rt");
776  } else {
777  if (instr->SaValue() == MUL_OP) {
778  Format(instr, "dmulu 'rd, 'rs, 'rt");
779  } else {
780  Format(instr, "dmuhu 'rd, 'rs, 'rt");
781  }
782  }
783  break;
784  case MULT: // @Mips64r6 == MUL_MUH.
785  if (kArchVariant != kMips64r6) {
786  Format(instr, "mult 'rs, 'rt");
787  } else {
788  if (instr->SaValue() == MUL_OP) {
789  Format(instr, "mul 'rd, 'rs, 'rt");
790  } else {
791  Format(instr, "muh 'rd, 'rs, 'rt");
792  }
793  }
794  break;
795  case MULTU: // @Mips64r6 == MUL_MUH_U.
796  if (kArchVariant != kMips64r6) {
797  Format(instr, "multu 'rs, 'rt");
798  } else {
799  if (instr->SaValue() == MUL_OP) {
800  Format(instr, "mulu 'rd, 'rs, 'rt");
801  } else {
802  Format(instr, "muhu 'rd, 'rs, 'rt");
803  }
804  }
805 
806  break;
807  case DIV: // @Mips64r6 == DIV_MOD.
808  if (kArchVariant != kMips64r6) {
809  Format(instr, "div 'rs, 'rt");
810  } else {
811  if (instr->SaValue() == DIV_OP) {
812  Format(instr, "div 'rd, 'rs, 'rt");
813  } else {
814  Format(instr, "mod 'rd, 'rs, 'rt");
815  }
816  }
817  break;
818  case DDIV: // @Mips64r6 == D_DIV_MOD.
819  if (kArchVariant != kMips64r6) {
820  Format(instr, "ddiv 'rs, 'rt");
821  } else {
822  if (instr->SaValue() == DIV_OP) {
823  Format(instr, "ddiv 'rd, 'rs, 'rt");
824  } else {
825  Format(instr, "dmod 'rd, 'rs, 'rt");
826  }
827  }
828  break;
829  case DIVU: // @Mips64r6 == DIV_MOD_U.
830  if (kArchVariant != kMips64r6) {
831  Format(instr, "divu 'rs, 'rt");
832  } else {
833  if (instr->SaValue() == DIV_OP) {
834  Format(instr, "divu 'rd, 'rs, 'rt");
835  } else {
836  Format(instr, "modu 'rd, 'rs, 'rt");
837  }
838  }
839  break;
840  case DDIVU: // @Mips64r6 == D_DIV_MOD_U.
841  if (kArchVariant != kMips64r6) {
842  Format(instr, "ddivu 'rs, 'rt");
843  } else {
844  if (instr->SaValue() == DIV_OP) {
845  Format(instr, "ddivu 'rd, 'rs, 'rt");
846  } else {
847  Format(instr, "dmodu 'rd, 'rs, 'rt");
848  }
849  }
850  break;
851  case ADD:
852  Format(instr, "add 'rd, 'rs, 'rt");
853  break;
854  case DADD:
855  Format(instr, "dadd 'rd, 'rs, 'rt");
856  break;
857  case ADDU:
858  Format(instr, "addu 'rd, 'rs, 'rt");
859  break;
860  case DADDU:
861  Format(instr, "daddu 'rd, 'rs, 'rt");
862  break;
863  case SUB:
864  Format(instr, "sub 'rd, 'rs, 'rt");
865  break;
866  case DSUB:
867  Format(instr, "dsub 'rd, 'rs, 'rt");
868  break;
869  case SUBU:
870  Format(instr, "subu 'rd, 'rs, 'rt");
871  break;
872  case DSUBU:
873  Format(instr, "dsubu 'rd, 'rs, 'rt");
874  break;
875  case AND:
876  Format(instr, "and 'rd, 'rs, 'rt");
877  break;
878  case OR:
879  if (0 == instr->RsValue()) {
880  Format(instr, "mov 'rd, 'rt");
881  } else if (0 == instr->RtValue()) {
882  Format(instr, "mov 'rd, 'rs");
883  } else {
884  Format(instr, "or 'rd, 'rs, 'rt");
885  }
886  break;
887  case XOR:
888  Format(instr, "xor 'rd, 'rs, 'rt");
889  break;
890  case NOR:
891  Format(instr, "nor 'rd, 'rs, 'rt");
892  break;
893  case SLT:
894  Format(instr, "slt 'rd, 'rs, 'rt");
895  break;
896  case SLTU:
897  Format(instr, "sltu 'rd, 'rs, 'rt");
898  break;
899  case BREAK:
900  return DecodeBreakInstr(instr);
901  case TGE:
902  Format(instr, "tge 'rs, 'rt, code: 'code");
903  break;
904  case TGEU:
905  Format(instr, "tgeu 'rs, 'rt, code: 'code");
906  break;
907  case TLT:
908  Format(instr, "tlt 'rs, 'rt, code: 'code");
909  break;
910  case TLTU:
911  Format(instr, "tltu 'rs, 'rt, code: 'code");
912  break;
913  case TEQ:
914  Format(instr, "teq 'rs, 'rt, code: 'code");
915  break;
916  case TNE:
917  Format(instr, "tne 'rs, 'rt, code: 'code");
918  break;
919  case MOVZ:
920  Format(instr, "movz 'rd, 'rs, 'rt");
921  break;
922  case MOVN:
923  Format(instr, "movn 'rd, 'rs, 'rt");
924  break;
925  case MOVCI:
926  if (instr->Bit(16)) {
927  Format(instr, "movt 'rd, 'rs, 'bc");
928  } else {
929  Format(instr, "movf 'rd, 'rs, 'bc");
930  }
931  break;
932  case SELEQZ_S:
933  Format(instr, "seleqz 'rd, 'rs, 'rt");
934  break;
935  case SELNEZ_S:
936  Format(instr, "selnez 'rd, 'rs, 'rt");
937  break;
938  default:
939  UNREACHABLE();
940  }
941  break;
942  case SPECIAL2:
943  switch (instr->FunctionFieldRaw()) {
944  case MUL:
945  Format(instr, "mul 'rd, 'rs, 'rt");
946  break;
947  case CLZ:
948  if (kArchVariant != kMips64r6) {
949  Format(instr, "clz 'rd, 'rs");
950  }
951  break;
952  default:
953  UNREACHABLE();
954  }
955  break;
956  case SPECIAL3:
957  switch (instr->FunctionFieldRaw()) {
958  case INS: {
959  Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
960  break;
961  }
962  case EXT: {
963  Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
964  break;
965  }
966  default:
967  UNREACHABLE();
968  }
969  break;
970  default:
971  UNREACHABLE();
972  }
974 }
975 
976 
977 void Decoder::DecodeTypeImmediate(Instruction* instr) {
978  switch (instr->OpcodeFieldRaw()) {
979  case COP1:
980  switch (instr->RsFieldRaw()) {
981  case BC1:
982  if (instr->FBtrueValue()) {
983  Format(instr, "bc1t 'bc, 'imm16u");
984  } else {
985  Format(instr, "bc1f 'bc, 'imm16u");
986  }
987  break;
988  case BC1EQZ:
989  Format(instr, "bc1eqz 'ft, 'imm16u");
990  break;
991  case BC1NEZ:
992  Format(instr, "bc1nez 'ft, 'imm16u");
993  break;
994  case W: // CMP.S instruction.
995  switch (instr->FunctionValue()) {
996  case CMP_AF:
997  Format(instr, "cmp.af.S 'ft, 'fs, 'fd");
998  break;
999  case CMP_UN:
1000  Format(instr, "cmp.un.S 'ft, 'fs, 'fd");
1001  break;
1002  case CMP_EQ:
1003  Format(instr, "cmp.eq.S 'ft, 'fs, 'fd");
1004  break;
1005  case CMP_UEQ:
1006  Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd");
1007  break;
1008  case CMP_LT:
1009  Format(instr, "cmp.lt.S 'ft, 'fs, 'fd");
1010  break;
1011  case CMP_ULT:
1012  Format(instr, "cmp.ult.S 'ft, 'fs, 'fd");
1013  break;
1014  case CMP_LE:
1015  Format(instr, "cmp.le.S 'ft, 'fs, 'fd");
1016  break;
1017  case CMP_ULE:
1018  Format(instr, "cmp.ule.S 'ft, 'fs, 'fd");
1019  break;
1020  case CMP_OR:
1021  Format(instr, "cmp.or.S 'ft, 'fs, 'fd");
1022  break;
1023  case CMP_UNE:
1024  Format(instr, "cmp.une.S 'ft, 'fs, 'fd");
1025  break;
1026  case CMP_NE:
1027  Format(instr, "cmp.ne.S 'ft, 'fs, 'fd");
1028  break;
1029  default:
1030  UNREACHABLE();
1031  }
1032  break;
1033  case L: // CMP.D instruction.
1034  switch (instr->FunctionValue()) {
1035  case CMP_AF:
1036  Format(instr, "cmp.af.D 'ft, 'fs, 'fd");
1037  break;
1038  case CMP_UN:
1039  Format(instr, "cmp.un.D 'ft, 'fs, 'fd");
1040  break;
1041  case CMP_EQ:
1042  Format(instr, "cmp.eq.D 'ft, 'fs, 'fd");
1043  break;
1044  case CMP_UEQ:
1045  Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd");
1046  break;
1047  case CMP_LT:
1048  Format(instr, "cmp.lt.D 'ft, 'fs, 'fd");
1049  break;
1050  case CMP_ULT:
1051  Format(instr, "cmp.ult.D 'ft, 'fs, 'fd");
1052  break;
1053  case CMP_LE:
1054  Format(instr, "cmp.le.D 'ft, 'fs, 'fd");
1055  break;
1056  case CMP_ULE:
1057  Format(instr, "cmp.ule.D 'ft, 'fs, 'fd");
1058  break;
1059  case CMP_OR:
1060  Format(instr, "cmp.or.D 'ft, 'fs, 'fd");
1061  break;
1062  case CMP_UNE:
1063  Format(instr, "cmp.une.D 'ft, 'fs, 'fd");
1064  break;
1065  case CMP_NE:
1066  Format(instr, "cmp.ne.D 'ft, 'fs, 'fd");
1067  break;
1068  default:
1069  UNREACHABLE();
1070  }
1071  break;
1072  case S:
1073  switch (instr->FunctionValue()) {
1074  case SEL:
1075  Format(instr, "sel.S 'ft, 'fs, 'fd");
1076  break;
1077  case SELEQZ_C:
1078  Format(instr, "seleqz.S 'ft, 'fs, 'fd");
1079  break;
1080  case SELNEZ_C:
1081  Format(instr, "selnez.S 'ft, 'fs, 'fd");
1082  break;
1083  case MIN:
1084  Format(instr, "min.S 'ft, 'fs, 'fd");
1085  break;
1086  case MINA:
1087  Format(instr, "mina.S 'ft, 'fs, 'fd");
1088  break;
1089  case MAX:
1090  Format(instr, "max.S 'ft, 'fs, 'fd");
1091  break;
1092  case MAXA:
1093  Format(instr, "maxa.S 'ft, 'fs, 'fd");
1094  break;
1095  default:
1096  UNREACHABLE();
1097  }
1098  break;
1099  case D:
1100  switch (instr->FunctionValue()) {
1101  case SEL:
1102  Format(instr, "sel.D 'ft, 'fs, 'fd");
1103  break;
1104  case SELEQZ_C:
1105  Format(instr, "seleqz.D 'ft, 'fs, 'fd");
1106  break;
1107  case SELNEZ_C:
1108  Format(instr, "selnez.D 'ft, 'fs, 'fd");
1109  break;
1110  case MIN:
1111  Format(instr, "min.D 'ft, 'fs, 'fd");
1112  break;
1113  case MINA:
1114  Format(instr, "mina.D 'ft, 'fs, 'fd");
1115  break;
1116  case MAX:
1117  Format(instr, "max.D 'ft, 'fs, 'fd");
1118  break;
1119  case MAXA:
1120  Format(instr, "maxa.D 'ft, 'fs, 'fd");
1121  break;
1122  default:
1123  UNREACHABLE();
1124  }
1125  break;
1126  default:
1127  UNREACHABLE();
1128  }
1129 
1130  break; // Case COP1.
1131  // ------------- REGIMM class.
1132  case REGIMM:
1133  switch (instr->RtFieldRaw()) {
1134  case BLTZ:
1135  Format(instr, "bltz 'rs, 'imm16u");
1136  break;
1137  case BLTZAL:
1138  Format(instr, "bltzal 'rs, 'imm16u");
1139  break;
1140  case BGEZ:
1141  Format(instr, "bgez 'rs, 'imm16u");
1142  break;
1143  case BGEZAL:
1144  Format(instr, "bgezal 'rs, 'imm16u");
1145  break;
1146  case BGEZALL:
1147  Format(instr, "bgezall 'rs, 'imm16u");
1148  break;
1149  case DAHI:
1150  Format(instr, "dahi 'rs, 'imm16u");
1151  break;
1152  case DATI:
1153  Format(instr, "dati 'rs, 'imm16u");
1154  break;
1155  default:
1156  UNREACHABLE();
1157  }
1158  break; // Case REGIMM.
1159  // ------------- Branch instructions.
1160  case BEQ:
1161  Format(instr, "beq 'rs, 'rt, 'imm16u");
1162  break;
1163  case BNE:
1164  Format(instr, "bne 'rs, 'rt, 'imm16u");
1165  break;
1166  case BLEZ:
1167  if ((instr->RtFieldRaw() == 0)
1168  && (instr->RsFieldRaw() != 0)) {
1169  Format(instr, "blez 'rs, 'imm16u");
1170  } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
1171  && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
1172  Format(instr, "bgeuc 'rs, 'rt, 'imm16u");
1173  } else if ((instr->RtFieldRaw() == instr->RsFieldRaw())
1174  && (instr->RtFieldRaw() != 0)) {
1175  Format(instr, "bgezalc 'rs, 'imm16u");
1176  } else if ((instr->RsFieldRaw() == 0)
1177  && (instr->RtFieldRaw() != 0)) {
1178  Format(instr, "blezalc 'rs, 'imm16u");
1179  } else {
1180  UNREACHABLE();
1181  }
1182  break;
1183  case BGTZ:
1184  if ((instr->RtFieldRaw() == 0)
1185  && (instr->RsFieldRaw() != 0)) {
1186  Format(instr, "bgtz 'rs, 'imm16u");
1187  } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
1188  && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
1189  Format(instr, "bltuc 'rs, 'rt, 'imm16u");
1190  } else if ((instr->RtFieldRaw() == instr->RsFieldRaw())
1191  && (instr->RtFieldRaw() != 0)) {
1192  Format(instr, "bltzalc 'rt, 'imm16u");
1193  } else if ((instr->RsFieldRaw() == 0)
1194  && (instr->RtFieldRaw() != 0)) {
1195  Format(instr, "bgtzalc 'rt, 'imm16u");
1196  } else {
1197  UNREACHABLE();
1198  }
1199  break;
1200  case BLEZL:
1201  if ((instr->RtFieldRaw() == instr->RsFieldRaw())
1202  && (instr->RtFieldRaw() != 0)) {
1203  Format(instr, "bgezc 'rt, 'imm16u");
1204  } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
1205  && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
1206  Format(instr, "bgec 'rs, 'rt, 'imm16u");
1207  } else if ((instr->RsFieldRaw() == 0)
1208  && (instr->RtFieldRaw() != 0)) {
1209  Format(instr, "blezc 'rt, 'imm16u");
1210  } else {
1211  UNREACHABLE();
1212  }
1213  break;
1214  case BGTZL:
1215  if ((instr->RtFieldRaw() == instr->RsFieldRaw())
1216  && (instr->RtFieldRaw() != 0)) {
1217  Format(instr, "bltzc 'rt, 'imm16u");
1218  } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
1219  && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
1220  Format(instr, "bltc 'rs, 'rt, 'imm16u");
1221  } else if ((instr->RsFieldRaw() == 0)
1222  && (instr->RtFieldRaw() != 0)) {
1223  Format(instr, "bgtzc 'rt, 'imm16u");
1224  } else {
1225  UNREACHABLE();
1226  }
1227  break;
1228  case BEQZC:
1229  if (instr->RsFieldRaw() != 0) {
1230  Format(instr, "beqzc 'rs, 'imm21x");
1231  }
1232  break;
1233  case BNEZC:
1234  if (instr->RsFieldRaw() != 0) {
1235  Format(instr, "bnezc 'rs, 'imm21x");
1236  }
1237  break;
1238  // ------------- Arithmetic instructions.
1239  case ADDI:
1240  if (kArchVariant != kMips64r6) {
1241  Format(instr, "addi 'rt, 'rs, 'imm16s");
1242  } else {
1243  // Check if BOVC or BEQC instruction.
1244  if (instr->RsFieldRaw() >= instr->RtFieldRaw()) {
1245  Format(instr, "bovc 'rs, 'rt, 'imm16s");
1246  } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) {
1247  Format(instr, "beqc 'rs, 'rt, 'imm16s");
1248  } else {
1249  UNREACHABLE();
1250  }
1251  }
1252  break;
1253  case DADDI:
1254  if (kArchVariant != kMips64r6) {
1255  Format(instr, "daddi 'rt, 'rs, 'imm16s");
1256  } else {
1257  // Check if BNVC or BNEC instruction.
1258  if (instr->RsFieldRaw() >= instr->RtFieldRaw()) {
1259  Format(instr, "bnvc 'rs, 'rt, 'imm16s");
1260  } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) {
1261  Format(instr, "bnec 'rs, 'rt, 'imm16s");
1262  } else {
1263  UNREACHABLE();
1264  }
1265  }
1266  break;
1267  case ADDIU:
1268  Format(instr, "addiu 'rt, 'rs, 'imm16s");
1269  break;
1270  case DADDIU:
1271  Format(instr, "daddiu 'rt, 'rs, 'imm16s");
1272  break;
1273  case SLTI:
1274  Format(instr, "slti 'rt, 'rs, 'imm16s");
1275  break;
1276  case SLTIU:
1277  Format(instr, "sltiu 'rt, 'rs, 'imm16u");
1278  break;
1279  case ANDI:
1280  Format(instr, "andi 'rt, 'rs, 'imm16x");
1281  break;
1282  case ORI:
1283  Format(instr, "ori 'rt, 'rs, 'imm16x");
1284  break;
1285  case XORI:
1286  Format(instr, "xori 'rt, 'rs, 'imm16x");
1287  break;
1288  case LUI:
1289  if (kArchVariant != kMips64r6) {
1290  Format(instr, "lui 'rt, 'imm16x");
1291  } else {
1292  if (instr->RsValue() != 0) {
1293  Format(instr, "aui 'rt, 'imm16x");
1294  } else {
1295  Format(instr, "lui 'rt, 'imm16x");
1296  }
1297  }
1298  break;
1299  case DAUI:
1300  Format(instr, "daui 'rt, 'imm16x");
1301  break;
1302  // ------------- Memory instructions.
1303  case LB:
1304  Format(instr, "lb 'rt, 'imm16s('rs)");
1305  break;
1306  case LH:
1307  Format(instr, "lh 'rt, 'imm16s('rs)");
1308  break;
1309  case LWL:
1310  Format(instr, "lwl 'rt, 'imm16s('rs)");
1311  break;
1312  case LDL:
1313  Format(instr, "ldl 'rt, 'imm16s('rs)");
1314  break;
1315  case LW:
1316  Format(instr, "lw 'rt, 'imm16s('rs)");
1317  break;
1318  case LWU:
1319  Format(instr, "lwu 'rt, 'imm16s('rs)");
1320  break;
1321  case LD:
1322  Format(instr, "ld 'rt, 'imm16s('rs)");
1323  break;
1324  case LBU:
1325  Format(instr, "lbu 'rt, 'imm16s('rs)");
1326  break;
1327  case LHU:
1328  Format(instr, "lhu 'rt, 'imm16s('rs)");
1329  break;
1330  case LWR:
1331  Format(instr, "lwr 'rt, 'imm16s('rs)");
1332  break;
1333  case LDR:
1334  Format(instr, "ldr 'rt, 'imm16s('rs)");
1335  break;
1336  case PREF:
1337  Format(instr, "pref 'rt, 'imm16s('rs)");
1338  break;
1339  case SB:
1340  Format(instr, "sb 'rt, 'imm16s('rs)");
1341  break;
1342  case SH:
1343  Format(instr, "sh 'rt, 'imm16s('rs)");
1344  break;
1345  case SWL:
1346  Format(instr, "swl 'rt, 'imm16s('rs)");
1347  break;
1348  case SW:
1349  Format(instr, "sw 'rt, 'imm16s('rs)");
1350  break;
1351  case SD:
1352  Format(instr, "sd 'rt, 'imm16s('rs)");
1353  break;
1354  case SWR:
1355  Format(instr, "swr 'rt, 'imm16s('rs)");
1356  break;
1357  case LWC1:
1358  Format(instr, "lwc1 'ft, 'imm16s('rs)");
1359  break;
1360  case LDC1:
1361  Format(instr, "ldc1 'ft, 'imm16s('rs)");
1362  break;
1363  case SWC1:
1364  Format(instr, "swc1 'ft, 'imm16s('rs)");
1365  break;
1366  case SDC1:
1367  Format(instr, "sdc1 'ft, 'imm16s('rs)");
1368  break;
1369  default:
1370  printf("a 0x%x \n", instr->OpcodeFieldRaw());
1371  UNREACHABLE();
1372  break;
1373  }
1374 }
1375 
1376 
1377 void Decoder::DecodeTypeJump(Instruction* instr) {
1378  switch (instr->OpcodeFieldRaw()) {
1379  case J:
1380  Format(instr, "j 'imm26x");
1381  break;
1382  case JAL:
1383  Format(instr, "jal 'imm26x");
1384  break;
1385  default:
1386  UNREACHABLE();
1387  }
1388 }
1389 
1390 
1391 // Disassemble the instruction at *instr_ptr into the output buffer.
1392 // All instructions are one word long, except for the simulator
1393 // psuedo-instruction stop(msg). For that one special case, we return
1394 // size larger than one kInstrSize.
1395 int Decoder::InstructionDecode(byte* instr_ptr) {
1396  Instruction* instr = Instruction::At(instr_ptr);
1397  // Print raw instruction bytes.
1398  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1399  "%08x ",
1400  instr->InstructionBits());
1401  switch (instr->InstructionType()) {
1403  return DecodeTypeRegister(instr);
1404  }
1406  DecodeTypeImmediate(instr);
1407  break;
1408  }
1409  case Instruction::kJumpType: {
1410  DecodeTypeJump(instr);
1411  break;
1412  }
1413  default: {
1414  Format(instr, "UNSUPPORTED");
1415  UNSUPPORTED_MIPS();
1416  }
1417  }
1418  return Instruction::kInstrSize;
1419 }
1420 
1421 
1422 } } // namespace v8::internal
1423 
1424 
1425 
1426 //------------------------------------------------------------------------------
1427 
1428 namespace disasm {
1429 
1430 const char* NameConverter::NameOfAddress(byte* addr) const {
1431  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1432  return tmp_buffer_.start();
1433 }
1434 
1435 
1436 const char* NameConverter::NameOfConstant(byte* addr) const {
1437  return NameOfAddress(addr);
1438 }
1439 
1440 
1441 const char* NameConverter::NameOfCPURegister(int reg) const {
1442  return v8::internal::Registers::Name(reg);
1443 }
1444 
1445 
1446 const char* NameConverter::NameOfXMMRegister(int reg) const {
1448 }
1449 
1450 
1451 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1452  UNREACHABLE(); // MIPS does not have the concept of a byte register.
1453  return "nobytereg";
1454 }
1455 
1456 
1457 const char* NameConverter::NameInCode(byte* addr) const {
1458  // The default name converter is called for unknown code. So we will not try
1459  // to access any memory.
1460  return "";
1461 }
1462 
1463 
1464 //------------------------------------------------------------------------------
1465 
1466 Disassembler::Disassembler(const NameConverter& converter)
1467  : converter_(converter) {}
1468 
1469 
1470 Disassembler::~Disassembler() {}
1471 
1472 
1473 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1474  byte* instruction) {
1475  v8::internal::Decoder d(converter_, buffer);
1476  return d.InstructionDecode(instruction);
1477 }
1478 
1479 
1480 // The MIPS assembler does not currently use constant pools.
1481 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1482  return -1;
1483 }
1484 
1485 
1486 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1487  NameConverter converter;
1488  Disassembler d(converter);
1489  for (byte* pc = begin; pc < end;) {
1491  buffer[0] = '\0';
1492  byte* prev_pc = pc;
1493  pc += d.InstructionDecode(buffer, pc);
1494  v8::internal::PrintF(f, "%p %08x %s\n",
1495  prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1496  }
1497 }
1498 
1499 
1500 #undef UNSUPPORTED
1501 
1502 } // namespace disasm
1503 
1504 #endif // V8_TARGET_ARCH_MIPS64
Disassembler(const NameConverter &converter)
v8::internal::EmbeddedVector< char, 128 > tmp_buffer_
Definition: disasm.h:26
virtual const char * NameInCode(byte *addr) const
virtual const char * NameOfByteCPURegister(int reg) const
virtual const char * NameOfXMMRegister(int reg) const
virtual const char * NameOfAddress(byte *addr) const
virtual const char * NameOfCPURegister(int reg) const
virtual const char * NameOfConstant(byte *addr) const
static const char * Name(int reg)
static Instruction * At(byte *pc)
static const char * Name(int reg)
T * start() const
Definition: vector.h:47
@ kMips64r6
@ kMips64r2
#define UNSUPPORTED_MIPS()
static const ArchVariants kArchVariant
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:244
Definition: disasm.h:8
int int32_t
Definition: unicode.cc:24
const uint32_t kMaxStopCode
int SNPrintF(Vector< char > str, const char *format,...)
Definition: utils.cc:105
const Register pc
void PrintF(const char *format,...)
Definition: utils.cc:80
const int kImmFieldShift
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20