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
35 #include "src/base/platform/platform.h"
36 #include "src/disasm.h"
37 #include "src/macro-assembler.h"
38 #include "src/mips64/constants-mips64.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 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
112 DISALLOW_COPY_AND_ASSIGN(Decoder);
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.
PrintChar(const char ch)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.
Print(const char * str)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.
PrintRegister(int reg)139 void Decoder::PrintRegister(int reg) {
140 Print(converter_.NameOfCPURegister(reg));
141 }
142
143
PrintRs(Instruction * instr)144 void Decoder::PrintRs(Instruction* instr) {
145 int reg = instr->RsValue();
146 PrintRegister(reg);
147 }
148
149
PrintRt(Instruction * instr)150 void Decoder::PrintRt(Instruction* instr) {
151 int reg = instr->RtValue();
152 PrintRegister(reg);
153 }
154
155
PrintRd(Instruction * instr)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.
PrintFPURegister(int freg)163 void Decoder::PrintFPURegister(int freg) {
164 Print(converter_.NameOfXMMRegister(freg));
165 }
166
167
PrintFs(Instruction * instr)168 void Decoder::PrintFs(Instruction* instr) {
169 int freg = instr->RsValue();
170 PrintFPURegister(freg);
171 }
172
173
PrintFt(Instruction * instr)174 void Decoder::PrintFt(Instruction* instr) {
175 int freg = instr->RtValue();
176 PrintFPURegister(freg);
177 }
178
179
PrintFd(Instruction * instr)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.
PrintSa(Instruction * instr)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.
PrintSd(Instruction * instr)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.
PrintSs1(Instruction * instr)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.
PrintSs2(Instruction * instr)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.
PrintBc(Instruction * instr)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.
PrintCc(Instruction * instr)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.
PrintUImm16(Instruction * instr)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.
PrintSImm16(Instruction * instr)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.
PrintXImm16(Instruction * instr)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.
PrintXImm21(Instruction * instr)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.
PrintXImm26(Instruction * instr)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.
PrintCode(Instruction * instr)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.
PrintInstructionName(Instruction * instr)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.
FormatRegister(Instruction * instr,const char * format)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.
FormatFPURegister(Instruction * instr,const char * format)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.
FormatOption(Instruction * instr,const char * format)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.
Format(Instruction * instr,const char * format)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.
Unknown(Instruction * instr)448 void Decoder::Unknown(Instruction* instr) {
449 Format(instr, "unknown");
450 }
451
452
DecodeBreakInstr(Instruction * instr)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
462 + Instruction::kInstrSize)),
463 reinterpret_cast<uint64_t>
464 (*reinterpret_cast<char**>(instr
465 + Instruction::kInstrSize)),
466 *reinterpret_cast<char**>(instr
467 + Instruction::kInstrSize));
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");
472 return Instruction::kInstrSize;
473 }
474 }
475
476
DecodeTypeRegister(Instruction * instr)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 }
973 return Instruction::kInstrSize;
974 }
975
976
DecodeTypeImmediate(Instruction * instr)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
DecodeTypeJump(Instruction * instr)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.
InstructionDecode(byte * instr_ptr)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()) {
1402 case Instruction::kRegisterType: {
1403 return DecodeTypeRegister(instr);
1404 }
1405 case Instruction::kImmediateType: {
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
NameOfAddress(byte * addr) const1430 const char* NameConverter::NameOfAddress(byte* addr) const {
1431 v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1432 return tmp_buffer_.start();
1433 }
1434
1435
NameOfConstant(byte * addr) const1436 const char* NameConverter::NameOfConstant(byte* addr) const {
1437 return NameOfAddress(addr);
1438 }
1439
1440
NameOfCPURegister(int reg) const1441 const char* NameConverter::NameOfCPURegister(int reg) const {
1442 return v8::internal::Registers::Name(reg);
1443 }
1444
1445
NameOfXMMRegister(int reg) const1446 const char* NameConverter::NameOfXMMRegister(int reg) const {
1447 return v8::internal::FPURegisters::Name(reg);
1448 }
1449
1450
NameOfByteCPURegister(int reg) const1451 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
NameInCode(byte * addr) const1457 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
Disassembler(const NameConverter & converter)1466 Disassembler::Disassembler(const NameConverter& converter)
1467 : converter_(converter) {}
1468
1469
~Disassembler()1470 Disassembler::~Disassembler() {}
1471
1472
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)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.
ConstantPoolSizeAt(byte * instruction)1481 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1482 return -1;
1483 }
1484
1485
Disassemble(FILE * f,byte * begin,byte * end)1486 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1487 NameConverter converter;
1488 Disassembler d(converter);
1489 for (byte* pc = begin; pc < end;) {
1490 v8::internal::EmbeddedVector<char, 128> buffer;
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
1505