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