18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Disassembler object is used to disassemble a block of code instruction by 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction. The default implementation of the NameConverter object can be 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overriden to modify register names or to do symbol lookup on addresses. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The example below will disassemble a block of code and print it to stdout. 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// NameConverter converter; 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembler d(converter); 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for (byte* pc = begin; pc < end;) { 146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// v8::internal::EmbeddedVector<char, 256> buffer; 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// byte* prev_pc = pc; 166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// pc += d.InstructionDecode(buffer, pc); 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// printf("%p %08x %s\n", 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer); 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The Disassembler class also has a convenience method to disassemble a block 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of code into a FILE*, meaning that the above functionality could also be 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// achieved by just calling Disassembler::Disassemble(stdout, begin, end); 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <assert.h> 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h> 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdio.h> 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <string.h> 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM 32f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/constants-arm.h" 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/bits.h" 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h" 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/disasm.h" 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h" 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace v8 { 411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace internal { 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochconst auto GetRegConfig = RegisterConfiguration::Crankshaft; 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Decoder decodes and disassembles instructions into an output buffer. 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// It uses the converter to convert register names and call destinations into 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// more informative description. 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Decoder { 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Decoder(const disasm::NameConverter& converter, 531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Vector<char> out_buffer) 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter), 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_(out_buffer), 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_pos_(0) { 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_] = '\0'; 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Decoder() {} 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes one disassembled instruction into 'buffer' (0-terminated). 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the length of the disassembled machine instruction in bytes. 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int InstructionDecode(byte* instruction); 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsConstantPoolAt(byte* instr_ptr); 6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static int ConstantPoolSizeAt(byte* instr_ptr); 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bottleneck functions to print into the out_buffer. 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PrintChar(const char ch); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Print(const char* str); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Printing of common values. 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PrintRegister(int reg); 76d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void PrintSRegister(int reg); 77d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void PrintDRegister(int reg); 781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int FormatVFPRegister(Instruction* instr, const char* format); 791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintMovwMovt(Instruction* instr); 801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int FormatVFPinstruction(Instruction* instr, const char* format); 811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintCondition(Instruction* instr); 821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintShiftRm(Instruction* instr); 831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintShiftImm(Instruction* instr); 841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintShiftSat(Instruction* instr); 851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void PrintPU(Instruction* instr); 863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu void PrintSoftwareInterrupt(SoftwareInterruptCodes svc); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle formatting of instructions and their options. 891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int FormatRegister(Instruction* instr, const char* option); 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FormatNeonList(int Vd, int type); 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FormatNeonMemory(int Rn, int align, int Rm); 921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int FormatOption(Instruction* instr, const char* option); 931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Format(Instruction* instr, const char* format); 941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Unknown(Instruction* instr); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Each of these functions decodes one particular instruction type, a 3-bit 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // field in the instruction encoding. 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Types 0 and 1 are combined as they are largely the same except for the way 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // they interpret the shifter operand. 1001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType01(Instruction* instr); 1011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType2(Instruction* instr); 1021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType3(Instruction* instr); 1031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType4(Instruction* instr); 1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType5(Instruction* instr); 1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType6(Instruction* instr); 1063e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Type 7 includes special Debugger instructions. 1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int DecodeType7(Instruction* instr); 108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // CP15 coprocessor instructions. 109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void DecodeTypeCP15(Instruction* instr); 110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // For VFP support. 1111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeTypeVFP(Instruction* instr); 1121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType6CoprocessorIns(Instruction* instr); 113d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeSpecialCondition(Instruction* instr); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); 1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCMP(Instruction* instr); 1181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); 1191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr); 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const disasm::NameConverter& converter_; 1221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Vector<char> out_buffer_; 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int out_buffer_pos_; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DISALLOW_COPY_AND_ASSIGN(Decoder); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Support for assertions in the Decoder formatting functions. 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define STRING_STARTS_WITH(string, compare_string) \ 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (strncmp(string, compare_string, strlen(compare_string)) == 0) 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Append the ch to the output buffer. 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::PrintChar(const char ch) { 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_++] = ch; 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Append the str to the output buffer. 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::Print(const char* str) { 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char cur = *str++; 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintChar(cur); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cur = *str++; 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_] = 0; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These condition names are defined in a way to match the native disassembler 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// formatting. See for example the command "objdump -d <binary file>". 153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const cond_names[kNumberOfConditions] = { 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" , 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the condition guarding the instruction. 1601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintCondition(Instruction* instr) { 1611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print(cond_names[instr->ConditionValue()]); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the register name according to the active name converter. 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::PrintRegister(int reg) { 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print(converter_.NameOfCPURegister(reg)); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Print the VFP S register name according to the active name converter. 172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Decoder::PrintSRegister(int reg) { 1731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print(VFPRegisters::Name(reg, false)); 174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Print the VFP D register name according to the active name converter. 178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Decoder::PrintDRegister(int reg) { 1791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print(VFPRegisters::Name(reg, true)); 180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These shift names are defined in a way to match the native disassembler 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// formatting. See for example the command "objdump -d <binary file>". 18569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const shift_names[kNumberOfShifts] = { 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "lsl", "lsr", "asr", "ror" 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the register shift operands for the instruction. Generally used for 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// data processing instructions. 1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftRm(Instruction* instr) { 1931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ShiftOp shift = instr->ShiftField(); 1941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int shift_index = instr->ShiftValue(); 1951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int shift_amount = instr->ShiftAmountValue(); 1961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rm = instr->RmValue(); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(rm); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) { 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Special case for using rm only. 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->RegShiftValue() == 0) { 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // by immediate 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((shift == ROR) && (shift_amount == 0)) { 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print(", RRX"); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_amount = 32; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ", %s #%d", 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift_names[shift_index], 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift_amount); 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // by register 2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rs = instr->RsValue(); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ", %s ", shift_names[shift_index]); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(rs); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the immediate operand for the instruction. Generally used for data 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// processing instructions. 2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftImm(Instruction* instr) { 2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rotate = instr->RotateValue() * 2; 2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int immed8 = instr->Immed8Value(); 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int imm = base::bits::RotateRight32(immed8, rotate); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Print the optional shift and immediate used by saturating instructions. 2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftSat(Instruction* instr) { 23850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int shift = instr->Bits(11, 7); 23950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (shift > 0) { 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ", %s #%d", 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift_names[instr->Bit(6) * 2], 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->Bits(11, 7)); 24450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 24550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen} 24650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 24750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print PU formatting to reduce complexity of FormatOption. 2491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintPU(Instruction* instr) { 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("da"); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("ia"); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("db"); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("ib"); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the FormatOption method. 2773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) { 2783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu switch (svc) { 2791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case kCallRtRedirected: 2801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print("call rt redirected"); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case kBreakpoint: 2831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Print("breakpoint"); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (svc >= kStopCode) { 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%d - 0x%x", 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch svc & kStopCodeMask, 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch svc & kStopCodeMask); 2913e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%d", 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch svc); 2953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle all register based formatting in this function to reduce the 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// complexity of FormatOption. 3031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatRegister(Instruction* instr, const char* format) { 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(format[0] == 'r'); 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (format[1] == 'n') { // 'rn: Rn register 3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RnValue(); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'd') { // 'rd: Rd register 3101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RdValue(); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 's') { // 'rs: Rs register 3141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RsValue(); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'm') { // 'rm: Rm register 3181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RmValue(); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (format[1] == 't') { // 'rt: Rt register 3221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int reg = instr->RtValue(); 323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PrintRegister(reg); 324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 2; 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'l') { 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'rlist: register list for load and store multiple instructions 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "rlist")); 3281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rlist = instr->RlistValue(); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int reg = 0; 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("{"); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print register list in ascending order, by scanning the bit mask. 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (rlist != 0) { 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((rlist & 1) != 0) { 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRegister(reg); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((rlist >> 1) != 0) { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print(", "); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reg++; 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rlist >>= 1; 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("}"); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -1; 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Handle all VFP register based formatting in this function to reduce the 351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// complexity of FormatOption. 3521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatVFPRegister(Instruction* instr, const char* format) { 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((format[0] == 'S') || (format[0] == 'D')); 354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch VFPRegPrecision precision = 3568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch format[0] == 'D' ? kDoublePrecision : kSinglePrecision; 3578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int retval = 2; 3598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int reg = -1; 360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (format[1] == 'n') { 3618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch reg = instr->VFPNRegValue(precision); 362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (format[1] == 'm') { 3638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch reg = instr->VFPMRegValue(precision); 364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (format[1] == 'd') { 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->TypeValue() == 7) && 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->Bit(24) == 0x0) && 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->Bits(11, 9) == 0x5) && 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->Bit(4) == 0x1)) { 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // vmov.32 has Vd in a different place. 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg = instr->Bits(19, 16) | (instr->Bit(7) << 4); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg = instr->VFPDRegValue(precision); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (format[2] == '+') { 3768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int immed8 = instr->Immed8Value(); 3778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (format[0] == 'S') reg += immed8 - 1; 3788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (format[0] == 'D') reg += (immed8 / 2 - 1); 3798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (format[2] == '+') retval = 3; 3818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 3828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch UNREACHABLE(); 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (precision == kSinglePrecision) { 3868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrintSRegister(reg); 3878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 3888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrintDRegister(reg); 3898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return retval; 392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatVFPinstruction(Instruction* instr, const char* format) { 396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Print(format); 397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 0; 398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Decoder::FormatNeonList(int Vd, int type) { 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type == nlt_1) { 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "{d%d}", Vd); 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type == nlt_2) { 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "{d%d, d%d}", Vd, Vd + 1); 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type == nlt_3) { 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2); 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type == nlt_4) { 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3); 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Decoder::FormatNeonMemory(int Rn, int align, int Rm) { 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "[r%d", Rn); 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (align != 0) { 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ":%d", (1 << align) << 6); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Rm == 15) { 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Print("]"); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (Rm == 13) { 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Print("]!"); 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "], r%d", Rm); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Print the movw or movt instruction. 4371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintMovwMovt(Instruction* instr) { 4381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int imm = instr->ImmedMovwMovtValue(); 4391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int rd = instr->RdValue(); 4409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen PrintRegister(rd); 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm); 4429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// FormatOption takes a formatting string and interprets it based on 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the current instructions. The format string points to the first 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// character of the option string (the option escape has already been 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// consumed by the caller.) FormatOption returns the number of 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// characters that were consumed from the formatting string. 4501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatOption(Instruction* instr, const char* format) { 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (format[0]) { 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'a': { // 'a: accumulate multiplies 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(21) == 0) { 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("ul"); 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("la"); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'b': { // 'b: byte loads or stores 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasB()) { 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("b"); 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'c': { // 'cond: conditional execution 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "cond")); 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintCondition(instr); 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 4; 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch case 'd': { // 'd: vmov double immediate. 4723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch double d = instr->DoubleImmedVmov(); 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d); 4743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return 1; 4753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 4767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch case 'f': { // 'f: bitfield instructions - v7 and above. 4777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t lsbit = instr->Bits(11, 7); 4787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t width = instr->Bits(20, 16) + 1; 4797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (instr->Bit(21) == 0) { 4807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // BFC/BFI: 4817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Bits 20-16 represent most-significant bit. Covert to width. 4827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch width -= lsbit; 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(width > 0); 4847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((width + lsbit) <= 32); 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "#%d, #%d", lsbit, width); 4887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return 1; 4897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'h': { // 'h: halfword operation for extra loads and stores 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasH()) { 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("h"); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("b"); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 49850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen case 'i': { // 'i: immediate value from adjacent bits. 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16 50050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int width = (format[3] - '0') * 10 + (format[4] - '0'); 50150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int lsb = (format[6] - '0') * 10 + (format[7] - '0'); 50250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((width >= 1) && (width <= 32)); 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((lsb >= 0) && (lsb <= 31)); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((width + lsb) <= 32); 50650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%d", 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->Bits(width + lsb - 1, lsb)); 51050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen return 8; 51150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'l': { // 'l: branch and link 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasLink()) { 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("l"); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'm': { 5199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (format[1] == 'w') { 5209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // 'mw: movt/movw instructions. 5219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen PrintMovwMovt(instr); 5229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return 2; 5239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (format[1] == 'e') { // 'memop: load/store instructions. 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "memop")); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasL()) { 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("ldr"); 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) && 530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) { 531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->Bit(5) == 1) { 532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Print("strd"); 533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Print("ldrd"); 535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return 5; 537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("str"); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'msg: for simulator break instructions 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "msg")); 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* str = 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%s", converter_.NameInCode(str)); 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 3; 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'o': { 5513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((format[3] == '1') && (format[4] == '2')) { 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'off12: 12-bit offset for load and store instructions 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "off12")); 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%d", instr->Offset12Value()); 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 5576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (format[3] == '0') { 5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19")); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%d", 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->Bits(19, 8) << 4) + 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->Bits(3, 0)); 5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return 15; 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'off8: 8-bit offset for extra load and store instructions 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "off8")); 5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 4; 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'p': { // 'pu: P and U bits for load and store instructions 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "pu")); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintPU(instr); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'r': { 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return FormatRegister(instr, format); 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': { 58150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat. 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (format[6] == 'o') { // 'shift_op 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "shift_op")); 5841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->TypeValue() == 0) { 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftRm(instr); 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->TypeValue() == 1); 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftImm(instr); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 8; 59150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } else if (format[6] == 's') { // 'shift_sat. 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "shift_sat")); 59350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen PrintShiftSat(instr); 59450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen return 9; 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // 'shift_rm 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "shift_rm")); 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintShiftRm(instr); 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 8; 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 6003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else if (format[1] == 'v') { // 'svc 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "svc")); 6021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintSoftwareInterrupt(instr->SvcValue()); 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 3; 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (format[1] == 'i') { // 'sign: signed extra loads and stores 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "sign")); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasSign()) { 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 4; 6103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else if (format[1] == 'p') { 6113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (format[8] == '_') { // 'spec_reg_fields 6123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(STRING_STARTS_WITH(format, "spec_reg_fields")); 6133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Print("_"); 6143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int mask = instr->Bits(19, 16); 6153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (mask == 0) Print("(none)"); 6163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if ((mask & 0x8) != 0) Print("f"); 6173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if ((mask & 0x4) != 0) Print("s"); 6183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if ((mask & 0x2) != 0) Print("x"); 6193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if ((mask & 0x1) != 0) Print("c"); 6203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return 15; 6213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { // 'spec_reg 6223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(STRING_STARTS_WITH(format, "spec_reg")); 6233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (instr->Bit(22) == 0) { 6243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Print("CPSR"); 6253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 6263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Print("SPSR"); 6273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 6283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return 8; 6293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 's: S field of data processing instructions 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 't': { // 'target: target of branch instructions 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(STRING_STARTS_WITH(format, "target")); 6391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int off = (instr->SImmed24Value() << 2) + 8; 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%+d -> %s", 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch off, 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch converter_.NameOfAddress( 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<byte*>(instr) + off)); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'u': { // 'u: signed or unsigned multiplies 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The manual gets the meaning of bit 22 backwards in the multiply 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction overview on page A3.16.2. The instructions that 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // exist in u and s variants are the following: 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smull A4.1.87 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // umull A4.1.129 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // umlal A4.1.128 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // smlal A4.1.76 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For these 0 means u and 1 means s. As can be seen on their individual 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pages. The other 18 mul instructions have the bit set or unset in 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arbitrary ways that are unrelated to the signedness of the instruction. 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // None of these 18 instructions exist in both a 'u' and an 's' variant. 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("u"); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("s"); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'v': { 668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return FormatVFPinstruction(instr, format); 669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'S': 671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 'D': { 672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return FormatVFPRegister(instr, format); 673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'w': { // 'w: W field of load and store instructions 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Print("!"); 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -1; 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Format takes a formatting string for a whole instruction and prints it into 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the output buffer. All escaped options are handed to FormatOption to be 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// parsed further. 6931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::Format(Instruction* instr, const char* format) { 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char cur = *format++; 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cur == '\'') { // Single quote is used as the formatting escape. 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block format += FormatOption(instr, format); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_++] = cur; 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cur = *format++; 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block out_buffer_[out_buffer_pos_] = '\0'; 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The disassembler may end up decoding data inlined in the code. We do not want 7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// it to crash if the data does not ressemble any known instruction. 7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define VERIFY(condition) \ 7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochif(!(condition)) { \ 7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Unknown(instr); \ 7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; \ 7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// For currently unimplemented decodings the disassembler calls Unknown(instr) 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// which will just print "unknown" of the instruction bits. 7181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::Unknown(Instruction* instr) { 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "unknown"); 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType01(Instruction* instr) { 7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int type = instr->TypeValue(); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((type == 0) && instr->IsSpecialType0()) { 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // multiply instruction or extra loads and stores 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bits(7, 4) == 9) { 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(24) == 0) { 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // multiply instructions 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(23) == 0) { 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(21) == 0) { 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The MUL instruction description (A 4.1.33) refers to Rd as being 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the destination for the operation, but it confusingly uses the 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Rn field to encode it. 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bit(22) == 0) { 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The MLA instruction description (A 4.1.28) refers to the order 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Rn field to encode the Rd register and the Rd field to encode 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the Rn register. 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The MLS instruction description (A 4.1.29) refers to the order 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Rn field to encode the Rd register and the Rd field to encode 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the Rn register. 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd"); 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The signed/long multiply instructions use the terms RdHi and RdLo 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // when referring to the target registers. They are mapped to the Rn 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and Rd fields as follows: 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RdLo == Rd field 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RdHi == Rn field 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs> 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs"); 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 76113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (instr->Bits(24, 23) == 3) { 76213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (instr->Bit(20) == 1) { 76313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // ldrex 76413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch switch (instr->Bits(22, 21)) { 76513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case 0: 76613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Format(instr, "ldrex'cond 'rt, ['rn]"); 76713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 76813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case 2: 76913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Format(instr, "ldrexb'cond 'rt, ['rn]"); 77013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 77113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case 3: 77213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Format(instr, "ldrexh'cond 'rt, ['rn]"); 77313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 77413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch default: 77513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch UNREACHABLE(); 77613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 77713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 77813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 77913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // strex 78013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // The instruction is documented as strex rd, rt, [rn], but the 78113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // "rt" register is using the rm bits. 78213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch switch (instr->Bits(22, 21)) { 78313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case 0: 78413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Format(instr, "strex'cond 'rd, 'rm, ['rn]"); 78513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 78613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case 2: 78713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Format(instr, "strexb'cond 'rd, 'rm, ['rn]"); 78813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 78913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case 3: 79013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Format(instr, "strexh'cond 'rd, 'rm, ['rn]"); 79113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 79213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch default: 79313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch UNREACHABLE(); 79413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 79513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 79613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 79713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else { 79813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Unknown(instr); // not used by V8 79913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 80125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) { 80225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // ldrd, strd 80325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen switch (instr->PUField()) { 8041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 80525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 80625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], -'rm"); 80725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 80825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], #-'off8"); 80925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 81025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 81125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 8121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 81325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 81425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], +'rm"); 81525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 81625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn], #+'off8"); 81725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 81825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 81925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 8201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 82125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 82225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w"); 82325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 82425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w"); 82525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 82625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 82725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 8281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 82925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (instr->Bit(22) == 0) { 83025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w"); 83125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 83225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w"); 83325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 83425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 83525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 83625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen default: { 83725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // The PU field is a 2-bit field. 83825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen UNREACHABLE(); 83925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen break; 84025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 84125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // extra load/store instructions 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(22) == 0) { 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if ((type == 0) && instr->IsMiscType0()) { 8863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) && 8873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (instr->Bits(15, 4) == 0xf00)) { 8883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Format(instr, "msr'cond 'spec_reg'spec_reg_fields, 'rm"); 8893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) && 8903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (instr->Bits(11, 0) == 0)) { 8913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Format(instr, "mrs'cond 'rd, 'spec_reg"); 8923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else if (instr->Bits(22, 21) == 1) { 8931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->BitField(7, 4)) { 8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BX: 8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "bx'cond 'rm"); 8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 8976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BLX: 8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "blx'cond 'rm"); 8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case BKPT: 9016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "bkpt 'off0to3and8to19"); 9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 9036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 9046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 9056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 9066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (instr->Bits(22, 21) == 3) { 9081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->BitField(7, 4)) { 9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case CLZ: 9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "clz'cond 'rd, 'rm"); 9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 9146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 9156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // not used by V8 9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if ((type == 1) && instr->IsNopType1()) { 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "nop'cond"); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->OpcodeField()) { 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case AND: { 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "and'cond's 'rd, 'rn, 'shift_op"); 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case EOR: { 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "eor'cond's 'rd, 'rn, 'shift_op"); 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SUB: { 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "sub'cond's 'rd, 'rn, 'shift_op"); 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RSB: { 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op"); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ADD: { 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "add'cond's 'rd, 'rn, 'shift_op"); 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ADC: { 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "adc'cond's 'rd, 'rn, 'shift_op"); 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SBC: { 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op"); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RSC: { 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op"); 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TST: { 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "tst'cond 'rn, 'shift_op"); 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 9599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Format(instr, "movw'cond 'mw"); 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TEQ: { 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "teq'cond 'rn, 'shift_op"); 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other instructions matching this pattern are handled in the 9686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // miscellaneous instructions part above. 9696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UNREACHABLE(); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CMP: { 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "cmp'cond 'rn, 'shift_op"); 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 9779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Format(instr, "movt'cond 'mw"); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CMN: { 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasS()) { 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "cmn'cond 'rn, 'shift_op"); 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 9856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other instructions matching this pattern are handled in the 9866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // miscellaneous instructions part above. 9876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UNREACHABLE(); 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ORR: { 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "orr'cond's 'rd, 'rn, 'shift_op"); 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MOV: { 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mov'cond's 'rd, 'shift_op"); 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case BIC: { 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "bic'cond's 'rd, 'rn, 'shift_op"); 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MVN: { 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "mvn'cond's 'rd, 'shift_op"); 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The Opcode field is a 4-bit field. 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType2(Instruction* instr) { 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 10191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unknown(instr); // not used in V8 102244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->HasW()) { 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Unknown(instr); // not used in V8 103044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType3(Instruction* instr) { 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (instr->PUField()) { 10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case da_x: { 10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(!instr->HasW()); 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ia_x: { 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bit(4) == 0) { 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bit(5) == 0) { 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->Bits(22, 21)) { 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0: 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bit(20) == 0) { 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bit(6) == 0) { 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07"); 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bits(11, 7) == 0) { 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32"); 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07"); 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 1: 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 2: 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 3: 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 109050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } else { 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->Bits(22, 21)) { 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0: 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 1: 1096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bits(9, 6) == 1) { 1097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bit(20) == 0) { 1098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bits(19, 16) == 0xF) { 1099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (instr->Bits(11, 10)) { 1100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0: 1101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtb'cond 'rd, 'rm"); 1102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 1: 1104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtb'cond 'rd, 'rm, ror #8"); 1105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 2: 1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtb'cond 'rd, 'rm, ror #16"); 1108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 3: 1110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtb'cond 'rd, 'rm, ror #24"); 1111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (instr->Bits(11, 10)) { 1115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0: 1116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtab'cond 'rd, 'rn, 'rm"); 1117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 1: 1119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8"); 1120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 2: 1122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16"); 1123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 3: 1125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24"); 1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bits(19, 16) == 0xF) { 1131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (instr->Bits(11, 10)) { 1132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0: 1133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxth'cond 'rd, 'rm"); 1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 1: 1136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxth'cond 'rd, 'rm, ror #8"); 1137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 2: 1139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxth'cond 'rd, 'rm, ror #16"); 1140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 3: 1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxth'cond 'rd, 'rm, ror #24"); 1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (instr->Bits(11, 10)) { 1147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0: 1148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtah'cond 'rd, 'rn, 'rm"); 1149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 1: 1151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8"); 1152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 2: 1154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16"); 1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 3: 1157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24"); 1158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 1164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 2: 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bits(19, 16) == 0xF) { 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->Bits(11, 10)) { 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0: 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "uxtb16'cond 'rd, 'rm"); 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 1: 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "uxtb16'cond 'rd, 'rm, ror #8"); 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 2: 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "uxtb16'cond 'rd, 'rm, ror #16"); 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 3: 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "uxtb16'cond 'rd, 'rm, ror #24"); 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 3: 1191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if ((instr->Bits(9, 6) == 1)) { 1192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if ((instr->Bit(20) == 0)) { 1193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bits(19, 16) == 0xF) { 1194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (instr->Bits(11, 10)) { 1195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0: 1196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtb'cond 'rd, 'rm"); 1197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 1: 1199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtb'cond 'rd, 'rm, ror #8"); 1200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 2: 1202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtb'cond 'rd, 'rm, ror #16"); 1203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 3: 1205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtb'cond 'rd, 'rm, ror #24"); 1206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (instr->Bits(11, 10)) { 1210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0: 1211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtab'cond 'rd, 'rn, 'rm"); 1212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 1: 1214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8"); 1215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 2: 1217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16"); 1218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 3: 1220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24"); 1221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bits(19, 16) == 0xF) { 1226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (instr->Bits(11, 10)) { 1227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0: 1228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxth'cond 'rd, 'rm"); 1229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 1: 1231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxth'cond 'rd, 'rm, ror #8"); 1232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 2: 1234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxth'cond 'rd, 'rm, ror #16"); 1235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 3: 1237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxth'cond 'rd, 'rm, ror #24"); 1238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (instr->Bits(11, 10)) { 1242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0: 1243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtah'cond 'rd, 'rn, 'rm"); 1244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 1: 1246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8"); 1247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 2: 1249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16"); 1250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 3: 1252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24"); 1253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1258109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001 1259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if ((instr->Bits(20, 16) == 0x1f) && 1260109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch (instr->Bits(11, 4) == 0xf3)) { 1261109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Format(instr, "rbit'cond 'rd, 'rm"); 1262109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 1263109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch UNREACHABLE(); 1264109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 126850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 126950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen } 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case db_x: { 1273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bits(22, 20) == 0x5) { 1274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bits(7, 4) == 0x1) { 1275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Bits(15, 12) == 0xF) { 1276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "smmul'cond 'rn, 'rm, 'rs"); 1277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // SMMLA (in V8 notation matching ARM ISA format) 1279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd"); 1280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1284f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (instr->Bits(5, 4) == 0x1) { 1285f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { 1286f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (instr->Bit(21) == 0x1) { 1287f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs 1288f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "udiv'cond'b 'rn, 'rm, 'rs"); 1289f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 1290f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs 1291f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs"); 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1293f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case ib_x: { 13003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 13013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 13027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 13033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t msbit = widthminus1 + lsbit; 13043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (msbit <= 31) { 13057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (instr->Bit(22)) { 13067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "ubfx'cond 'rd, 'rm, 'f"); 13077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 13087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "sbfx'cond 'rd, 'rm, 'f"); 13097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch UNREACHABLE(); 13127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { 13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); 13167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (msbit >= lsbit) { 13171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->RmValue() == 15) { 13187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "bfc'cond 'rd, 'f"); 13197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 13207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Format(instr, "bfi'cond 'rd, 'rm, 'f"); 13217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 13233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 13243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 13253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 13263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 13273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The PU field is a 2-bit field. 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType4(Instruction* instr) { 134044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->Bit(22) != 0) { 134144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Privileged mode currently not supported. 134244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Unknown(instr); 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 134444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->HasL()) { 134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 134844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType5(Instruction* instr) { 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Format(instr, "b'l'cond 'target"); 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType6(Instruction* instr) { 1359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block DecodeType6CoprocessorIns(instr); 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::DecodeType7(Instruction* instr) { 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr->Bit(24) == 1) { 13651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SvcValue() >= kStopCode) { 13663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Format(instr, "stop'cond 'svc"); 1367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch out_buffer_pos_ += SNPrintF( 1368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch out_buffer_ + out_buffer_pos_, "\n %p %08x", 1369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch reinterpret_cast<void*>(instr + Instruction::kInstrSize), 1370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *reinterpret_cast<uint32_t*>(instr + Instruction::kInstrSize)); 13711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We have decoded 2 * Instruction::kInstrSize bytes. 13721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 2 * Instruction::kInstrSize; 13733e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 13743e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Format(instr, "svc'cond 'svc"); 13753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1377f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch switch (instr->CoprocessorValue()) { 1378f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case 10: // Fall through. 1379f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case 11: 1380f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DecodeTypeVFP(instr); 1381f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 1382f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case 15: 1383f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DecodeTypeCP15(instr); 1384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 1385f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch default: 1386f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Unknown(instr); 1387f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 1388f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// void Decoder::DecodeTypeVFP(Instruction* instr) 1395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vmov: Sn = Rt 1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vmov: Rt = Sn 1397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vcvt: Dd = Sm 1398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vcvt: Sd = Dm 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// vcvt.f64.s32 Dd, Dd, #<fbits> 140044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Dd = vabs(Dm) 1401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vabs(Sm) 140244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Dd = vneg(Dm) 1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vneg(Sm) 1404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vadd(Dn, Dm) 1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vadd(Sn, Sm) 1406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vsub(Dn, Dm) 1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vsub(Sn, Sm) 1408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vmul(Dn, Dm) 1409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vmul(Sn, Sm) 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Dd = vmla(Dn, Dm) 1411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vmla(Sn, Sm) 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Dd = vmls(Dn, Dm) 1413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vmls(Sn, Sm) 1414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vdiv(Dn, Dm) 1415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vdiv(Sn, Sm) 1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// vcmp(Dd, Dm) 1417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// vcmp(Sd, Sm) 1418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Dd = vsqrt(Dm) 1419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Sd = vsqrt(Sm) 14208defd9ff6930b4e24729971a61cf7469daf119beSteve Block// vmrs 14218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// vmsr 142262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Qd = vdup.size(Qd, Rt) 142362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// vmov.size: Dd[i] = Rt 142462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// vmov.sign.size: Rt = Dn[i] 14251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeTypeVFP(Instruction* instr) { 14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); 14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(instr->Bits(11, 9) == 0x5); 14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->Bit(4) == 0) { 14301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc1Value() == 0x7) { 14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Other data processing instructions 14321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { 14338defd9ff6930b4e24729971a61cf7469daf119beSteve Block // vmov register to register. 14341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vmov'cond.f64 'Dd, 'Dm"); 14368defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vmov'cond.f32 'Sd, 'Sm"); 14388defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 14391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { 14401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // vabs 1441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (instr->SzValue() == 0x1) { 1442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vabs'cond.f64 'Dd, 'Dm"); 1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vabs'cond.f32 'Sd, 'Sm"); 1445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 144644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { 144744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // vneg 1448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (instr->SzValue() == 0x1) { 1449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vneg'cond.f64 'Dd, 'Dm"); 1450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vneg'cond.f32 'Sd, 'Sm"); 1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 14531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { 14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenDoubleAndSingle(instr); 14551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { 14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenFloatingPointAndInteger(instr); 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->Bit(8) == 1)) { 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // vcvt.f64.s32 Dd, Dd, #<fbits> 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd"); 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ", #%d", fraction_bits); 14641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() >> 1) == 0x6) && 14651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)) { 14666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCVTBetweenFloatingPointAndInteger(instr); 14671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 14681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)) { 14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVCMP(instr); 14701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { 1471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (instr->SzValue() == 0x1) { 1472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vsqrt'cond.f64 'Dd, 'Dm"); 1473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vsqrt'cond.f32 'Sd, 'Sm"); 1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 14761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc3Value() == 0x0) { 14771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vmov'cond.f64 'Dd, 'd"); 14793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } else { 14803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Format(instr, "vmov'cond.f32 'Sd, 'd"); 14813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 1482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) { 1483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // vrintz - round towards zero (truncate) 1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (instr->SzValue() == 0x1) { 1485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm"); 1486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm"); 1488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc1Value() == 0x3) { 14931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 14941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc3Value() & 0x1) { 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm"); 14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm"); 14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (instr->Opc3Value() & 0x1) { 1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm"); 1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm"); 1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { 15071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm"); 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm"); 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) { 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->SzValue() == 0x1) { 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm"); 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm"); 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) { 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->SzValue() == 0x1) { 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm"); 15216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm"); 15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { 15251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->SzValue() == 0x1) { 1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm"); 15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm"); 15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Unknown(instr); // Not used by V8. 1532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 15341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if ((instr->VCValue() == 0x0) && 15351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x0)) { 15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); 153762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) { 153862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(23) == 0) { 153962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5); 154062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if ((opc1_opc2 & 0xb) == 0) { 154162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NeonS32/NeonU32 154262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(21) == 0x0) { 154362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Format(instr, "vmov'cond.32 'Dd[0], 'rt"); 154462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 154562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Format(instr, "vmov'cond.32 'Dd[1], 'rt"); 154662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 154762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 154862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int vd = instr->VFPNRegValue(kDoublePrecision); 154962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int rt = instr->RtValue(); 155062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if ((opc1_opc2 & 0x8) != 0) { 155162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NeonS8 / NeonU8 155262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int i = opc1_opc2 & 0x7; 155362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 155462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vmov.8 d%d[%d], r%d", vd, i, rt); 155562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if ((opc1_opc2 & 0x1) != 0) { 155662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NeonS16 / NeonU16 155762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int i = (opc1_opc2 >> 1) & 0x3; 155862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 155962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vmov.16 d%d[%d], r%d", vd, i, rt); 156062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 156162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 156262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 156362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 156562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = 32; 156662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(5) != 0) 156762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size = 16; 156862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch else if (instr->Bit(22) != 0) 156962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size = 8; 157062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPNRegValue(kSimd128Precision); 157162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Rt = instr->RtValue(); 157262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 157362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vdup.%i q%d, r%d", size, Vd, Rt); 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 157562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) { 157662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5); 157762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if ((opc1_opc2 & 0xb) == 0) { 157862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NeonS32 / NeonU32 157962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(21) == 0x0) { 158062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Format(instr, "vmov'cond.32 'rt, 'Dd[0]"); 158162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 158262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Format(instr, "vmov'cond.32 'rt, 'Dd[1]"); 158362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 158562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* sign = instr->Bit(23) != 0 ? "u" : "s"; 158662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int rt = instr->RtValue(); 158762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int vn = instr->VFPNRegValue(kDoublePrecision); 158862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if ((opc1_opc2 & 0x8) != 0) { 158962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NeonS8 / NeonU8 159062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int i = opc1_opc2 & 0x7; 159162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 159262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vmov.%s8 r%d, d%d[%d]", sign, rt, vn, i); 159362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if ((opc1_opc2 & 0x1) != 0) { 159462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NeonS16 / NeonU16 159562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int i = (opc1_opc2 >> 1) & 0x3; 159662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 159762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%s16 r%d, d%d[%d]", 159862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch sign, rt, vn, i); 159962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 160062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 160162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 16031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((instr->VCValue() == 0x0) && 16041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x7) && 16056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (instr->Bits(19, 16) == 0x1)) { 16061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->VLValue() == 0) { 16078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (instr->Bits(15, 12) == 0xF) { 16088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmsr'cond FPSCR, APSR"); 16098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 16108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmsr'cond FPSCR, 'rt"); 16118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 16138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (instr->Bits(15, 12) == 0xF) { 16148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmrs'cond APSR, FPSCR"); 16158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 16168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Format(instr, "vmrs'cond 'rt, FPSCR"); 16178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 161962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 162062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); // Not used by V8. 1621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 16226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 16236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 16246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1625f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Decoder::DecodeTypeCP15(Instruction* instr) { 1626f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0)); 1627f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch VERIFY(instr->CoprocessorValue() == 15); 1628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1629f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (instr->Bit(4) == 1) { 1630f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int crn = instr->Bits(19, 16); 1631f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int crm = instr->Bits(3, 0); 1632f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int opc1 = instr->Bits(23, 21); 1633f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int opc2 = instr->Bits(7, 5); 1634f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if ((opc1 == 0) && (crn == 7)) { 1635f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // ARMv6 memory barrier operations. 1636f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Details available in ARM DDI 0406C.b, B3-1750. 1637f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if ((crm == 10) && (opc2 == 5)) { 1638f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "mcr'cond (CP15DMB)"); 1639f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if ((crm == 10) && (opc2 == 4)) { 1640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "mcr'cond (CP15DSB)"); 1641f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if ((crm == 5) && (opc2 == 4)) { 1642f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "mcr'cond (CP15ISB)"); 1643f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 1644f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Unknown(instr); 1645f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1646f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 1647f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Unknown(instr); 1648f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1649f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 1650f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Unknown(instr); 1651f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1652f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 16536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( 16551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instruction* instr) { 16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && 16571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->VAValue() == 0x0)); 16586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool to_arm_register = (instr->VLValue() == 0x1); 16606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (to_arm_register) { 16626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vmov'cond 'rt, 'Sn"); 1663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 16646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Format(instr, "vmov'cond 'Sn, 'rt"); 16656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 16666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 16676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCMP(Instruction* instr) { 16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 16721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (instr->Opc3Value() & 0x1)); 16736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Comparison. 16751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool dp_operation = (instr->SzValue() == 1); 16766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); 16776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation && !raise_exception_for_qnan) { 16791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->Opc2Value() == 0x4) { 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcmp'cond.f64 'Dd, 'Dm"); 16811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->Opc2Value() == 0x5) { 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcmp'cond.f64 'Dd, #0.0"); 1683756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 1684756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Unknown(instr); // invalid 1685756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 1686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (!raise_exception_for_qnan) { 1687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (instr->Opc2Value() == 0x4) { 1688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vcmp'cond.f32 'Sd, 'Sm"); 1689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (instr->Opc2Value() == 0x5) { 1690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vcmp'cond.f32 'Sd, #0.0"); 1691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Unknown(instr); // invalid 1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 16946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 16956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 16966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 16976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 16986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { 17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); 17036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool double_to_single = (instr->SzValue() == 1); 17056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (double_to_single) { 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm"); 17086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm"); 17106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 17116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 17171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 17186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool to_integer = (instr->Bit(18) == 1); 17201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool dp_operation = (instr->SzValue() == 1); 17216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (to_integer) { 17226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool unsigned_integer = (instr->Bit(16) == 0); 17236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation) { 17256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm"); 17276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm"); 17296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 17316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm"); 17336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm"); 17356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 17366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 17376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 17386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool unsigned_integer = (instr->Bit(7) == 0); 17396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (dp_operation) { 17416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm"); 17436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm"); 17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 17466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unsigned_integer) { 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm"); 17496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm"); 17516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Decode Type 6 coprocessor instructions. 1758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dm = vmov(Rt, Rt2) 1759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// <Rt, Rt2> = vmov(Dm) 1760d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Ddst = MEM(Rbase + 4*offset). 1761d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// MEM(Rbase + 4*offset) = Dsrc. 17621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType6CoprocessorIns(Instruction* instr) { 17633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VERIFY(instr->TypeValue() == 6); 1764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 17651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->CoprocessorValue() == 0xA) { 17661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->OpcodeValue()) { 17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x8: 176880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case 0xA: 17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->HasL()) { 177080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]"); 17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 177280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]"); 17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0xC: 177680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case 0xE: 17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (instr->HasL()) { 177880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]"); 17796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]"); 17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 17826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 17838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x4: 17848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x5: 17858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x6: 17868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x7: 17878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x9: 17888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB: { 17898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool to_vfp_register = (instr->VLValue() == 0x1); 17908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (to_vfp_register) { 17918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}"); 17928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 17938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}"); 17948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 17958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 17968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 17976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 17986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Unknown(instr); // Not used by V8. 17996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 18001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->CoprocessorValue() == 0xB) { 18011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->OpcodeValue()) { 1802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0x2: 1803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Load and store double to two GP registers 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { 1805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Unknown(instr); // Not used by V8. 1806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (instr->HasL()) { 1807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Format(instr, "vmov'cond 'rt, 'rn, 'Dm"); 1808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1809d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Format(instr, "vmov'cond 'Dm, 'rt, 'rn"); 1810d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1811d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 1812d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0x8: 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xA: 1814d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (instr->HasL()) { 181580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]"); 1816d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 181780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]"); 1818d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1819d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 1820d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case 0xC: 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xE: 1822d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (instr->HasL()) { 182380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]"); 1824d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 182580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]"); 1826d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 18288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x4: 18298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0x5: 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x6: 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x7: 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x9: 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xB: { 18348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool to_vfp_register = (instr->VLValue() == 0x1); 18358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (to_vfp_register) { 18368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}"); 18378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 18388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}"); 18398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 18408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 18418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1842d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke default: 1843d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Unknown(instr); // Not used by V8. 1844d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 18456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 184644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Unknown(instr); // Not used by V8. 184744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 184844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 184944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1851109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic const char* const barrier_option_names[] = { 1852109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch "invalid", "oshld", "oshst", "osh", "invalid", "nshld", "nshst", "nsh", 1853109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch "invalid", "ishld", "ishst", "ish", "invalid", "ld", "st", "sy", 1854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}; 1855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Decoder::DecodeSpecialCondition(Instruction* instr) { 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->SpecialValue()) { 185962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 4: { 186062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd, Vm, Vn; 186162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(6) == 0) { 186262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vd = instr->VFPDRegValue(kDoublePrecision); 186362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vm = instr->VFPMRegValue(kDoublePrecision); 186462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vn = instr->VFPNRegValue(kDoublePrecision); 186562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 186662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vd = instr->VFPDRegValue(kSimd128Precision); 186762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vm = instr->VFPMRegValue(kSimd128Precision); 186862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vn = instr->VFPNRegValue(kSimd128Precision); 186962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 187062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch switch (instr->Bits(11, 8)) { 187162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x0: { 187262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(4) == 1) { 187362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 187462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vqadd.s<size> Qd, Qm, Qn. 187562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 187662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 187762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vqadd.s%d q%d, q%d, q%d", size, Vd, Vn, Vm); 187862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 187962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 188062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 188162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 188262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 188362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x1: { 188462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 && 188562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch instr->Bit(4) == 1) { 188662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (Vm == Vn) { 188762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vmov Qd, Qm 188862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 188962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vmov q%d, q%d", Vd, Vm); 189062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 189162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vorr Qd, Qm, Qn. 189262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 189362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vorr q%d, q%d, q%d", Vd, Vn, Vm); 189462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 189562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 && 189662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch instr->Bit(4) == 1) { 189762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vand Qd, Qm, Qn. 189862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 189962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vand q%d, q%d, q%d", Vd, Vn, Vm); 190062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 190162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 190262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 190362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 190462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 190562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x2: { 190662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(4) == 1) { 190762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 190862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vqsub.s<size> Qd, Qm, Qn. 190962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 191062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 191162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vqsub.s%d q%d, q%d, q%d", size, Vd, Vn, Vm); 191262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 191362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 191462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 191562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 191662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 191762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x3: { 191862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 191962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt"; 192062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vcge/vcgt.s<size> Qd, Qm, Qn. 192162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 192262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d", 192362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch op, size, Vd, Vn, Vm); 192462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 192562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 192662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x6: { 192762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 192862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vmin/vmax.s<size> Qd, Qm, Qn. 192962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax"; 193062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 193162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d", 193262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch op, size, Vd, Vn, Vm); 193362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 193462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 193562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x8: { 193662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = (instr->Bit(4) == 0) ? "vadd" : "vtst"; 193762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 193862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vadd/vtst.i<size> Qd, Qm, Qn. 193962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 194062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "%s.i%d q%d, q%d, q%d", 194162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch op, size, Vd, Vn, Vm); 194262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 194362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 194462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x9: { 194562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(6) == 1 && instr->Bit(4) == 1) { 194662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 194762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vmul.i<size> Qd, Qm, Qn. 194862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 194962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 195062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vmul.i%d q%d, q%d, q%d", size, Vd, Vn, Vm); 195162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 195262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 195362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 195462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 195562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 195662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0xd: { 195762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(4) == 0) { 195862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = (instr->Bits(21, 20) == 0) ? "vadd" : "vsub"; 195962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vadd/vsub.f32 Qd, Qm, Qn. 196062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 196162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm); 196262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 196362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 196462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 196562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 196662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 196762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0xe: { 196862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) { 196962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vceq.f32 Qd, Qm, Qn. 197062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 197162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vceq.f32 q%d, q%d, q%d", Vd, Vn, Vm); 197262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 197362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 197462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 197562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 197662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 197762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0xf: { 197862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(20) == 0 && instr->Bit(6) == 1) { 197962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(4) == 1) { 198062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vrecps/vrsqrts.f32 Qd, Qm, Qn. 198162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = instr->Bit(21) == 0 ? "vrecps" : "vrsqrts"; 198262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 198362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 198462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm); 198562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 198662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vmin/max.f32 Qd, Qm, Qn. 198762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = instr->Bit(21) == 1 ? "vmin" : "vmax"; 198862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 198962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 199062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm); 199162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 199262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 199362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 199462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 199562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 199662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 199762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch default: 199862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 199962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 200062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 200162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 200262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 5: 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->Bit(4) == 1)) { 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // vmovl signed 2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->VdValue() & 1) != 0) Unknown(instr); 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Vm = (instr->Bit(5) << 4) | instr->VmValue(); 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int imm3 = instr->Bits(21, 19); 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 201262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vmovl.s%d q%d, d%d", imm3 * 8, Vd, Vm); 201362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) { 201462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vext.8 Qd, Qm, Qn, imm4 201562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int imm4 = instr->Bits(11, 8); 201662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 201762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 201862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vn = instr->VFPNRegValue(kSimd128Precision); 201962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 202062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "vext.8 q%d, q%d, q%d, #%d", 202162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vd, Vn, Vm, imm4); 202262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) { 202362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vshl.i<size> Qd, Qm, shift 202462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); 202562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int shift = instr->Bits(21, 16) - size; 202662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 202762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 202862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 202962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "vshl.i%d q%d, q%d, #%d", 203062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size, Vd, Vm, shift); 203162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) { 203262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vshr.s<size> Qd, Qm, shift 203362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); 203462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int shift = 2 * size - instr->Bits(21, 16); 203562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 203662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 203762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 203862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.s%d q%d, q%d, #%d", 203962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size, Vd, Vm, shift); 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Unknown(instr); 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 204462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 6: { 204562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd, Vm, Vn; 204662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(6) == 0) { 204762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vd = instr->VFPDRegValue(kDoublePrecision); 204862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vm = instr->VFPMRegValue(kDoublePrecision); 204962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vn = instr->VFPNRegValue(kDoublePrecision); 205062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 205162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vd = instr->VFPDRegValue(kSimd128Precision); 205262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vm = instr->VFPMRegValue(kSimd128Precision); 205362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Vn = instr->VFPNRegValue(kSimd128Precision); 205462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 205562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch switch (instr->Bits(11, 8)) { 205662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x0: { 205762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(4) == 1) { 205862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 205962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vqadd.u<size> Qd, Qm, Qn. 206062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 206162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 206262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vqadd.u%d q%d, q%d, q%d", size, Vd, Vn, Vm); 206362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 206462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 206562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 206662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 206762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 206862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x1: { 206962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) { 207062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 207162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vbsl q%d, q%d, q%d", Vd, Vn, Vm); 207262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) { 207362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(6) == 0) { 207462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // veor Dd, Dn, Dm 207562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 207662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "veor d%d, d%d, d%d", Vd, Vn, Vm); 207762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 207862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 207962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // veor Qd, Qn, Qm 208062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 208162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "veor q%d, q%d, q%d", Vd, Vn, Vm); 208262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 208362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 208462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 208562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 208662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 208762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 208862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x2: { 208962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(4) == 1) { 209062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 209162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vqsub.u<size> Qd, Qm, Qn. 209262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 209362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 209462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vqsub.u%d q%d, q%d, q%d", size, Vd, Vn, Vm); 209562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 209662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 209762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 209862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 209962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 210062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x3: { 210162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 210262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt"; 210362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vcge/vcgt.u<size> Qd, Qm, Qn. 210462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 210562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d", 210662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch op, size, Vd, Vn, Vm); 210762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 210862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 210962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x6: { 211062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 211162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vmin/vmax.u<size> Qd, Qm, Qn. 211262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax"; 211362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 211462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d", 211562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch op, size, Vd, Vn, Vm); 211662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 211762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 211862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0x8: { 211962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(21, 20)); 212062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(4) == 0) { 212162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 212262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 212362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vsub.i%d q%d, q%d, q%d", size, Vd, Vn, Vm); 212462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 212562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 212662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 212762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vceq.i%d q%d, q%d, q%d", size, Vd, Vn, Vm); 212862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 212962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 213062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 213162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0xd: { 213262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) { 213362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vmul.f32 Qd, Qn, Qm 213462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 213562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vmul.f32 q%d, q%d, q%d", Vd, Vn, Vm); 213662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 213762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 213862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 213962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 214062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 214162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0xe: { 214262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(20) == 0 && instr->Bit(4) == 0) { 214362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = (instr->Bit(21) == 0) ? "vcge" : "vcgt"; 214462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vcge/vcgt.f32 Qd, Qm, Qn. 214562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 214662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm); 214762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 214862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 214962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 215062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 215162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 215262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch default: 215362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 215462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 215562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 215662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 215762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 7: 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->Bit(4) == 1)) { 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // vmovl unsigned 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->VdValue() & 1) != 0) Unknown(instr); 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Vm = (instr->Bit(5) << 4) | instr->VmValue(); 2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int imm3 = instr->Bits(21, 19); 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 216762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vmovl.u%d q%d, d%d", imm3 * 8, Vd, Vm); 216862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Opc1Value() == 7 && instr->Bits(21, 20) == 0x3 && 216962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch instr->Bit(4) == 0) { 217062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) { 217162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bit(6) == 0) { 217262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kDoublePrecision); 217362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kDoublePrecision); 217462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 217562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vswp d%d, d%d", Vd, Vm); 217662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 217762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 217862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 217962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 218062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vswp q%d, q%d", Vd, Vm); 218162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 218262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(11, 7) == 0x18) { 218362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 218462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kDoublePrecision); 218562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int index = instr->Bit(19); 218662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 218762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vdup q%d, d%d[%d]", Vd, Vm, index); 218862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) { 218962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 219062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 219162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 219262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "vmvn q%d, q%d", Vd, Vm); 219362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 && 219462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch instr->Bit(6) == 1) { 219562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 219662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 219762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* suffix = nullptr; 219862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int op = instr->Bits(8, 7); 219962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch switch (op) { 220062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 0: 220162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch suffix = "f32.s32"; 220262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 220362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 1: 220462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch suffix = "f32.u32"; 220562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 220662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 2: 220762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch suffix = "s32.f32"; 220862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 220962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case 3: 221062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch suffix = "u32.f32"; 221162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 221262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 221362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 221462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vcvt.%s q%d, q%d", suffix, Vd, Vm); 221562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(11, 10) == 0x2) { 221662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kDoublePrecision); 221762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vn = instr->VFPNRegValue(kDoublePrecision); 221862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kDoublePrecision); 221962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int len = instr->Bits(9, 8); 222062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NeonListOperand list(DwVfpRegister::from_code(Vn), len + 1); 222162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 222262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "%s d%d, ", 222362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch instr->Bit(6) == 0 ? "vtbl.8" : "vtbx.8", Vd); 222462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FormatNeonList(Vn, list.type()); 222562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Print(", "); 222662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch PrintDRegister(Vm); 222762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 6) == 0x7) { 222862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 222962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 223062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(19, 18)); 223162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vzip.<size> Qd, Qm. 223262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 223362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vzip.%d q%d, q%d", size, Vd, Vm); 223462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0) { 223562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 223662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 223762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(19, 18)); 223862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int op = kBitsPerByte 223962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch << (static_cast<int>(Neon64) - instr->Bits(8, 7)); 224062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vrev<op>.<size> Qd, Qm. 224162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 224262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "vrev%d.%d q%d, q%d", op, size, Vd, Vm); 224362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) { 224462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 224562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 224662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = kBitsPerByte * (1 << instr->Bits(19, 18)); 224762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* type = instr->Bit(10) != 0 ? "f" : "s"; 224862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (instr->Bits(9, 6) == 0xd) { 224962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vabs<type>.<size> Qd, Qm. 225062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 225162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "vabs.%s%d q%d, q%d", 225262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch type, size, Vd, Vm); 225362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(9, 6) == 0xf) { 225462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vneg<type>.<size> Qd, Qm. 225562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 225662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "vneg.%s%d q%d, q%d", 225762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch type, size, Vd, Vm); 225862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 225962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 226062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 226162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5) { 226262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vrecpe/vrsqrte.f32 Qd, Qm. 226362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 226462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 226562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* op = instr->Bit(7) == 0 ? "vrecpe" : "vrsqrte"; 226662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 226762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "%s.f32 q%d, q%d", op, Vd, Vm); 226862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 226962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Unknown(instr); 227062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 227162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) { 227262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // vshr.u<size> Qd, Qm, shift 227362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); 227462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int shift = 2 * size - instr->Bits(21, 16); 227562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vd = instr->VFPDRegValue(kSimd128Precision); 227662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int Vm = instr->VFPMRegValue(kSimd128Precision); 227762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 227862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.u%d q%d, q%d, #%d", 227962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size, Vd, Vm, shift); 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Unknown(instr); 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 8: 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->Bits(21, 20) == 0) { 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // vst1 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Vd = (instr->Bit(22) << 4) | instr->VdValue(); 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Rn = instr->VnValue(); 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int type = instr->Bits(11, 8); 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int size = instr->Bits(7, 6); 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int align = instr->Bits(5, 4); 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Rm = instr->VmValue(); 229362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vst1.%d ", 229462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (1 << size) << 3); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FormatNeonList(Vd, type); 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Print(", "); 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FormatNeonMemory(Rn, align, Rm); 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->Bits(21, 20) == 2) { 2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // vld1 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Vd = (instr->Bit(22) << 4) | instr->VdValue(); 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Rn = instr->VnValue(); 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int type = instr->Bits(11, 8); 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int size = instr->Bits(7, 6); 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int align = instr->Bits(5, 4); 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Rm = instr->VmValue(); 230662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vld1.%d ", 230762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (1 << size) << 3); 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FormatNeonList(Vd, type); 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Print(", "); 2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FormatNeonMemory(Rn, align, Rm); 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Unknown(instr); 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xA: 2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xB: 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Rn = instr->Bits(19, 16); 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = instr->Bits(11, 0); 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (offset == 0) { 232162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += 232262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, "pld [r%d]", Rn); 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->Bit(23) == 0) { 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "pld [r%d, #-%d]", Rn, offset); 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "pld [r%d, #+%d]", Rn, offset); 2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) { 2331109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int option = instr->Bits(3, 0); 2332109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch switch (instr->Bits(7, 4)) { 2333109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case 4: 233462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "dsb %s", 233562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch barrier_option_names[option]); 2336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 2337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case 5: 233862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "dmb %s", 233962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch barrier_option_names[option]); 2340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 2341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case 6: 234262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "isb %s", 234362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch barrier_option_names[option]); 2344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 2345109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch default: 2346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Unknown(instr); 2347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Unknown(instr); 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x1D: 2353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 && 2354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 && 2355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier instr->Bit(4) == 0x0) { 2356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // VRINTA, VRINTN, VRINTP, VRINTM (floating-point) 2357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool dp_operation = (instr->SzValue() == 1); 2358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int rounding_mode = instr->Bits(17, 16); 2359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (rounding_mode) { 2360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x0: 2361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (dp_operation) { 2362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "vrinta.f64.f64 'Dd, 'Dm"); 2363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vrinta.f32.f32 'Sd, 'Sm"); 2365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x1: 2368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (dp_operation) { 2369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "vrintn.f64.f64 'Dd, 'Dm"); 2370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vrintn.f32.f32 'Sd, 'Sm"); 2372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x2: 2375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (dp_operation) { 2376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "vrintp.f64.f64 'Dd, 'Dm"); 2377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vrintp.f32.f32 'Sd, 'Sm"); 2379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x3: 2382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (dp_operation) { 2383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Format(instr, "vrintm.f64.f64 'Dd, 'Dm"); 2384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Format(instr, "vrintm.f32.f32 'Sd, 'Sm"); 2386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier default: 2389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); // Case analysis is exhaustive. 2390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2392f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) && 2393f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch (instr->Bit(4) == 0x0)) { 2394f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // VMAXNM, VMINNM (floating-point) 2395f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (instr->SzValue() == 0x1) { 2396f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (instr->Bit(6) == 0x1) { 2397f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "vminnm.f64 'Dd, 'Dn, 'Dm"); 2398f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2399f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "vmaxnm.f64 'Dd, 'Dn, 'Dm"); 2400f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2401f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2402f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (instr->Bit(6) == 0x1) { 2403f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "vminnm.f32 'Sd, 'Sn, 'Sm"); 2404f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2405f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Format(instr, "vmaxnm.f32 'Sd, 'Sn, 'Sm"); 2406f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2407f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 2409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Unknown(instr); 2410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case 0x1C: 2413bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) && 2414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch (instr->Bit(4) == 0)) { 2415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // VSEL* (floating-point) 2416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch bool dp_operation = (instr->SzValue() == 1); 2417bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch switch (instr->Bits(21, 20)) { 2418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case 0x0: 2419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (dp_operation) { 2420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Format(instr, "vseleq.f64 'Dd, 'Dn, 'Dm"); 2421bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 2422bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Format(instr, "vseleq.f32 'Sd, 'Sn, 'Sm"); 2423bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2424bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 2425bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case 0x1: 2426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (dp_operation) { 2427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Format(instr, "vselvs.f64 'Dd, 'Dn, 'Dm"); 2428bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 2429bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Format(instr, "vselvs.f32 'Sd, 'Sn, 'Sm"); 2430bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2431bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 2432bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case 0x2: 2433bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (dp_operation) { 2434bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Format(instr, "vselge.f64 'Dd, 'Dn, 'Dm"); 2435bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 2436bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Format(instr, "vselge.f32 'Sd, 'Sn, 'Sm"); 2437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 2439bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case 0x3: 2440bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (dp_operation) { 2441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Format(instr, "vselgt.f64 'Dd, 'Dn, 'Dm"); 2442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 2443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Format(instr, "vselgt.f32 'Sd, 'Sn, 'Sm"); 2444bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2445bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 2446bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch default: 2447bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UNREACHABLE(); // Case analysis is exhaustive. 2448bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 2449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 2451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Unknown(instr); 2452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Unknown(instr); 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 24603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef VERIFIY 246144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 246244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Decoder::IsConstantPoolAt(byte* instr_ptr) { 246344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 246444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker; 246544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 246644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 246744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 246844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint Decoder::ConstantPoolSizeAt(byte* instr_ptr) { 246944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (IsConstantPoolAt(instr_ptr)) { 247044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return DecodeConstantPoolLength(instruction_bits); 247244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 247344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return -1; 2474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassemble the instruction at *instr_ptr into the output buffer. 2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Decoder::InstructionDecode(byte* instr_ptr) { 24801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instruction* instr = Instruction::At(instr_ptr); 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print raw instruction bytes. 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%08x ", 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->InstructionBits()); 24851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->ConditionField() == kSpecialCondition) { 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeSpecialCondition(instr); 248744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Instruction::kInstrSize; 248844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 248944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 249044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) { 2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "constant pool begin (length %d)", 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeConstantPoolLength(instruction_bits)); 24941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instruction_bits == kCodeAgeJumpInstruction) { 2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The code age prologue has a constant immediatly following the jump 2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction. 2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize); 2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DecodeType2(instr); 2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(out_buffer_ + out_buffer_pos_, 2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " (0x%08x)", target->InstructionBits()); 2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 2 * Instruction::kInstrSize; 2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 25041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->TypeValue()) { 2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: { 2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType01(instr); 2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: { 2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType2(instr); 2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: { 2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType3(instr); 2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: { 2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType4(instr); 2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: { 2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType5(instr); 2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: { 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DecodeType6(instr); 2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: { 25313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu return DecodeType7(instr); 2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The type field is 3-bits in the ARM encoding. 2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 25391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return Instruction::kInstrSize; 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 2544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm { 2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 255313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr)); 255444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return tmp_buffer_.start(); 2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 256413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return v8::internal::GetRegConfig()->GetGeneralRegisterName(reg); 2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); // ARM does not have the concept of a byte register 2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "nobytereg"; 2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); // ARM does not have any XMM registers 2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The default name converter is called for unknown code. So we will not try 2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to access any memory. 2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) {} 2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {} 2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 25981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block v8::internal::Decoder d(converter_, buffer); 2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(instruction); 2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { 260444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return v8::internal::Decoder::ConstantPoolSizeAt(instruction); 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 261613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc), 261713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 2625