blob: 1917526c4220b9b7953a51a3862047eef8408e8e [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 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001460 case SEB: {
1461 Format(instr, "seb 'rd, 'rt");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001462 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001463 }
1464 case SEH: {
1465 Format(instr, "seh 'rd, 'rt");
1466 break;
1467 }
1468 case WSBH: {
1469 Format(instr, "wsbh 'rd, 'rt");
1470 break;
1471 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001472 default: {
1473 sa >>= kBp2Bits;
1474 switch (sa) {
1475 case ALIGN: {
1476 Format(instr, "align 'rd, 'rs, 'rt, 'bp2");
1477 break;
1478 }
1479 default:
1480 UNREACHABLE();
1481 break;
1482 }
1483 break;
1484 }
1485 }
1486 break;
1487 }
1488 case DBSHFL: {
1489 int sa = instr->SaFieldRaw() >> kSaShift;
1490 switch (sa) {
1491 case DBITSWAP: {
1492 switch (instr->SaFieldRaw() >> kSaShift) {
1493 case DBITSWAP_SA:
1494 Format(instr, "dbitswap 'rd, 'rt");
1495 break;
1496 default:
1497 UNREACHABLE();
1498 break;
1499 }
1500 break;
1501 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001502 case DSBH: {
1503 Format(instr, "dsbh 'rd, 'rt");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001505 }
1506 case DSHD: {
1507 Format(instr, "dshd 'rd, 'rt");
1508 break;
1509 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001510 default: {
1511 sa >>= kBp3Bits;
1512 switch (sa) {
1513 case DALIGN: {
1514 Format(instr, "dalign 'rd, 'rs, 'rt, 'bp3");
1515 break;
1516 }
1517 default:
1518 UNREACHABLE();
1519 break;
1520 }
1521 break;
1522 }
1523 }
1524 break;
1525 }
1526 default:
1527 UNREACHABLE();
1528 }
1529}
1530
1531
1532int Decoder::DecodeTypeRegister(Instruction* instr) {
1533 switch (instr->OpcodeFieldRaw()) {
1534 case COP1: // Coprocessor instructions.
1535 DecodeTypeRegisterCOP1(instr);
1536 break;
1537 case COP1X:
1538 DecodeTypeRegisterCOP1X(instr);
1539 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 case SPECIAL:
1541 switch (instr->FunctionFieldRaw()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001542 case BREAK:
1543 return DecodeBreakInstr(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001545 DecodeTypeRegisterSPECIAL(instr);
1546 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001547 }
1548 break;
1549 case SPECIAL2:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001550 DecodeTypeRegisterSPECIAL2(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001551 break;
1552 case SPECIAL3:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001553 DecodeTypeRegisterSPECIAL3(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001554 break;
1555 default:
1556 UNREACHABLE();
1557 }
1558 return Instruction::kInstrSize;
1559}
1560
1561
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001562void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
1563 switch (instr->RsFieldRaw()) {
1564 case BC1:
1565 if (instr->FBtrueValue()) {
1566 Format(instr, "bc1t 'bc, 'imm16u -> 'imm16p4s2");
1567 } else {
1568 Format(instr, "bc1f 'bc, 'imm16u -> 'imm16p4s2");
1569 }
1570 break;
1571 case BC1EQZ:
1572 Format(instr, "bc1eqz 'ft, 'imm16u -> 'imm16p4s2");
1573 break;
1574 case BC1NEZ:
1575 Format(instr, "bc1nez 'ft, 'imm16u -> 'imm16p4s2");
1576 break;
1577 default:
1578 UNREACHABLE();
1579 }
1580}
1581
1582
1583void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) {
1584 switch (instr->RtFieldRaw()) {
1585 case BLTZ:
1586 Format(instr, "bltz 'rs, 'imm16u -> 'imm16p4s2");
1587 break;
1588 case BLTZAL:
1589 Format(instr, "bltzal 'rs, 'imm16u -> 'imm16p4s2");
1590 break;
1591 case BGEZ:
1592 Format(instr, "bgez 'rs, 'imm16u -> 'imm16p4s2");
1593 break;
1594 case BGEZAL: {
1595 if (instr->RsValue() == 0)
1596 Format(instr, "bal 'imm16s -> 'imm16p4s2");
1597 else
1598 Format(instr, "bgezal 'rs, 'imm16u -> 'imm16p4s2");
1599 break;
1600 }
1601 case BGEZALL:
1602 Format(instr, "bgezall 'rs, 'imm16u -> 'imm16p4s2");
1603 break;
1604 case DAHI:
1605 Format(instr, "dahi 'rs, 'imm16x");
1606 break;
1607 case DATI:
1608 Format(instr, "dati 'rs, 'imm16x");
1609 break;
1610 default:
1611 UNREACHABLE();
1612 }
1613}
1614
1615
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001616void Decoder::DecodeTypeImmediate(Instruction* instr) {
1617 switch (instr->OpcodeFieldRaw()) {
1618 case COP1:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001619 DecodeTypeImmediateCOP1(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001620 break; // Case COP1.
1621 // ------------- REGIMM class.
1622 case REGIMM:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001623 DecodeTypeImmediateREGIMM(instr);
1624 break; // Case REGIMM.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001625 // ------------- Branch instructions.
1626 case BEQ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001627 Format(instr, "beq 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1628 break;
1629 case BC:
1630 Format(instr, "bc 'imm26s -> 'imm26p4s2");
1631 break;
1632 case BALC:
1633 Format(instr, "balc 'imm26s -> 'imm26p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001634 break;
1635 case BNE:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001636 Format(instr, "bne 'rs, 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001637 break;
1638 case BLEZ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001639 if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
1640 Format(instr, "blez 'rs, 'imm16u -> 'imm16p4s2");
1641 } else if ((instr->RtValue() != instr->RsValue()) &&
1642 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1643 Format(instr, "bgeuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1644 } else if ((instr->RtValue() == instr->RsValue()) &&
1645 (instr->RtValue() != 0)) {
1646 Format(instr, "bgezalc 'rs, 'imm16u -> 'imm16p4s2");
1647 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1648 Format(instr, "blezalc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001649 } else {
1650 UNREACHABLE();
1651 }
1652 break;
1653 case BGTZ:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001654 if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
1655 Format(instr, "bgtz 'rs, 'imm16u -> 'imm16p4s2");
1656 } else if ((instr->RtValue() != instr->RsValue()) &&
1657 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1658 Format(instr, "bltuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1659 } else if ((instr->RtValue() == instr->RsValue()) &&
1660 (instr->RtValue() != 0)) {
1661 Format(instr, "bltzalc 'rt, 'imm16u -> 'imm16p4s2");
1662 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1663 Format(instr, "bgtzalc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001664 } else {
1665 UNREACHABLE();
1666 }
1667 break;
1668 case BLEZL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001669 if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
1670 Format(instr, "bgezc 'rt, 'imm16u -> 'imm16p4s2");
1671 } else if ((instr->RtValue() != instr->RsValue()) &&
1672 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1673 Format(instr, "bgec 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1674 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1675 Format(instr, "blezc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001676 } else {
1677 UNREACHABLE();
1678 }
1679 break;
1680 case BGTZL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001681 if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
1682 Format(instr, "bltzc 'rt, 'imm16u -> 'imm16p4s2");
1683 } else if ((instr->RtValue() != instr->RsValue()) &&
1684 (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
1685 Format(instr, "bltc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
1686 } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
1687 Format(instr, "bgtzc 'rt, 'imm16u -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001688 } else {
1689 UNREACHABLE();
1690 }
1691 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001692 case POP66:
1693 if (instr->RsValue() == JIC) {
1694 Format(instr, "jic 'rt, 'imm16s");
1695 } else {
1696 Format(instr, "beqzc 'rs, 'imm21s -> 'imm21p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001697 }
1698 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001699 case POP76:
1700 if (instr->RsValue() == JIALC) {
1701 Format(instr, "jialc 'rt, 'imm16s");
1702 } else {
1703 Format(instr, "bnezc 'rs, 'imm21s -> 'imm21p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 }
1705 break;
1706 // ------------- Arithmetic instructions.
1707 case ADDI:
1708 if (kArchVariant != kMips64r6) {
1709 Format(instr, "addi 'rt, 'rs, 'imm16s");
1710 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001711 int rs_reg = instr->RsValue();
1712 int rt_reg = instr->RtValue();
1713 // Check if BOVC, BEQZALC or BEQC instruction.
1714 if (rs_reg >= rt_reg) {
1715 Format(instr, "bovc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001716 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001717 DCHECK(rt_reg > 0);
1718 if (rs_reg == 0) {
1719 Format(instr, "beqzalc 'rt, 'imm16s -> 'imm16p4s2");
1720 } else {
1721 Format(instr, "beqc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
1722 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001723 }
1724 }
1725 break;
1726 case DADDI:
1727 if (kArchVariant != kMips64r6) {
1728 Format(instr, "daddi 'rt, 'rs, 'imm16s");
1729 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001730 int rs_reg = instr->RsValue();
1731 int rt_reg = instr->RtValue();
1732 // Check if BNVC, BNEZALC or BNEC instruction.
1733 if (rs_reg >= rt_reg) {
1734 Format(instr, "bnvc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001735 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001736 DCHECK(rt_reg > 0);
1737 if (rs_reg == 0) {
1738 Format(instr, "bnezalc 'rt, 'imm16s -> 'imm16p4s2");
1739 } else {
1740 Format(instr, "bnec 'rs, 'rt, 'imm16s -> 'imm16p4s2");
1741 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001742 }
1743 }
1744 break;
1745 case ADDIU:
1746 Format(instr, "addiu 'rt, 'rs, 'imm16s");
1747 break;
1748 case DADDIU:
1749 Format(instr, "daddiu 'rt, 'rs, 'imm16s");
1750 break;
1751 case SLTI:
1752 Format(instr, "slti 'rt, 'rs, 'imm16s");
1753 break;
1754 case SLTIU:
1755 Format(instr, "sltiu 'rt, 'rs, 'imm16u");
1756 break;
1757 case ANDI:
1758 Format(instr, "andi 'rt, 'rs, 'imm16x");
1759 break;
1760 case ORI:
1761 Format(instr, "ori 'rt, 'rs, 'imm16x");
1762 break;
1763 case XORI:
1764 Format(instr, "xori 'rt, 'rs, 'imm16x");
1765 break;
1766 case LUI:
1767 if (kArchVariant != kMips64r6) {
1768 Format(instr, "lui 'rt, 'imm16x");
1769 } else {
1770 if (instr->RsValue() != 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001771 Format(instr, "aui 'rt, 'rs, 'imm16x");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001772 } else {
1773 Format(instr, "lui 'rt, 'imm16x");
1774 }
1775 }
1776 break;
1777 case DAUI:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001778 Format(instr, "daui 'rt, 'rs, 'imm16x");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001779 break;
1780 // ------------- Memory instructions.
1781 case LB:
1782 Format(instr, "lb 'rt, 'imm16s('rs)");
1783 break;
1784 case LH:
1785 Format(instr, "lh 'rt, 'imm16s('rs)");
1786 break;
1787 case LWL:
1788 Format(instr, "lwl 'rt, 'imm16s('rs)");
1789 break;
1790 case LDL:
1791 Format(instr, "ldl 'rt, 'imm16s('rs)");
1792 break;
1793 case LW:
1794 Format(instr, "lw 'rt, 'imm16s('rs)");
1795 break;
1796 case LWU:
1797 Format(instr, "lwu 'rt, 'imm16s('rs)");
1798 break;
1799 case LD:
1800 Format(instr, "ld 'rt, 'imm16s('rs)");
1801 break;
1802 case LBU:
1803 Format(instr, "lbu 'rt, 'imm16s('rs)");
1804 break;
1805 case LHU:
1806 Format(instr, "lhu 'rt, 'imm16s('rs)");
1807 break;
1808 case LWR:
1809 Format(instr, "lwr 'rt, 'imm16s('rs)");
1810 break;
1811 case LDR:
1812 Format(instr, "ldr 'rt, 'imm16s('rs)");
1813 break;
1814 case PREF:
1815 Format(instr, "pref 'rt, 'imm16s('rs)");
1816 break;
1817 case SB:
1818 Format(instr, "sb 'rt, 'imm16s('rs)");
1819 break;
1820 case SH:
1821 Format(instr, "sh 'rt, 'imm16s('rs)");
1822 break;
1823 case SWL:
1824 Format(instr, "swl 'rt, 'imm16s('rs)");
1825 break;
1826 case SW:
1827 Format(instr, "sw 'rt, 'imm16s('rs)");
1828 break;
1829 case SD:
1830 Format(instr, "sd 'rt, 'imm16s('rs)");
1831 break;
1832 case SWR:
1833 Format(instr, "swr 'rt, 'imm16s('rs)");
1834 break;
1835 case LWC1:
1836 Format(instr, "lwc1 'ft, 'imm16s('rs)");
1837 break;
1838 case LDC1:
1839 Format(instr, "ldc1 'ft, 'imm16s('rs)");
1840 break;
1841 case SWC1:
1842 Format(instr, "swc1 'ft, 'imm16s('rs)");
1843 break;
1844 case SDC1:
1845 Format(instr, "sdc1 'ft, 'imm16s('rs)");
1846 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001847 case PCREL: {
1848 int32_t imm21 = instr->Imm21Value();
1849 // rt field: 5-bits checking
1850 uint8_t rt = (imm21 >> kImm16Bits);
1851 switch (rt) {
1852 case ALUIPC:
1853 Format(instr, "aluipc 'rs, 'imm16s");
1854 break;
1855 case AUIPC:
1856 Format(instr, "auipc 'rs, 'imm16s");
1857 break;
1858 default: {
1859 // rt field: checking of the most significant 3-bits
1860 rt = (imm21 >> kImm18Bits);
1861 switch (rt) {
1862 case LDPC:
1863 Format(instr, "ldpc 'rs, 'imm18s");
1864 break;
1865 default: {
1866 // rt field: checking of the most significant 2-bits
1867 rt = (imm21 >> kImm19Bits);
1868 switch (rt) {
1869 case LWUPC:
1870 Format(instr, "lwupc 'rs, 'imm19s");
1871 break;
1872 case LWPC:
1873 Format(instr, "lwpc 'rs, 'imm19s");
1874 break;
1875 case ADDIUPC:
1876 Format(instr, "addiupc 'rs, 'imm19s");
1877 break;
1878 default:
1879 UNREACHABLE();
1880 break;
1881 }
1882 break;
1883 }
1884 }
1885 break;
1886 }
1887 }
1888 break;
1889 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001890 default:
1891 printf("a 0x%x \n", instr->OpcodeFieldRaw());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001892 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001893 break;
1894 }
1895}
1896
1897
1898void Decoder::DecodeTypeJump(Instruction* instr) {
1899 switch (instr->OpcodeFieldRaw()) {
1900 case J:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001901 Format(instr, "j 'imm26x -> 'imm26j");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001902 break;
1903 case JAL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001904 Format(instr, "jal 'imm26x -> 'imm26j");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001905 break;
1906 default:
1907 UNREACHABLE();
1908 }
1909}
1910
1911
1912// Disassemble the instruction at *instr_ptr into the output buffer.
1913// All instructions are one word long, except for the simulator
1914// psuedo-instruction stop(msg). For that one special case, we return
1915// size larger than one kInstrSize.
1916int Decoder::InstructionDecode(byte* instr_ptr) {
1917 Instruction* instr = Instruction::At(instr_ptr);
1918 // Print raw instruction bytes.
1919 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1920 "%08x ",
1921 instr->InstructionBits());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001922 switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001923 case Instruction::kRegisterType: {
1924 return DecodeTypeRegister(instr);
1925 }
1926 case Instruction::kImmediateType: {
1927 DecodeTypeImmediate(instr);
1928 break;
1929 }
1930 case Instruction::kJumpType: {
1931 DecodeTypeJump(instr);
1932 break;
1933 }
1934 default: {
1935 Format(instr, "UNSUPPORTED");
1936 UNSUPPORTED_MIPS();
1937 }
1938 }
1939 return Instruction::kInstrSize;
1940}
1941
1942
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001943} // namespace internal
1944} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001945
1946
1947//------------------------------------------------------------------------------
1948
1949namespace disasm {
1950
1951const char* NameConverter::NameOfAddress(byte* addr) const {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001952 v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001953 return tmp_buffer_.start();
1954}
1955
1956
1957const char* NameConverter::NameOfConstant(byte* addr) const {
1958 return NameOfAddress(addr);
1959}
1960
1961
1962const char* NameConverter::NameOfCPURegister(int reg) const {
1963 return v8::internal::Registers::Name(reg);
1964}
1965
1966
1967const char* NameConverter::NameOfXMMRegister(int reg) const {
1968 return v8::internal::FPURegisters::Name(reg);
1969}
1970
1971
1972const char* NameConverter::NameOfByteCPURegister(int reg) const {
1973 UNREACHABLE(); // MIPS does not have the concept of a byte register.
1974 return "nobytereg";
1975}
1976
1977
1978const char* NameConverter::NameInCode(byte* addr) const {
1979 // The default name converter is called for unknown code. So we will not try
1980 // to access any memory.
1981 return "";
1982}
1983
1984
1985//------------------------------------------------------------------------------
1986
1987Disassembler::Disassembler(const NameConverter& converter)
1988 : converter_(converter) {}
1989
1990
1991Disassembler::~Disassembler() {}
1992
1993
1994int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1995 byte* instruction) {
1996 v8::internal::Decoder d(converter_, buffer);
1997 return d.InstructionDecode(instruction);
1998}
1999
2000
2001// The MIPS assembler does not currently use constant pools.
2002int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2003 return -1;
2004}
2005
2006
2007void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
2008 NameConverter converter;
2009 Disassembler d(converter);
2010 for (byte* pc = begin; pc < end;) {
2011 v8::internal::EmbeddedVector<char, 128> buffer;
2012 buffer[0] = '\0';
2013 byte* prev_pc = pc;
2014 pc += d.InstructionDecode(buffer, pc);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002015 v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc),
2016 *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002017 }
2018}
2019
2020
2021#undef UNSUPPORTED
2022
2023} // namespace disasm
2024
2025#endif // V8_TARGET_ARCH_MIPS64