blob: 0eca71f2b84124970062184fa029f11a5190fa2c [file] [log] [blame]
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +00001// Copyright 2012 the V8 project authors. All rights reserved.
ager@chromium.org5c838252010-02-19 08:53:10 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// A Disassembler object is used to disassemble a block of code instruction by
29// instruction. The default implementation of the NameConverter object can be
30// overriden to modify register names or to do symbol lookup on addresses.
31//
32// The example below will disassemble a block of code and print it to stdout.
33//
34// NameConverter converter;
35// Disassembler d(converter);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000036// for (byte* pc = begin; pc < end;) {
lrn@chromium.org7516f052011-03-30 08:52:27 +000037// v8::internal::EmbeddedVector<char, 256> buffer;
38// byte* prev_pc = pc;
39// pc += d.InstructionDecode(buffer, pc);
ager@chromium.org5c838252010-02-19 08:53:10 +000040// printf("%p %08x %s\n",
41// prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
42// }
43//
44// The Disassembler class also has a convenience method to disassemble a block
45// of code into a FILE*, meaning that the above functionality could also be
46// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
47
48
49#include <assert.h>
50#include <stdio.h>
51#include <stdarg.h>
52#include <string.h>
53#ifndef WIN32
54#include <stdint.h>
55#endif
56
57#include "v8.h"
58
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +000059#if defined(V8_TARGET_ARCH_MIPS)
60
lrn@chromium.org7516f052011-03-30 08:52:27 +000061#include "mips/constants-mips.h"
ager@chromium.org5c838252010-02-19 08:53:10 +000062#include "disasm.h"
63#include "macro-assembler.h"
64#include "platform.h"
65
lrn@chromium.org7516f052011-03-30 08:52:27 +000066namespace v8 {
67namespace internal {
ager@chromium.org5c838252010-02-19 08:53:10 +000068
69//------------------------------------------------------------------------------
70
71// Decoder decodes and disassembles instructions into an output buffer.
72// It uses the converter to convert register names and call destinations into
73// more informative description.
74class Decoder {
75 public:
76 Decoder(const disasm::NameConverter& converter,
77 v8::internal::Vector<char> out_buffer)
78 : converter_(converter),
79 out_buffer_(out_buffer),
80 out_buffer_pos_(0) {
81 out_buffer_[out_buffer_pos_] = '\0';
82 }
83
84 ~Decoder() {}
85
86 // Writes one disassembled instruction into 'buffer' (0-terminated).
87 // Returns the length of the disassembled machine instruction in bytes.
karlklose@chromium.org83a47282011-05-11 11:54:09 +000088 int InstructionDecode(byte* instruction);
ager@chromium.org5c838252010-02-19 08:53:10 +000089
90 private:
91 // Bottleneck functions to print into the out_buffer.
92 void PrintChar(const char ch);
93 void Print(const char* str);
94
95 // Printing of common values.
96 void PrintRegister(int reg);
lrn@chromium.org7516f052011-03-30 08:52:27 +000097 void PrintFPURegister(int freg);
ager@chromium.org5c838252010-02-19 08:53:10 +000098 void PrintRs(Instruction* instr);
99 void PrintRt(Instruction* instr);
100 void PrintRd(Instruction* instr);
101 void PrintFs(Instruction* instr);
102 void PrintFt(Instruction* instr);
103 void PrintFd(Instruction* instr);
104 void PrintSa(Instruction* instr);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000105 void PrintSd(Instruction* instr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000106 void PrintSs1(Instruction* instr);
107 void PrintSs2(Instruction* instr);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000108 void PrintBc(Instruction* instr);
109 void PrintCc(Instruction* instr);
ager@chromium.org5c838252010-02-19 08:53:10 +0000110 void PrintFunction(Instruction* instr);
111 void PrintSecondaryField(Instruction* instr);
112 void PrintUImm16(Instruction* instr);
113 void PrintSImm16(Instruction* instr);
114 void PrintXImm16(Instruction* instr);
lrn@chromium.org34e60782011-09-15 07:25:40 +0000115 void PrintXImm26(Instruction* instr);
ager@chromium.org5c838252010-02-19 08:53:10 +0000116 void PrintCode(Instruction* instr); // For break and trap instructions.
117 // Printing of instruction name.
118 void PrintInstructionName(Instruction* instr);
119
120 // Handle formatting of instructions and their options.
121 int FormatRegister(Instruction* instr, const char* option);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000122 int FormatFPURegister(Instruction* instr, const char* option);
ager@chromium.org5c838252010-02-19 08:53:10 +0000123 int FormatOption(Instruction* instr, const char* option);
124 void Format(Instruction* instr, const char* format);
125 void Unknown(Instruction* instr);
126
127 // Each of these functions decodes one particular instruction type.
128 void DecodeTypeRegister(Instruction* instr);
129 void DecodeTypeImmediate(Instruction* instr);
130 void DecodeTypeJump(Instruction* instr);
131
132 const disasm::NameConverter& converter_;
133 v8::internal::Vector<char> out_buffer_;
134 int out_buffer_pos_;
135
136 DISALLOW_COPY_AND_ASSIGN(Decoder);
137};
138
139
140// Support for assertions in the Decoder formatting functions.
141#define STRING_STARTS_WITH(string, compare_string) \
142 (strncmp(string, compare_string, strlen(compare_string)) == 0)
143
144
145// Append the ch to the output buffer.
146void Decoder::PrintChar(const char ch) {
147 out_buffer_[out_buffer_pos_++] = ch;
148}
149
150
151// Append the str to the output buffer.
152void Decoder::Print(const char* str) {
153 char cur = *str++;
154 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
155 PrintChar(cur);
156 cur = *str++;
157 }
158 out_buffer_[out_buffer_pos_] = 0;
159}
160
161
162// Print the register name according to the active name converter.
163void Decoder::PrintRegister(int reg) {
164 Print(converter_.NameOfCPURegister(reg));
165}
166
167
168void Decoder::PrintRs(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000169 int reg = instr->RsValue();
ager@chromium.org5c838252010-02-19 08:53:10 +0000170 PrintRegister(reg);
171}
172
173
174void Decoder::PrintRt(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000175 int reg = instr->RtValue();
ager@chromium.org5c838252010-02-19 08:53:10 +0000176 PrintRegister(reg);
177}
178
179
180void Decoder::PrintRd(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000181 int reg = instr->RdValue();
ager@chromium.org5c838252010-02-19 08:53:10 +0000182 PrintRegister(reg);
183}
184
185
lrn@chromium.org7516f052011-03-30 08:52:27 +0000186// Print the FPUregister name according to the active name converter.
187void Decoder::PrintFPURegister(int freg) {
188 Print(converter_.NameOfXMMRegister(freg));
ager@chromium.org5c838252010-02-19 08:53:10 +0000189}
190
191
192void Decoder::PrintFs(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000193 int freg = instr->RsValue();
194 PrintFPURegister(freg);
ager@chromium.org5c838252010-02-19 08:53:10 +0000195}
196
197
198void Decoder::PrintFt(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000199 int freg = instr->RtValue();
200 PrintFPURegister(freg);
ager@chromium.org5c838252010-02-19 08:53:10 +0000201}
202
203
204void Decoder::PrintFd(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000205 int freg = instr->RdValue();
206 PrintFPURegister(freg);
ager@chromium.org5c838252010-02-19 08:53:10 +0000207}
208
209
210// Print the integer value of the sa field.
211void Decoder::PrintSa(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000212 int sa = instr->SaValue();
213 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
214}
215
216
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000217// Print the integer value of the rd field, when it is not used as reg.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000218void Decoder::PrintSd(Instruction* instr) {
219 int sd = instr->RdValue();
220 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd);
221}
222
223
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000224// Print the integer value of the rd field, when used as 'ext' size.
225void Decoder::PrintSs1(Instruction* instr) {
226 int ss = instr->RdValue();
227 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1);
228}
229
230
231// Print the integer value of the rd field, when used as 'ins' size.
232void Decoder::PrintSs2(Instruction* instr) {
233 int ss = instr->RdValue();
234 int pos = instr->SaValue();
235 out_buffer_pos_ +=
236 OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1);
237}
238
239
lrn@chromium.org7516f052011-03-30 08:52:27 +0000240// Print the integer value of the cc field for the bc1t/f instructions.
241void Decoder::PrintBc(Instruction* instr) {
242 int cc = instr->FBccValue();
243 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc);
244}
245
246
247// Print the integer value of the cc field for the FP compare instructions.
248void Decoder::PrintCc(Instruction* instr) {
249 int cc = instr->FCccValue();
250 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc);
ager@chromium.org5c838252010-02-19 08:53:10 +0000251}
252
253
254// Print 16-bit unsigned immediate value.
255void Decoder::PrintUImm16(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000256 int32_t imm = instr->Imm16Value();
257 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
ager@chromium.org5c838252010-02-19 08:53:10 +0000258}
259
260
261// Print 16-bit signed immediate value.
262void Decoder::PrintSImm16(Instruction* instr) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000263 int32_t imm = ((instr->Imm16Value()) << 16) >> 16;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000264 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
ager@chromium.org5c838252010-02-19 08:53:10 +0000265}
266
267
268// Print 16-bit hexa immediate value.
269void Decoder::PrintXImm16(Instruction* instr) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000270 int32_t imm = instr->Imm16Value();
271 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
ager@chromium.org5c838252010-02-19 08:53:10 +0000272}
273
274
275// Print 26-bit immediate value.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000276void Decoder::PrintXImm26(Instruction* instr) {
277 uint32_t imm = instr->Imm26Value() << kImmFieldShift;
278 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
ager@chromium.org5c838252010-02-19 08:53:10 +0000279}
280
281
282// Print 26-bit immediate value.
283void Decoder::PrintCode(Instruction* instr) {
284 if (instr->OpcodeFieldRaw() != SPECIAL)
285 return; // Not a break or trap instruction.
286 switch (instr->FunctionFieldRaw()) {
287 case BREAK: {
288 int32_t code = instr->Bits(25, 6);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000289 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
290 "0x%05x (%d)", code, code);
ager@chromium.org5c838252010-02-19 08:53:10 +0000291 break;
292 }
293 case TGE:
294 case TGEU:
295 case TLT:
296 case TLTU:
297 case TEQ:
298 case TNE: {
299 int32_t code = instr->Bits(15, 6);
300 out_buffer_pos_ +=
lrn@chromium.org7516f052011-03-30 08:52:27 +0000301 OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
ager@chromium.org5c838252010-02-19 08:53:10 +0000302 break;
303 }
304 default: // Not a break or trap instruction.
305 break;
306 };
307}
308
309
310// Printing of instruction name.
311void Decoder::PrintInstructionName(Instruction* instr) {
312}
313
314
315// Handle all register based formatting in this function to reduce the
316// complexity of FormatOption.
317int Decoder::FormatRegister(Instruction* instr, const char* format) {
318 ASSERT(format[0] == 'r');
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000319 if (format[1] == 's') { // 'rs: Rs register.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000320 int reg = instr->RsValue();
ager@chromium.org5c838252010-02-19 08:53:10 +0000321 PrintRegister(reg);
322 return 2;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000323 } else if (format[1] == 't') { // 'rt: rt register.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000324 int reg = instr->RtValue();
ager@chromium.org5c838252010-02-19 08:53:10 +0000325 PrintRegister(reg);
326 return 2;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000327 } else if (format[1] == 'd') { // 'rd: rd register.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000328 int reg = instr->RdValue();
ager@chromium.org5c838252010-02-19 08:53:10 +0000329 PrintRegister(reg);
330 return 2;
331 }
332 UNREACHABLE();
333 return -1;
334}
335
336
lrn@chromium.org7516f052011-03-30 08:52:27 +0000337// Handle all FPUregister based formatting in this function to reduce the
ager@chromium.org5c838252010-02-19 08:53:10 +0000338// complexity of FormatOption.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000339int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000340 ASSERT(format[0] == 'f');
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000341 if (format[1] == 's') { // 'fs: fs register.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000342 int reg = instr->FsValue();
343 PrintFPURegister(reg);
ager@chromium.org5c838252010-02-19 08:53:10 +0000344 return 2;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000345 } else if (format[1] == 't') { // 'ft: ft register.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000346 int reg = instr->FtValue();
347 PrintFPURegister(reg);
ager@chromium.org5c838252010-02-19 08:53:10 +0000348 return 2;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000349 } else if (format[1] == 'd') { // 'fd: fd register.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000350 int reg = instr->FdValue();
351 PrintFPURegister(reg);
ager@chromium.org5c838252010-02-19 08:53:10 +0000352 return 2;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000353 } else if (format[1] == 'r') { // 'fr: fr register.
354 int reg = instr->FrValue();
355 PrintFPURegister(reg);
356 return 2;
ager@chromium.org5c838252010-02-19 08:53:10 +0000357 }
358 UNREACHABLE();
359 return -1;
360}
361
362
363// FormatOption takes a formatting string and interprets it based on
364// the current instructions. The format string points to the first
365// character of the option string (the option escape has already been
366// consumed by the caller.) FormatOption returns the number of
367// characters that were consumed from the formatting string.
368int Decoder::FormatOption(Instruction* instr, const char* format) {
369 switch (format[0]) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000370 case 'c': { // 'code for break or trap instructions.
ager@chromium.org5c838252010-02-19 08:53:10 +0000371 ASSERT(STRING_STARTS_WITH(format, "code"));
372 PrintCode(instr);
373 return 4;
374 }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000375 case 'i': { // 'imm16u or 'imm26.
ager@chromium.org5c838252010-02-19 08:53:10 +0000376 if (format[3] == '1') {
377 ASSERT(STRING_STARTS_WITH(format, "imm16"));
378 if (format[5] == 's') {
379 ASSERT(STRING_STARTS_WITH(format, "imm16s"));
380 PrintSImm16(instr);
381 } else if (format[5] == 'u') {
382 ASSERT(STRING_STARTS_WITH(format, "imm16u"));
383 PrintSImm16(instr);
384 } else {
385 ASSERT(STRING_STARTS_WITH(format, "imm16x"));
386 PrintXImm16(instr);
387 }
388 return 6;
389 } else {
lrn@chromium.org34e60782011-09-15 07:25:40 +0000390 ASSERT(STRING_STARTS_WITH(format, "imm26x"));
391 PrintXImm26(instr);
392 return 6;
ager@chromium.org5c838252010-02-19 08:53:10 +0000393 }
394 }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000395 case 'r': { // 'r: registers.
ager@chromium.org5c838252010-02-19 08:53:10 +0000396 return FormatRegister(instr, format);
397 }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000398 case 'f': { // 'f: FPUregisters.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000399 return FormatFPURegister(instr, format);
ager@chromium.org5c838252010-02-19 08:53:10 +0000400 }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000401 case 's': { // 'sa.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000402 switch (format[1]) {
403 case 'a': {
404 ASSERT(STRING_STARTS_WITH(format, "sa"));
405 PrintSa(instr);
406 return 2;
407 }
408 case 'd': {
409 ASSERT(STRING_STARTS_WITH(format, "sd"));
410 PrintSd(instr);
411 return 2;
412 }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000413 case 's': {
414 if (format[2] == '1') {
415 ASSERT(STRING_STARTS_WITH(format, "ss1")); /* ext size */
416 PrintSs1(instr);
417 return 3;
418 } else {
419 ASSERT(STRING_STARTS_WITH(format, "ss2")); /* ins size */
420 PrintSs2(instr);
421 return 3;
422 }
423 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000424 }
425 }
426 case 'b': { // 'bc - Special for bc1 cc field.
427 ASSERT(STRING_STARTS_WITH(format, "bc"));
428 PrintBc(instr);
429 return 2;
430 }
431 case 'C': { // 'Cc - Special for c.xx.d cc field.
432 ASSERT(STRING_STARTS_WITH(format, "Cc"));
433 PrintCc(instr);
ager@chromium.org5c838252010-02-19 08:53:10 +0000434 return 2;
435 }
436 };
437 UNREACHABLE();
438 return -1;
439}
440
441
442// Format takes a formatting string for a whole instruction and prints it into
443// the output buffer. All escaped options are handed to FormatOption to be
444// parsed further.
445void Decoder::Format(Instruction* instr, const char* format) {
446 char cur = *format++;
447 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
448 if (cur == '\'') { // Single quote is used as the formatting escape.
449 format += FormatOption(instr, format);
450 } else {
451 out_buffer_[out_buffer_pos_++] = cur;
452 }
453 cur = *format++;
454 }
455 out_buffer_[out_buffer_pos_] = '\0';
456}
457
458
459// For currently unimplemented decodings the disassembler calls Unknown(instr)
460// which will just print "unknown" of the instruction bits.
461void Decoder::Unknown(Instruction* instr) {
462 Format(instr, "unknown");
463}
464
465
466void Decoder::DecodeTypeRegister(Instruction* instr) {
467 switch (instr->OpcodeFieldRaw()) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000468 case COP1: // Coprocessor instructions.
ager@chromium.org5c838252010-02-19 08:53:10 +0000469 switch (instr->RsFieldRaw()) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000470 case BC1: // bc1 handled in DecodeTypeImmediate.
ager@chromium.org5c838252010-02-19 08:53:10 +0000471 UNREACHABLE();
472 break;
473 case MFC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000474 Format(instr, "mfc1 'rt, 'fs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000475 break;
476 case MFHC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000477 Format(instr, "mfhc1 'rt, 'fs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000478 break;
479 case MTC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000480 Format(instr, "mtc1 'rt, 'fs");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000481 break;
482 // These are called "fs" too, although they are not FPU registers.
483 case CTC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000484 Format(instr, "ctc1 'rt, 'fs");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000485 break;
486 case CFC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000487 Format(instr, "cfc1 'rt, 'fs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000488 break;
489 case MTHC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000490 Format(instr, "mthc1 'rt, 'fs");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000491 break;
492 case D:
493 switch (instr->FunctionFieldRaw()) {
494 case ADD_D:
495 Format(instr, "add.d 'fd, 'fs, 'ft");
496 break;
497 case SUB_D:
498 Format(instr, "sub.d 'fd, 'fs, 'ft");
499 break;
500 case MUL_D:
501 Format(instr, "mul.d 'fd, 'fs, 'ft");
502 break;
503 case DIV_D:
504 Format(instr, "div.d 'fd, 'fs, 'ft");
505 break;
506 case ABS_D:
507 Format(instr, "abs.d 'fd, 'fs");
508 break;
509 case MOV_D:
510 Format(instr, "mov.d 'fd, 'fs");
511 break;
512 case NEG_D:
513 Format(instr, "neg.d 'fd, 'fs");
514 break;
515 case SQRT_D:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000516 Format(instr, "sqrt.d 'fd, 'fs");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000517 break;
518 case CVT_W_D:
519 Format(instr, "cvt.w.d 'fd, 'fs");
520 break;
521 case CVT_L_D: {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000522 if (kArchVariant == kMips32r2) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000523 Format(instr, "cvt.l.d 'fd, 'fs");
524 } else {
525 Unknown(instr);
526 }
527 break;
528 }
529 case TRUNC_W_D:
530 Format(instr, "trunc.w.d 'fd, 'fs");
531 break;
532 case TRUNC_L_D: {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000533 if (kArchVariant == kMips32r2) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000534 Format(instr, "trunc.l.d 'fd, 'fs");
535 } else {
536 Unknown(instr);
537 }
538 break;
539 }
540 case ROUND_W_D:
541 Format(instr, "round.w.d 'fd, 'fs");
542 break;
543 case FLOOR_W_D:
544 Format(instr, "floor.w.d 'fd, 'fs");
545 break;
546 case CEIL_W_D:
547 Format(instr, "ceil.w.d 'fd, 'fs");
548 break;
549 case CVT_S_D:
550 Format(instr, "cvt.s.d 'fd, 'fs");
551 break;
552 case C_F_D:
553 Format(instr, "c.f.d 'fs, 'ft, 'Cc");
554 break;
555 case C_UN_D:
556 Format(instr, "c.un.d 'fs, 'ft, 'Cc");
557 break;
558 case C_EQ_D:
559 Format(instr, "c.eq.d 'fs, 'ft, 'Cc");
560 break;
561 case C_UEQ_D:
562 Format(instr, "c.ueq.d 'fs, 'ft, 'Cc");
563 break;
564 case C_OLT_D:
565 Format(instr, "c.olt.d 'fs, 'ft, 'Cc");
566 break;
567 case C_ULT_D:
568 Format(instr, "c.ult.d 'fs, 'ft, 'Cc");
569 break;
570 case C_OLE_D:
571 Format(instr, "c.ole.d 'fs, 'ft, 'Cc");
572 break;
573 case C_ULE_D:
574 Format(instr, "c.ule.d 'fs, 'ft, 'Cc");
575 break;
576 default:
577 Format(instr, "unknown.cop1.d");
578 break;
579 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000580 break;
581 case S:
ager@chromium.org5c838252010-02-19 08:53:10 +0000582 UNIMPLEMENTED_MIPS();
583 break;
584 case W:
585 switch (instr->FunctionFieldRaw()) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000586 case CVT_S_W: // Convert word to float (single).
587 Format(instr, "cvt.s.w 'fd, 'fs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000588 break;
589 case CVT_D_W: // Convert word to double.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000590 Format(instr, "cvt.d.w 'fd, 'fs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000591 break;
592 default:
593 UNREACHABLE();
lrn@chromium.org7516f052011-03-30 08:52:27 +0000594 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000595 break;
596 case L:
lrn@chromium.org7516f052011-03-30 08:52:27 +0000597 switch (instr->FunctionFieldRaw()) {
598 case CVT_D_L: {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000599 if (kArchVariant == kMips32r2) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000600 Format(instr, "cvt.d.l 'fd, 'fs");
601 } else {
602 Unknown(instr);
603 }
604 break;
605 }
606 case CVT_S_L: {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000607 if (kArchVariant == kMips32r2) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000608 Format(instr, "cvt.s.l 'fd, 'fs");
609 } else {
610 Unknown(instr);
611 }
612 break;
613 }
614 default:
615 UNREACHABLE();
616 }
617 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000618 case PS:
619 UNIMPLEMENTED_MIPS();
620 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000621 default:
622 UNREACHABLE();
lrn@chromium.org7516f052011-03-30 08:52:27 +0000623 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000624 break;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000625 case COP1X:
626 switch (instr->FunctionFieldRaw()) {
627 case MADD_D:
628 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
629 break;
630 default:
631 UNREACHABLE();
632 };
633 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000634 case SPECIAL:
635 switch (instr->FunctionFieldRaw()) {
636 case JR:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000637 Format(instr, "jr 'rs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000638 break;
639 case JALR:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000640 Format(instr, "jalr 'rs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000641 break;
642 case SLL:
643 if ( 0x0 == static_cast<int>(instr->InstructionBits()))
644 Format(instr, "nop");
645 else
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000646 Format(instr, "sll 'rd, 'rt, 'sa");
ager@chromium.org5c838252010-02-19 08:53:10 +0000647 break;
648 case SRL:
lrn@chromium.org7516f052011-03-30 08:52:27 +0000649 if (instr->RsValue() == 0) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000650 Format(instr, "srl 'rd, 'rt, 'sa");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000651 } else {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000652 if (kArchVariant == kMips32r2) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000653 Format(instr, "rotr 'rd, 'rt, 'sa");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000654 } else {
655 Unknown(instr);
656 }
657 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000658 break;
659 case SRA:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000660 Format(instr, "sra 'rd, 'rt, 'sa");
ager@chromium.org5c838252010-02-19 08:53:10 +0000661 break;
662 case SLLV:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000663 Format(instr, "sllv 'rd, 'rt, 'rs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000664 break;
665 case SRLV:
lrn@chromium.org7516f052011-03-30 08:52:27 +0000666 if (instr->SaValue() == 0) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000667 Format(instr, "srlv 'rd, 'rt, 'rs");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000668 } else {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000669 if (kArchVariant == kMips32r2) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000670 Format(instr, "rotrv 'rd, 'rt, 'rs");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000671 } else {
672 Unknown(instr);
673 }
674 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000675 break;
676 case SRAV:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000677 Format(instr, "srav 'rd, 'rt, 'rs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000678 break;
679 case MFHI:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000680 Format(instr, "mfhi 'rd");
ager@chromium.org5c838252010-02-19 08:53:10 +0000681 break;
682 case MFLO:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000683 Format(instr, "mflo 'rd");
ager@chromium.org5c838252010-02-19 08:53:10 +0000684 break;
685 case MULT:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000686 Format(instr, "mult 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000687 break;
688 case MULTU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000689 Format(instr, "multu 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000690 break;
691 case DIV:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000692 Format(instr, "div 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000693 break;
694 case DIVU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000695 Format(instr, "divu 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000696 break;
697 case ADD:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000698 Format(instr, "add 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000699 break;
700 case ADDU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000701 Format(instr, "addu 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000702 break;
703 case SUB:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000704 Format(instr, "sub 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000705 break;
706 case SUBU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000707 Format(instr, "subu 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000708 break;
709 case AND:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000710 Format(instr, "and 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000711 break;
712 case OR:
lrn@chromium.org7516f052011-03-30 08:52:27 +0000713 if (0 == instr->RsValue()) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000714 Format(instr, "mov 'rd, 'rt");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000715 } else if (0 == instr->RtValue()) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000716 Format(instr, "mov 'rd, 'rs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000717 } else {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000718 Format(instr, "or 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000719 }
720 break;
721 case XOR:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000722 Format(instr, "xor 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000723 break;
724 case NOR:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000725 Format(instr, "nor 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000726 break;
727 case SLT:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000728 Format(instr, "slt 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000729 break;
730 case SLTU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000731 Format(instr, "sltu 'rd, 'rs, 'rt");
ager@chromium.org5c838252010-02-19 08:53:10 +0000732 break;
733 case BREAK:
734 Format(instr, "break, code: 'code");
735 break;
736 case TGE:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000737 Format(instr, "tge 'rs, 'rt, code: 'code");
ager@chromium.org5c838252010-02-19 08:53:10 +0000738 break;
739 case TGEU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000740 Format(instr, "tgeu 'rs, 'rt, code: 'code");
ager@chromium.org5c838252010-02-19 08:53:10 +0000741 break;
742 case TLT:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000743 Format(instr, "tlt 'rs, 'rt, code: 'code");
ager@chromium.org5c838252010-02-19 08:53:10 +0000744 break;
745 case TLTU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000746 Format(instr, "tltu 'rs, 'rt, code: 'code");
ager@chromium.org5c838252010-02-19 08:53:10 +0000747 break;
748 case TEQ:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000749 Format(instr, "teq 'rs, 'rt, code: 'code");
ager@chromium.org5c838252010-02-19 08:53:10 +0000750 break;
751 case TNE:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000752 Format(instr, "tne 'rs, 'rt, code: 'code");
ager@chromium.org5c838252010-02-19 08:53:10 +0000753 break;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000754 case MOVZ:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000755 Format(instr, "movz 'rd, 'rs, 'rt");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000756 break;
757 case MOVN:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000758 Format(instr, "movn 'rd, 'rs, 'rt");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000759 break;
760 case MOVCI:
761 if (instr->Bit(16)) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000762 Format(instr, "movt 'rd, 'rs, 'bc");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000763 } else {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000764 Format(instr, "movf 'rd, 'rs, 'bc");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000765 }
766 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000767 default:
768 UNREACHABLE();
lrn@chromium.org7516f052011-03-30 08:52:27 +0000769 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000770 break;
771 case SPECIAL2:
772 switch (instr->FunctionFieldRaw()) {
773 case MUL:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000774 Format(instr, "mul 'rd, 'rs, 'rt");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000775 break;
776 case CLZ:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000777 Format(instr, "clz 'rd, 'rs");
ager@chromium.org5c838252010-02-19 08:53:10 +0000778 break;
779 default:
780 UNREACHABLE();
lrn@chromium.org7516f052011-03-30 08:52:27 +0000781 }
782 break;
783 case SPECIAL3:
784 switch (instr->FunctionFieldRaw()) {
785 case INS: {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000786 if (kArchVariant == kMips32r2) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000787 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000788 } else {
789 Unknown(instr);
790 }
791 break;
792 }
793 case EXT: {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000794 if (kArchVariant == kMips32r2) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000795 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000796 } else {
797 Unknown(instr);
798 }
799 break;
800 }
801 default:
802 UNREACHABLE();
803 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000804 break;
805 default:
806 UNREACHABLE();
lrn@chromium.org7516f052011-03-30 08:52:27 +0000807 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000808}
809
810
811void Decoder::DecodeTypeImmediate(Instruction* instr) {
812 switch (instr->OpcodeFieldRaw()) {
813 // ------------- REGIMM class.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000814 case COP1:
815 switch (instr->RsFieldRaw()) {
816 case BC1:
817 if (instr->FBtrueValue()) {
818 Format(instr, "bc1t 'bc, 'imm16u");
819 } else {
820 Format(instr, "bc1f 'bc, 'imm16u");
821 }
822 break;
823 default:
824 UNREACHABLE();
825 };
826 break; // Case COP1.
ager@chromium.org5c838252010-02-19 08:53:10 +0000827 case REGIMM:
828 switch (instr->RtFieldRaw()) {
829 case BLTZ:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000830 Format(instr, "bltz 'rs, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000831 break;
832 case BLTZAL:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000833 Format(instr, "bltzal 'rs, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000834 break;
835 case BGEZ:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000836 Format(instr, "bgez 'rs, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000837 break;
838 case BGEZAL:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000839 Format(instr, "bgezal 'rs, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000840 break;
841 default:
842 UNREACHABLE();
lrn@chromium.org7516f052011-03-30 08:52:27 +0000843 }
844 break; // Case REGIMM.
ager@chromium.org5c838252010-02-19 08:53:10 +0000845 // ------------- Branch instructions.
846 case BEQ:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000847 Format(instr, "beq 'rs, 'rt, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000848 break;
849 case BNE:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000850 Format(instr, "bne 'rs, 'rt, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000851 break;
852 case BLEZ:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000853 Format(instr, "blez 'rs, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000854 break;
855 case BGTZ:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000856 Format(instr, "bgtz 'rs, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000857 break;
858 // ------------- Arithmetic instructions.
859 case ADDI:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000860 Format(instr, "addi 'rt, 'rs, 'imm16s");
ager@chromium.org5c838252010-02-19 08:53:10 +0000861 break;
862 case ADDIU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000863 Format(instr, "addiu 'rt, 'rs, 'imm16s");
ager@chromium.org5c838252010-02-19 08:53:10 +0000864 break;
865 case SLTI:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000866 Format(instr, "slti 'rt, 'rs, 'imm16s");
ager@chromium.org5c838252010-02-19 08:53:10 +0000867 break;
868 case SLTIU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000869 Format(instr, "sltiu 'rt, 'rs, 'imm16u");
ager@chromium.org5c838252010-02-19 08:53:10 +0000870 break;
871 case ANDI:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000872 Format(instr, "andi 'rt, 'rs, 'imm16x");
ager@chromium.org5c838252010-02-19 08:53:10 +0000873 break;
874 case ORI:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000875 Format(instr, "ori 'rt, 'rs, 'imm16x");
ager@chromium.org5c838252010-02-19 08:53:10 +0000876 break;
877 case XORI:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000878 Format(instr, "xori 'rt, 'rs, 'imm16x");
ager@chromium.org5c838252010-02-19 08:53:10 +0000879 break;
880 case LUI:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000881 Format(instr, "lui 'rt, 'imm16x");
ager@chromium.org5c838252010-02-19 08:53:10 +0000882 break;
883 // ------------- Memory instructions.
884 case LB:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000885 Format(instr, "lb 'rt, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000886 break;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000887 case LH:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000888 Format(instr, "lh 'rt, 'imm16s('rs)");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000889 break;
890 case LWL:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000891 Format(instr, "lwl 'rt, 'imm16s('rs)");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000892 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000893 case LW:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000894 Format(instr, "lw 'rt, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000895 break;
896 case LBU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000897 Format(instr, "lbu 'rt, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000898 break;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000899 case LHU:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000900 Format(instr, "lhu 'rt, 'imm16s('rs)");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000901 break;
902 case LWR:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000903 Format(instr, "lwr 'rt, 'imm16s('rs)");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000904 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000905 case SB:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000906 Format(instr, "sb 'rt, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000907 break;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000908 case SH:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000909 Format(instr, "sh 'rt, 'imm16s('rs)");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000910 break;
911 case SWL:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000912 Format(instr, "swl 'rt, 'imm16s('rs)");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000913 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000914 case SW:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000915 Format(instr, "sw 'rt, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000916 break;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000917 case SWR:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000918 Format(instr, "swr 'rt, 'imm16s('rs)");
lrn@chromium.org7516f052011-03-30 08:52:27 +0000919 break;
ager@chromium.org5c838252010-02-19 08:53:10 +0000920 case LWC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000921 Format(instr, "lwc1 'ft, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000922 break;
923 case LDC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000924 Format(instr, "ldc1 'ft, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000925 break;
926 case SWC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000927 Format(instr, "swc1 'ft, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000928 break;
929 case SDC1:
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000930 Format(instr, "sdc1 'ft, 'imm16s('rs)");
ager@chromium.org5c838252010-02-19 08:53:10 +0000931 break;
932 default:
933 UNREACHABLE();
934 break;
935 };
936}
937
938
939void Decoder::DecodeTypeJump(Instruction* instr) {
940 switch (instr->OpcodeFieldRaw()) {
941 case J:
lrn@chromium.org34e60782011-09-15 07:25:40 +0000942 Format(instr, "j 'imm26x");
ager@chromium.org5c838252010-02-19 08:53:10 +0000943 break;
944 case JAL:
lrn@chromium.org34e60782011-09-15 07:25:40 +0000945 Format(instr, "jal 'imm26x");
ager@chromium.org5c838252010-02-19 08:53:10 +0000946 break;
947 default:
948 UNREACHABLE();
949 }
950}
951
952
953// Disassemble the instruction at *instr_ptr into the output buffer.
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000954int Decoder::InstructionDecode(byte* instr_ptr) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000955 Instruction* instr = Instruction::At(instr_ptr);
956 // Print raw instruction bytes.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000957 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
ager@chromium.org5c838252010-02-19 08:53:10 +0000958 "%08x ",
959 instr->InstructionBits());
960 switch (instr->InstructionType()) {
961 case Instruction::kRegisterType: {
962 DecodeTypeRegister(instr);
963 break;
964 }
965 case Instruction::kImmediateType: {
966 DecodeTypeImmediate(instr);
967 break;
968 }
969 case Instruction::kJumpType: {
970 DecodeTypeJump(instr);
971 break;
972 }
973 default: {
lrn@chromium.org34e60782011-09-15 07:25:40 +0000974 Format(instr, "UNSUPPORTED");
ager@chromium.org5c838252010-02-19 08:53:10 +0000975 UNSUPPORTED_MIPS();
976 }
977 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000978 return Instruction::kInstrSize;
ager@chromium.org5c838252010-02-19 08:53:10 +0000979}
980
981
lrn@chromium.org7516f052011-03-30 08:52:27 +0000982} } // namespace v8::internal
ager@chromium.org5c838252010-02-19 08:53:10 +0000983
984
985
986//------------------------------------------------------------------------------
987
988namespace disasm {
989
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000990const char* NameConverter::NameOfAddress(byte* addr) const {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000991 v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
992 return tmp_buffer_.start();
ager@chromium.org5c838252010-02-19 08:53:10 +0000993}
994
995
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000996const char* NameConverter::NameOfConstant(byte* addr) const {
ager@chromium.org5c838252010-02-19 08:53:10 +0000997 return NameOfAddress(addr);
998}
999
1000
1001const char* NameConverter::NameOfCPURegister(int reg) const {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001002 return v8::internal::Registers::Name(reg);
ager@chromium.org5c838252010-02-19 08:53:10 +00001003}
1004
1005
1006const char* NameConverter::NameOfXMMRegister(int reg) const {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001007 return v8::internal::FPURegisters::Name(reg);
ager@chromium.org5c838252010-02-19 08:53:10 +00001008}
1009
1010
1011const char* NameConverter::NameOfByteCPURegister(int reg) const {
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001012 UNREACHABLE(); // MIPS does not have the concept of a byte register.
ager@chromium.org5c838252010-02-19 08:53:10 +00001013 return "nobytereg";
1014}
1015
1016
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001017const char* NameConverter::NameInCode(byte* addr) const {
ager@chromium.org5c838252010-02-19 08:53:10 +00001018 // The default name converter is called for unknown code. So we will not try
1019 // to access any memory.
1020 return "";
1021}
1022
1023
1024//------------------------------------------------------------------------------
1025
1026Disassembler::Disassembler(const NameConverter& converter)
1027 : converter_(converter) {}
1028
1029
1030Disassembler::~Disassembler() {}
1031
1032
1033int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001034 byte* instruction) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001035 v8::internal::Decoder d(converter_, buffer);
ager@chromium.org5c838252010-02-19 08:53:10 +00001036 return d.InstructionDecode(instruction);
1037}
1038
1039
lrn@chromium.org7516f052011-03-30 08:52:27 +00001040// The MIPS assembler does not currently use constant pools.
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001041int Disassembler::ConstantPoolSizeAt(byte* instruction) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001042 return -1;
1043}
1044
1045
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001046void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001047 NameConverter converter;
1048 Disassembler d(converter);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001049 for (byte* pc = begin; pc < end;) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001050 v8::internal::EmbeddedVector<char, 128> buffer;
1051 buffer[0] = '\0';
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001052 byte* prev_pc = pc;
ager@chromium.org5c838252010-02-19 08:53:10 +00001053 pc += d.InstructionDecode(buffer, pc);
1054 fprintf(f, "%p %08x %s\n",
1055 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1056 }
1057}
1058
lrn@chromium.org7516f052011-03-30 08:52:27 +00001059
ager@chromium.org5c838252010-02-19 08:53:10 +00001060#undef UNSUPPORTED
1061
1062} // namespace disasm
1063
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001064#endif // V8_TARGET_ARCH_MIPS