blob: 7b054933ebb80aa472bc1884c49e94e3f0b269bd [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031#if V8_TARGET_ARCH_MIPS64
32
33#include "src/base/platform/platform.h"
34#include "src/disasm.h"
35#include "src/macro-assembler.h"
36#include "src/mips64/constants-mips64.h"
37
38namespace v8 {
39namespace internal {
40
41//------------------------------------------------------------------------------
42
43// Decoder decodes and disassembles instructions into an output buffer.
44// It uses the converter to convert register names and call destinations into
45// more informative description.
46class Decoder {
47 public:
48 Decoder(const disasm::NameConverter& converter,
49 v8::internal::Vector<char> out_buffer)
50 : converter_(converter),
51 out_buffer_(out_buffer),
52 out_buffer_pos_(0) {
53 out_buffer_[out_buffer_pos_] = '\0';
54 }
55
56 ~Decoder() {}
57
58 // Writes one disassembled instruction into 'buffer' (0-terminated).
59 // Returns the length of the disassembled machine instruction in bytes.
60 int InstructionDecode(byte* instruction);
61
62 private:
63 // Bottleneck functions to print into the out_buffer.
64 void PrintChar(const char ch);
65 void Print(const char* str);
66
67 // Printing of common values.
68 void PrintRegister(int reg);
69 void PrintFPURegister(int freg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 void PrintFPUStatusRegister(int freg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 void PrintRs(Instruction* instr);
72 void PrintRt(Instruction* instr);
73 void PrintRd(Instruction* instr);
74 void PrintFs(Instruction* instr);
75 void PrintFt(Instruction* instr);
76 void PrintFd(Instruction* instr);
77 void PrintSa(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 void PrintLsaSa(Instruction* instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089 void PrintPCImm16(Instruction* instr, int delta_pc, int n_bits);
90 void PrintXImm18(Instruction* instr);
91 void PrintSImm18(Instruction* instr);
92 void PrintXImm19(Instruction* instr);
93 void PrintSImm19(Instruction* instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094 void PrintXImm21(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 void PrintSImm21(Instruction* instr);
96 void PrintPCImm21(Instruction* instr, int delta_pc, int n_bits);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000097 void PrintXImm26(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 void PrintSImm26(Instruction* instr);
99 void PrintPCImm26(Instruction* instr, int delta_pc, int n_bits);
100 void PrintPCImm26(Instruction* instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101 void PrintCode(Instruction* instr); // For break and trap instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 void PrintFormat(Instruction* instr); // For floating format postfix.
103 void PrintBp2(Instruction* instr);
104 void PrintBp3(Instruction* instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 // Printing of instruction name.
106 void PrintInstructionName(Instruction* instr);
107
108 // Handle formatting of instructions and their options.
109 int FormatRegister(Instruction* instr, const char* option);
110 int FormatFPURegister(Instruction* instr, const char* option);
111 int FormatOption(Instruction* instr, const char* option);
112 void Format(Instruction* instr, const char* format);
113 void Unknown(Instruction* instr);
114 int DecodeBreakInstr(Instruction* instr);
115
116 // Each of these functions decodes one particular instruction type.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 bool DecodeTypeRegisterRsType(Instruction* instr);
118 void DecodeTypeRegisterSRsType(Instruction* instr);
119 void DecodeTypeRegisterDRsType(Instruction* instr);
120 void DecodeTypeRegisterLRsType(Instruction* instr);
121 void DecodeTypeRegisterWRsType(Instruction* instr);
122 void DecodeTypeRegisterSPECIAL(Instruction* instr);
123 void DecodeTypeRegisterSPECIAL2(Instruction* instr);
124 void DecodeTypeRegisterSPECIAL3(Instruction* instr);
125 void DecodeTypeRegisterCOP1(Instruction* instr);
126 void DecodeTypeRegisterCOP1X(Instruction* instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 int DecodeTypeRegister(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128
129 void DecodeTypeImmediateCOP1(Instruction* instr);
130 void DecodeTypeImmediateREGIMM(Instruction* instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131 void DecodeTypeImmediate(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 void DecodeTypeJump(Instruction* instr);
134
135 const disasm::NameConverter& converter_;
136 v8::internal::Vector<char> out_buffer_;
137 int out_buffer_pos_;
138
139 DISALLOW_COPY_AND_ASSIGN(Decoder);
140};
141
142
143// Support for assertions in the Decoder formatting functions.
144#define STRING_STARTS_WITH(string, compare_string) \
145 (strncmp(string, compare_string, strlen(compare_string)) == 0)
146
147
148// Append the ch to the output buffer.
149void Decoder::PrintChar(const char ch) {
150 out_buffer_[out_buffer_pos_++] = ch;
151}
152
153
154// Append the str to the output buffer.
155void Decoder::Print(const char* str) {
156 char cur = *str++;
157 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
158 PrintChar(cur);
159 cur = *str++;
160 }
161 out_buffer_[out_buffer_pos_] = 0;
162}
163
164
165// Print the register name according to the active name converter.
166void Decoder::PrintRegister(int reg) {
167 Print(converter_.NameOfCPURegister(reg));
168}
169
170
171void Decoder::PrintRs(Instruction* instr) {
172 int reg = instr->RsValue();
173 PrintRegister(reg);
174}
175
176
177void Decoder::PrintRt(Instruction* instr) {
178 int reg = instr->RtValue();
179 PrintRegister(reg);
180}
181
182
183void Decoder::PrintRd(Instruction* instr) {
184 int reg = instr->RdValue();
185 PrintRegister(reg);
186}
187
188
189// Print the FPUregister name according to the active name converter.
190void Decoder::PrintFPURegister(int freg) {
191 Print(converter_.NameOfXMMRegister(freg));
192}
193
194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195void Decoder::PrintFPUStatusRegister(int freg) {
196 switch (freg) {
197 case kFCSRRegister:
198 Print("FCSR");
199 break;
200 default:
201 Print(converter_.NameOfXMMRegister(freg));
202 }
203}
204
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206void Decoder::PrintFs(Instruction* instr) {
207 int freg = instr->RsValue();
208 PrintFPURegister(freg);
209}
210
211
212void Decoder::PrintFt(Instruction* instr) {
213 int freg = instr->RtValue();
214 PrintFPURegister(freg);
215}
216
217
218void Decoder::PrintFd(Instruction* instr) {
219 int freg = instr->RdValue();
220 PrintFPURegister(freg);
221}
222
223
224// Print the integer value of the sa field.
225void Decoder::PrintSa(Instruction* instr) {
226 int sa = instr->SaValue();
227 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
228}
229
230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231// Print the integer value of the sa field of a lsa instruction.
232void Decoder::PrintLsaSa(Instruction* instr) {
233 int sa = instr->LsaSaValue() + 1;
234 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
235}
236
237
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238// Print the integer value of the rd field, when it is not used as reg.
239void Decoder::PrintSd(Instruction* instr) {
240 int sd = instr->RdValue();
241 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd);
242}
243
244
245// Print the integer value of the rd field, when used as 'ext' size.
246void Decoder::PrintSs1(Instruction* instr) {
247 int ss = instr->RdValue();
248 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1);
249}
250
251
252// Print the integer value of the rd field, when used as 'ins' size.
253void Decoder::PrintSs2(Instruction* instr) {
254 int ss = instr->RdValue();
255 int pos = instr->SaValue();
256 out_buffer_pos_ +=
257 SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1);
258}
259
260
261// Print the integer value of the cc field for the bc1t/f instructions.
262void Decoder::PrintBc(Instruction* instr) {
263 int cc = instr->FBccValue();
264 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc);
265}
266
267
268// Print the integer value of the cc field for the FP compare instructions.
269void Decoder::PrintCc(Instruction* instr) {
270 int cc = instr->FCccValue();
271 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc);
272}
273
274
275// Print 16-bit unsigned immediate value.
276void Decoder::PrintUImm16(Instruction* instr) {
277 int32_t imm = instr->Imm16Value();
278 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
279}
280
281
282// Print 16-bit signed immediate value.
283void Decoder::PrintSImm16(Instruction* instr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284 int32_t imm =
285 ((instr->Imm16Value()) << (32 - kImm16Bits)) >> (32 - kImm16Bits);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
287}
288
289
290// Print 16-bit hexa immediate value.
291void Decoder::PrintXImm16(Instruction* instr) {
292 int32_t imm = instr->Imm16Value();
293 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
294}
295
296
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297// Print absoulte address for 16-bit offset or immediate value.
298// The absolute address is calculated according following expression:
299// PC + delta_pc + (offset << n_bits)
300void Decoder::PrintPCImm16(Instruction* instr, int delta_pc, int n_bits) {
301 int16_t offset = instr->Imm16Value();
302 out_buffer_pos_ +=
303 SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
304 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
305 delta_pc + (offset << n_bits)));
306}
307
308
309// Print 18-bit signed immediate value.
310void Decoder::PrintSImm18(Instruction* instr) {
311 int32_t imm =
312 ((instr->Imm18Value()) << (32 - kImm18Bits)) >> (32 - kImm18Bits);
313 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
314}
315
316
317// Print 18-bit hexa immediate value.
318void Decoder::PrintXImm18(Instruction* instr) {
319 int32_t imm = instr->Imm18Value();
320 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
321}
322
323
324// Print 19-bit hexa immediate value.
325void Decoder::PrintXImm19(Instruction* instr) {
326 int32_t imm = instr->Imm19Value();
327 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
328}
329
330
331// Print 19-bit signed immediate value.
332void Decoder::PrintSImm19(Instruction* instr) {
333 int32_t imm19 = instr->Imm19Value();
334 // set sign
335 imm19 <<= (32 - kImm19Bits);
336 imm19 >>= (32 - kImm19Bits);
337 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm19);
338}
339
340
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341// Print 21-bit immediate value.
342void Decoder::PrintXImm21(Instruction* instr) {
343 uint32_t imm = instr->Imm21Value();
344 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
345}
346
347
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348// Print 21-bit signed immediate value.
349void Decoder::PrintSImm21(Instruction* instr) {
350 int32_t imm21 = instr->Imm21Value();
351 // set sign
352 imm21 <<= (32 - kImm21Bits);
353 imm21 >>= (32 - kImm21Bits);
354 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm21);
355}
356
357
358// Print absoulte address for 21-bit offset or immediate value.
359// The absolute address is calculated according following expression:
360// PC + delta_pc + (offset << n_bits)
361void Decoder::PrintPCImm21(Instruction* instr, int delta_pc, int n_bits) {
362 int32_t imm21 = instr->Imm21Value();
363 // set sign
364 imm21 <<= (32 - kImm21Bits);
365 imm21 >>= (32 - kImm21Bits);
366 out_buffer_pos_ +=
367 SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
368 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
369 delta_pc + (imm21 << n_bits)));
370}
371
372
373// Print 26-bit hex immediate value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374void Decoder::PrintXImm26(Instruction* instr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 uint64_t target = static_cast<uint64_t>(instr->Imm26Value())
376 << kImmFieldShift;
377 target = (reinterpret_cast<uint64_t>(instr) & ~0xfffffff) | target;
Ben Murdochc5610432016-08-08 18:44:38 +0100378 out_buffer_pos_ +=
379 SNPrintF(out_buffer_ + out_buffer_pos_, "0x%" PRIx64, target);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380}
381
382
383// Print 26-bit signed immediate value.
384void Decoder::PrintSImm26(Instruction* instr) {
385 int32_t imm26 = instr->Imm26Value();
386 // set sign
387 imm26 <<= (32 - kImm26Bits);
388 imm26 >>= (32 - kImm26Bits);
389 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm26);
390}
391
392
393// Print absoulte address for 26-bit offset or immediate value.
394// The absolute address is calculated according following expression:
395// PC + delta_pc + (offset << n_bits)
396void Decoder::PrintPCImm26(Instruction* instr, int delta_pc, int n_bits) {
397 int32_t imm26 = instr->Imm26Value();
398 // set sign
399 imm26 <<= (32 - kImm26Bits);
400 imm26 >>= (32 - kImm26Bits);
401 out_buffer_pos_ +=
402 SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
403 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
404 delta_pc + (imm26 << n_bits)));
405}
406
407
408// Print absoulte address for 26-bit offset or immediate value.
409// The absolute address is calculated according following expression:
410// PC[GPRLEN-1 .. 28] || instr_index26 || 00
411void Decoder::PrintPCImm26(Instruction* instr) {
412 int32_t imm26 = instr->Imm26Value();
413 uint64_t pc_mask = ~0xfffffff;
414 uint64_t pc = ((uint64_t)(instr + 1) & pc_mask) | (imm26 << 2);
415 out_buffer_pos_ +=
416 SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
417 converter_.NameOfAddress((reinterpret_cast<byte*>(pc))));
418}
419
420
421void Decoder::PrintBp2(Instruction* instr) {
422 int bp2 = instr->Bp2Value();
423 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", bp2);
424}
425
426
427void Decoder::PrintBp3(Instruction* instr) {
428 int bp3 = instr->Bp3Value();
429 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", bp3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430}
431
432
433// Print 26-bit immediate value.
434void Decoder::PrintCode(Instruction* instr) {
435 if (instr->OpcodeFieldRaw() != SPECIAL)
436 return; // Not a break or trap instruction.
437 switch (instr->FunctionFieldRaw()) {
438 case BREAK: {
439 int32_t code = instr->Bits(25, 6);
440 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
441 "0x%05x (%d)", code, code);
442 break;
443 }
444 case TGE:
445 case TGEU:
446 case TLT:
447 case TLTU:
448 case TEQ:
449 case TNE: {
450 int32_t code = instr->Bits(15, 6);
451 out_buffer_pos_ +=
452 SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
453 break;
454 }
455 default: // Not a break or trap instruction.
456 break;
457 }
458}
459
460
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461void Decoder::PrintFormat(Instruction* instr) {
462 char formatLetter = ' ';
463 switch (instr->RsFieldRaw()) {
464 case S:
465 formatLetter = 's';
466 break;
467 case D:
468 formatLetter = 'd';
469 break;
470 case W:
471 formatLetter = 'w';
472 break;
473 case L:
474 formatLetter = 'l';
475 break;
476 default:
477 UNREACHABLE();
478 break;
479 }
480 PrintChar(formatLetter);
481}
482
483
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000484// Printing of instruction name.
485void Decoder::PrintInstructionName(Instruction* instr) {
486}
487
488
489// Handle all register based formatting in this function to reduce the
490// complexity of FormatOption.
491int Decoder::FormatRegister(Instruction* instr, const char* format) {
492 DCHECK(format[0] == 'r');
493 if (format[1] == 's') { // 'rs: Rs register.
494 int reg = instr->RsValue();
495 PrintRegister(reg);
496 return 2;
497 } else if (format[1] == 't') { // 'rt: rt register.
498 int reg = instr->RtValue();
499 PrintRegister(reg);
500 return 2;
501 } else if (format[1] == 'd') { // 'rd: rd register.
502 int reg = instr->RdValue();
503 PrintRegister(reg);
504 return 2;
505 }
506 UNREACHABLE();
507 return -1;
508}
509
510
511// Handle all FPUregister based formatting in this function to reduce the
512// complexity of FormatOption.
513int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
514 DCHECK(format[0] == 'f');
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 if ((CTC1 == instr->RsFieldRaw()) || (CFC1 == instr->RsFieldRaw())) {
516 if (format[1] == 's') { // 'fs: fs register.
517 int reg = instr->FsValue();
518 PrintFPUStatusRegister(reg);
519 return 2;
520 } else if (format[1] == 't') { // 'ft: ft register.
521 int reg = instr->FtValue();
522 PrintFPUStatusRegister(reg);
523 return 2;
524 } else if (format[1] == 'd') { // 'fd: fd register.
525 int reg = instr->FdValue();
526 PrintFPUStatusRegister(reg);
527 return 2;
528 } else if (format[1] == 'r') { // 'fr: fr register.
529 int reg = instr->FrValue();
530 PrintFPUStatusRegister(reg);
531 return 2;
532 }
533 } else {
534 if (format[1] == 's') { // 'fs: fs register.
535 int reg = instr->FsValue();
536 PrintFPURegister(reg);
537 return 2;
538 } else if (format[1] == 't') { // 'ft: ft register.
539 int reg = instr->FtValue();
540 PrintFPURegister(reg);
541 return 2;
542 } else if (format[1] == 'd') { // 'fd: fd register.
543 int reg = instr->FdValue();
544 PrintFPURegister(reg);
545 return 2;
546 } else if (format[1] == 'r') { // 'fr: fr register.
547 int reg = instr->FrValue();
548 PrintFPURegister(reg);
549 return 2;
550 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551 }
552 UNREACHABLE();
553 return -1;
554}
555
556
557// FormatOption takes a formatting string and interprets it based on
558// the current instructions. The format string points to the first
559// character of the option string (the option escape has already been
560// consumed by the caller.) FormatOption returns the number of
561// characters that were consumed from the formatting string.
562int Decoder::FormatOption(Instruction* instr, const char* format) {
563 switch (format[0]) {
564 case 'c': { // 'code for break or trap instructions.
565 DCHECK(STRING_STARTS_WITH(format, "code"));
566 PrintCode(instr);
567 return 4;
568 }
569 case 'i': { // 'imm16u or 'imm26.
570 if (format[3] == '1') {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571 if (format[4] == '6') {
572 DCHECK(STRING_STARTS_WITH(format, "imm16"));
573 switch (format[5]) {
574 case 's':
575 DCHECK(STRING_STARTS_WITH(format, "imm16s"));
576 PrintSImm16(instr);
577 break;
578 case 'u':
579 DCHECK(STRING_STARTS_WITH(format, "imm16u"));
580 PrintSImm16(instr);
581 break;
582 case 'x':
583 DCHECK(STRING_STARTS_WITH(format, "imm16x"));
584 PrintXImm16(instr);
585 break;
586 case 'p': { // The PC relative address.
587 DCHECK(STRING_STARTS_WITH(format, "imm16p"));
588 int delta_pc = 0;
589 int n_bits = 0;
590 switch (format[6]) {
591 case '4': {
592 DCHECK(STRING_STARTS_WITH(format, "imm16p4"));
593 delta_pc = 4;
594 switch (format[8]) {
595 case '2':
596 DCHECK(STRING_STARTS_WITH(format, "imm16p4s2"));
597 n_bits = 2;
598 PrintPCImm16(instr, delta_pc, n_bits);
599 return 9;
600 }
601 }
602 }
603 }
604 }
605 return 6;
606 } else if (format[4] == '8') {
607 DCHECK(STRING_STARTS_WITH(format, "imm18"));
608 switch (format[5]) {
609 case 's':
610 DCHECK(STRING_STARTS_WITH(format, "imm18s"));
611 PrintSImm18(instr);
612 break;
613 case 'x':
614 DCHECK(STRING_STARTS_WITH(format, "imm18x"));
615 PrintXImm18(instr);
616 break;
617 }
618 return 6;
619 } else if (format[4] == '9') {
620 DCHECK(STRING_STARTS_WITH(format, "imm19"));
621 switch (format[5]) {
622 case 's':
623 DCHECK(STRING_STARTS_WITH(format, "imm19s"));
624 PrintSImm19(instr);
625 break;
626 case 'x':
627 DCHECK(STRING_STARTS_WITH(format, "imm19x"));
628 PrintXImm19(instr);
629 break;
630 }
631 return 6;
632 }
633 } else if (format[3] == '2' && format[4] == '1') {
634 DCHECK(STRING_STARTS_WITH(format, "imm21"));
635 switch (format[5]) {
636 case 's':
637 DCHECK(STRING_STARTS_WITH(format, "imm21s"));
638 PrintSImm21(instr);
639 break;
640 case 'x':
641 DCHECK(STRING_STARTS_WITH(format, "imm21x"));
642 PrintXImm21(instr);
643 break;
644 case 'p': { // The PC relative address.
645 DCHECK(STRING_STARTS_WITH(format, "imm21p"));
646 int delta_pc = 0;
647 int n_bits = 0;
648 switch (format[6]) {
649 case '4': {
650 DCHECK(STRING_STARTS_WITH(format, "imm21p4"));
651 delta_pc = 4;
652 switch (format[8]) {
653 case '2':
654 DCHECK(STRING_STARTS_WITH(format, "imm21p4s2"));
655 n_bits = 2;
656 PrintPCImm21(instr, delta_pc, n_bits);
657 return 9;
658 }
659 }
660 }
661 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662 }
663 return 6;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000664 } else if (format[3] == '2' && format[4] == '6') {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000665 DCHECK(STRING_STARTS_WITH(format, "imm26"));
666 switch (format[5]) {
667 case 's':
668 DCHECK(STRING_STARTS_WITH(format, "imm26s"));
669 PrintSImm26(instr);
670 break;
671 case 'x':
672 DCHECK(STRING_STARTS_WITH(format, "imm26x"));
673 PrintXImm26(instr);
674 break;
675 case 'p': { // The PC relative address.
676 DCHECK(STRING_STARTS_WITH(format, "imm26p"));
677 int delta_pc = 0;
678 int n_bits = 0;
679 switch (format[6]) {
680 case '4': {
681 DCHECK(STRING_STARTS_WITH(format, "imm26p4"));
682 delta_pc = 4;
683 switch (format[8]) {
684 case '2':
685 DCHECK(STRING_STARTS_WITH(format, "imm26p4s2"));
686 n_bits = 2;
687 PrintPCImm26(instr, delta_pc, n_bits);
688 return 9;
689 }
690 }
691 }
692 }
693 case 'j': { // Absolute address for jump instructions.
694 DCHECK(STRING_STARTS_WITH(format, "imm26j"));
695 PrintPCImm26(instr);
696 break;
697 }
698 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 return 6;
700 }
701 }
702 case 'r': { // 'r: registers.
703 return FormatRegister(instr, format);
704 }
705 case 'f': { // 'f: FPUregisters.
706 return FormatFPURegister(instr, format);
707 }
708 case 's': { // 'sa.
709 switch (format[1]) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000710 case 'a':
711 if (format[2] == '2') {
712 DCHECK(STRING_STARTS_WITH(format, "sa2")); // 'sa2
713 PrintLsaSa(instr);
714 return 3;
715 } else {
716 DCHECK(STRING_STARTS_WITH(format, "sa"));
717 PrintSa(instr);
718 return 2;
719 }
720 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721 case 'd': {
722 DCHECK(STRING_STARTS_WITH(format, "sd"));
723 PrintSd(instr);
724 return 2;
725 }
726 case 's': {
727 if (format[2] == '1') {
728 DCHECK(STRING_STARTS_WITH(format, "ss1")); /* ext size */
729 PrintSs1(instr);
730 return 3;
731 } else {
732 DCHECK(STRING_STARTS_WITH(format, "ss2")); /* ins size */
733 PrintSs2(instr);
734 return 3;
735 }
736 }
737 }
738 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000739 case 'b': {
740 switch (format[1]) {
741 case 'c': { // 'bc - Special for bc1 cc field.
742 DCHECK(STRING_STARTS_WITH(format, "bc"));
743 PrintBc(instr);
744 return 2;
745 }
746 case 'p': {
747 switch (format[2]) {
748 case '2': { // 'bp2
749 DCHECK(STRING_STARTS_WITH(format, "bp2"));
750 PrintBp2(instr);
751 return 3;
752 }
753 case '3': { // 'bp3
754 DCHECK(STRING_STARTS_WITH(format, "bp3"));
755 PrintBp3(instr);
756 return 3;
757 }
758 }
759 }
760 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 }
762 case 'C': { // 'Cc - Special for c.xx.d cc field.
763 DCHECK(STRING_STARTS_WITH(format, "Cc"));
764 PrintCc(instr);
765 return 2;
766 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767 case 't':
768 PrintFormat(instr);
769 return 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770 }
771 UNREACHABLE();
772 return -1;
773}
774
775
776// Format takes a formatting string for a whole instruction and prints it into
777// the output buffer. All escaped options are handed to FormatOption to be
778// parsed further.
779void Decoder::Format(Instruction* instr, const char* format) {
780 char cur = *format++;
781 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
782 if (cur == '\'') { // Single quote is used as the formatting escape.
783 format += FormatOption(instr, format);
784 } else {
785 out_buffer_[out_buffer_pos_++] = cur;
786 }
787 cur = *format++;
788 }
789 out_buffer_[out_buffer_pos_] = '\0';
790}
791
792
793// For currently unimplemented decodings the disassembler calls Unknown(instr)
794// which will just print "unknown" of the instruction bits.
795void Decoder::Unknown(Instruction* instr) {
796 Format(instr, "unknown");
797}
798
799
800int Decoder::DecodeBreakInstr(Instruction* instr) {
801 // This is already known to be BREAK instr, just extract the code.
802 if (instr->Bits(25, 6) == static_cast<int>(kMaxStopCode)) {
803 // This is stop(msg).
804 Format(instr, "break, code: 'code");
Ben Murdochc5610432016-08-08 18:44:38 +0100805 out_buffer_pos_ += SNPrintF(
806 out_buffer_ + out_buffer_pos_,
807 "\n%p %08" PRIx64 " stop msg: %s",
808 static_cast<void*>(
809 reinterpret_cast<int32_t*>(instr + Instruction::kInstrSize)),
810 reinterpret_cast<uint64_t>(
811 *reinterpret_cast<char**>(instr + Instruction::kInstrSize)),
812 *reinterpret_cast<char**>(instr + Instruction::kInstrSize));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000813 // Size 3: the break_ instr, plus embedded 64-bit char pointer.
814 return 3 * Instruction::kInstrSize;
815 } else {
816 Format(instr, "break, code: 'code");
817 return Instruction::kInstrSize;
818 }
819}
820
821
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000822bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
823 switch (instr->FunctionFieldRaw()) {
824 case RINT:
825 Format(instr, "rint.'t 'fd, 'fs");
826 break;
827 case SEL:
828 Format(instr, "sel.'t 'fd, 'fs, 'ft");
829 break;
830 case SELEQZ_C:
831 Format(instr, "seleqz.'t 'fd, 'fs, 'ft");
832 break;
833 case SELNEZ_C:
834 Format(instr, "selnez.'t 'fd, 'fs, 'ft");
835 break;
836 case MOVZ_C:
837 Format(instr, "movz.'t 'fd, 'fs, 'rt");
838 break;
839 case MOVN_C:
840 Format(instr, "movn.'t 'fd, 'fs, 'rt");
841 break;
842 case MOVF:
843 if (instr->Bit(16)) {
844 Format(instr, "movt.'t 'fd, 'fs, 'Cc");
845 } else {
846 Format(instr, "movf.'t 'fd, 'fs, 'Cc");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 }
848 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 case MIN:
850 Format(instr, "min.'t 'fd, 'fs, 'ft");
851 break;
852 case MAX:
853 Format(instr, "max.'t 'fd, 'fs, 'ft");
854 break;
855 case MINA:
856 Format(instr, "mina.'t 'fd, 'fs, 'ft");
857 break;
858 case MAXA:
859 Format(instr, "maxa.'t 'fd, 'fs, 'ft");
860 break;
861 case ADD_D:
862 Format(instr, "add.'t 'fd, 'fs, 'ft");
863 break;
864 case SUB_D:
865 Format(instr, "sub.'t 'fd, 'fs, 'ft");
866 break;
867 case MUL_D:
868 Format(instr, "mul.'t 'fd, 'fs, 'ft");
869 break;
870 case DIV_D:
871 Format(instr, "div.'t 'fd, 'fs, 'ft");
872 break;
873 case ABS_D:
874 Format(instr, "abs.'t 'fd, 'fs");
875 break;
876 case MOV_D:
877 Format(instr, "mov.'t 'fd, 'fs");
878 break;
879 case NEG_D:
880 Format(instr, "neg.'t 'fd, 'fs");
881 break;
882 case SQRT_D:
883 Format(instr, "sqrt.'t 'fd, 'fs");
884 break;
885 case RECIP_D:
886 Format(instr, "recip.'t 'fd, 'fs");
887 break;
888 case RSQRT_D:
889 Format(instr, "rsqrt.'t 'fd, 'fs");
890 break;
891 case CVT_W_D:
892 Format(instr, "cvt.w.'t 'fd, 'fs");
893 break;
894 case CVT_L_D:
895 Format(instr, "cvt.l.'t 'fd, 'fs");
896 break;
897 case TRUNC_W_D:
898 Format(instr, "trunc.w.'t 'fd, 'fs");
899 break;
900 case TRUNC_L_D:
901 Format(instr, "trunc.l.'t 'fd, 'fs");
902 break;
903 case ROUND_W_D:
904 Format(instr, "round.w.'t 'fd, 'fs");
905 break;
906 case ROUND_L_D:
907 Format(instr, "round.l.'t 'fd, 'fs");
908 break;
909 case FLOOR_W_D:
910 Format(instr, "floor.w.'t 'fd, 'fs");
911 break;
912 case FLOOR_L_D:
913 Format(instr, "floor.l.'t 'fd, 'fs");
914 break;
915 case CEIL_W_D:
916 Format(instr, "ceil.w.'t 'fd, 'fs");
917 break;
918 case CEIL_L_D:
919 Format(instr, "ceil.l.'t 'fd, 'fs");
920 break;
921 case CLASS_D:
922 Format(instr, "class.'t 'fd, 'fs");
923 break;
924 case CVT_S_D:
925 Format(instr, "cvt.s.'t 'fd, 'fs");
926 break;
927 case C_F_D:
928 Format(instr, "c.f.'t 'fs, 'ft, 'Cc");
929 break;
930 case C_UN_D:
931 Format(instr, "c.un.'t 'fs, 'ft, 'Cc");
932 break;
933 case C_EQ_D:
934 Format(instr, "c.eq.'t 'fs, 'ft, 'Cc");
935 break;
936 case C_UEQ_D:
937 Format(instr, "c.ueq.'t 'fs, 'ft, 'Cc");
938 break;
939 case C_OLT_D:
940 Format(instr, "c.olt.'t 'fs, 'ft, 'Cc");
941 break;
942 case C_ULT_D:
943 Format(instr, "c.ult.'t 'fs, 'ft, 'Cc");
944 break;
945 case C_OLE_D:
946 Format(instr, "c.ole.'t 'fs, 'ft, 'Cc");
947 break;
948 case C_ULE_D:
949 Format(instr, "c.ule.'t 'fs, 'ft, 'Cc");
950 break;
951 default:
952 return false;
953 }
954 return true;
955}
956
957
958void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
959 if (!DecodeTypeRegisterRsType(instr)) {
960 switch (instr->FunctionFieldRaw()) {
961 case CVT_D_S:
962 Format(instr, "cvt.d.'t 'fd, 'fs");
963 break;
964 default:
965 Format(instr, "unknown.cop1.'t");
966 break;
967 }
968 }
969}
970
971
972void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) {
973 if (!DecodeTypeRegisterRsType(instr)) {
974 Format(instr, "unknown.cop1.'t");
975 }
976}
977
978
979void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) {
980 switch (instr->FunctionFieldRaw()) {
981 case CVT_D_L:
982 Format(instr, "cvt.d.l 'fd, 'fs");
983 break;
984 case CVT_S_L:
985 Format(instr, "cvt.s.l 'fd, 'fs");
986 break;
987 case CMP_AF:
988 Format(instr, "cmp.af.d 'fd, 'fs, 'ft");
989 break;
990 case CMP_UN:
991 Format(instr, "cmp.un.d 'fd, 'fs, 'ft");
992 break;
993 case CMP_EQ:
994 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft");
995 break;
996 case CMP_UEQ:
997 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft");
998 break;
999 case CMP_LT:
1000 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft");
1001 break;
1002 case CMP_ULT:
1003 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft");
1004 break;
1005 case CMP_LE:
1006 Format(instr, "cmp.le.d 'fd, 'fs, 'ft");
1007 break;
1008 case CMP_ULE:
1009 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft");
1010 break;
1011 case CMP_OR:
1012 Format(instr, "cmp.or.d 'fd, 'fs, 'ft");
1013 break;
1014 case CMP_UNE:
1015 Format(instr, "cmp.une.d 'fd, 'fs, 'ft");
1016 break;
1017 case CMP_NE:
1018 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft");
1019 break;
1020 default:
1021 UNREACHABLE();
1022 }
1023}
1024
1025
1026void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) {
1027 switch (instr->FunctionValue()) {
1028 case CVT_S_W: // Convert word to float (single).
1029 Format(instr, "cvt.s.w 'fd, 'fs");
1030 break;
1031 case CVT_D_W: // Convert word to double.
1032 Format(instr, "cvt.d.w 'fd, 'fs");
1033 break;
1034 case CMP_AF:
1035 Format(instr, "cmp.af.s 'fd, 'fs, 'ft");
1036 break;
1037 case CMP_UN:
1038 Format(instr, "cmp.un.s 'fd, 'fs, 'ft");
1039 break;
1040 case CMP_EQ:
1041 Format(instr, "cmp.eq.s 'fd, 'fs, 'ft");
1042 break;
1043 case CMP_UEQ:
1044 Format(instr, "cmp.ueq.s 'fd, 'fs, 'ft");
1045 break;
1046 case CMP_LT:
1047 Format(instr, "cmp.lt.s 'fd, 'fs, 'ft");
1048 break;
1049 case CMP_ULT:
1050 Format(instr, "cmp.ult.s 'fd, 'fs, 'ft");
1051 break;
1052 case CMP_LE:
1053 Format(instr, "cmp.le.s 'fd, 'fs, 'ft");
1054 break;
1055 case CMP_ULE:
1056 Format(instr, "cmp.ule.s 'fd, 'fs, 'ft");
1057 break;
1058 case CMP_OR:
1059 Format(instr, "cmp.or.s 'fd, 'fs, 'ft");
1060 break;
1061 case CMP_UNE:
1062 Format(instr, "cmp.une.s 'fd, 'fs, 'ft");
1063 break;
1064 case CMP_NE:
1065 Format(instr, "cmp.ne.s 'fd, 'fs, 'ft");
1066 break;
1067 default:
1068 UNREACHABLE();
1069 }
1070}
1071
1072
1073void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) {
1074 switch (instr->RsFieldRaw()) {
1075 case MFC1:
1076 Format(instr, "mfc1 'rt, 'fs");
1077 break;
1078 case DMFC1:
1079 Format(instr, "dmfc1 'rt, 'fs");
1080 break;
1081 case MFHC1:
1082 Format(instr, "mfhc1 'rt, 'fs");
1083 break;
1084 case MTC1:
1085 Format(instr, "mtc1 'rt, 'fs");
1086 break;
1087 case DMTC1:
1088 Format(instr, "dmtc1 'rt, 'fs");
1089 break;
1090 // These are called "fs" too, although they are not FPU registers.
1091 case CTC1:
1092 Format(instr, "ctc1 'rt, 'fs");
1093 break;
1094 case CFC1:
1095 Format(instr, "cfc1 'rt, 'fs");
1096 break;
1097 case MTHC1:
1098 Format(instr, "mthc1 'rt, 'fs");
1099 break;
1100 case S:
1101 DecodeTypeRegisterSRsType(instr);
1102 break;
1103 case D:
1104 DecodeTypeRegisterDRsType(instr);
1105 break;
1106 case W:
1107 DecodeTypeRegisterWRsType(instr);
1108 break;
1109 case L:
1110 DecodeTypeRegisterLRsType(instr);
1111 break;
1112 default:
1113 UNREACHABLE();
1114 }
1115}
1116
1117
1118void Decoder::DecodeTypeRegisterCOP1X(Instruction* instr) {
1119 switch (instr->FunctionFieldRaw()) {
1120 case MADD_D:
1121 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
1122 break;
1123 default:
1124 UNREACHABLE();
1125 }
1126}
1127
1128
1129void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
1130 switch (instr->FunctionFieldRaw()) {
1131 case JR:
1132 Format(instr, "jr 'rs");
1133 break;
1134 case JALR:
1135 Format(instr, "jalr 'rs, 'rd");
1136 break;
1137 case SLL:
1138 if (0x0 == static_cast<int>(instr->InstructionBits()))
1139 Format(instr, "nop");
1140 else
1141 Format(instr, "sll 'rd, 'rt, 'sa");
1142 break;
1143 case DSLL:
1144 Format(instr, "dsll 'rd, 'rt, 'sa");
1145 break;
1146 case D_MUL_MUH: // Equals to DMUL.
1147 if (kArchVariant != kMips64r6) {
1148 Format(instr, "dmult 'rs, 'rt");
1149 } else {
1150 if (instr->SaValue() == MUL_OP) {
1151 Format(instr, "dmul 'rd, 'rs, 'rt");
1152 } else {
1153 Format(instr, "dmuh 'rd, 'rs, 'rt");
1154 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155 }
1156 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157 case DSLL32:
1158 Format(instr, "dsll32 'rd, 'rt, 'sa");
1159 break;
1160 case SRL:
1161 if (instr->RsValue() == 0) {
1162 Format(instr, "srl 'rd, 'rt, 'sa");
1163 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001164 Format(instr, "rotr 'rd, 'rt, 'sa");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001165 }
1166 break;
1167 case DSRL:
1168 if (instr->RsValue() == 0) {
1169 Format(instr, "dsrl 'rd, 'rt, 'sa");
1170 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001171 Format(instr, "drotr 'rd, 'rt, 'sa");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001172 }
1173 break;
1174 case DSRL32:
Ben Murdochc5610432016-08-08 18:44:38 +01001175 if (instr->RsValue() == 0) {
1176 Format(instr, "dsrl32 'rd, 'rt, 'sa");
1177 } else {
1178 Format(instr, "drotr32 'rd, 'rt, 'sa");
1179 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 break;
1181 case SRA:
1182 Format(instr, "sra 'rd, 'rt, 'sa");
1183 break;
1184 case DSRA:
1185 Format(instr, "dsra 'rd, 'rt, 'sa");
1186 break;
1187 case DSRA32:
1188 Format(instr, "dsra32 'rd, 'rt, 'sa");
1189 break;
1190 case SLLV:
1191 Format(instr, "sllv 'rd, 'rt, 'rs");
1192 break;
1193 case DSLLV:
1194 Format(instr, "dsllv 'rd, 'rt, 'rs");
1195 break;
1196 case SRLV:
1197 if (instr->SaValue() == 0) {
1198 Format(instr, "srlv 'rd, 'rt, 'rs");
1199 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001200 Format(instr, "rotrv 'rd, 'rt, 'rs");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001201 }
1202 break;
1203 case DSRLV:
1204 if (instr->SaValue() == 0) {
1205 Format(instr, "dsrlv 'rd, 'rt, 'rs");
1206 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001207 Format(instr, "drotrv 'rd, 'rt, 'rs");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001208 }
1209 break;
1210 case SRAV:
1211 Format(instr, "srav 'rd, 'rt, 'rs");
1212 break;
1213 case DSRAV:
1214 Format(instr, "dsrav 'rd, 'rt, 'rs");
1215 break;
1216 case LSA:
1217 Format(instr, "lsa 'rd, 'rt, 'rs, 'sa2");
1218 break;
1219 case DLSA:
1220 Format(instr, "dlsa 'rd, 'rt, 'rs, 'sa2");
1221 break;
1222 case MFHI:
1223 if (instr->Bits(25, 16) == 0) {
1224 Format(instr, "mfhi 'rd");
1225 } else {
1226 if ((instr->FunctionFieldRaw() == CLZ_R6) && (instr->FdValue() == 1)) {
1227 Format(instr, "clz 'rd, 'rs");
1228 } else if ((instr->FunctionFieldRaw() == CLO_R6) &&
1229 (instr->FdValue() == 1)) {
1230 Format(instr, "clo 'rd, 'rs");
1231 }
1232 }
1233 break;
1234 case MFLO:
1235 if (instr->Bits(25, 16) == 0) {
1236 Format(instr, "mflo 'rd");
1237 } else {
1238 if ((instr->FunctionFieldRaw() == DCLZ_R6) && (instr->FdValue() == 1)) {
1239 Format(instr, "dclz 'rd, 'rs");
1240 } else if ((instr->FunctionFieldRaw() == DCLO_R6) &&
1241 (instr->FdValue() == 1)) {
1242 Format(instr, "dclo 'rd, 'rs");
1243 }
1244 }
1245 break;
1246 case D_MUL_MUH_U: // Equals to DMULTU.
1247 if (kArchVariant != kMips64r6) {
1248 Format(instr, "dmultu 'rs, 'rt");
1249 } else {
1250 if (instr->SaValue() == MUL_OP) {
1251 Format(instr, "dmulu 'rd, 'rs, 'rt");
1252 } else {
1253 Format(instr, "dmuhu 'rd, 'rs, 'rt");
1254 }
1255 }
1256 break;
1257 case MULT: // @Mips64r6 == MUL_MUH.
1258 if (kArchVariant != kMips64r6) {
1259 Format(instr, "mult 'rs, 'rt");
1260 } else {
1261 if (instr->SaValue() == MUL_OP) {
1262 Format(instr, "mul 'rd, 'rs, 'rt");
1263 } else {
1264 Format(instr, "muh 'rd, 'rs, 'rt");
1265 }
1266 }
1267 break;
1268 case MULTU: // @Mips64r6 == MUL_MUH_U.
1269 if (kArchVariant != kMips64r6) {
1270 Format(instr, "multu 'rs, 'rt");
1271 } else {
1272 if (instr->SaValue() == MUL_OP) {
1273 Format(instr, "mulu 'rd, 'rs, 'rt");
1274 } else {
1275 Format(instr, "muhu 'rd, 'rs, 'rt");
1276 }
1277 }
1278
1279 break;
1280 case DIV: // @Mips64r6 == DIV_MOD.
1281 if (kArchVariant != kMips64r6) {
1282 Format(instr, "div 'rs, 'rt");
1283 } else {
1284 if (instr->SaValue() == DIV_OP) {
1285 Format(instr, "div 'rd, 'rs, 'rt");
1286 } else {
1287 Format(instr, "mod 'rd, 'rs, 'rt");
1288 }
1289 }
1290 break;
1291 case DDIV: // @Mips64r6 == D_DIV_MOD.
1292 if (kArchVariant != kMips64r6) {
1293 Format(instr, "ddiv 'rs, 'rt");
1294 } else {
1295 if (instr->SaValue() == DIV_OP) {
1296 Format(instr, "ddiv 'rd, 'rs, 'rt");
1297 } else {
1298 Format(instr, "dmod 'rd, 'rs, 'rt");
1299 }
1300 }
1301 break;
1302 case DIVU: // @Mips64r6 == DIV_MOD_U.
1303 if (kArchVariant != kMips64r6) {
1304 Format(instr, "divu 'rs, 'rt");
1305 } else {
1306 if (instr->SaValue() == DIV_OP) {
1307 Format(instr, "divu 'rd, 'rs, 'rt");
1308 } else {
1309 Format(instr, "modu 'rd, 'rs, 'rt");
1310 }
1311 }
1312 break;
1313 case DDIVU: // @Mips64r6 == D_DIV_MOD_U.
1314 if (kArchVariant != kMips64r6) {
1315 Format(instr, "ddivu 'rs, 'rt");
1316 } else {
1317 if (instr->SaValue() == DIV_OP) {
1318 Format(instr, "ddivu 'rd, 'rs, 'rt");
1319 } else {
1320 Format(instr, "dmodu 'rd, 'rs, 'rt");
1321 }
1322 }
1323 break;
1324 case ADD:
1325 Format(instr, "add 'rd, 'rs, 'rt");
1326 break;
1327 case DADD:
1328 Format(instr, "dadd 'rd, 'rs, 'rt");
1329 break;
1330 case ADDU:
1331 Format(instr, "addu 'rd, 'rs, 'rt");
1332 break;
1333 case DADDU:
1334 Format(instr, "daddu 'rd, 'rs, 'rt");
1335 break;
1336 case SUB:
1337 Format(instr, "sub 'rd, 'rs, 'rt");
1338 break;
1339 case DSUB:
1340 Format(instr, "dsub 'rd, 'rs, 'rt");
1341 break;
1342 case SUBU:
1343 Format(instr, "subu 'rd, 'rs, 'rt");
1344 break;
1345 case DSUBU:
1346 Format(instr, "dsubu 'rd, 'rs, 'rt");
1347 break;
1348 case AND:
1349 Format(instr, "and 'rd, 'rs, 'rt");
1350 break;
1351 case OR:
1352 if (0 == instr->RsValue()) {
1353 Format(instr, "mov 'rd, 'rt");
1354 } else if (0 == instr->RtValue()) {
1355 Format(instr, "mov 'rd, 'rs");
1356 } else {
1357 Format(instr, "or 'rd, 'rs, 'rt");
1358 }
1359 break;
1360 case XOR:
1361 Format(instr, "xor 'rd, 'rs, 'rt");
1362 break;
1363 case NOR:
1364 Format(instr, "nor 'rd, 'rs, 'rt");
1365 break;
1366 case SLT:
1367 Format(instr, "slt 'rd, 'rs, 'rt");
1368 break;
1369 case SLTU:
1370 Format(instr, "sltu 'rd, 'rs, 'rt");
1371 break;
1372 case TGE:
1373 Format(instr, "tge 'rs, 'rt, code: 'code");
1374 break;
1375 case TGEU:
1376 Format(instr, "tgeu 'rs, 'rt, code: 'code");
1377 break;
1378 case TLT:
1379 Format(instr, "tlt 'rs, 'rt, code: 'code");
1380 break;
1381 case TLTU:
1382 Format(instr, "tltu 'rs, 'rt, code: 'code");
1383 break;
1384 case TEQ:
1385 Format(instr, "teq 'rs, 'rt, code: 'code");
1386 break;
1387 case TNE:
1388 Format(instr, "tne 'rs, 'rt, code: 'code");
1389 break;
Ben Murdochc5610432016-08-08 18:44:38 +01001390 case SYNC:
1391 Format(instr, "sync");
1392 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001393 case MOVZ:
1394 Format(instr, "movz 'rd, 'rs, 'rt");
1395 break;
1396 case MOVN:
1397 Format(instr, "movn 'rd, 'rs, 'rt");
1398 break;
1399 case MOVCI:
1400 if (instr->Bit(16)) {
1401 Format(instr, "movt 'rd, 'rs, 'bc");
1402 } else {
1403 Format(instr, "movf 'rd, 'rs, 'bc");
1404 }
1405 break;
1406 case SELEQZ_S:
1407 Format(instr, "seleqz 'rd, 'rs, 'rt");
1408 break;
1409 case SELNEZ_S:
1410 Format(instr, "selnez 'rd, 'rs, 'rt");
1411 break;
1412 default:
1413 UNREACHABLE();
1414 }
1415}
1416
1417
1418void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) {
1419 switch (instr->FunctionFieldRaw()) {
1420 case MUL:
1421 Format(instr, "mul 'rd, 'rs, 'rt");
1422 break;
1423 case CLZ:
1424 if (kArchVariant != kMips64r6) {
1425 Format(instr, "clz 'rd, 'rs");
1426 }
1427 break;
1428 case DCLZ:
1429 if (kArchVariant != kMips64r6) {
1430 Format(instr, "dclz 'rd, 'rs");
1431 }
1432 break;
1433 default:
1434 UNREACHABLE();
1435 }
1436}
1437
1438
1439void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
1440 switch (instr->FunctionFieldRaw()) {
1441 case INS: {
1442 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
1443 break;
1444 }
1445 case EXT: {
1446 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
1447 break;
1448 }
1449 case DEXT: {
1450 Format(instr, "dext 'rt, 'rs, 'sa, 'ss1");
1451 break;
1452 }
1453 case BSHFL: {
1454 int sa = instr->SaFieldRaw() >> kSaShift;
1455 switch (sa) {
1456 case BITSWAP: {
1457 Format(instr, "bitswap 'rd, 'rt");
1458 break;
1459 }
1460 case SEB:
1461 case SEH:
1462 case WSBH:
1463 UNREACHABLE();
1464 break;
1465 default: {
1466 sa >>= kBp2Bits;
1467 switch (sa) {
1468 case ALIGN: {
1469 Format(instr, "align 'rd, 'rs, 'rt, 'bp2");
1470 break;
1471 }
1472 default:
1473 UNREACHABLE();
1474 break;
1475 }
1476 break;
1477 }
1478 }
1479 break;
1480 }
1481 case DBSHFL: {
1482 int sa = instr->SaFieldRaw() >> kSaShift;
1483 switch (sa) {
1484 case DBITSWAP: {
1485 switch (instr->SaFieldRaw() >> kSaShift) {
1486 case DBITSWAP_SA:
1487 Format(instr, "dbitswap 'rd, 'rt");
1488 break;
1489 default:
1490 UNREACHABLE();
1491 break;
1492 }
1493 break;
1494 }
1495 case DSBH:
1496 case DSHD:
1497 UNREACHABLE();
1498 break;
1499 default: {
1500 sa >>= kBp3Bits;
1501 switch (sa) {
1502 case DALIGN: {
1503 Format(instr, "dalign 'rd, 'rs, 'rt, 'bp3");
1504 break;
1505 }
1506 default:
1507 UNREACHABLE();
1508 break;
1509 }
1510 break;
1511 }
1512 }
1513 break;
1514 }
1515 default:
1516 UNREACHABLE();
1517 }
1518}
1519
1520
1521int Decoder::DecodeTypeRegister(Instruction* instr) {
1522 switch (instr->OpcodeFieldRaw()) {
1523 case COP1: // Coprocessor instructions.
1524 DecodeTypeRegisterCOP1(instr);
1525 break;
1526 case COP1X:
1527 DecodeTypeRegisterCOP1X(instr);
1528 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001529 case SPECIAL:
1530 switch (instr->FunctionFieldRaw()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531 case BREAK:
1532 return DecodeBreakInstr(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001533 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001534 DecodeTypeRegisterSPECIAL(instr);
1535 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001536 }
1537 break;
1538 case SPECIAL2:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001539 DecodeTypeRegisterSPECIAL2(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 break;
1541 case SPECIAL3:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001542 DecodeTypeRegisterSPECIAL3(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001543 break;
1544 default:
1545 UNREACHABLE();
1546 }
1547 return Instruction::kInstrSize;
1548}
1549
1550
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
1552 switch (instr->RsFieldRaw()) {
1553 case BC1:
1554 if (instr->FBtrueValue()) {
1555 Format(instr, "bc1t 'bc, 'imm16u -> 'imm16p4s2");
1556 } else {
1557 Format(instr, "bc1f 'bc, 'imm16u -> 'imm16p4s2");
1558 }
1559 break;
1560 case BC1EQZ:
1561 Format(instr, "bc1eqz 'ft, 'imm16u -> 'imm16p4s2");
1562 break;
1563 case BC1NEZ:
1564 Format(instr, "bc1nez 'ft, 'imm16u -> 'imm16p4s2");
1565 break;
1566 default:
1567 UNREACHABLE();
1568 }
1569}
1570
1571
1572void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) {
1573 switch (instr->RtFieldRaw()) {
1574 case BLTZ:
1575 Format(instr, "bltz 'rs, 'imm16u -> 'imm16p4s2");
1576 break;
1577 case BLTZAL:
1578 Format(instr, "bltzal 'rs, 'imm16u -> 'imm16p4s2");
1579 break;
1580 case BGEZ:
1581 Format(instr, "bgez 'rs, 'imm16u -> 'imm16p4s2");
1582 break;
1583 case BGEZAL: {
1584 if (instr->RsValue() == 0)
1585 Format(instr, "bal 'imm16s -> 'imm16p4s2");
1586 else
1587 Format(instr, "bgezal 'rs, 'imm16u -> 'imm16p4s2");
1588 break;
1589 }
1590 case BGEZALL:
1591 Format(instr, "bgezall 'rs, 'imm16u -> 'imm16p4s2");
1592 break;
1593 case DAHI:
1594 Format(instr, "dahi 'rs, 'imm16x");
1595 break;
1596 case DATI:
1597 Format(instr, "dati 'rs, 'imm16x");
1598 break;
1599 default:
1600 UNREACHABLE();
1601 }
1602}
1603
1604
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001605void Decoder::DecodeTypeImmediate(Instruction* instr) {
1606 switch (instr->OpcodeFieldRaw()) {
1607 case COP1:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001608 DecodeTypeImmediateCOP1(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001609 break; // Case COP1.
1610 // ------------- REGIMM class.
1611 case REGIMM:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001612 DecodeTypeImmediateREGIMM(instr);
1613 break; // Case REGIMM.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001614 // ------------- Branch instructions.
1615 case BEQ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616 Format(instr, "beq 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1617 break;
1618 case BC:
1619 Format(instr, "bc 'imm26s -> 'imm26p4s2");
1620 break;
1621 case BALC:
1622 Format(instr, "balc 'imm26s -> 'imm26p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623 break;
1624 case BNE:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001625 Format(instr, "bne 'rs, 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001626 break;
1627 case BLEZ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001628 if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
1629 Format(instr, "blez 'rs, 'imm16u -> 'imm16p4s2");
1630 } else if ((instr->RtValue() != instr->RsValue()) &&
1631 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1632 Format(instr, "bgeuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1633 } else if ((instr->RtValue() == instr->RsValue()) &&
1634 (instr->RtValue() != 0)) {
1635 Format(instr, "bgezalc 'rs, 'imm16u -> 'imm16p4s2");
1636 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1637 Format(instr, "blezalc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001638 } else {
1639 UNREACHABLE();
1640 }
1641 break;
1642 case BGTZ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001643 if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
1644 Format(instr, "bgtz 'rs, 'imm16u -> 'imm16p4s2");
1645 } else if ((instr->RtValue() != instr->RsValue()) &&
1646 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1647 Format(instr, "bltuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1648 } else if ((instr->RtValue() == instr->RsValue()) &&
1649 (instr->RtValue() != 0)) {
1650 Format(instr, "bltzalc 'rt, 'imm16u -> 'imm16p4s2");
1651 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1652 Format(instr, "bgtzalc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001653 } else {
1654 UNREACHABLE();
1655 }
1656 break;
1657 case BLEZL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001658 if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
1659 Format(instr, "bgezc 'rt, 'imm16u -> 'imm16p4s2");
1660 } else if ((instr->RtValue() != instr->RsValue()) &&
1661 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1662 Format(instr, "bgec 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1663 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1664 Format(instr, "blezc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001665 } else {
1666 UNREACHABLE();
1667 }
1668 break;
1669 case BGTZL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001670 if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
1671 Format(instr, "bltzc 'rt, 'imm16u -> 'imm16p4s2");
1672 } else if ((instr->RtValue() != instr->RsValue()) &&
1673 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1674 Format(instr, "bltc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1675 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1676 Format(instr, "bgtzc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001677 } else {
1678 UNREACHABLE();
1679 }
1680 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001681 case POP66:
1682 if (instr->RsValue() == JIC) {
1683 Format(instr, "jic 'rt, 'imm16s");
1684 } else {
1685 Format(instr, "beqzc 'rs, 'imm21s -> 'imm21p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001686 }
1687 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001688 case POP76:
1689 if (instr->RsValue() == JIALC) {
1690 Format(instr, "jialc 'rt, 'imm16s");
1691 } else {
1692 Format(instr, "bnezc 'rs, 'imm21s -> 'imm21p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001693 }
1694 break;
1695 // ------------- Arithmetic instructions.
1696 case ADDI:
1697 if (kArchVariant != kMips64r6) {
1698 Format(instr, "addi 'rt, 'rs, 'imm16s");
1699 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001700 int rs_reg = instr->RsValue();
1701 int rt_reg = instr->RtValue();
1702 // Check if BOVC, BEQZALC or BEQC instruction.
1703 if (rs_reg >= rt_reg) {
1704 Format(instr, "bovc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001705 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001706 DCHECK(rt_reg > 0);
1707 if (rs_reg == 0) {
1708 Format(instr, "beqzalc 'rt, 'imm16s -> 'imm16p4s2");
1709 } else {
1710 Format(instr, "beqc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
1711 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001712 }
1713 }
1714 break;
1715 case DADDI:
1716 if (kArchVariant != kMips64r6) {
1717 Format(instr, "daddi 'rt, 'rs, 'imm16s");
1718 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001719 int rs_reg = instr->RsValue();
1720 int rt_reg = instr->RtValue();
1721 // Check if BNVC, BNEZALC or BNEC instruction.
1722 if (rs_reg >= rt_reg) {
1723 Format(instr, "bnvc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001724 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001725 DCHECK(rt_reg > 0);
1726 if (rs_reg == 0) {
1727 Format(instr, "bnezalc 'rt, 'imm16s -> 'imm16p4s2");
1728 } else {
1729 Format(instr, "bnec 'rs, 'rt, 'imm16s -> 'imm16p4s2");
1730 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001731 }
1732 }
1733 break;
1734 case ADDIU:
1735 Format(instr, "addiu 'rt, 'rs, 'imm16s");
1736 break;
1737 case DADDIU:
1738 Format(instr, "daddiu 'rt, 'rs, 'imm16s");
1739 break;
1740 case SLTI:
1741 Format(instr, "slti 'rt, 'rs, 'imm16s");
1742 break;
1743 case SLTIU:
1744 Format(instr, "sltiu 'rt, 'rs, 'imm16u");
1745 break;
1746 case ANDI:
1747 Format(instr, "andi 'rt, 'rs, 'imm16x");
1748 break;
1749 case ORI:
1750 Format(instr, "ori 'rt, 'rs, 'imm16x");
1751 break;
1752 case XORI:
1753 Format(instr, "xori 'rt, 'rs, 'imm16x");
1754 break;
1755 case LUI:
1756 if (kArchVariant != kMips64r6) {
1757 Format(instr, "lui 'rt, 'imm16x");
1758 } else {
1759 if (instr->RsValue() != 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001760 Format(instr, "aui 'rt, 'rs, 'imm16x");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001761 } else {
1762 Format(instr, "lui 'rt, 'imm16x");
1763 }
1764 }
1765 break;
1766 case DAUI:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001767 Format(instr, "daui 'rt, 'rs, 'imm16x");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001768 break;
1769 // ------------- Memory instructions.
1770 case LB:
1771 Format(instr, "lb 'rt, 'imm16s('rs)");
1772 break;
1773 case LH:
1774 Format(instr, "lh 'rt, 'imm16s('rs)");
1775 break;
1776 case LWL:
1777 Format(instr, "lwl 'rt, 'imm16s('rs)");
1778 break;
1779 case LDL:
1780 Format(instr, "ldl 'rt, 'imm16s('rs)");
1781 break;
1782 case LW:
1783 Format(instr, "lw 'rt, 'imm16s('rs)");
1784 break;
1785 case LWU:
1786 Format(instr, "lwu 'rt, 'imm16s('rs)");
1787 break;
1788 case LD:
1789 Format(instr, "ld 'rt, 'imm16s('rs)");
1790 break;
1791 case LBU:
1792 Format(instr, "lbu 'rt, 'imm16s('rs)");
1793 break;
1794 case LHU:
1795 Format(instr, "lhu 'rt, 'imm16s('rs)");
1796 break;
1797 case LWR:
1798 Format(instr, "lwr 'rt, 'imm16s('rs)");
1799 break;
1800 case LDR:
1801 Format(instr, "ldr 'rt, 'imm16s('rs)");
1802 break;
1803 case PREF:
1804 Format(instr, "pref 'rt, 'imm16s('rs)");
1805 break;
1806 case SB:
1807 Format(instr, "sb 'rt, 'imm16s('rs)");
1808 break;
1809 case SH:
1810 Format(instr, "sh 'rt, 'imm16s('rs)");
1811 break;
1812 case SWL:
1813 Format(instr, "swl 'rt, 'imm16s('rs)");
1814 break;
1815 case SW:
1816 Format(instr, "sw 'rt, 'imm16s('rs)");
1817 break;
1818 case SD:
1819 Format(instr, "sd 'rt, 'imm16s('rs)");
1820 break;
1821 case SWR:
1822 Format(instr, "swr 'rt, 'imm16s('rs)");
1823 break;
1824 case LWC1:
1825 Format(instr, "lwc1 'ft, 'imm16s('rs)");
1826 break;
1827 case LDC1:
1828 Format(instr, "ldc1 'ft, 'imm16s('rs)");
1829 break;
1830 case SWC1:
1831 Format(instr, "swc1 'ft, 'imm16s('rs)");
1832 break;
1833 case SDC1:
1834 Format(instr, "sdc1 'ft, 'imm16s('rs)");
1835 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001836 case PCREL: {
1837 int32_t imm21 = instr->Imm21Value();
1838 // rt field: 5-bits checking
1839 uint8_t rt = (imm21 >> kImm16Bits);
1840 switch (rt) {
1841 case ALUIPC:
1842 Format(instr, "aluipc 'rs, 'imm16s");
1843 break;
1844 case AUIPC:
1845 Format(instr, "auipc 'rs, 'imm16s");
1846 break;
1847 default: {
1848 // rt field: checking of the most significant 3-bits
1849 rt = (imm21 >> kImm18Bits);
1850 switch (rt) {
1851 case LDPC:
1852 Format(instr, "ldpc 'rs, 'imm18s");
1853 break;
1854 default: {
1855 // rt field: checking of the most significant 2-bits
1856 rt = (imm21 >> kImm19Bits);
1857 switch (rt) {
1858 case LWUPC:
1859 Format(instr, "lwupc 'rs, 'imm19s");
1860 break;
1861 case LWPC:
1862 Format(instr, "lwpc 'rs, 'imm19s");
1863 break;
1864 case ADDIUPC:
1865 Format(instr, "addiupc 'rs, 'imm19s");
1866 break;
1867 default:
1868 UNREACHABLE();
1869 break;
1870 }
1871 break;
1872 }
1873 }
1874 break;
1875 }
1876 }
1877 break;
1878 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001879 default:
1880 printf("a 0x%x \n", instr->OpcodeFieldRaw());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001881 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001882 break;
1883 }
1884}
1885
1886
1887void Decoder::DecodeTypeJump(Instruction* instr) {
1888 switch (instr->OpcodeFieldRaw()) {
1889 case J:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001890 Format(instr, "j 'imm26x -> 'imm26j");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001891 break;
1892 case JAL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001893 Format(instr, "jal 'imm26x -> 'imm26j");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001894 break;
1895 default:
1896 UNREACHABLE();
1897 }
1898}
1899
1900
1901// Disassemble the instruction at *instr_ptr into the output buffer.
1902// All instructions are one word long, except for the simulator
1903// psuedo-instruction stop(msg). For that one special case, we return
1904// size larger than one kInstrSize.
1905int Decoder::InstructionDecode(byte* instr_ptr) {
1906 Instruction* instr = Instruction::At(instr_ptr);
1907 // Print raw instruction bytes.
1908 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1909 "%08x ",
1910 instr->InstructionBits());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001911 switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001912 case Instruction::kRegisterType: {
1913 return DecodeTypeRegister(instr);
1914 }
1915 case Instruction::kImmediateType: {
1916 DecodeTypeImmediate(instr);
1917 break;
1918 }
1919 case Instruction::kJumpType: {
1920 DecodeTypeJump(instr);
1921 break;
1922 }
1923 default: {
1924 Format(instr, "UNSUPPORTED");
1925 UNSUPPORTED_MIPS();
1926 }
1927 }
1928 return Instruction::kInstrSize;
1929}
1930
1931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001932} // namespace internal
1933} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001934
1935
1936//------------------------------------------------------------------------------
1937
1938namespace disasm {
1939
1940const char* NameConverter::NameOfAddress(byte* addr) const {
1941 v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1942 return tmp_buffer_.start();
1943}
1944
1945
1946const char* NameConverter::NameOfConstant(byte* addr) const {
1947 return NameOfAddress(addr);
1948}
1949
1950
1951const char* NameConverter::NameOfCPURegister(int reg) const {
1952 return v8::internal::Registers::Name(reg);
1953}
1954
1955
1956const char* NameConverter::NameOfXMMRegister(int reg) const {
1957 return v8::internal::FPURegisters::Name(reg);
1958}
1959
1960
1961const char* NameConverter::NameOfByteCPURegister(int reg) const {
1962 UNREACHABLE(); // MIPS does not have the concept of a byte register.
1963 return "nobytereg";
1964}
1965
1966
1967const char* NameConverter::NameInCode(byte* addr) const {
1968 // The default name converter is called for unknown code. So we will not try
1969 // to access any memory.
1970 return "";
1971}
1972
1973
1974//------------------------------------------------------------------------------
1975
1976Disassembler::Disassembler(const NameConverter& converter)
1977 : converter_(converter) {}
1978
1979
1980Disassembler::~Disassembler() {}
1981
1982
1983int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1984 byte* instruction) {
1985 v8::internal::Decoder d(converter_, buffer);
1986 return d.InstructionDecode(instruction);
1987}
1988
1989
1990// The MIPS assembler does not currently use constant pools.
1991int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1992 return -1;
1993}
1994
1995
1996void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1997 NameConverter converter;
1998 Disassembler d(converter);
1999 for (byte* pc = begin; pc < end;) {
2000 v8::internal::EmbeddedVector<char, 128> buffer;
2001 buffer[0] = '\0';
2002 byte* prev_pc = pc;
2003 pc += d.InstructionDecode(buffer, pc);
2004 v8::internal::PrintF(f, "%p %08x %s\n",
2005 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
2006 }
2007}
2008
2009
2010#undef UNSUPPORTED
2011
2012} // namespace disasm
2013
2014#endif // V8_TARGET_ARCH_MIPS64