disasm-mips.cc revision 257744e915dfc84d6d07a6b2accf8402d9ffc708
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
23100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Redistribution and use in source and binary forms, with or without
33100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modification, are permitted provided that the following conditions are
43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// met:
53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions of source code must retain the above copyright
73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       notice, this list of conditions and the following disclaimer.
83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions in binary form must reproduce the above
93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       copyright notice, this list of conditions and the following
103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       disclaimer in the documentation and/or other materials provided
113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       with the distribution.
123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Neither the name of Google Inc. nor the names of its
133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       contributors may be used to endorse or promote products derived
143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       from this software without specific prior written permission.
153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// A Disassembler object is used to disassemble a block of code instruction by
293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// instruction. The default implementation of the NameConverter object can be
303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// overriden to modify register names or to do symbol lookup on addresses.
313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// The example below will disassemble a block of code and print it to stdout.
333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//   NameConverter converter;
353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//   Disassembler d(converter);
36257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   for (byte* pc = begin; pc < end;) {
3744f0eee88ff00398ff7f715fab053374d808c90dSteve Block//     v8::internal::EmbeddedVector<char, 256> buffer;
3844f0eee88ff00398ff7f715fab053374d808c90dSteve Block//     byte* prev_pc = pc;
3944f0eee88ff00398ff7f715fab053374d808c90dSteve Block//     pc += d.InstructionDecode(buffer, pc);
403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     printf("%p    %08x      %s\n",
413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//   }
433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// The Disassembler class also has a convenience method to disassemble a block
453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// of code into a FILE*, meaning that the above functionality could also be
463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include <assert.h>
503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include <stdio.h>
513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include <stdarg.h>
523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include <string.h>
533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifndef WIN32
543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include <stdint.h>
553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif
563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "v8.h"
583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
59f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_MIPS)
60f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "mips/constants-mips.h"
623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "disasm.h"
633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "macro-assembler.h"
643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "platform.h"
653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace v8 {
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace internal {
683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//------------------------------------------------------------------------------
703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Decoder decodes and disassembles instructions into an output buffer.
723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// It uses the converter to convert register names and call destinations into
733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// more informative description.
743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass Decoder {
753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public:
763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Decoder(const disasm::NameConverter& converter,
773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          v8::internal::Vector<char> out_buffer)
783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    : converter_(converter),
793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      out_buffer_(out_buffer),
803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      out_buffer_pos_(0) {
813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    out_buffer_[out_buffer_pos_] = '\0';
823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ~Decoder() {}
853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Writes one disassembled instruction into 'buffer' (0-terminated).
873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Returns the length of the disassembled machine instruction in bytes.
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int InstructionDecode(byte* instruction);
893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private:
913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Bottleneck functions to print into the out_buffer.
923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintChar(const char ch);
933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Print(const char* str);
943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Printing of common values.
963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintRegister(int reg);
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void PrintFPURegister(int freg);
983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintRs(Instruction* instr);
993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintRt(Instruction* instr);
1003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintRd(Instruction* instr);
1013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintFs(Instruction* instr);
1023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintFt(Instruction* instr);
1033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintFd(Instruction* instr);
1043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintSa(Instruction* instr);
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void PrintSd(Instruction* instr);
106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrintSs1(Instruction* instr);
107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrintSs2(Instruction* instr);
10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void PrintBc(Instruction* instr);
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void PrintCc(Instruction* instr);
1103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintFunction(Instruction* instr);
1113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintSecondaryField(Instruction* instr);
1123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintUImm16(Instruction* instr);
1133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintSImm16(Instruction* instr);
1143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintXImm16(Instruction* instr);
1153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintImm26(Instruction* instr);
1163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintCode(Instruction* instr);   // For break and trap instructions.
1173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Printing of instruction name.
1183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PrintInstructionName(Instruction* instr);
1193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Handle formatting of instructions and their options.
1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int FormatRegister(Instruction* instr, const char* option);
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int FormatFPURegister(Instruction* instr, const char* option);
1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int FormatOption(Instruction* instr, const char* option);
1243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Format(Instruction* instr, const char* format);
1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Unknown(Instruction* instr);
1263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Each of these functions decodes one particular instruction type.
1283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void DecodeTypeRegister(Instruction* instr);
1293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void DecodeTypeImmediate(Instruction* instr);
1303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void DecodeTypeJump(Instruction* instr);
1313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  const disasm::NameConverter& converter_;
1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  v8::internal::Vector<char> out_buffer_;
1343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int out_buffer_pos_;
1353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DISALLOW_COPY_AND_ASSIGN(Decoder);
1373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu};
1383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Support for assertions in the Decoder formatting functions.
1413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define STRING_STARTS_WITH(string, compare_string) \
1423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  (strncmp(string, compare_string, strlen(compare_string)) == 0)
1433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Append the ch to the output buffer.
1463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintChar(const char ch) {
1473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  out_buffer_[out_buffer_pos_++] = ch;
1483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Append the str to the output buffer.
1523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::Print(const char* str) {
1533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  char cur = *str++;
1543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
1553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    PrintChar(cur);
1563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    cur = *str++;
1573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
1583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  out_buffer_[out_buffer_pos_] = 0;
1593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Print the register name according to the active name converter.
1633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintRegister(int reg) {
1643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Print(converter_.NameOfCPURegister(reg));
1653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintRs(Instruction* instr) {
16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int reg = instr->RsValue();
1703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  PrintRegister(reg);
1713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintRt(Instruction* instr) {
17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int reg = instr->RtValue();
1763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  PrintRegister(reg);
1773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintRd(Instruction* instr) {
18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int reg = instr->RdValue();
1823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  PrintRegister(reg);
1833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Print the FPUregister name according to the active name converter.
18744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Decoder::PrintFPURegister(int freg) {
18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Print(converter_.NameOfXMMRegister(freg));
1893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintFs(Instruction* instr) {
19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int freg = instr->RsValue();
19444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PrintFPURegister(freg);
1953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintFt(Instruction* instr) {
19944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int freg = instr->RtValue();
20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PrintFPURegister(freg);
2013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintFd(Instruction* instr) {
20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int freg = instr->RdValue();
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PrintFPURegister(freg);
2073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Print the integer value of the sa field.
2113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintSa(Instruction* instr) {
21244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int sa = instr->SaValue();
21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
21644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Print the integer value of the rd field, when it is not used as reg.
21844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Decoder::PrintSd(Instruction* instr) {
21944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int sd = instr->RdValue();
22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd);
22144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
22244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Print the integer value of the rd field, when used as 'ext' size.
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Decoder::PrintSs1(Instruction* instr) {
226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int ss = instr->RdValue();
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1);
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Print the integer value of the rd field, when used as 'ins' size.
232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Decoder::PrintSs2(Instruction* instr) {
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int ss = instr->RdValue();
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int pos = instr->SaValue();
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  out_buffer_pos_ +=
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1);
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
24044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Print the integer value of the cc field for the bc1t/f instructions.
24144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Decoder::PrintBc(Instruction* instr) {
24244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int cc = instr->FBccValue();
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc);
24444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
24544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Print the integer value of the cc field for the FP compare instructions.
24844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Decoder::PrintCc(Instruction* instr) {
24944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int cc = instr->FCccValue();
25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc);
2513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Print 16-bit unsigned immediate value.
2553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintUImm16(Instruction* instr) {
25644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int32_t imm = instr->Imm16Value();
25744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
2583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Print 16-bit signed immediate value.
2623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintSImm16(Instruction* instr) {
263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int32_t imm = ((instr->Imm16Value()) << 16) >> 16;
26444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
2653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Print 16-bit hexa immediate value.
2693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintXImm16(Instruction* instr) {
27044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int32_t imm = instr->Imm16Value();
27144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
2723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Print 26-bit immediate value.
2763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintImm26(Instruction* instr) {
27744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int32_t imm = instr->Imm26Value();
27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
2793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Print 26-bit immediate value.
2833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintCode(Instruction* instr) {
2843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (instr->OpcodeFieldRaw() != SPECIAL)
2853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return;  // Not a break or trap instruction.
2863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  switch (instr->FunctionFieldRaw()) {
2873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case BREAK: {
2883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int32_t code = instr->Bits(25, 6);
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      "0x%05x (%d)", code, code);
2913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
2923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                }
2933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case TGE:
2943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case TGEU:
2953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case TLT:
2963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case TLTU:
2973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case TEQ:
2983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case TNE: {
2993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int32_t code = instr->Bits(15, 6);
3003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      out_buffer_pos_ +=
30144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
3023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
3033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
3043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    default:  // Not a break or trap instruction.
3053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    break;
3063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  };
3073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Printing of instruction name.
3113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::PrintInstructionName(Instruction* instr) {
3123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Handle all register based formatting in this function to reduce the
3163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// complexity of FormatOption.
3173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint Decoder::FormatRegister(Instruction* instr, const char* format) {
3183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(format[0] == 'r');
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (format[1] == 's') {  // 'rs: Rs register.
32044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int reg = instr->RsValue();
3213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    PrintRegister(reg);
3223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return 2;
323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (format[1] == 't') {  // 'rt: rt register.
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int reg = instr->RtValue();
3253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    PrintRegister(reg);
3263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return 2;
327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (format[1] == 'd') {  // 'rd: rd register.
32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int reg = instr->RdValue();
3293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    PrintRegister(reg);
3303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return 2;
3313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
3323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  UNREACHABLE();
3333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return -1;
3343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Handle all FPUregister based formatting in this function to reduce the
3383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// complexity of FormatOption.
33944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint Decoder::FormatFPURegister(Instruction* instr, const char* format) {
3403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(format[0] == 'f');
341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (format[1] == 's') {  // 'fs: fs register.
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int reg = instr->FsValue();
34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PrintFPURegister(reg);
3443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return 2;
345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (format[1] == 't') {  // 'ft: ft register.
34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int reg = instr->FtValue();
34744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PrintFPURegister(reg);
3483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return 2;
349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (format[1] == 'd') {  // 'fd: fd register.
35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int reg = instr->FdValue();
35144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PrintFPURegister(reg);
3523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return 2;
3533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
3543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  UNREACHABLE();
3553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return -1;
3563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// FormatOption takes a formatting string and interprets it based on
3603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// the current instructions. The format string points to the first
3613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// character of the option string (the option escape has already been
3623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// consumed by the caller.)  FormatOption returns the number of
3633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// characters that were consumed from the formatting string.
3643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint Decoder::FormatOption(Instruction* instr, const char* format) {
3653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  switch (format[0]) {
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case 'c': {   // 'code for break or trap instructions.
3673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      ASSERT(STRING_STARTS_WITH(format, "code"));
3683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      PrintCode(instr);
3693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      return 4;
3703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case 'i': {   // 'imm16u or 'imm26.
3723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      if (format[3] == '1') {
3733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        ASSERT(STRING_STARTS_WITH(format, "imm16"));
3743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        if (format[5] == 's') {
3753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          ASSERT(STRING_STARTS_WITH(format, "imm16s"));
3763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          PrintSImm16(instr);
3773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        } else if (format[5] == 'u') {
3783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          ASSERT(STRING_STARTS_WITH(format, "imm16u"));
3793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          PrintSImm16(instr);
3803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        } else {
3813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          ASSERT(STRING_STARTS_WITH(format, "imm16x"));
3823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          PrintXImm16(instr);
3833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        }
3843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        return 6;
3853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      } else {
3863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        ASSERT(STRING_STARTS_WITH(format, "imm26"));
3873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        PrintImm26(instr);
3883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        return 5;
3893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      }
3903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case 'r': {   // 'r: registers.
3923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      return FormatRegister(instr, format);
3933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case 'f': {   // 'f: FPUregisters.
39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return FormatFPURegister(instr, format);
3963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case 's': {   // 'sa.
39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      switch (format[1]) {
39944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case 'a': {
40044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ASSERT(STRING_STARTS_WITH(format, "sa"));
40144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          PrintSa(instr);
40244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          return 2;
40344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case 'd': {
40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ASSERT(STRING_STARTS_WITH(format, "sd"));
40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          PrintSd(instr);
40744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          return 2;
40844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        case 's': {
410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          if (format[2] == '1') {
411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              ASSERT(STRING_STARTS_WITH(format, "ss1"));  /* ext size */
412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              PrintSs1(instr);
413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              return 3;
414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          } else {
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              ASSERT(STRING_STARTS_WITH(format, "ss2"));  /* ins size */
416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              PrintSs2(instr);
417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              return 3;
418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          }
419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case 'b': {   // 'bc - Special for bc1 cc field.
42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(STRING_STARTS_WITH(format, "bc"));
42444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      PrintBc(instr);
42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return 2;
42644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
42744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case 'C': {   // 'Cc - Special for c.xx.d cc field.
42844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(STRING_STARTS_WITH(format, "Cc"));
42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      PrintCc(instr);
4303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      return 2;
4313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
4323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  };
4333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  UNREACHABLE();
4343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return -1;
4353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
4363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Format takes a formatting string for a whole instruction and prints it into
4393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// the output buffer. All escaped options are handed to FormatOption to be
4403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// parsed further.
4413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::Format(Instruction* instr, const char* format) {
4423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  char cur = *format++;
4433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
4443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if (cur == '\'') {  // Single quote is used as the formatting escape.
4453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      format += FormatOption(instr, format);
4463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
4473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      out_buffer_[out_buffer_pos_++] = cur;
4483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
4493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    cur = *format++;
4503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
4513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  out_buffer_[out_buffer_pos_]  = '\0';
4523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
4533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// For currently unimplemented decodings the disassembler calls Unknown(instr)
4563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// which will just print "unknown" of the instruction bits.
4573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::Unknown(Instruction* instr) {
4583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Format(instr, "unknown");
4593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
4603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::DecodeTypeRegister(Instruction* instr) {
4633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  switch (instr->OpcodeFieldRaw()) {
464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case COP1:    // Coprocessor instructions.
4653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      switch (instr->RsFieldRaw()) {
46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case BC1:   // bc1 handled in DecodeTypeImmediate.
4673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          UNREACHABLE();
4683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
4693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MFC1:
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "mfc1    'rt, 'fs");
4713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
4723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MFHC1:
473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "mfhc1   'rt, 'fs");
4743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
4753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MTC1:
476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "mtc1    'rt, 'fs");
47744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
47844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // These are called "fs" too, although they are not FPU registers.
47944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case CTC1:
480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "ctc1    'rt, 'fs");
48144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
48244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case CFC1:
483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "cfc1    'rt, 'fs");
4843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
4853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MTHC1:
486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "mthc1   'rt, 'fs");
4873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
4883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case D:
48944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          switch (instr->FunctionFieldRaw()) {
49044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case ADD_D:
49144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "add.d   'fd, 'fs, 'ft");
49244f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
49344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case SUB_D:
49444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "sub.d   'fd, 'fs, 'ft");
49544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
49644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case MUL_D:
49744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "mul.d   'fd, 'fs, 'ft");
49844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case DIV_D:
50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "div.d   'fd, 'fs, 'ft");
50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case ABS_D:
50344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "abs.d   'fd, 'fs");
50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case MOV_D:
50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "mov.d   'fd, 'fs");
50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case NEG_D:
50944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "neg.d   'fd, 'fs");
51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
51144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case SQRT_D:
512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Format(instr, "sqrt.d  'fd, 'fs");
51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case CVT_W_D:
51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "cvt.w.d 'fd, 'fs");
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case CVT_L_D: {
51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              if (mips32r2) {
51944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Format(instr, "cvt.l.d 'fd, 'fs");
52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              } else {
52144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Unknown(instr);
52244f0eee88ff00398ff7f715fab053374d808c90dSteve Block              }
52344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
52444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
52544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case TRUNC_W_D:
52644f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "trunc.w.d 'fd, 'fs");
52744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case TRUNC_L_D: {
52944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              if (mips32r2) {
53044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Format(instr, "trunc.l.d 'fd, 'fs");
53144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              } else {
53244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Unknown(instr);
53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              }
53444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
53544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
53644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case ROUND_W_D:
53744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "round.w.d 'fd, 'fs");
53844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
53944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case FLOOR_W_D:
54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "floor.w.d 'fd, 'fs");
54144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
54244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case CEIL_W_D:
54344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "ceil.w.d 'fd, 'fs");
54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case CVT_S_D:
54644f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "cvt.s.d 'fd, 'fs");
54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case C_F_D:
54944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "c.f.d   'fs, 'ft, 'Cc");
55044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case C_UN_D:
55244f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "c.un.d  'fs, 'ft, 'Cc");
55344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
55444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case C_EQ_D:
55544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "c.eq.d  'fs, 'ft, 'Cc");
55644f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
55744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case C_UEQ_D:
55844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "c.ueq.d 'fs, 'ft, 'Cc");
55944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
56044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case C_OLT_D:
56144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "c.olt.d 'fs, 'ft, 'Cc");
56244f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
56344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case C_ULT_D:
56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "c.ult.d 'fs, 'ft, 'Cc");
56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
56644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case C_OLE_D:
56744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "c.ole.d 'fs, 'ft, 'Cc");
56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
56944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case C_ULE_D:
57044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "c.ule.d 'fs, 'ft, 'Cc");
57144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
57244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            default:
57344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "unknown.cop1.d");
57444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
57544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
57644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case S:
5783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          UNIMPLEMENTED_MIPS();
5793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
5803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case W:
5813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          switch (instr->FunctionFieldRaw()) {
58244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case CVT_S_W:   // Convert word to float (single).
58344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "cvt.s.w 'fd, 'fs");
5843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu              break;
5853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            case CVT_D_W:   // Convert word to double.
58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Format(instr, "cvt.d.w 'fd, 'fs");
5873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu              break;
5883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            default:
5893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu              UNREACHABLE();
59044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
5913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
5923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case L:
59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          switch (instr->FunctionFieldRaw()) {
59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case CVT_D_L: {
59544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              if (mips32r2) {
59644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Format(instr, "cvt.d.l 'fd, 'fs");
59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              } else {
59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Unknown(instr);
59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              }
60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
60144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            case CVT_S_L: {
60344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              if (mips32r2) {
60444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Format(instr, "cvt.s.l 'fd, 'fs");
60544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              } else {
60644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Unknown(instr);
60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              }
60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
60944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
61044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            default:
61144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              UNREACHABLE();
61244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
61344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
6143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case PS:
6153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          UNIMPLEMENTED_MIPS();
6163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        default:
6183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          UNREACHABLE();
61944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
6203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
6213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case SPECIAL:
6223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      switch (instr->FunctionFieldRaw()) {
6233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case JR:
624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "jr      'rs");
6253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case JALR:
627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "jalr    'rs");
6283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SLL:
6303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          if ( 0x0 == static_cast<int>(instr->InstructionBits()))
6313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            Format(instr, "nop");
6323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          else
633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "sll     'rd, 'rt, 'sa");
6343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SRL:
63644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (instr->RsValue() == 0) {
637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "srl     'rd, 'rt, 'sa");
63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
63944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            if (mips32r2) {
640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Format(instr, "rotr    'rd, 'rt, 'sa");
64144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            } else {
64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Unknown(instr);
64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
6453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SRA:
647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "sra     'rd, 'rt, 'sa");
6483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SLLV:
650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "sllv    'rd, 'rt, 'rs");
6513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SRLV:
65344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (instr->SaValue() == 0) {
654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "srlv    'rd, 'rt, 'rs");
65544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
65644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            if (mips32r2) {
657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Format(instr, "rotrv   'rd, 'rt, 'rs");
65844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            } else {
65944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              Unknown(instr);
66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
6623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SRAV:
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "srav    'rd, 'rt, 'rs");
6653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MFHI:
667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "mfhi    'rd");
6683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MFLO:
670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "mflo    'rd");
6713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MULT:
673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "mult    'rs, 'rt");
6743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MULTU:
676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "multu   'rs, 'rt");
6773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case DIV:
679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "div     'rs, 'rt");
6803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case DIVU:
682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "divu    'rs, 'rt");
6833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case ADD:
685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "add     'rd, 'rs, 'rt");
6863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case ADDU:
688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "addu    'rd, 'rs, 'rt");
6893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SUB:
691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "sub     'rd, 'rs, 'rt");
6923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SUBU:
694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "subu    'rd, 'rs, 'rt");
6953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case AND:
697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "and     'rd, 'rs, 'rt");
6983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
6993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case OR:
70044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (0 == instr->RsValue()) {
701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "mov     'rd, 'rt");
70244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else if (0 == instr->RtValue()) {
703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "mov     'rd, 'rs");
7043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          } else {
705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "or      'rd, 'rs, 'rt");
7063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          }
7073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case XOR:
709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "xor     'rd, 'rs, 'rt");
7103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case NOR:
712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "nor     'rd, 'rs, 'rt");
7133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SLT:
715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "slt     'rd, 'rs, 'rt");
7163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case SLTU:
718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "sltu    'rd, 'rs, 'rt");
7193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case BREAK:
7213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          Format(instr, "break, code: 'code");
7223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case TGE:
724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "tge     'rs, 'rt, code: 'code");
7253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case TGEU:
727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "tgeu    'rs, 'rt, code: 'code");
7283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case TLT:
730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "tlt     'rs, 'rt, code: 'code");
7313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case TLTU:
733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "tltu    'rs, 'rt, code: 'code");
7343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case TEQ:
736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "teq     'rs, 'rt, code: 'code");
7373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case TNE:
739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "tne     'rs, 'rt, code: 'code");
7403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
74144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case MOVZ:
742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "movz    'rd, 'rs, 'rt");
74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case MOVN:
745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "movn    'rd, 'rs, 'rt");
74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case MOVCI:
74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (instr->Bit(16)) {
749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "movt    'rd, 'rs, 'bc");
75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "movf    'rd, 'rs, 'bc");
75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
7543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        default:
7553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          UNREACHABLE();
75644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
7573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
7583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case SPECIAL2:
7593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      switch (instr->FunctionFieldRaw()) {
7603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case MUL:
761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "mul     'rd, 'rs, 'rt");
76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case CLZ:
764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "clz     'rd, 'rs");
7653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
7663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        default:
7673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          UNREACHABLE();
76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case SPECIAL3:
77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      switch (instr->FunctionFieldRaw()) {
77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case INS: {
77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (mips32r2) {
774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "ins     'rt, 'rs, 'sa, 'ss2");
77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            Unknown(instr);
77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case EXT: {
78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (mips32r2) {
782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Format(instr, "ext     'rt, 'rs, 'sa, 'ss1");
78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            Unknown(instr);
78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        default:
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          UNREACHABLE();
79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
7913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
7923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    default:
7933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      UNREACHABLE();
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
7953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
7963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
7983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::DecodeTypeImmediate(Instruction* instr) {
7993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  switch (instr->OpcodeFieldRaw()) {
8003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // ------------- REGIMM class.
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case COP1:
80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      switch (instr->RsFieldRaw()) {
80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case BC1:
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (instr->FBtrueValue()) {
80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            Format(instr, "bc1t    'bc, 'imm16u");
80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            Format(instr, "bc1f    'bc, 'imm16u");
80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        default:
81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          UNREACHABLE();
81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      };
81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;  // Case COP1.
8143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case REGIMM:
8153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      switch (instr->RtFieldRaw()) {
8163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case BLTZ:
817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "bltz    'rs, 'imm16u");
8183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
8193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case BLTZAL:
820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "bltzal  'rs, 'imm16u");
8213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
8223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case BGEZ:
823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "bgez    'rs, 'imm16u");
8243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
8253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        case BGEZAL:
826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Format(instr, "bgezal  'rs, 'imm16u");
8273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          break;
8283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        default:
8293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          UNREACHABLE();
83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    break;  // Case REGIMM.
8323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // ------------- Branch instructions.
8333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case BEQ:
834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "beq     'rs, 'rt, 'imm16u");
8353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case BNE:
837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "bne     'rs, 'rt, 'imm16u");
8383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case BLEZ:
840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "blez    'rs, 'imm16u");
8413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case BGTZ:
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "bgtz    'rs, 'imm16u");
8443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // ------------- Arithmetic instructions.
8463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case ADDI:
847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "addi    'rt, 'rs, 'imm16s");
8483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case ADDIU:
850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "addiu   'rt, 'rs, 'imm16s");
8513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case SLTI:
853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "slti    'rt, 'rs, 'imm16s");
8543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case SLTIU:
856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "sltiu   'rt, 'rs, 'imm16u");
8573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case ANDI:
859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "andi    'rt, 'rs, 'imm16x");
8603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case ORI:
862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "ori     'rt, 'rs, 'imm16x");
8633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case XORI:
865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "xori    'rt, 'rs, 'imm16x");
8663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case LUI:
868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lui     'rt, 'imm16x");
8693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // ------------- Memory instructions.
8713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case LB:
872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lb      'rt, 'imm16s('rs)");
8733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case LH:
875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lh      'rt, 'imm16s('rs)");
87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case LWL:
878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lwl     'rt, 'imm16s('rs)");
87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
8803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case LW:
881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lw      'rt, 'imm16s('rs)");
8823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
8833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case LBU:
884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lbu     'rt, 'imm16s('rs)");
8853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case LHU:
887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lhu     'rt, 'imm16s('rs)");
88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case LWR:
890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lwr     'rt, 'imm16s('rs)");
89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
8923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case SB:
893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "sb      'rt, 'imm16s('rs)");
8943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case SH:
896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "sh      'rt, 'imm16s('rs)");
89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case SWL:
899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "swl     'rt, 'imm16s('rs)");
90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
9013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case SW:
902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "sw      'rt, 'imm16s('rs)");
9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case SWR:
905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "swr     'rt, 'imm16s('rs)");
90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
9073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case LWC1:
908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "lwc1    'ft, 'imm16s('rs)");
9093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case LDC1:
911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "ldc1    'ft, 'imm16s('rs)");
9123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case SWC1:
914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "swc1    'ft, 'imm16s('rs)");
9153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case SDC1:
917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "sdc1    'ft, 'imm16s('rs)");
9183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    default:
9203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      UNREACHABLE();
9213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  };
9233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Decoder::DecodeTypeJump(Instruction* instr) {
9273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  switch (instr->OpcodeFieldRaw()) {
9283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case J:
929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "j       'imm26");
9303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case JAL:
932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Format(instr, "jal     'imm26");
9333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    default:
9353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      UNREACHABLE();
9363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Disassemble the instruction at *instr_ptr into the output buffer.
941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochint Decoder::InstructionDecode(byte* instr_ptr) {
9423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instruction* instr = Instruction::At(instr_ptr);
9433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Print raw instruction bytes.
94444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
9453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                       "%08x       ",
9463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                       instr->InstructionBits());
9473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  switch (instr->InstructionType()) {
9483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Instruction::kRegisterType: {
9493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      DecodeTypeRegister(instr);
9503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Instruction::kImmediateType: {
9533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      DecodeTypeImmediate(instr);
9543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    case Instruction::kJumpType: {
9573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      DecodeTypeJump(instr);
9583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      break;
9593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    default: {
9613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      UNSUPPORTED_MIPS();
9623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
96444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return Instruction::kInstrSize;
9653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
96844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} }  // namespace v8::internal
9693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//------------------------------------------------------------------------------
9733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace disasm {
9753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochconst char* NameConverter::NameOfAddress(byte* addr) const {
97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
97844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return tmp_buffer_.start();
9793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochconst char* NameConverter::NameOfConstant(byte* addr) const {
9833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return NameOfAddress(addr);
9843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuconst char* NameConverter::NameOfCPURegister(int reg) const {
98844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return v8::internal::Registers::Name(reg);
9893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuconst char* NameConverter::NameOfXMMRegister(int reg) const {
99344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return v8::internal::FPURegisters::Name(reg);
9943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuconst char* NameConverter::NameOfByteCPURegister(int reg) const {
998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UNREACHABLE();  // MIPS does not have the concept of a byte register.
9993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return "nobytereg";
10003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochconst char* NameConverter::NameInCode(byte* addr) const {
10043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // The default name converter is called for unknown code. So we will not try
10053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // to access any memory.
10063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return "";
10073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//------------------------------------------------------------------------------
10113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuDisassembler::Disassembler(const NameConverter& converter)
10133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    : converter_(converter) {}
10143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuDisassembler::~Disassembler() {}
10173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    byte* instruction) {
102144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::Decoder d(converter_, buffer);
10223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return d.InstructionDecode(instruction);
10233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The MIPS assembler does not currently use constant pools.
1027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochint Disassembler::ConstantPoolSizeAt(byte* instruction) {
10283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return -1;
10293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
10333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  NameConverter converter;
10343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Disassembler d(converter);
1035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (byte* pc = begin; pc < end;) {
10363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    v8::internal::EmbeddedVector<char, 128> buffer;
10373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    buffer[0] = '\0';
1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    byte* prev_pc = pc;
10393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    pc += d.InstructionDecode(buffer, pc);
10403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(f, "%p    %08x      %s\n",
10413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
10423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
10433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
104544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
10463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef UNSUPPORTED
10473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}  // namespace disasm
10493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
1051