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>". 20369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const 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. 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Expects tokens in the form imm%02d@%02d, i.e. 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"); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) && 507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) { 508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->Bit(5) == 1) { 509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Print("strd"); 510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Print("ldrd"); 512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return 5; 514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("str"); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'msg: for simulator break instructions 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "msg")); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* str = 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); 5231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%s", converter_.NameInCode(str)); 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 3; 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'o': { 5283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((format[3] == '1') && (format[4] == '2')) { 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'off12: 12-bit offset for load and store instructions 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "off12")); 5311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d", instr->Offset12Value()); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (format[3] == '0') { 5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. 5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19")); 5371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d", 5391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Bits(19, 8) << 4) + 5401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->Bits(3, 0)); 5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return 15; 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'off8: 8-bit offset for extra load and store instructions 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "off8")); 5451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); 5461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%d", offs8); 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 4; 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'p': { // 'pu: P and U bits for load and store instructions 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "pu")); 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintPU(instr); 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'r': { 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return FormatRegister(instr, format); 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': { 55950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat. 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (format[6] == 'o') { // 'shift_op 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "shift_op")); 5621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->TypeValue() == 0) { 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftRm(instr); 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 5651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->TypeValue() == 1); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftImm(instr); 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 8; 56950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } else if (format[6] == 's') { // 'shift_sat. 57050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT(STRING_STARTS_WITH(format, "shift_sat")); 57150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen PrintShiftSat(instr); 57250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen return 9; 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // 'shift_rm 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "shift_rm")); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftRm(instr); 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 8; 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 5783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else if (format[1] == 'v') { // 'svc 5793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(STRING_STARTS_WITH(format, "svc")); 5801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintSoftwareInterrupt(instr->SvcValue()); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 3; 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'i') { // 'sign: signed extra loads and stores 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "sign")); 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasSign()) { 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 4; 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 's: S field of data processing instructions 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 't': { // 'target: target of branch instructions 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(STRING_STARTS_WITH(format, "target")); 5971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int off = (instr->SImmed24Value() << 2) + 8; 5981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 5991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%+d -> %s", 6001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block off, 6011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block converter_.NameOfAddress( 6021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block reinterpret_cast<byte*>(instr) + off)); 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'u': { // 'u: signed or unsigned multiplies 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The manual gets the meaning of bit 22 backwards in the multiply 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction overview on page A3.16.2. The instructions that 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // exist in u and s variants are the following: 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smull A4.1.87 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // umull A4.1.129 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // umlal A4.1.128 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smlal A4.1.76 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For these 0 means u and 1 means s. As can be seen on their individual 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pages. The other 18 mul instructions have the bit set or unset in 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arbitrary ways that are unrelated to the signedness of the instruction. 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // None of these 18 instructions exist in both a 'u' and an 's' variant. 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("u"); 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'v': { 626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return FormatVFPinstruction(instr, format); 627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'S': 629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'D': { 630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return FormatVFPRegister(instr, format); 631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'w': { // 'w: W field of load and store instructions 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("!"); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -1; 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Format takes a formatting string for a whole instruction and prints it into 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the output buffer. All escaped options are handed to FormatOption to be 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// parsed further. 6511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::Format(Instruction* instr, const char* format) { 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char cur = *format++; 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cur == '\'') { // Single quote is used as the formatting escape. 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block format += FormatOption(instr, format); 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_++] = cur; 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cur = *format++; 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_] = '\0'; 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The disassembler may end up decoding data inlined in the code. We do not want 6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// it to crash if the data does not ressemble any known instruction. 6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define VERIFY(condition) \ 6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochif(!(condition)) { \ 6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Unknown(instr); \ 6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; \ 6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// For currently unimplemented decodings the disassembler calls Unknown(instr) 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// which will just print "unknown" of the instruction bits. 6761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::Unknown(Instruction* instr) { 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "unknown"); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType01(Instruction* instr) { 6821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int type = instr->TypeValue(); 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((type == 0) && instr->IsSpecialType0()) { 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // multiply instruction or extra loads and stores 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bits(7, 4) == 9) { 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(24) == 0) { 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // multiply instructions 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(23) == 0) { 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(21) == 0) { 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The MUL instruction description (A 4.1.33) refers to Rd as being 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the destination for the operation, but it confusingly uses the 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rn field to encode it. 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The MLA instruction description (A 4.1.28) refers to the order 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rn field to encode the Rd register and the Rd field to encode 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the Rn register. 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The signed/long multiply instructions use the terms RdHi and RdLo 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // when referring to the target registers. They are mapped to the Rn 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and Rd fields as follows: 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RdLo == Rd field 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RdHi == Rn field 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs> 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs"); 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unknown(instr); // not used by V8 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 71325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) { 71425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // ldrd, strd 71525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen switch (instr->PUField()) { 7161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 71725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 71825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], -'rm"); 71925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 72025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], #-'off8"); 72125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 72225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 72325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 72525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 72625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], +'rm"); 72725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 72825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], #+'off8"); 72925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 73025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 73125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 7321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 73325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 73425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w"); 73525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 73625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w"); 73725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 73825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 73925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 7401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 74125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 74225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w"); 74325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 74425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w"); 74525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 74625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 74725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 74825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen default: { 74925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // The PU field is a 2-bit field. 75025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen UNREACHABLE(); 75125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 75225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 75325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // extra load/store instructions 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 7571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if ((type == 0) && instr->IsMiscType0()) { 7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->Bits(22, 21) == 1) { 7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->BitField(7, 4)) { 8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BX: 8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "bx'cond 'rm"); 8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BLX: 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "blx'cond 'rm"); 8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BKPT: 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "bkpt 'off0to3and8to19"); 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (instr->Bits(22, 21) == 3) { 8141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->BitField(7, 4)) { 8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case CLZ: 8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "clz'cond 'rd, 'rm"); 8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->OpcodeField()) { 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case AND: { 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "and'cond's 'rd, 'rn, 'shift_op"); 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case EOR: { 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "eor'cond's 'rd, 'rn, 'shift_op"); 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SUB: { 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "sub'cond's 'rd, 'rn, 'shift_op"); 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RSB: { 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op"); 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ADD: { 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "add'cond's 'rd, 'rn, 'shift_op"); 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ADC: { 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "adc'cond's 'rd, 'rn, 'shift_op"); 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SBC: { 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op"); 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RSC: { 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op"); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TST: { 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "tst'cond 'rn, 'shift_op"); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Format(instr, "movw'cond 'mw"); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TEQ: { 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "teq'cond 'rn, 'shift_op"); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other instructions matching this pattern are handled in the 8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // miscellaneous instructions part above. 8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UNREACHABLE(); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CMP: { 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "cmp'cond 'rn, 'shift_op"); 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Format(instr, "movt'cond 'mw"); 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CMN: { 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "cmn'cond 'rn, 'shift_op"); 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 8896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other instructions matching this pattern are handled in the 8906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // miscellaneous instructions part above. 8916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UNREACHABLE(); 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ORR: { 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "orr'cond's 'rd, 'rn, 'shift_op"); 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MOV: { 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mov'cond's 'rd, 'shift_op"); 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case BIC: { 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "bic'cond's 'rd, 'rn, 'shift_op"); 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MVN: { 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mvn'cond's 'rd, 'shift_op"); 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The Opcode field is a 4-bit field. 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType2(Instruction* instr) { 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 9231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unknown(instr); // not used in V8 92644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unknown(instr); // not used in V8 93444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType3(Instruction* instr) { 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 9581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(!instr->HasW()); 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 96450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (instr->HasW()) { 9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(instr->Bits(5, 4) == 0x1); 96650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (instr->Bit(22) == 0x1) { 96780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); 96850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } else { 96950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen UNREACHABLE(); // SSAT. 97050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 97150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } else { 97250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); 97350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 9813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 9823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 9837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 9843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t msbit = widthminus1 + lsbit; 9853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (msbit <= 31) { 9867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (instr->Bit(22)) { 9877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "ubfx'cond 'rd, 'rm, 'f"); 9887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 9897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "sbfx'cond 'rd, 'rm, 'f"); 9907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 9917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 9927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch UNREACHABLE(); 9937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 9947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { 9957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 9967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); 9977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (msbit >= lsbit) { 9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->RmValue() == 15) { 9997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "bfc'cond 'rd, 'f"); 10007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 10017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "bfi'cond 'rd, 'rm, 'f"); 10027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 10033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 10043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 10053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 10063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 10073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 10083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType4(Instruction* instr) { 102144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->Bit(22) != 0) { 102244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Privileged mode currently not supported. 102344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Unknown(instr); 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 102544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->HasL()) { 102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 102844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType5(Instruction* instr) { 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "b'l'cond 'target"); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType6(Instruction* instr) { 1040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block DecodeType6CoprocessorIns(instr); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::DecodeType7(Instruction* instr) { 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(24) == 1) { 10461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SvcValue() >= kStopCode) { 10473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Format(instr, "stop'cond 'svc"); 10483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Also print the stop message. Its address is encoded 10493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // in the following 4 bytes. 10501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 10511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "\n %p %08x stop message: %s", 10521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block reinterpret_cast<int32_t*>(instr 10531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block + Instruction::kInstrSize), 10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block *reinterpret_cast<char**>(instr 10551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block + Instruction::kInstrSize), 10561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block *reinterpret_cast<char**>(instr 10571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block + Instruction::kInstrSize)); 10581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We have decoded 2 * Instruction::kInstrSize bytes. 10591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 2 * Instruction::kInstrSize; 10603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 10613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Format(instr, "svc'cond 'svc"); 10623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block DecodeTypeVFP(instr); 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// void Decoder::DecodeTypeVFP(Instruction* instr) 1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vmov: Sn = Rt 1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vmov: Rt = Sn 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vcvt: Dd = Sm 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vcvt: Sd = Dm 107544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Dd = vabs(Dm) 107644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Dd = vneg(Dm) 1077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vadd(Dn, Dm) 1078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vsub(Dn, Dm) 1079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vmul(Dn, Dm) 1080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vdiv(Dn, Dm) 1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// vcmp(Dd, Dm) 10828defd9ff6930b4e24729971a61cf7469daf119beSteve Block// vmrs 10838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// vmsr 10848defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Dd = vsqrt(Dm) 10851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeTypeVFP(Instruction* instr) { 10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); 10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(instr->Bits(11, 9) == 0x5); 10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->Bit(4) == 0) { 10901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc1Value() == 0x7) { 10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other data processing instructions 10921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { 10938defd9ff6930b4e24729971a61cf7469daf119beSteve Block // vmov register to register. 10941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 10958defd9ff6930b4e24729971a61cf7469daf119beSteve Block Format(instr, "vmov.f64'cond 'Dd, 'Dm"); 10968defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 10973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Format(instr, "vmov.f32'cond 'Sd, 'Sm"); 10988defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 10991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { 11001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // vabs 1101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Format(instr, "vabs.f64'cond 'Dd, 'Dm"); 110244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { 110344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // vneg 1104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Format(instr, "vneg.f64'cond 'Dd, 'Dm"); 11051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { 11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenDoubleAndSingle(instr); 11071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { 11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenFloatingPointAndInteger(instr); 11091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() >> 1) == 0x6) && 11101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)) { 11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenFloatingPointAndInteger(instr); 11121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 11131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)) { 11146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCMP(instr); 11151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { 11168defd9ff6930b4e24729971a61cf7469daf119beSteve Block Format(instr, "vsqrt.f64'cond 'Dd, 'Dm"); 11171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc3Value() == 0x0) { 11181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 11193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Format(instr, "vmov.f64'cond 'Dd, 'd"); 11203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } else { 11213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Unknown(instr); // Not used by V8. 11223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc1Value() == 0x3) { 11271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 11281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc3Value() & 0x1) { 11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm"); 11306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm"); 11326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { 11371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm"); 11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { 11431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 1144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm"); 11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Unknown(instr); // Not used by V8. 1150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if ((instr->VCValue() == 0x0) && 11531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x0)) { 11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); 11551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->VCValue() == 0x0) && 11561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x7) && 11576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (instr->Bits(19, 16) == 0x1)) { 11581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->VLValue() == 0) { 11598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (instr->Bits(15, 12) == 0xF) { 11608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmsr'cond FPSCR, APSR"); 11618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 11628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmsr'cond FPSCR, 'rt"); 11638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 11648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 11658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (instr->Bits(15, 12) == 0xF) { 11668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmrs'cond APSR, FPSCR"); 11678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 11688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmrs'cond 'rt, FPSCR"); 11698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 11708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( 11771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instruction* instr) { 11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && 11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x0)); 11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool to_arm_register = (instr->VLValue() == 0x1); 11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (to_arm_register) { 11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vmov'cond 'rt, 'Sn"); 1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vmov'cond 'Sn, 'rt"); 11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCMP(Instruction* instr) { 11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 11941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)); 11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Comparison. 11971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool dp_operation = (instr->SzValue() == 1); 11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); 11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation && !raise_exception_for_qnan) { 12011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc2Value() == 0x4) { 1202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Format(instr, "vcmp.f64'cond 'Dd, 'Dm"); 12031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc2Value() == 0x5) { 1204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Format(instr, "vcmp.f64'cond 'Dd, #0.0"); 1205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 1206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Unknown(instr); // invalid 1207756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { 12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); 12176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool double_to_single = (instr->SzValue() == 1); 12196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (double_to_single) { 12216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm"); 12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm"); 12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 12311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool to_integer = (instr->Bit(18) == 1); 12341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool dp_operation = (instr->SzValue() == 1); 12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (to_integer) { 12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool unsigned_integer = (instr->Bit(16) == 0); 12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation) { 12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm"); 12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm"); 12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm"); 12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm"); 12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool unsigned_integer = (instr->Bit(7) == 0); 12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation) { 12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm"); 12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm"); 12596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm"); 12636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm"); 12656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Decode Type 6 coprocessor instructions. 1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dm = vmov(Rt, Rt2) 1273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// <Rt, Rt2> = vmov(Dm) 1274d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Ddst = MEM(Rbase + 4*offset). 1275d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// MEM(Rbase + 4*offset) = Dsrc. 12761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType6CoprocessorIns(Instruction* instr) { 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(instr->TypeValue() == 6); 1278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 12791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->CoprocessorValue() == 0xA) { 12801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->OpcodeValue()) { 12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x8: 128280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case 0xA: 12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->HasL()) { 128480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]"); 12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 128680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]"); 12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0xC: 129080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case 0xE: 12916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->HasL()) { 129280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]"); 12936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 129480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]"); 12956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 12978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x4: 12988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x5: 12998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x6: 13008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x7: 13018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x9: 13028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB: { 13038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool to_vfp_register = (instr->VLValue() == 0x1); 13048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (to_vfp_register) { 13058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}"); 13068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 13078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}"); 13088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 13098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 13108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->CoprocessorValue() == 0xB) { 13151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->OpcodeValue()) { 1316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0x2: 1317d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Load and store double to two GP registers 1318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (instr->Bits(7, 4) != 0x1) { 1319d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Unknown(instr); // Not used by V8. 1320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (instr->HasL()) { 1321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Format(instr, "vmov'cond 'rt, 'rn, 'Dm"); 1322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1323d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Format(instr, "vmov'cond 'Dm, 'rt, 'rn"); 1324d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1325d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 1326d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0x8: 1327d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (instr->HasL()) { 132880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]"); 1329d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 133080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]"); 1331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1332d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 1333d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0xC: 1334d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (instr->HasL()) { 133580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]"); 1336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 133780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]"); 1338d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 13408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x4: 13418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x5: 13428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x9: { 13438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool to_vfp_register = (instr->VLValue() == 0x1); 13448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (to_vfp_register) { 13458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}"); 13468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 13478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}"); 13488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 13498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 13508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke default: 1352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Unknown(instr); // Not used by V8. 1353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 13546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Unknown(instr); // Not used by V8. 135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef VERIFIY 136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 136144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Decoder::IsConstantPoolAt(byte* instr_ptr) { 136244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker; 136444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 136544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 136744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint Decoder::ConstantPoolSizeAt(byte* instr_ptr) { 136844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (IsConstantPoolAt(instr_ptr)) { 136944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return instruction_bits & kConstantPoolLengthMask; 137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return -1; 1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassemble the instruction at *instr_ptr into the output buffer. 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Decoder::InstructionDecode(byte* instr_ptr) { 13791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instruction* instr = Instruction::At(instr_ptr); 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print raw instruction bytes. 13811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 13821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block "%08x ", 13831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->InstructionBits()); 13841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->ConditionField() == kSpecialCondition) { 138544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Unknown(instr); 138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Instruction::kInstrSize; 138744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 138844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 138944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) { 139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, 139144f0eee88ff00398ff7f715fab053374d808c90dSteve Block "constant pool begin (length %d)", 139244f0eee88ff00398ff7f715fab053374d808c90dSteve Block instruction_bits & 139344f0eee88ff00398ff7f715fab053374d808c90dSteve Block kConstantPoolLengthMask); 13941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->TypeValue()) { 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: { 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType01(instr); 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: { 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType2(instr); 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: { 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType3(instr); 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: { 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType4(instr); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: { 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType5(instr); 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: { 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType6(instr); 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: { 14233e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu return DecodeType7(instr); 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The type field is 3-bits in the ARM encoding. 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 14311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} } // namespace v8::internal 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm { 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 144544f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); 144644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return tmp_buffer_.start(); 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 14561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return v8::internal::Registers::Name(reg); 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); // ARM does not have the concept of a byte register 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "nobytereg"; 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); // ARM does not have any XMM registers 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The default name converter is called for unknown code. So we will not try 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to access any memory. 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) {} 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {} 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 14901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block v8::internal::Decoder d(converter_, buffer); 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(instruction); 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { 149644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return v8::internal::Decoder::ConstantPoolSizeAt(instruction); 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%p %08x %s\n", 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 1517