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