blob: 3d0e10c20a586372e4fb6b2b147ab6ae56e8b8a5 [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;
378 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%lx", target);
379}
380
381
382// Print 26-bit signed immediate value.
383void Decoder::PrintSImm26(Instruction* instr) {
384 int32_t imm26 = instr->Imm26Value();
385 // set sign
386 imm26 <<= (32 - kImm26Bits);
387 imm26 >>= (32 - kImm26Bits);
388 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm26);
389}
390
391
392// Print absoulte address for 26-bit offset or immediate value.
393// The absolute address is calculated according following expression:
394// PC + delta_pc + (offset << n_bits)
395void Decoder::PrintPCImm26(Instruction* instr, int delta_pc, int n_bits) {
396 int32_t imm26 = instr->Imm26Value();
397 // set sign
398 imm26 <<= (32 - kImm26Bits);
399 imm26 >>= (32 - kImm26Bits);
400 out_buffer_pos_ +=
401 SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
402 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
403 delta_pc + (imm26 << n_bits)));
404}
405
406
407// Print absoulte address for 26-bit offset or immediate value.
408// The absolute address is calculated according following expression:
409// PC[GPRLEN-1 .. 28] || instr_index26 || 00
410void Decoder::PrintPCImm26(Instruction* instr) {
411 int32_t imm26 = instr->Imm26Value();
412 uint64_t pc_mask = ~0xfffffff;
413 uint64_t pc = ((uint64_t)(instr + 1) & pc_mask) | (imm26 << 2);
414 out_buffer_pos_ +=
415 SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
416 converter_.NameOfAddress((reinterpret_cast<byte*>(pc))));
417}
418
419
420void Decoder::PrintBp2(Instruction* instr) {
421 int bp2 = instr->Bp2Value();
422 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", bp2);
423}
424
425
426void Decoder::PrintBp3(Instruction* instr) {
427 int bp3 = instr->Bp3Value();
428 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", bp3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429}
430
431
432// Print 26-bit immediate value.
433void Decoder::PrintCode(Instruction* instr) {
434 if (instr->OpcodeFieldRaw() != SPECIAL)
435 return; // Not a break or trap instruction.
436 switch (instr->FunctionFieldRaw()) {
437 case BREAK: {
438 int32_t code = instr->Bits(25, 6);
439 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
440 "0x%05x (%d)", code, code);
441 break;
442 }
443 case TGE:
444 case TGEU:
445 case TLT:
446 case TLTU:
447 case TEQ:
448 case TNE: {
449 int32_t code = instr->Bits(15, 6);
450 out_buffer_pos_ +=
451 SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
452 break;
453 }
454 default: // Not a break or trap instruction.
455 break;
456 }
457}
458
459
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460void Decoder::PrintFormat(Instruction* instr) {
461 char formatLetter = ' ';
462 switch (instr->RsFieldRaw()) {
463 case S:
464 formatLetter = 's';
465 break;
466 case D:
467 formatLetter = 'd';
468 break;
469 case W:
470 formatLetter = 'w';
471 break;
472 case L:
473 formatLetter = 'l';
474 break;
475 default:
476 UNREACHABLE();
477 break;
478 }
479 PrintChar(formatLetter);
480}
481
482
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483// Printing of instruction name.
484void Decoder::PrintInstructionName(Instruction* instr) {
485}
486
487
488// Handle all register based formatting in this function to reduce the
489// complexity of FormatOption.
490int Decoder::FormatRegister(Instruction* instr, const char* format) {
491 DCHECK(format[0] == 'r');
492 if (format[1] == 's') { // 'rs: Rs register.
493 int reg = instr->RsValue();
494 PrintRegister(reg);
495 return 2;
496 } else if (format[1] == 't') { // 'rt: rt register.
497 int reg = instr->RtValue();
498 PrintRegister(reg);
499 return 2;
500 } else if (format[1] == 'd') { // 'rd: rd register.
501 int reg = instr->RdValue();
502 PrintRegister(reg);
503 return 2;
504 }
505 UNREACHABLE();
506 return -1;
507}
508
509
510// Handle all FPUregister based formatting in this function to reduce the
511// complexity of FormatOption.
512int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
513 DCHECK(format[0] == 'f');
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000514 if ((CTC1 == instr->RsFieldRaw()) || (CFC1 == instr->RsFieldRaw())) {
515 if (format[1] == 's') { // 'fs: fs register.
516 int reg = instr->FsValue();
517 PrintFPUStatusRegister(reg);
518 return 2;
519 } else if (format[1] == 't') { // 'ft: ft register.
520 int reg = instr->FtValue();
521 PrintFPUStatusRegister(reg);
522 return 2;
523 } else if (format[1] == 'd') { // 'fd: fd register.
524 int reg = instr->FdValue();
525 PrintFPUStatusRegister(reg);
526 return 2;
527 } else if (format[1] == 'r') { // 'fr: fr register.
528 int reg = instr->FrValue();
529 PrintFPUStatusRegister(reg);
530 return 2;
531 }
532 } else {
533 if (format[1] == 's') { // 'fs: fs register.
534 int reg = instr->FsValue();
535 PrintFPURegister(reg);
536 return 2;
537 } else if (format[1] == 't') { // 'ft: ft register.
538 int reg = instr->FtValue();
539 PrintFPURegister(reg);
540 return 2;
541 } else if (format[1] == 'd') { // 'fd: fd register.
542 int reg = instr->FdValue();
543 PrintFPURegister(reg);
544 return 2;
545 } else if (format[1] == 'r') { // 'fr: fr register.
546 int reg = instr->FrValue();
547 PrintFPURegister(reg);
548 return 2;
549 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000550 }
551 UNREACHABLE();
552 return -1;
553}
554
555
556// FormatOption takes a formatting string and interprets it based on
557// the current instructions. The format string points to the first
558// character of the option string (the option escape has already been
559// consumed by the caller.) FormatOption returns the number of
560// characters that were consumed from the formatting string.
561int Decoder::FormatOption(Instruction* instr, const char* format) {
562 switch (format[0]) {
563 case 'c': { // 'code for break or trap instructions.
564 DCHECK(STRING_STARTS_WITH(format, "code"));
565 PrintCode(instr);
566 return 4;
567 }
568 case 'i': { // 'imm16u or 'imm26.
569 if (format[3] == '1') {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 if (format[4] == '6') {
571 DCHECK(STRING_STARTS_WITH(format, "imm16"));
572 switch (format[5]) {
573 case 's':
574 DCHECK(STRING_STARTS_WITH(format, "imm16s"));
575 PrintSImm16(instr);
576 break;
577 case 'u':
578 DCHECK(STRING_STARTS_WITH(format, "imm16u"));
579 PrintSImm16(instr);
580 break;
581 case 'x':
582 DCHECK(STRING_STARTS_WITH(format, "imm16x"));
583 PrintXImm16(instr);
584 break;
585 case 'p': { // The PC relative address.
586 DCHECK(STRING_STARTS_WITH(format, "imm16p"));
587 int delta_pc = 0;
588 int n_bits = 0;
589 switch (format[6]) {
590 case '4': {
591 DCHECK(STRING_STARTS_WITH(format, "imm16p4"));
592 delta_pc = 4;
593 switch (format[8]) {
594 case '2':
595 DCHECK(STRING_STARTS_WITH(format, "imm16p4s2"));
596 n_bits = 2;
597 PrintPCImm16(instr, delta_pc, n_bits);
598 return 9;
599 }
600 }
601 }
602 }
603 }
604 return 6;
605 } else if (format[4] == '8') {
606 DCHECK(STRING_STARTS_WITH(format, "imm18"));
607 switch (format[5]) {
608 case 's':
609 DCHECK(STRING_STARTS_WITH(format, "imm18s"));
610 PrintSImm18(instr);
611 break;
612 case 'x':
613 DCHECK(STRING_STARTS_WITH(format, "imm18x"));
614 PrintXImm18(instr);
615 break;
616 }
617 return 6;
618 } else if (format[4] == '9') {
619 DCHECK(STRING_STARTS_WITH(format, "imm19"));
620 switch (format[5]) {
621 case 's':
622 DCHECK(STRING_STARTS_WITH(format, "imm19s"));
623 PrintSImm19(instr);
624 break;
625 case 'x':
626 DCHECK(STRING_STARTS_WITH(format, "imm19x"));
627 PrintXImm19(instr);
628 break;
629 }
630 return 6;
631 }
632 } else if (format[3] == '2' && format[4] == '1') {
633 DCHECK(STRING_STARTS_WITH(format, "imm21"));
634 switch (format[5]) {
635 case 's':
636 DCHECK(STRING_STARTS_WITH(format, "imm21s"));
637 PrintSImm21(instr);
638 break;
639 case 'x':
640 DCHECK(STRING_STARTS_WITH(format, "imm21x"));
641 PrintXImm21(instr);
642 break;
643 case 'p': { // The PC relative address.
644 DCHECK(STRING_STARTS_WITH(format, "imm21p"));
645 int delta_pc = 0;
646 int n_bits = 0;
647 switch (format[6]) {
648 case '4': {
649 DCHECK(STRING_STARTS_WITH(format, "imm21p4"));
650 delta_pc = 4;
651 switch (format[8]) {
652 case '2':
653 DCHECK(STRING_STARTS_WITH(format, "imm21p4s2"));
654 n_bits = 2;
655 PrintPCImm21(instr, delta_pc, n_bits);
656 return 9;
657 }
658 }
659 }
660 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 }
662 return 6;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000663 } else if (format[3] == '2' && format[4] == '6') {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000664 DCHECK(STRING_STARTS_WITH(format, "imm26"));
665 switch (format[5]) {
666 case 's':
667 DCHECK(STRING_STARTS_WITH(format, "imm26s"));
668 PrintSImm26(instr);
669 break;
670 case 'x':
671 DCHECK(STRING_STARTS_WITH(format, "imm26x"));
672 PrintXImm26(instr);
673 break;
674 case 'p': { // The PC relative address.
675 DCHECK(STRING_STARTS_WITH(format, "imm26p"));
676 int delta_pc = 0;
677 int n_bits = 0;
678 switch (format[6]) {
679 case '4': {
680 DCHECK(STRING_STARTS_WITH(format, "imm26p4"));
681 delta_pc = 4;
682 switch (format[8]) {
683 case '2':
684 DCHECK(STRING_STARTS_WITH(format, "imm26p4s2"));
685 n_bits = 2;
686 PrintPCImm26(instr, delta_pc, n_bits);
687 return 9;
688 }
689 }
690 }
691 }
692 case 'j': { // Absolute address for jump instructions.
693 DCHECK(STRING_STARTS_WITH(format, "imm26j"));
694 PrintPCImm26(instr);
695 break;
696 }
697 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000698 return 6;
699 }
700 }
701 case 'r': { // 'r: registers.
702 return FormatRegister(instr, format);
703 }
704 case 'f': { // 'f: FPUregisters.
705 return FormatFPURegister(instr, format);
706 }
707 case 's': { // 'sa.
708 switch (format[1]) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000709 case 'a':
710 if (format[2] == '2') {
711 DCHECK(STRING_STARTS_WITH(format, "sa2")); // 'sa2
712 PrintLsaSa(instr);
713 return 3;
714 } else {
715 DCHECK(STRING_STARTS_WITH(format, "sa"));
716 PrintSa(instr);
717 return 2;
718 }
719 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720 case 'd': {
721 DCHECK(STRING_STARTS_WITH(format, "sd"));
722 PrintSd(instr);
723 return 2;
724 }
725 case 's': {
726 if (format[2] == '1') {
727 DCHECK(STRING_STARTS_WITH(format, "ss1")); /* ext size */
728 PrintSs1(instr);
729 return 3;
730 } else {
731 DCHECK(STRING_STARTS_WITH(format, "ss2")); /* ins size */
732 PrintSs2(instr);
733 return 3;
734 }
735 }
736 }
737 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 case 'b': {
739 switch (format[1]) {
740 case 'c': { // 'bc - Special for bc1 cc field.
741 DCHECK(STRING_STARTS_WITH(format, "bc"));
742 PrintBc(instr);
743 return 2;
744 }
745 case 'p': {
746 switch (format[2]) {
747 case '2': { // 'bp2
748 DCHECK(STRING_STARTS_WITH(format, "bp2"));
749 PrintBp2(instr);
750 return 3;
751 }
752 case '3': { // 'bp3
753 DCHECK(STRING_STARTS_WITH(format, "bp3"));
754 PrintBp3(instr);
755 return 3;
756 }
757 }
758 }
759 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760 }
761 case 'C': { // 'Cc - Special for c.xx.d cc field.
762 DCHECK(STRING_STARTS_WITH(format, "Cc"));
763 PrintCc(instr);
764 return 2;
765 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 case 't':
767 PrintFormat(instr);
768 return 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000769 }
770 UNREACHABLE();
771 return -1;
772}
773
774
775// Format takes a formatting string for a whole instruction and prints it into
776// the output buffer. All escaped options are handed to FormatOption to be
777// parsed further.
778void Decoder::Format(Instruction* instr, const char* format) {
779 char cur = *format++;
780 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
781 if (cur == '\'') { // Single quote is used as the formatting escape.
782 format += FormatOption(instr, format);
783 } else {
784 out_buffer_[out_buffer_pos_++] = cur;
785 }
786 cur = *format++;
787 }
788 out_buffer_[out_buffer_pos_] = '\0';
789}
790
791
792// For currently unimplemented decodings the disassembler calls Unknown(instr)
793// which will just print "unknown" of the instruction bits.
794void Decoder::Unknown(Instruction* instr) {
795 Format(instr, "unknown");
796}
797
798
799int Decoder::DecodeBreakInstr(Instruction* instr) {
800 // This is already known to be BREAK instr, just extract the code.
801 if (instr->Bits(25, 6) == static_cast<int>(kMaxStopCode)) {
802 // This is stop(msg).
803 Format(instr, "break, code: 'code");
804 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
805 "\n%p %08lx stop msg: %s",
806 static_cast<void*>
807 (reinterpret_cast<int32_t*>(instr
808 + Instruction::kInstrSize)),
809 reinterpret_cast<uint64_t>
810 (*reinterpret_cast<char**>(instr
811 + Instruction::kInstrSize)),
812 *reinterpret_cast<char**>(instr
813 + Instruction::kInstrSize));
814 // Size 3: the break_ instr, plus embedded 64-bit char pointer.
815 return 3 * Instruction::kInstrSize;
816 } else {
817 Format(instr, "break, code: 'code");
818 return Instruction::kInstrSize;
819 }
820}
821
822
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000823bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
824 switch (instr->FunctionFieldRaw()) {
825 case RINT:
826 Format(instr, "rint.'t 'fd, 'fs");
827 break;
828 case SEL:
829 Format(instr, "sel.'t 'fd, 'fs, 'ft");
830 break;
831 case SELEQZ_C:
832 Format(instr, "seleqz.'t 'fd, 'fs, 'ft");
833 break;
834 case SELNEZ_C:
835 Format(instr, "selnez.'t 'fd, 'fs, 'ft");
836 break;
837 case MOVZ_C:
838 Format(instr, "movz.'t 'fd, 'fs, 'rt");
839 break;
840 case MOVN_C:
841 Format(instr, "movn.'t 'fd, 'fs, 'rt");
842 break;
843 case MOVF:
844 if (instr->Bit(16)) {
845 Format(instr, "movt.'t 'fd, 'fs, 'Cc");
846 } else {
847 Format(instr, "movf.'t 'fd, 'fs, 'Cc");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 }
849 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850 case MIN:
851 Format(instr, "min.'t 'fd, 'fs, 'ft");
852 break;
853 case MAX:
854 Format(instr, "max.'t 'fd, 'fs, 'ft");
855 break;
856 case MINA:
857 Format(instr, "mina.'t 'fd, 'fs, 'ft");
858 break;
859 case MAXA:
860 Format(instr, "maxa.'t 'fd, 'fs, 'ft");
861 break;
862 case ADD_D:
863 Format(instr, "add.'t 'fd, 'fs, 'ft");
864 break;
865 case SUB_D:
866 Format(instr, "sub.'t 'fd, 'fs, 'ft");
867 break;
868 case MUL_D:
869 Format(instr, "mul.'t 'fd, 'fs, 'ft");
870 break;
871 case DIV_D:
872 Format(instr, "div.'t 'fd, 'fs, 'ft");
873 break;
874 case ABS_D:
875 Format(instr, "abs.'t 'fd, 'fs");
876 break;
877 case MOV_D:
878 Format(instr, "mov.'t 'fd, 'fs");
879 break;
880 case NEG_D:
881 Format(instr, "neg.'t 'fd, 'fs");
882 break;
883 case SQRT_D:
884 Format(instr, "sqrt.'t 'fd, 'fs");
885 break;
886 case RECIP_D:
887 Format(instr, "recip.'t 'fd, 'fs");
888 break;
889 case RSQRT_D:
890 Format(instr, "rsqrt.'t 'fd, 'fs");
891 break;
892 case CVT_W_D:
893 Format(instr, "cvt.w.'t 'fd, 'fs");
894 break;
895 case CVT_L_D:
896 Format(instr, "cvt.l.'t 'fd, 'fs");
897 break;
898 case TRUNC_W_D:
899 Format(instr, "trunc.w.'t 'fd, 'fs");
900 break;
901 case TRUNC_L_D:
902 Format(instr, "trunc.l.'t 'fd, 'fs");
903 break;
904 case ROUND_W_D:
905 Format(instr, "round.w.'t 'fd, 'fs");
906 break;
907 case ROUND_L_D:
908 Format(instr, "round.l.'t 'fd, 'fs");
909 break;
910 case FLOOR_W_D:
911 Format(instr, "floor.w.'t 'fd, 'fs");
912 break;
913 case FLOOR_L_D:
914 Format(instr, "floor.l.'t 'fd, 'fs");
915 break;
916 case CEIL_W_D:
917 Format(instr, "ceil.w.'t 'fd, 'fs");
918 break;
919 case CEIL_L_D:
920 Format(instr, "ceil.l.'t 'fd, 'fs");
921 break;
922 case CLASS_D:
923 Format(instr, "class.'t 'fd, 'fs");
924 break;
925 case CVT_S_D:
926 Format(instr, "cvt.s.'t 'fd, 'fs");
927 break;
928 case C_F_D:
929 Format(instr, "c.f.'t 'fs, 'ft, 'Cc");
930 break;
931 case C_UN_D:
932 Format(instr, "c.un.'t 'fs, 'ft, 'Cc");
933 break;
934 case C_EQ_D:
935 Format(instr, "c.eq.'t 'fs, 'ft, 'Cc");
936 break;
937 case C_UEQ_D:
938 Format(instr, "c.ueq.'t 'fs, 'ft, 'Cc");
939 break;
940 case C_OLT_D:
941 Format(instr, "c.olt.'t 'fs, 'ft, 'Cc");
942 break;
943 case C_ULT_D:
944 Format(instr, "c.ult.'t 'fs, 'ft, 'Cc");
945 break;
946 case C_OLE_D:
947 Format(instr, "c.ole.'t 'fs, 'ft, 'Cc");
948 break;
949 case C_ULE_D:
950 Format(instr, "c.ule.'t 'fs, 'ft, 'Cc");
951 break;
952 default:
953 return false;
954 }
955 return true;
956}
957
958
959void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
960 if (!DecodeTypeRegisterRsType(instr)) {
961 switch (instr->FunctionFieldRaw()) {
962 case CVT_D_S:
963 Format(instr, "cvt.d.'t 'fd, 'fs");
964 break;
965 default:
966 Format(instr, "unknown.cop1.'t");
967 break;
968 }
969 }
970}
971
972
973void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) {
974 if (!DecodeTypeRegisterRsType(instr)) {
975 Format(instr, "unknown.cop1.'t");
976 }
977}
978
979
980void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) {
981 switch (instr->FunctionFieldRaw()) {
982 case CVT_D_L:
983 Format(instr, "cvt.d.l 'fd, 'fs");
984 break;
985 case CVT_S_L:
986 Format(instr, "cvt.s.l 'fd, 'fs");
987 break;
988 case CMP_AF:
989 Format(instr, "cmp.af.d 'fd, 'fs, 'ft");
990 break;
991 case CMP_UN:
992 Format(instr, "cmp.un.d 'fd, 'fs, 'ft");
993 break;
994 case CMP_EQ:
995 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft");
996 break;
997 case CMP_UEQ:
998 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft");
999 break;
1000 case CMP_LT:
1001 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft");
1002 break;
1003 case CMP_ULT:
1004 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft");
1005 break;
1006 case CMP_LE:
1007 Format(instr, "cmp.le.d 'fd, 'fs, 'ft");
1008 break;
1009 case CMP_ULE:
1010 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft");
1011 break;
1012 case CMP_OR:
1013 Format(instr, "cmp.or.d 'fd, 'fs, 'ft");
1014 break;
1015 case CMP_UNE:
1016 Format(instr, "cmp.une.d 'fd, 'fs, 'ft");
1017 break;
1018 case CMP_NE:
1019 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft");
1020 break;
1021 default:
1022 UNREACHABLE();
1023 }
1024}
1025
1026
1027void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) {
1028 switch (instr->FunctionValue()) {
1029 case CVT_S_W: // Convert word to float (single).
1030 Format(instr, "cvt.s.w 'fd, 'fs");
1031 break;
1032 case CVT_D_W: // Convert word to double.
1033 Format(instr, "cvt.d.w 'fd, 'fs");
1034 break;
1035 case CMP_AF:
1036 Format(instr, "cmp.af.s 'fd, 'fs, 'ft");
1037 break;
1038 case CMP_UN:
1039 Format(instr, "cmp.un.s 'fd, 'fs, 'ft");
1040 break;
1041 case CMP_EQ:
1042 Format(instr, "cmp.eq.s 'fd, 'fs, 'ft");
1043 break;
1044 case CMP_UEQ:
1045 Format(instr, "cmp.ueq.s 'fd, 'fs, 'ft");
1046 break;
1047 case CMP_LT:
1048 Format(instr, "cmp.lt.s 'fd, 'fs, 'ft");
1049 break;
1050 case CMP_ULT:
1051 Format(instr, "cmp.ult.s 'fd, 'fs, 'ft");
1052 break;
1053 case CMP_LE:
1054 Format(instr, "cmp.le.s 'fd, 'fs, 'ft");
1055 break;
1056 case CMP_ULE:
1057 Format(instr, "cmp.ule.s 'fd, 'fs, 'ft");
1058 break;
1059 case CMP_OR:
1060 Format(instr, "cmp.or.s 'fd, 'fs, 'ft");
1061 break;
1062 case CMP_UNE:
1063 Format(instr, "cmp.une.s 'fd, 'fs, 'ft");
1064 break;
1065 case CMP_NE:
1066 Format(instr, "cmp.ne.s 'fd, 'fs, 'ft");
1067 break;
1068 default:
1069 UNREACHABLE();
1070 }
1071}
1072
1073
1074void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) {
1075 switch (instr->RsFieldRaw()) {
1076 case MFC1:
1077 Format(instr, "mfc1 'rt, 'fs");
1078 break;
1079 case DMFC1:
1080 Format(instr, "dmfc1 'rt, 'fs");
1081 break;
1082 case MFHC1:
1083 Format(instr, "mfhc1 'rt, 'fs");
1084 break;
1085 case MTC1:
1086 Format(instr, "mtc1 'rt, 'fs");
1087 break;
1088 case DMTC1:
1089 Format(instr, "dmtc1 'rt, 'fs");
1090 break;
1091 // These are called "fs" too, although they are not FPU registers.
1092 case CTC1:
1093 Format(instr, "ctc1 'rt, 'fs");
1094 break;
1095 case CFC1:
1096 Format(instr, "cfc1 'rt, 'fs");
1097 break;
1098 case MTHC1:
1099 Format(instr, "mthc1 'rt, 'fs");
1100 break;
1101 case S:
1102 DecodeTypeRegisterSRsType(instr);
1103 break;
1104 case D:
1105 DecodeTypeRegisterDRsType(instr);
1106 break;
1107 case W:
1108 DecodeTypeRegisterWRsType(instr);
1109 break;
1110 case L:
1111 DecodeTypeRegisterLRsType(instr);
1112 break;
1113 default:
1114 UNREACHABLE();
1115 }
1116}
1117
1118
1119void Decoder::DecodeTypeRegisterCOP1X(Instruction* instr) {
1120 switch (instr->FunctionFieldRaw()) {
1121 case MADD_D:
1122 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
1123 break;
1124 default:
1125 UNREACHABLE();
1126 }
1127}
1128
1129
1130void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
1131 switch (instr->FunctionFieldRaw()) {
1132 case JR:
1133 Format(instr, "jr 'rs");
1134 break;
1135 case JALR:
1136 Format(instr, "jalr 'rs, 'rd");
1137 break;
1138 case SLL:
1139 if (0x0 == static_cast<int>(instr->InstructionBits()))
1140 Format(instr, "nop");
1141 else
1142 Format(instr, "sll 'rd, 'rt, 'sa");
1143 break;
1144 case DSLL:
1145 Format(instr, "dsll 'rd, 'rt, 'sa");
1146 break;
1147 case D_MUL_MUH: // Equals to DMUL.
1148 if (kArchVariant != kMips64r6) {
1149 Format(instr, "dmult 'rs, 'rt");
1150 } else {
1151 if (instr->SaValue() == MUL_OP) {
1152 Format(instr, "dmul 'rd, 'rs, 'rt");
1153 } else {
1154 Format(instr, "dmuh 'rd, 'rs, 'rt");
1155 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001156 }
1157 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001158 case DSLL32:
1159 Format(instr, "dsll32 'rd, 'rt, 'sa");
1160 break;
1161 case SRL:
1162 if (instr->RsValue() == 0) {
1163 Format(instr, "srl 'rd, 'rt, 'sa");
1164 } else {
1165 if (kArchVariant == kMips64r2) {
1166 Format(instr, "rotr 'rd, 'rt, 'sa");
1167 } else {
1168 Unknown(instr);
1169 }
1170 }
1171 break;
1172 case DSRL:
1173 if (instr->RsValue() == 0) {
1174 Format(instr, "dsrl 'rd, 'rt, 'sa");
1175 } else {
1176 if (kArchVariant == kMips64r2) {
1177 Format(instr, "drotr 'rd, 'rt, 'sa");
1178 } else {
1179 Unknown(instr);
1180 }
1181 }
1182 break;
1183 case DSRL32:
1184 Format(instr, "dsrl32 'rd, 'rt, 'sa");
1185 break;
1186 case SRA:
1187 Format(instr, "sra 'rd, 'rt, 'sa");
1188 break;
1189 case DSRA:
1190 Format(instr, "dsra 'rd, 'rt, 'sa");
1191 break;
1192 case DSRA32:
1193 Format(instr, "dsra32 'rd, 'rt, 'sa");
1194 break;
1195 case SLLV:
1196 Format(instr, "sllv 'rd, 'rt, 'rs");
1197 break;
1198 case DSLLV:
1199 Format(instr, "dsllv 'rd, 'rt, 'rs");
1200 break;
1201 case SRLV:
1202 if (instr->SaValue() == 0) {
1203 Format(instr, "srlv 'rd, 'rt, 'rs");
1204 } else {
1205 if (kArchVariant == kMips64r2) {
1206 Format(instr, "rotrv 'rd, 'rt, 'rs");
1207 } else {
1208 Unknown(instr);
1209 }
1210 }
1211 break;
1212 case DSRLV:
1213 if (instr->SaValue() == 0) {
1214 Format(instr, "dsrlv 'rd, 'rt, 'rs");
1215 } else {
1216 if (kArchVariant == kMips64r2) {
1217 Format(instr, "drotrv 'rd, 'rt, 'rs");
1218 } else {
1219 Unknown(instr);
1220 }
1221 }
1222 break;
1223 case SRAV:
1224 Format(instr, "srav 'rd, 'rt, 'rs");
1225 break;
1226 case DSRAV:
1227 Format(instr, "dsrav 'rd, 'rt, 'rs");
1228 break;
1229 case LSA:
1230 Format(instr, "lsa 'rd, 'rt, 'rs, 'sa2");
1231 break;
1232 case DLSA:
1233 Format(instr, "dlsa 'rd, 'rt, 'rs, 'sa2");
1234 break;
1235 case MFHI:
1236 if (instr->Bits(25, 16) == 0) {
1237 Format(instr, "mfhi 'rd");
1238 } else {
1239 if ((instr->FunctionFieldRaw() == CLZ_R6) && (instr->FdValue() == 1)) {
1240 Format(instr, "clz 'rd, 'rs");
1241 } else if ((instr->FunctionFieldRaw() == CLO_R6) &&
1242 (instr->FdValue() == 1)) {
1243 Format(instr, "clo 'rd, 'rs");
1244 }
1245 }
1246 break;
1247 case MFLO:
1248 if (instr->Bits(25, 16) == 0) {
1249 Format(instr, "mflo 'rd");
1250 } else {
1251 if ((instr->FunctionFieldRaw() == DCLZ_R6) && (instr->FdValue() == 1)) {
1252 Format(instr, "dclz 'rd, 'rs");
1253 } else if ((instr->FunctionFieldRaw() == DCLO_R6) &&
1254 (instr->FdValue() == 1)) {
1255 Format(instr, "dclo 'rd, 'rs");
1256 }
1257 }
1258 break;
1259 case D_MUL_MUH_U: // Equals to DMULTU.
1260 if (kArchVariant != kMips64r6) {
1261 Format(instr, "dmultu 'rs, 'rt");
1262 } else {
1263 if (instr->SaValue() == MUL_OP) {
1264 Format(instr, "dmulu 'rd, 'rs, 'rt");
1265 } else {
1266 Format(instr, "dmuhu 'rd, 'rs, 'rt");
1267 }
1268 }
1269 break;
1270 case MULT: // @Mips64r6 == MUL_MUH.
1271 if (kArchVariant != kMips64r6) {
1272 Format(instr, "mult 'rs, 'rt");
1273 } else {
1274 if (instr->SaValue() == MUL_OP) {
1275 Format(instr, "mul 'rd, 'rs, 'rt");
1276 } else {
1277 Format(instr, "muh 'rd, 'rs, 'rt");
1278 }
1279 }
1280 break;
1281 case MULTU: // @Mips64r6 == MUL_MUH_U.
1282 if (kArchVariant != kMips64r6) {
1283 Format(instr, "multu 'rs, 'rt");
1284 } else {
1285 if (instr->SaValue() == MUL_OP) {
1286 Format(instr, "mulu 'rd, 'rs, 'rt");
1287 } else {
1288 Format(instr, "muhu 'rd, 'rs, 'rt");
1289 }
1290 }
1291
1292 break;
1293 case DIV: // @Mips64r6 == DIV_MOD.
1294 if (kArchVariant != kMips64r6) {
1295 Format(instr, "div 'rs, 'rt");
1296 } else {
1297 if (instr->SaValue() == DIV_OP) {
1298 Format(instr, "div 'rd, 'rs, 'rt");
1299 } else {
1300 Format(instr, "mod 'rd, 'rs, 'rt");
1301 }
1302 }
1303 break;
1304 case DDIV: // @Mips64r6 == D_DIV_MOD.
1305 if (kArchVariant != kMips64r6) {
1306 Format(instr, "ddiv 'rs, 'rt");
1307 } else {
1308 if (instr->SaValue() == DIV_OP) {
1309 Format(instr, "ddiv 'rd, 'rs, 'rt");
1310 } else {
1311 Format(instr, "dmod 'rd, 'rs, 'rt");
1312 }
1313 }
1314 break;
1315 case DIVU: // @Mips64r6 == DIV_MOD_U.
1316 if (kArchVariant != kMips64r6) {
1317 Format(instr, "divu 'rs, 'rt");
1318 } else {
1319 if (instr->SaValue() == DIV_OP) {
1320 Format(instr, "divu 'rd, 'rs, 'rt");
1321 } else {
1322 Format(instr, "modu 'rd, 'rs, 'rt");
1323 }
1324 }
1325 break;
1326 case DDIVU: // @Mips64r6 == D_DIV_MOD_U.
1327 if (kArchVariant != kMips64r6) {
1328 Format(instr, "ddivu 'rs, 'rt");
1329 } else {
1330 if (instr->SaValue() == DIV_OP) {
1331 Format(instr, "ddivu 'rd, 'rs, 'rt");
1332 } else {
1333 Format(instr, "dmodu 'rd, 'rs, 'rt");
1334 }
1335 }
1336 break;
1337 case ADD:
1338 Format(instr, "add 'rd, 'rs, 'rt");
1339 break;
1340 case DADD:
1341 Format(instr, "dadd 'rd, 'rs, 'rt");
1342 break;
1343 case ADDU:
1344 Format(instr, "addu 'rd, 'rs, 'rt");
1345 break;
1346 case DADDU:
1347 Format(instr, "daddu 'rd, 'rs, 'rt");
1348 break;
1349 case SUB:
1350 Format(instr, "sub 'rd, 'rs, 'rt");
1351 break;
1352 case DSUB:
1353 Format(instr, "dsub 'rd, 'rs, 'rt");
1354 break;
1355 case SUBU:
1356 Format(instr, "subu 'rd, 'rs, 'rt");
1357 break;
1358 case DSUBU:
1359 Format(instr, "dsubu 'rd, 'rs, 'rt");
1360 break;
1361 case AND:
1362 Format(instr, "and 'rd, 'rs, 'rt");
1363 break;
1364 case OR:
1365 if (0 == instr->RsValue()) {
1366 Format(instr, "mov 'rd, 'rt");
1367 } else if (0 == instr->RtValue()) {
1368 Format(instr, "mov 'rd, 'rs");
1369 } else {
1370 Format(instr, "or 'rd, 'rs, 'rt");
1371 }
1372 break;
1373 case XOR:
1374 Format(instr, "xor 'rd, 'rs, 'rt");
1375 break;
1376 case NOR:
1377 Format(instr, "nor 'rd, 'rs, 'rt");
1378 break;
1379 case SLT:
1380 Format(instr, "slt 'rd, 'rs, 'rt");
1381 break;
1382 case SLTU:
1383 Format(instr, "sltu 'rd, 'rs, 'rt");
1384 break;
1385 case TGE:
1386 Format(instr, "tge 'rs, 'rt, code: 'code");
1387 break;
1388 case TGEU:
1389 Format(instr, "tgeu 'rs, 'rt, code: 'code");
1390 break;
1391 case TLT:
1392 Format(instr, "tlt 'rs, 'rt, code: 'code");
1393 break;
1394 case TLTU:
1395 Format(instr, "tltu 'rs, 'rt, code: 'code");
1396 break;
1397 case TEQ:
1398 Format(instr, "teq 'rs, 'rt, code: 'code");
1399 break;
1400 case TNE:
1401 Format(instr, "tne 'rs, 'rt, code: 'code");
1402 break;
1403 case MOVZ:
1404 Format(instr, "movz 'rd, 'rs, 'rt");
1405 break;
1406 case MOVN:
1407 Format(instr, "movn 'rd, 'rs, 'rt");
1408 break;
1409 case MOVCI:
1410 if (instr->Bit(16)) {
1411 Format(instr, "movt 'rd, 'rs, 'bc");
1412 } else {
1413 Format(instr, "movf 'rd, 'rs, 'bc");
1414 }
1415 break;
1416 case SELEQZ_S:
1417 Format(instr, "seleqz 'rd, 'rs, 'rt");
1418 break;
1419 case SELNEZ_S:
1420 Format(instr, "selnez 'rd, 'rs, 'rt");
1421 break;
1422 default:
1423 UNREACHABLE();
1424 }
1425}
1426
1427
1428void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) {
1429 switch (instr->FunctionFieldRaw()) {
1430 case MUL:
1431 Format(instr, "mul 'rd, 'rs, 'rt");
1432 break;
1433 case CLZ:
1434 if (kArchVariant != kMips64r6) {
1435 Format(instr, "clz 'rd, 'rs");
1436 }
1437 break;
1438 case DCLZ:
1439 if (kArchVariant != kMips64r6) {
1440 Format(instr, "dclz 'rd, 'rs");
1441 }
1442 break;
1443 default:
1444 UNREACHABLE();
1445 }
1446}
1447
1448
1449void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
1450 switch (instr->FunctionFieldRaw()) {
1451 case INS: {
1452 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
1453 break;
1454 }
1455 case EXT: {
1456 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
1457 break;
1458 }
1459 case DEXT: {
1460 Format(instr, "dext 'rt, 'rs, 'sa, 'ss1");
1461 break;
1462 }
1463 case BSHFL: {
1464 int sa = instr->SaFieldRaw() >> kSaShift;
1465 switch (sa) {
1466 case BITSWAP: {
1467 Format(instr, "bitswap 'rd, 'rt");
1468 break;
1469 }
1470 case SEB:
1471 case SEH:
1472 case WSBH:
1473 UNREACHABLE();
1474 break;
1475 default: {
1476 sa >>= kBp2Bits;
1477 switch (sa) {
1478 case ALIGN: {
1479 Format(instr, "align 'rd, 'rs, 'rt, 'bp2");
1480 break;
1481 }
1482 default:
1483 UNREACHABLE();
1484 break;
1485 }
1486 break;
1487 }
1488 }
1489 break;
1490 }
1491 case DBSHFL: {
1492 int sa = instr->SaFieldRaw() >> kSaShift;
1493 switch (sa) {
1494 case DBITSWAP: {
1495 switch (instr->SaFieldRaw() >> kSaShift) {
1496 case DBITSWAP_SA:
1497 Format(instr, "dbitswap 'rd, 'rt");
1498 break;
1499 default:
1500 UNREACHABLE();
1501 break;
1502 }
1503 break;
1504 }
1505 case DSBH:
1506 case DSHD:
1507 UNREACHABLE();
1508 break;
1509 default: {
1510 sa >>= kBp3Bits;
1511 switch (sa) {
1512 case DALIGN: {
1513 Format(instr, "dalign 'rd, 'rs, 'rt, 'bp3");
1514 break;
1515 }
1516 default:
1517 UNREACHABLE();
1518 break;
1519 }
1520 break;
1521 }
1522 }
1523 break;
1524 }
1525 default:
1526 UNREACHABLE();
1527 }
1528}
1529
1530
1531int Decoder::DecodeTypeRegister(Instruction* instr) {
1532 switch (instr->OpcodeFieldRaw()) {
1533 case COP1: // Coprocessor instructions.
1534 DecodeTypeRegisterCOP1(instr);
1535 break;
1536 case COP1X:
1537 DecodeTypeRegisterCOP1X(instr);
1538 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539 case SPECIAL:
1540 switch (instr->FunctionFieldRaw()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 case BREAK:
1542 return DecodeBreakInstr(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001543 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544 DecodeTypeRegisterSPECIAL(instr);
1545 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001546 }
1547 break;
1548 case SPECIAL2:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001549 DecodeTypeRegisterSPECIAL2(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550 break;
1551 case SPECIAL3:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552 DecodeTypeRegisterSPECIAL3(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001553 break;
1554 default:
1555 UNREACHABLE();
1556 }
1557 return Instruction::kInstrSize;
1558}
1559
1560
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001561void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
1562 switch (instr->RsFieldRaw()) {
1563 case BC1:
1564 if (instr->FBtrueValue()) {
1565 Format(instr, "bc1t 'bc, 'imm16u -> 'imm16p4s2");
1566 } else {
1567 Format(instr, "bc1f 'bc, 'imm16u -> 'imm16p4s2");
1568 }
1569 break;
1570 case BC1EQZ:
1571 Format(instr, "bc1eqz 'ft, 'imm16u -> 'imm16p4s2");
1572 break;
1573 case BC1NEZ:
1574 Format(instr, "bc1nez 'ft, 'imm16u -> 'imm16p4s2");
1575 break;
1576 default:
1577 UNREACHABLE();
1578 }
1579}
1580
1581
1582void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) {
1583 switch (instr->RtFieldRaw()) {
1584 case BLTZ:
1585 Format(instr, "bltz 'rs, 'imm16u -> 'imm16p4s2");
1586 break;
1587 case BLTZAL:
1588 Format(instr, "bltzal 'rs, 'imm16u -> 'imm16p4s2");
1589 break;
1590 case BGEZ:
1591 Format(instr, "bgez 'rs, 'imm16u -> 'imm16p4s2");
1592 break;
1593 case BGEZAL: {
1594 if (instr->RsValue() == 0)
1595 Format(instr, "bal 'imm16s -> 'imm16p4s2");
1596 else
1597 Format(instr, "bgezal 'rs, 'imm16u -> 'imm16p4s2");
1598 break;
1599 }
1600 case BGEZALL:
1601 Format(instr, "bgezall 'rs, 'imm16u -> 'imm16p4s2");
1602 break;
1603 case DAHI:
1604 Format(instr, "dahi 'rs, 'imm16x");
1605 break;
1606 case DATI:
1607 Format(instr, "dati 'rs, 'imm16x");
1608 break;
1609 default:
1610 UNREACHABLE();
1611 }
1612}
1613
1614
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001615void Decoder::DecodeTypeImmediate(Instruction* instr) {
1616 switch (instr->OpcodeFieldRaw()) {
1617 case COP1:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001618 DecodeTypeImmediateCOP1(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001619 break; // Case COP1.
1620 // ------------- REGIMM class.
1621 case REGIMM:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001622 DecodeTypeImmediateREGIMM(instr);
1623 break; // Case REGIMM.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001624 // ------------- Branch instructions.
1625 case BEQ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001626 Format(instr, "beq 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1627 break;
1628 case BC:
1629 Format(instr, "bc 'imm26s -> 'imm26p4s2");
1630 break;
1631 case BALC:
1632 Format(instr, "balc 'imm26s -> 'imm26p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001633 break;
1634 case BNE:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001635 Format(instr, "bne 'rs, 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001636 break;
1637 case BLEZ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001638 if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
1639 Format(instr, "blez 'rs, 'imm16u -> 'imm16p4s2");
1640 } else if ((instr->RtValue() != instr->RsValue()) &&
1641 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1642 Format(instr, "bgeuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1643 } else if ((instr->RtValue() == instr->RsValue()) &&
1644 (instr->RtValue() != 0)) {
1645 Format(instr, "bgezalc 'rs, 'imm16u -> 'imm16p4s2");
1646 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1647 Format(instr, "blezalc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001648 } else {
1649 UNREACHABLE();
1650 }
1651 break;
1652 case BGTZ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001653 if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
1654 Format(instr, "bgtz 'rs, 'imm16u -> 'imm16p4s2");
1655 } else if ((instr->RtValue() != instr->RsValue()) &&
1656 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1657 Format(instr, "bltuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1658 } else if ((instr->RtValue() == instr->RsValue()) &&
1659 (instr->RtValue() != 0)) {
1660 Format(instr, "bltzalc 'rt, 'imm16u -> 'imm16p4s2");
1661 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1662 Format(instr, "bgtzalc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001663 } else {
1664 UNREACHABLE();
1665 }
1666 break;
1667 case BLEZL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001668 if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
1669 Format(instr, "bgezc 'rt, 'imm16u -> 'imm16p4s2");
1670 } else if ((instr->RtValue() != instr->RsValue()) &&
1671 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1672 Format(instr, "bgec 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1673 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1674 Format(instr, "blezc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001675 } else {
1676 UNREACHABLE();
1677 }
1678 break;
1679 case BGTZL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001680 if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
1681 Format(instr, "bltzc 'rt, 'imm16u -> 'imm16p4s2");
1682 } else if ((instr->RtValue() != instr->RsValue()) &&
1683 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1684 Format(instr, "bltc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1685 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1686 Format(instr, "bgtzc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001687 } else {
1688 UNREACHABLE();
1689 }
1690 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001691 case POP66:
1692 if (instr->RsValue() == JIC) {
1693 Format(instr, "jic 'rt, 'imm16s");
1694 } else {
1695 Format(instr, "beqzc 'rs, 'imm21s -> 'imm21p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001696 }
1697 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001698 case POP76:
1699 if (instr->RsValue() == JIALC) {
1700 Format(instr, "jialc 'rt, 'imm16s");
1701 } else {
1702 Format(instr, "bnezc 'rs, 'imm21s -> 'imm21p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001703 }
1704 break;
1705 // ------------- Arithmetic instructions.
1706 case ADDI:
1707 if (kArchVariant != kMips64r6) {
1708 Format(instr, "addi 'rt, 'rs, 'imm16s");
1709 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001710 int rs_reg = instr->RsValue();
1711 int rt_reg = instr->RtValue();
1712 // Check if BOVC, BEQZALC or BEQC instruction.
1713 if (rs_reg >= rt_reg) {
1714 Format(instr, "bovc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001715 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001716 DCHECK(rt_reg > 0);
1717 if (rs_reg == 0) {
1718 Format(instr, "beqzalc 'rt, 'imm16s -> 'imm16p4s2");
1719 } else {
1720 Format(instr, "beqc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
1721 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001722 }
1723 }
1724 break;
1725 case DADDI:
1726 if (kArchVariant != kMips64r6) {
1727 Format(instr, "daddi 'rt, 'rs, 'imm16s");
1728 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001729 int rs_reg = instr->RsValue();
1730 int rt_reg = instr->RtValue();
1731 // Check if BNVC, BNEZALC or BNEC instruction.
1732 if (rs_reg >= rt_reg) {
1733 Format(instr, "bnvc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001734 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001735 DCHECK(rt_reg > 0);
1736 if (rs_reg == 0) {
1737 Format(instr, "bnezalc 'rt, 'imm16s -> 'imm16p4s2");
1738 } else {
1739 Format(instr, "bnec 'rs, 'rt, 'imm16s -> 'imm16p4s2");
1740 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001741 }
1742 }
1743 break;
1744 case ADDIU:
1745 Format(instr, "addiu 'rt, 'rs, 'imm16s");
1746 break;
1747 case DADDIU:
1748 Format(instr, "daddiu 'rt, 'rs, 'imm16s");
1749 break;
1750 case SLTI:
1751 Format(instr, "slti 'rt, 'rs, 'imm16s");
1752 break;
1753 case SLTIU:
1754 Format(instr, "sltiu 'rt, 'rs, 'imm16u");
1755 break;
1756 case ANDI:
1757 Format(instr, "andi 'rt, 'rs, 'imm16x");
1758 break;
1759 case ORI:
1760 Format(instr, "ori 'rt, 'rs, 'imm16x");
1761 break;
1762 case XORI:
1763 Format(instr, "xori 'rt, 'rs, 'imm16x");
1764 break;
1765 case LUI:
1766 if (kArchVariant != kMips64r6) {
1767 Format(instr, "lui 'rt, 'imm16x");
1768 } else {
1769 if (instr->RsValue() != 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001770 Format(instr, "aui 'rt, 'rs, 'imm16x");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001771 } else {
1772 Format(instr, "lui 'rt, 'imm16x");
1773 }
1774 }
1775 break;
1776 case DAUI:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001777 Format(instr, "daui 'rt, 'rs, 'imm16x");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001778 break;
1779 // ------------- Memory instructions.
1780 case LB:
1781 Format(instr, "lb 'rt, 'imm16s('rs)");
1782 break;
1783 case LH:
1784 Format(instr, "lh 'rt, 'imm16s('rs)");
1785 break;
1786 case LWL:
1787 Format(instr, "lwl 'rt, 'imm16s('rs)");
1788 break;
1789 case LDL:
1790 Format(instr, "ldl 'rt, 'imm16s('rs)");
1791 break;
1792 case LW:
1793 Format(instr, "lw 'rt, 'imm16s('rs)");
1794 break;
1795 case LWU:
1796 Format(instr, "lwu 'rt, 'imm16s('rs)");
1797 break;
1798 case LD:
1799 Format(instr, "ld 'rt, 'imm16s('rs)");
1800 break;
1801 case LBU:
1802 Format(instr, "lbu 'rt, 'imm16s('rs)");
1803 break;
1804 case LHU:
1805 Format(instr, "lhu 'rt, 'imm16s('rs)");
1806 break;
1807 case LWR:
1808 Format(instr, "lwr 'rt, 'imm16s('rs)");
1809 break;
1810 case LDR:
1811 Format(instr, "ldr 'rt, 'imm16s('rs)");
1812 break;
1813 case PREF:
1814 Format(instr, "pref 'rt, 'imm16s('rs)");
1815 break;
1816 case SB:
1817 Format(instr, "sb 'rt, 'imm16s('rs)");
1818 break;
1819 case SH:
1820 Format(instr, "sh 'rt, 'imm16s('rs)");
1821 break;
1822 case SWL:
1823 Format(instr, "swl 'rt, 'imm16s('rs)");
1824 break;
1825 case SW:
1826 Format(instr, "sw 'rt, 'imm16s('rs)");
1827 break;
1828 case SD:
1829 Format(instr, "sd 'rt, 'imm16s('rs)");
1830 break;
1831 case SWR:
1832 Format(instr, "swr 'rt, 'imm16s('rs)");
1833 break;
1834 case LWC1:
1835 Format(instr, "lwc1 'ft, 'imm16s('rs)");
1836 break;
1837 case LDC1:
1838 Format(instr, "ldc1 'ft, 'imm16s('rs)");
1839 break;
1840 case SWC1:
1841 Format(instr, "swc1 'ft, 'imm16s('rs)");
1842 break;
1843 case SDC1:
1844 Format(instr, "sdc1 'ft, 'imm16s('rs)");
1845 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001846 case PCREL: {
1847 int32_t imm21 = instr->Imm21Value();
1848 // rt field: 5-bits checking
1849 uint8_t rt = (imm21 >> kImm16Bits);
1850 switch (rt) {
1851 case ALUIPC:
1852 Format(instr, "aluipc 'rs, 'imm16s");
1853 break;
1854 case AUIPC:
1855 Format(instr, "auipc 'rs, 'imm16s");
1856 break;
1857 default: {
1858 // rt field: checking of the most significant 3-bits
1859 rt = (imm21 >> kImm18Bits);
1860 switch (rt) {
1861 case LDPC:
1862 Format(instr, "ldpc 'rs, 'imm18s");
1863 break;
1864 default: {
1865 // rt field: checking of the most significant 2-bits
1866 rt = (imm21 >> kImm19Bits);
1867 switch (rt) {
1868 case LWUPC:
1869 Format(instr, "lwupc 'rs, 'imm19s");
1870 break;
1871 case LWPC:
1872 Format(instr, "lwpc 'rs, 'imm19s");
1873 break;
1874 case ADDIUPC:
1875 Format(instr, "addiupc 'rs, 'imm19s");
1876 break;
1877 default:
1878 UNREACHABLE();
1879 break;
1880 }
1881 break;
1882 }
1883 }
1884 break;
1885 }
1886 }
1887 break;
1888 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001889 default:
1890 printf("a 0x%x \n", instr->OpcodeFieldRaw());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001891 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001892 break;
1893 }
1894}
1895
1896
1897void Decoder::DecodeTypeJump(Instruction* instr) {
1898 switch (instr->OpcodeFieldRaw()) {
1899 case J:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001900 Format(instr, "j 'imm26x -> 'imm26j");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001901 break;
1902 case JAL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001903 Format(instr, "jal 'imm26x -> 'imm26j");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001904 break;
1905 default:
1906 UNREACHABLE();
1907 }
1908}
1909
1910
1911// Disassemble the instruction at *instr_ptr into the output buffer.
1912// All instructions are one word long, except for the simulator
1913// psuedo-instruction stop(msg). For that one special case, we return
1914// size larger than one kInstrSize.
1915int Decoder::InstructionDecode(byte* instr_ptr) {
1916 Instruction* instr = Instruction::At(instr_ptr);
1917 // Print raw instruction bytes.
1918 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1919 "%08x ",
1920 instr->InstructionBits());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001921 switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922 case Instruction::kRegisterType: {
1923 return DecodeTypeRegister(instr);
1924 }
1925 case Instruction::kImmediateType: {
1926 DecodeTypeImmediate(instr);
1927 break;
1928 }
1929 case Instruction::kJumpType: {
1930 DecodeTypeJump(instr);
1931 break;
1932 }
1933 default: {
1934 Format(instr, "UNSUPPORTED");
1935 UNSUPPORTED_MIPS();
1936 }
1937 }
1938 return Instruction::kInstrSize;
1939}
1940
1941
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001942} // namespace internal
1943} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001944
1945
1946//------------------------------------------------------------------------------
1947
1948namespace disasm {
1949
1950const char* NameConverter::NameOfAddress(byte* addr) const {
1951 v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1952 return tmp_buffer_.start();
1953}
1954
1955
1956const char* NameConverter::NameOfConstant(byte* addr) const {
1957 return NameOfAddress(addr);
1958}
1959
1960
1961const char* NameConverter::NameOfCPURegister(int reg) const {
1962 return v8::internal::Registers::Name(reg);
1963}
1964
1965
1966const char* NameConverter::NameOfXMMRegister(int reg) const {
1967 return v8::internal::FPURegisters::Name(reg);
1968}
1969
1970
1971const char* NameConverter::NameOfByteCPURegister(int reg) const {
1972 UNREACHABLE(); // MIPS does not have the concept of a byte register.
1973 return "nobytereg";
1974}
1975
1976
1977const char* NameConverter::NameInCode(byte* addr) const {
1978 // The default name converter is called for unknown code. So we will not try
1979 // to access any memory.
1980 return "";
1981}
1982
1983
1984//------------------------------------------------------------------------------
1985
1986Disassembler::Disassembler(const NameConverter& converter)
1987 : converter_(converter) {}
1988
1989
1990Disassembler::~Disassembler() {}
1991
1992
1993int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1994 byte* instruction) {
1995 v8::internal::Decoder d(converter_, buffer);
1996 return d.InstructionDecode(instruction);
1997}
1998
1999
2000// The MIPS assembler does not currently use constant pools.
2001int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2002 return -1;
2003}
2004
2005
2006void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
2007 NameConverter converter;
2008 Disassembler d(converter);
2009 for (byte* pc = begin; pc < end;) {
2010 v8::internal::EmbeddedVector<char, 128> buffer;
2011 buffer[0] = '\0';
2012 byte* prev_pc = pc;
2013 pc += d.InstructionDecode(buffer, pc);
2014 v8::internal::PrintF(f, "%p %08x %s\n",
2015 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
2016 }
2017}
2018
2019
2020#undef UNSUPPORTED
2021
2022} // namespace disasm
2023
2024#endif // V8_TARGET_ARCH_MIPS64