disasm-arm.cc revision 8b112d2025046f85ef7f6be087c6129c872ebad2
18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Disassembler object is used to disassemble a block of code instruction by 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction. The default implementation of the NameConverter object can be 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overriden to modify register names or to do symbol lookup on addresses. 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The example below will disassemble a block of code and print it to stdout. 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// NameConverter converter; 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembler d(converter); 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for (byte* pc = begin; pc < end;) { 376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// v8::internal::EmbeddedVector<char, 256> buffer; 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// byte* prev_pc = pc; 396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// pc += d.InstructionDecode(buffer, pc); 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// printf("%p %08x %s\n", 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer); 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The Disassembler class also has a convenience method to disassemble a block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of code into a FILE*, meaning that the above functionality could also be 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// achieved by just calling Disassembler::Disassemble(stdout, begin, end); 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <assert.h> 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdio.h> 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h> 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <string.h> 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef WIN32 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdint.h> 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM) 60f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "constants-arm.h" 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disasm.h" 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h" 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h" 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace v8 { 681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace internal { 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Decoder decodes and disassembles instructions into an output buffer. 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// It uses the converter to convert register names and call destinations into 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// more informative description. 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Decoder { 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Decoder(const disasm::NameConverter& converter, 791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Vector<char> out_buffer) 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter), 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_(out_buffer), 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_pos_(0) { 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_] = '\0'; 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Decoder() {} 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes one disassembled instruction into 'buffer' (0-terminated). 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the length of the disassembled machine instruction in bytes. 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int InstructionDecode(byte* instruction); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsConstantPoolAt(byte* instr_ptr); 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static int ConstantPoolSizeAt(byte* instr_ptr); 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bottleneck functions to print into the out_buffer. 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PrintChar(const char ch); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Print(const char* str); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Printing of common values. 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PrintRegister(int reg); 102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void PrintSRegister(int reg); 103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void PrintDRegister(int reg); 1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int FormatVFPRegister(Instruction* instr, const char* format); 1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintMovwMovt(Instruction* instr); 1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int FormatVFPinstruction(Instruction* instr, const char* format); 1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintCondition(Instruction* instr); 1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintShiftRm(Instruction* instr); 1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintShiftImm(Instruction* instr); 1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintShiftSat(Instruction* instr); 1111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintPU(Instruction* instr); 1123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu void PrintSoftwareInterrupt(SoftwareInterruptCodes svc); 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle formatting of instructions and their options. 1151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int FormatRegister(Instruction* instr, const char* option); 1161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int FormatOption(Instruction* instr, const char* option); 1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Format(Instruction* instr, const char* format); 1181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Unknown(Instruction* instr); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Each of these functions decodes one particular instruction type, a 3-bit 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // field in the instruction encoding. 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Types 0 and 1 are combined as they are largely the same except for the way 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // they interpret the shifter operand. 1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType01(Instruction* instr); 1251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType2(Instruction* instr); 1261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType3(Instruction* instr); 1271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType4(Instruction* instr); 1281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType5(Instruction* instr); 1291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType6(Instruction* instr); 1303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Type 7 includes special Debugger instructions. 1311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int DecodeType7(Instruction* instr); 132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // For VFP support. 1331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeTypeVFP(Instruction* instr); 1341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType6CoprocessorIns(Instruction* instr); 135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); 1371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCMP(Instruction* instr); 1381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); 1391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const disasm::NameConverter& converter_; 1421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Vector<char> out_buffer_; 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int out_buffer_pos_; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DISALLOW_COPY_AND_ASSIGN(Decoder); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Support for assertions in the Decoder formatting functions. 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define STRING_STARTS_WITH(string, compare_string) \ 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (strncmp(string, compare_string, strlen(compare_string)) == 0) 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Append the ch to the output buffer. 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::PrintChar(const char ch) { 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_++] = ch; 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Append the str to the output buffer. 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::Print(const char* str) { 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char cur = *str++; 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintChar(cur); 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cur = *str++; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_] = 0; 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These condition names are defined in a way to match the native disassembler 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// formatting. See for example the command "objdump -d <binary file>". 1731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic const char* cond_names[kNumberOfConditions] = { 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" , 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the condition guarding the instruction. 1801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintCondition(Instruction* instr) { 1811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print(cond_names[instr->ConditionValue()]); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the register name according to the active name converter. 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::PrintRegister(int reg) { 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print(converter_.NameOfCPURegister(reg)); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Print the VFP S register name according to the active name converter. 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Decoder::PrintSRegister(int reg) { 1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print(VFPRegisters::Name(reg, false)); 193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Print the VFP D register name according to the active name converter. 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Decoder::PrintDRegister(int reg) { 1971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print(VFPRegisters::Name(reg, true)); 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These shift names are defined in a way to match the native disassembler 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// formatting. See for example the command "objdump -d <binary file>". 2031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic const char* shift_names[kNumberOfShifts] = { 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "lsl", "lsr", "asr", "ror" 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the register shift operands for the instruction. Generally used for 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// data processing instructions. 2101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftRm(Instruction* instr) { 2111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ShiftOp shift = instr->ShiftField(); 2121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int shift_index = instr->ShiftValue(); 2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int shift_amount = instr->ShiftAmountValue(); 2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rm = instr->RmValue(); 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(rm); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) { 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Special case for using rm only. 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->RegShiftValue() == 0) { 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // by immediate 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((shift == ROR) && (shift_amount == 0)) { 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print(", RRX"); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_amount = 32; 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ", %s #%d", 2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block shift_names[shift_index], 2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block shift_amount); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // by register 2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rs = instr->RsValue(); 2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ", %s ", shift_names[shift_index]); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(rs); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the immediate operand for the instruction. Generally used for data 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// processing instructions. 2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftImm(Instruction* instr) { 2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rotate = instr->RotateValue() * 2; 2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int immed8 = instr->Immed8Value(); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); 2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "#%d", imm); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Print the optional shift and immediate used by saturating instructions. 2561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftSat(Instruction* instr) { 25750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int shift = instr->Bits(11, 7); 25850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (shift > 0) { 2591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 2601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ", %s #%d", 2611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block shift_names[instr->Bit(6) * 2], 2621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->Bits(11, 7)); 26350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 26450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen} 26550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 26650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print PU formatting to reduce complexity of FormatOption. 2681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintPU(Instruction* instr) { 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 2701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("da"); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("ia"); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("db"); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("ib"); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the FormatOption method. 2963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) { 2973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu switch (svc) { 2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case kCallRtRedirected: 2991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print("call rt redirected"); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 3011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case kBreakpoint: 3021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print("breakpoint"); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (svc >= kStopCode) { 3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d - 0x%x", 3081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block svc & kStopCodeMask, 3091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block svc & kStopCodeMask); 3103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 3111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d", 3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block svc); 3143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle all register based formatting in this function to reduce the 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// complexity of FormatOption. 3221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatRegister(Instruction* instr, const char* format) { 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(format[0] == 'r'); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (format[1] == 'n') { // 'rn: Rn register 3251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RnValue(); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'd') { // 'rd: Rd register 3291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RdValue(); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 's') { // 'rs: Rs register 3331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RsValue(); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'm') { // 'rm: Rm register 3371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RmValue(); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (format[1] == 't') { // 'rt: Rt register 3411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RtValue(); 342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PrintRegister(reg); 343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 2; 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'l') { 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'rlist: register list for load and store multiple instructions 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "rlist")); 3471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rlist = instr->RlistValue(); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int reg = 0; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("{"); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print register list in ascending order, by scanning the bit mask. 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (rlist != 0) { 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((rlist & 1) != 0) { 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((rlist >> 1) != 0) { 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print(", "); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reg++; 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rlist >>= 1; 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("}"); 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -1; 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Handle all VFP register based formatting in this function to reduce the 370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// complexity of FormatOption. 3711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatVFPRegister(Instruction* instr, const char* format) { 372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT((format[0] == 'S') || (format[0] == 'D')); 373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch VFPRegPrecision precision = 3758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch format[0] == 'D' ? kDoublePrecision : kSinglePrecision; 3768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int retval = 2; 3788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int reg = -1; 379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (format[1] == 'n') { 3808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch reg = instr->VFPNRegValue(precision); 381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (format[1] == 'm') { 3828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch reg = instr->VFPMRegValue(precision); 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (format[1] == 'd') { 3848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch reg = instr->VFPDRegValue(precision); 3858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (format[2] == '+') { 3868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int immed8 = instr->Immed8Value(); 3878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (format[0] == 'S') reg += immed8 - 1; 3888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (format[0] == 'D') reg += (immed8 / 2 - 1); 3898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (format[2] == '+') retval = 3; 3918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 3928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch UNREACHABLE(); 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (precision == kSinglePrecision) { 3968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrintSRegister(reg); 3978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 3988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrintDRegister(reg); 3998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return retval; 402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatVFPinstruction(Instruction* instr, const char* format) { 406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Print(format); 407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 0; 408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Print the movw or movt instruction. 4121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintMovwMovt(Instruction* instr) { 4131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int imm = instr->ImmedMovwMovtValue(); 4141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rd = instr->RdValue(); 4159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen PrintRegister(rd); 4161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 4171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ", #%d", imm); 4189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// FormatOption takes a formatting string and interprets it based on 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the current instructions. The format string points to the first 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// character of the option string (the option escape has already been 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// consumed by the caller.) FormatOption returns the number of 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// characters that were consumed from the formatting string. 4261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatOption(Instruction* instr, const char* format) { 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (format[0]) { 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'a': { // 'a: accumulate multiplies 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(21) == 0) { 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("ul"); 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("la"); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'b': { // 'b: byte loads or stores 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasB()) { 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("b"); 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'c': { // 'cond: conditional execution 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "cond")); 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintCondition(instr); 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 4; 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch case 'd': { // 'd: vmov double immediate. 4483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch double d = instr->DoubleImmedVmov(); 4491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 4501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "#%g", d); 4513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return 1; 4523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 4537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch case 'f': { // 'f: bitfield instructions - v7 and above. 4547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t lsbit = instr->Bits(11, 7); 4557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t width = instr->Bits(20, 16) + 1; 4567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (instr->Bit(21) == 0) { 4577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // BFC/BFI: 4587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Bits 20-16 represent most-significant bit. Covert to width. 4597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch width -= lsbit; 4607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(width > 0); 4617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 4627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT((width + lsbit) <= 32); 4631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 4641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "#%d, #%d", lsbit, width); 4657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return 1; 4667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'h': { // 'h: halfword operation for extra loads and stores 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasH()) { 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("h"); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("b"); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 47550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen case 'i': { // 'i: immediate value from adjacent bits. 47650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Expects tokens in the form imm%02d@%02d, ie. imm05@07, imm10@16 47750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int width = (format[3] - '0') * 10 + (format[4] - '0'); 47850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int lsb = (format[6] - '0') * 10 + (format[7] - '0'); 47950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 48050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT((width >= 1) && (width <= 32)); 48150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT((lsb >= 0) && (lsb <= 31)); 48250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT((width + lsb) <= 32); 48350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 4841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 4851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d", 4861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->Bits(width + lsb - 1, lsb)); 48750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen return 8; 48850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'l': { // 'l: branch and link 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasLink()) { 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("l"); 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'm': { 4969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (format[1] == 'w') { 4979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // 'mw: movt/movw instructions. 4989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen PrintMovwMovt(instr); 4999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return 2; 5009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (format[1] == 'e') { // 'memop: load/store instructions. 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "memop")); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasL()) { 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("ldr"); 50525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0)) { 50625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bits(7, 4) == 0xf) { 50725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Print("strd"); 50825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 50925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Print("ldrd"); 51025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("str"); 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'msg: for simulator break instructions 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "msg")); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* str = 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); 5201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%s", converter_.NameInCode(str)); 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 3; 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'o': { 5253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((format[3] == '1') && (format[4] == '2')) { 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'off12: 12-bit offset for load and store instructions 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "off12")); 5281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d", instr->Offset12Value()); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (format[3] == '0') { 5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. 5336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19")); 5341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d", 5361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Bits(19, 8) << 4) + 5371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->Bits(3, 0)); 5386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return 15; 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'off8: 8-bit offset for extra load and store instructions 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "off8")); 5421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); 5431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d", offs8); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 4; 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'p': { // 'pu: P and U bits for load and store instructions 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "pu")); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintPU(instr); 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'r': { 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return FormatRegister(instr, format); 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': { 55650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat. 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (format[6] == 'o') { // 'shift_op 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "shift_op")); 5591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->TypeValue() == 0) { 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftRm(instr); 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 5621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->TypeValue() == 1); 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftImm(instr); 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 8; 56650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } else if (format[6] == 's') { // 'shift_sat. 56750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT(STRING_STARTS_WITH(format, "shift_sat")); 56850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen PrintShiftSat(instr); 56950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen return 9; 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // 'shift_rm 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "shift_rm")); 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftRm(instr); 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 8; 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 5753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else if (format[1] == 'v') { // 'svc 5763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(STRING_STARTS_WITH(format, "svc")); 5771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintSoftwareInterrupt(instr->SvcValue()); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 3; 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'i') { // 'sign: signed extra loads and stores 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "sign")); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasSign()) { 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 4; 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 's: S field of data processing instructions 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 't': { // 'target: target of branch instructions 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "target")); 5941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int off = (instr->SImmed24Value() << 2) + 8; 5951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%+d -> %s", 5971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block off, 5981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block converter_.NameOfAddress( 5991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block reinterpret_cast<byte*>(instr) + off)); 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'u': { // 'u: signed or unsigned multiplies 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The manual gets the meaning of bit 22 backwards in the multiply 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction overview on page A3.16.2. The instructions that 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // exist in u and s variants are the following: 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smull A4.1.87 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // umull A4.1.129 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // umlal A4.1.128 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smlal A4.1.76 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For these 0 means u and 1 means s. As can be seen on their individual 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pages. The other 18 mul instructions have the bit set or unset in 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arbitrary ways that are unrelated to the signedness of the instruction. 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // None of these 18 instructions exist in both a 'u' and an 's' variant. 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("u"); 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'v': { 623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return FormatVFPinstruction(instr, format); 624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'S': 626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'D': { 627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return FormatVFPRegister(instr, format); 628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'w': { // 'w: W field of load and store instructions 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("!"); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -1; 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Format takes a formatting string for a whole instruction and prints it into 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the output buffer. All escaped options are handed to FormatOption to be 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// parsed further. 6481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::Format(Instruction* instr, const char* format) { 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char cur = *format++; 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cur == '\'') { // Single quote is used as the formatting escape. 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block format += FormatOption(instr, format); 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_++] = cur; 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cur = *format++; 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_] = '\0'; 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// For currently unimplemented decodings the disassembler calls Unknown(instr) 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// which will just print "unknown" of the instruction bits. 6641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::Unknown(Instruction* instr) { 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "unknown"); 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType01(Instruction* instr) { 6701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int type = instr->TypeValue(); 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((type == 0) && instr->IsSpecialType0()) { 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // multiply instruction or extra loads and stores 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bits(7, 4) == 9) { 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(24) == 0) { 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // multiply instructions 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(23) == 0) { 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(21) == 0) { 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The MUL instruction description (A 4.1.33) refers to Rd as being 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the destination for the operation, but it confusingly uses the 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rn field to encode it. 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The MLA instruction description (A 4.1.28) refers to the order 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rn field to encode the Rd register and the Rd field to encode 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the Rn register. 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The signed/long multiply instructions use the terms RdHi and RdLo 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // when referring to the target registers. They are mapped to the Rn 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and Rd fields as follows: 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RdLo == Rd field 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RdHi == Rn field 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs> 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs"); 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unknown(instr); // not used by V8 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 70125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) { 70225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // ldrd, strd 70325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen switch (instr->PUField()) { 7041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 70525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 70625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], -'rm"); 70725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 70825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], #-'off8"); 70925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 71025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 71125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 7121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 71325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 71425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], +'rm"); 71525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 71625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], #+'off8"); 71725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 71825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 71925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 7201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 72125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 72225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w"); 72325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 72425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w"); 72525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 72625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 72725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 7281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 72925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 73025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w"); 73125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 73225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w"); 73325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 73425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 73525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 73625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen default: { 73725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // The PU field is a 2-bit field. 73825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen UNREACHABLE(); 73925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 74025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 74125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // extra load/store instructions 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 7451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if ((type == 0) && instr->IsMiscType0()) { 7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->Bits(22, 21) == 1) { 7871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->BitField(7, 4)) { 7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BX: 7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "bx'cond 'rm"); 7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BLX: 7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "blx'cond 'rm"); 7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BKPT: 7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "bkpt 'off0to3and8to19"); 7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (instr->Bits(22, 21) == 3) { 8021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->BitField(7, 4)) { 8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case CLZ: 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "clz'cond 'rd, 'rm"); 8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->OpcodeField()) { 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case AND: { 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "and'cond's 'rd, 'rn, 'shift_op"); 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case EOR: { 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "eor'cond's 'rd, 'rn, 'shift_op"); 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SUB: { 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "sub'cond's 'rd, 'rn, 'shift_op"); 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RSB: { 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op"); 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ADD: { 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "add'cond's 'rd, 'rn, 'shift_op"); 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ADC: { 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "adc'cond's 'rd, 'rn, 'shift_op"); 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SBC: { 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op"); 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RSC: { 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op"); 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TST: { 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "tst'cond 'rn, 'shift_op"); 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Format(instr, "movw'cond 'mw"); 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TEQ: { 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "teq'cond 'rn, 'shift_op"); 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other instructions matching this pattern are handled in the 8606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // miscellaneous instructions part above. 8616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UNREACHABLE(); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CMP: { 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "cmp'cond 'rn, 'shift_op"); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Format(instr, "movt'cond 'mw"); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CMN: { 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "cmn'cond 'rn, 'shift_op"); 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other instructions matching this pattern are handled in the 8786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // miscellaneous instructions part above. 8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UNREACHABLE(); 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ORR: { 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "orr'cond's 'rd, 'rn, 'shift_op"); 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MOV: { 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mov'cond's 'rd, 'shift_op"); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case BIC: { 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "bic'cond's 'rd, 'rn, 'shift_op"); 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MVN: { 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mvn'cond's 'rd, 'shift_op"); 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The Opcode field is a 4-bit field. 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType2(Instruction* instr) { 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 9111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unknown(instr); // not used in V8 91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unknown(instr); // not used in V8 92244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType3(Instruction* instr) { 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 9461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!instr->HasW()); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 95250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (instr->HasW()) { 95350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT(instr->Bits(5, 4) == 0x1); 95450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (instr->Bit(22) == 0x1) { 95580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); 95650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } else { 95750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen UNREACHABLE(); // SSAT. 95850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 95950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } else { 96050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); 96150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 9693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 9703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 9717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 9723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t msbit = widthminus1 + lsbit; 9733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (msbit <= 31) { 9747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (instr->Bit(22)) { 9757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "ubfx'cond 'rd, 'rm, 'f"); 9767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 9777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "sbfx'cond 'rd, 'rm, 'f"); 9787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 9797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 9807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch UNREACHABLE(); 9817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 9827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { 9837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 9847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); 9857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (msbit >= lsbit) { 9861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->RmValue() == 15) { 9877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "bfc'cond 'rd, 'f"); 9887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 9897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "bfi'cond 'rd, 'rm, 'f"); 9907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 9913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 9923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 9933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 9953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 9963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType4(Instruction* instr) { 100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->Bit(22) != 0) { 101044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Privileged mode currently not supported. 101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Unknown(instr); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 101344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->HasL()) { 101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 101544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 101644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 101744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType5(Instruction* instr) { 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "b'l'cond 'target"); 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType6(Instruction* instr) { 1028d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block DecodeType6CoprocessorIns(instr); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::DecodeType7(Instruction* instr) { 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(24) == 1) { 10341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SvcValue() >= kStopCode) { 10353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Format(instr, "stop'cond 'svc"); 10363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Also print the stop message. Its address is encoded 10373e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // in the following 4 bytes. 10381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 10391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "\n %p %08x stop message: %s", 10401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block reinterpret_cast<int32_t*>(instr 10411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block + Instruction::kInstrSize), 10421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block *reinterpret_cast<char**>(instr 10431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block + Instruction::kInstrSize), 10441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block *reinterpret_cast<char**>(instr 10451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block + Instruction::kInstrSize)); 10461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We have decoded 2 * Instruction::kInstrSize bytes. 10471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 2 * Instruction::kInstrSize; 10483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 10493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Format(instr, "svc'cond 'svc"); 10503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block DecodeTypeVFP(instr); 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// void Decoder::DecodeTypeVFP(Instruction* instr) 1059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vmov: Sn = Rt 1060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vmov: Rt = Sn 1061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vcvt: Dd = Sm 1062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vcvt: Sd = Dm 106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Dd = vabs(Dm) 106444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Dd = vneg(Dm) 1065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vadd(Dn, Dm) 1066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vsub(Dn, Dm) 1067e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vmul(Dn, Dm) 1068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vdiv(Dn, Dm) 1069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// vcmp(Dd, Dm) 10708defd9ff6930b4e24729971a61cf7469daf119beSteve Block// vmrs 10718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// vmsr 10728defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Dd = vsqrt(Dm) 10731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeTypeVFP(Instruction* instr) { 10741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); 10756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(instr->Bits(11, 9) == 0x5); 10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->Bit(4) == 0) { 10781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc1Value() == 0x7) { 10796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other data processing instructions 10801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { 10818defd9ff6930b4e24729971a61cf7469daf119beSteve Block // vmov register to register. 10821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 10838defd9ff6930b4e24729971a61cf7469daf119beSteve Block Format(instr, "vmov.f64'cond 'Dd, 'Dm"); 10848defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 10853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Format(instr, "vmov.f32'cond 'Sd, 'Sm"); 10868defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 10871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { 10881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // vabs 10891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Format(instr, "vabs'cond 'Dd, 'Dm"); 109044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { 109144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // vneg 109244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Format(instr, "vneg'cond 'Dd, 'Dm"); 10931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { 10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenDoubleAndSingle(instr); 10951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { 10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenFloatingPointAndInteger(instr); 10971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() >> 1) == 0x6) && 10981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)) { 10996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenFloatingPointAndInteger(instr); 11001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 11011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)) { 11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCMP(instr); 11031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { 11048defd9ff6930b4e24729971a61cf7469daf119beSteve Block Format(instr, "vsqrt.f64'cond 'Dd, 'Dm"); 11051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc3Value() == 0x0) { 11061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 11073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Format(instr, "vmov.f64'cond 'Dd, 'd"); 11083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } else { 11093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Unknown(instr); // Not used by V8. 11103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc1Value() == 0x3) { 11151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 11161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc3Value() & 0x1) { 11176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm"); 11186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm"); 11206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { 11251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 11266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm"); 11276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { 11311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm"); 11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Unknown(instr); // Not used by V8. 1138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if ((instr->VCValue() == 0x0) && 11411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x0)) { 11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); 11431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->VCValue() == 0x0) && 11441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x7) && 11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (instr->Bits(19, 16) == 0x1)) { 11461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->VLValue() == 0) { 11478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (instr->Bits(15, 12) == 0xF) { 11488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmsr'cond FPSCR, APSR"); 11498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 11508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmsr'cond FPSCR, 'rt"); 11518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 11528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 11538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (instr->Bits(15, 12) == 0xF) { 11548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmrs'cond APSR, FPSCR"); 11558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 11568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmrs'cond 'rt, FPSCR"); 11578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 11588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 1159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( 11651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instruction* instr) { 11661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && 11671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x0)); 11686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool to_arm_register = (instr->VLValue() == 0x1); 11706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (to_arm_register) { 11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vmov'cond 'rt, 'Sn"); 1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vmov'cond 'Sn, 'rt"); 11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCMP(Instruction* instr) { 11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 11811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 11821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)); 11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Comparison. 11851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool dp_operation = (instr->SzValue() == 1); 11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); 11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation && !raise_exception_for_qnan) { 11891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc2Value() == 0x4) { 1190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Format(instr, "vcmp.f64'cond 'Dd, 'Dm"); 11911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc2Value() == 0x5) { 1192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Format(instr, "vcmp.f64'cond 'Dd, #0.0"); 1193756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 1194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Unknown(instr); // invalid 1195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { 12031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 12041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); 12056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool double_to_single = (instr->SzValue() == 1); 12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (double_to_single) { 12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm"); 12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm"); 12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 12171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 12181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 12191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool to_integer = (instr->Bit(18) == 1); 12221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool dp_operation = (instr->SzValue() == 1); 12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (to_integer) { 12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool unsigned_integer = (instr->Bit(16) == 0); 12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation) { 12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm"); 12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm"); 12316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm"); 12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm"); 12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool unsigned_integer = (instr->Bit(7) == 0); 12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation) { 12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm"); 12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm"); 12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm"); 12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm"); 12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Decode Type 6 coprocessor instructions. 1260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dm = vmov(Rt, Rt2) 1261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// <Rt, Rt2> = vmov(Dm) 1262d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Ddst = MEM(Rbase + 4*offset). 1263d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// MEM(Rbase + 4*offset) = Dsrc. 12641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType6CoprocessorIns(Instruction* instr) { 12651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->TypeValue() == 6); 1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 12671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->CoprocessorValue() == 0xA) { 12681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->OpcodeValue()) { 12696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x8: 127080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case 0xA: 12716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->HasL()) { 127280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]"); 12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 127480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]"); 12756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 12776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0xC: 127880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case 0xE: 12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->HasL()) { 128080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]"); 12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 128280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]"); 12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 12858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x4: 12868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x5: 12878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x6: 12888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x7: 12898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x9: 12908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB: { 12918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool to_vfp_register = (instr->VLValue() == 0x1); 12928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (to_vfp_register) { 12938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}"); 12948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 12958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}"); 12968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 12988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 13006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 13016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->CoprocessorValue() == 0xB) { 13031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->OpcodeValue()) { 1304d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0x2: 1305d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Load and store double to two GP registers 1306d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (instr->Bits(7, 4) != 0x1) { 1307d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Unknown(instr); // Not used by V8. 1308d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (instr->HasL()) { 1309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Format(instr, "vmov'cond 'rt, 'rn, 'Dm"); 1310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Format(instr, "vmov'cond 'Dm, 'rt, 'rn"); 1312d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 1314d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0x8: 1315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (instr->HasL()) { 131680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]"); 1317d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 131880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]"); 1319d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 1321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0xC: 1322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (instr->HasL()) { 132380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]"); 1324d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 132580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]"); 1326d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1327d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 13288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x4: 13298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x5: 13308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x9: { 13318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool to_vfp_register = (instr->VLValue() == 0x1); 13328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (to_vfp_register) { 13338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}"); 13348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 13358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}"); 13368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 13378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 13388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke default: 1340d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Unknown(instr); // Not used by V8. 1341d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 13426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 134344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Unknown(instr); // Not used by V8. 134444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 134844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Decoder::IsConstantPoolAt(byte* instr_ptr) { 134944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker; 135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 135344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 135444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint Decoder::ConstantPoolSizeAt(byte* instr_ptr) { 135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (IsConstantPoolAt(instr_ptr)) { 135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return instruction_bits & kConstantPoolLengthMask; 135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return -1; 1360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassemble the instruction at *instr_ptr into the output buffer. 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Decoder::InstructionDecode(byte* instr_ptr) { 13661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instruction* instr = Instruction::At(instr_ptr); 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print raw instruction bytes. 13681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 13691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%08x ", 13701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->InstructionBits()); 13711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->ConditionField() == kSpecialCondition) { 137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Unknown(instr); 137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Instruction::kInstrSize; 137444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 137544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 137644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) { 137744f0eee88ff00398ff7f715fab053374d808c90dSteve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 137844f0eee88ff00398ff7f715fab053374d808c90dSteve Block "constant pool begin (length %d)", 137944f0eee88ff00398ff7f715fab053374d808c90dSteve Block instruction_bits & 138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block kConstantPoolLengthMask); 13811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->TypeValue()) { 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: { 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType01(instr); 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: { 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType2(instr); 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: { 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType3(instr); 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: { 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType4(instr); 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: { 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType5(instr); 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: { 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType6(instr); 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: { 14103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu return DecodeType7(instr); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The type field is 3-bits in the ARM encoding. 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 14181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} } // namespace v8::internal 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm { 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 143244f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); 143344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return tmp_buffer_.start(); 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 14431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return v8::internal::Registers::Name(reg); 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); // ARM does not have the concept of a byte register 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "nobytereg"; 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); // ARM does not have any XMM registers 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The default name converter is called for unknown code. So we will not try 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to access any memory. 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) {} 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {} 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 14771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block v8::internal::Decoder d(converter_, buffer); 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(instruction); 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { 148344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return v8::internal::Decoder::ConstantPoolSizeAt(instruction); 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%p %08x %s\n", 1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 1504