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