18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Disassembler object is used to disassemble a block of code instruction by
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction. The default implementation of the NameConverter object can be
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overriden to modify register names or to do symbol lookup on addresses.
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The example below will disassemble a block of code and print it to stdout.
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   NameConverter converter;
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Disassembler d(converter);
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   for (byte* pc = begin; pc < end;) {
376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block//     v8::internal::EmbeddedVector<char, 256> buffer;
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     byte* prev_pc = pc;
396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block//     pc += d.InstructionDecode(buffer, pc);
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     printf("%p    %08x      %s\n",
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   }
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The Disassembler class also has a convenience method to disassemble a block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of code into a FILE*, meaning that the above functionality could also be
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <assert.h>
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdio.h>
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h>
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <string.h>
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef WIN32
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdint.h>
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM)
60f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "constants-arm.h"
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disasm.h"
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h"
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h"
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace v8 {
681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace internal {
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Decoder decodes and disassembles instructions into an output buffer.
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// It uses the converter to convert register names and call destinations into
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// more informative description.
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Decoder {
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Decoder(const disasm::NameConverter& converter,
791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          Vector<char> out_buffer)
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : converter_(converter),
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      out_buffer_(out_buffer),
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      out_buffer_pos_(0) {
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    out_buffer_[out_buffer_pos_] = '\0';
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~Decoder() {}
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Writes one disassembled instruction into 'buffer' (0-terminated).
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the length of the disassembled machine instruction in bytes.
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int InstructionDecode(byte* instruction);
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static bool IsConstantPoolAt(byte* instr_ptr);
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static int ConstantPoolSizeAt(byte* instr_ptr);
9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Bottleneck functions to print into the out_buffer.
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintChar(const char ch);
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Print(const char* str);
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Printing of common values.
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintRegister(int reg);
102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void PrintSRegister(int reg);
103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void PrintDRegister(int reg);
1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int FormatVFPRegister(Instruction* instr, const char* format);
1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void PrintMovwMovt(Instruction* instr);
1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int FormatVFPinstruction(Instruction* instr, const char* format);
1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void PrintCondition(Instruction* instr);
1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void PrintShiftRm(Instruction* instr);
1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void PrintShiftImm(Instruction* instr);
1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void PrintShiftSat(Instruction* instr);
1111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void PrintPU(Instruction* instr);
1123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle formatting of instructions and their options.
1151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int FormatRegister(Instruction* instr, const char* option);
1161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int FormatOption(Instruction* instr, const char* option);
1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Format(Instruction* instr, const char* format);
1181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Unknown(Instruction* instr);
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Each of these functions decodes one particular instruction type, a 3-bit
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // field in the instruction encoding.
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Types 0 and 1 are combined as they are largely the same except for the way
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // they interpret the shifter operand.
1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeType01(Instruction* instr);
1251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeType2(Instruction* instr);
1261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeType3(Instruction* instr);
1271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeType4(Instruction* instr);
1281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeType5(Instruction* instr);
1291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeType6(Instruction* instr);
1303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Type 7 includes special Debugger instructions.
1311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int DecodeType7(Instruction* instr);
132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // For VFP support.
1331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeTypeVFP(Instruction* instr);
1341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeType6CoprocessorIns(Instruction* instr);
135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
1371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeVCMP(Instruction* instr);
1381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
1391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const disasm::NameConverter& converter_;
1421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Vector<char> out_buffer_;
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int out_buffer_pos_;
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DISALLOW_COPY_AND_ASSIGN(Decoder);
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Support for assertions in the Decoder formatting functions.
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define STRING_STARTS_WITH(string, compare_string) \
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  (strncmp(string, compare_string, strlen(compare_string)) == 0)
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Append the ch to the output buffer.
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::PrintChar(const char ch) {
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  out_buffer_[out_buffer_pos_++] = ch;
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Append the str to the output buffer.
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::Print(const char* str) {
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char cur = *str++;
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintChar(cur);
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cur = *str++;
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  out_buffer_[out_buffer_pos_] = 0;
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These condition names are defined in a way to match the native disassembler
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// formatting. See for example the command "objdump -d <binary file>".
1731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic const char* cond_names[kNumberOfConditions] = {
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the condition guarding the instruction.
1801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintCondition(Instruction* instr) {
1811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Print(cond_names[instr->ConditionValue()]);
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the register name according to the active name converter.
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Decoder::PrintRegister(int reg) {
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Print(converter_.NameOfCPURegister(reg));
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Print the VFP S register name according to the active name converter.
191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Decoder::PrintSRegister(int reg) {
1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Print(VFPRegisters::Name(reg, false));
193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Print the  VFP D register name according to the active name converter.
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Decoder::PrintDRegister(int reg) {
1971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Print(VFPRegisters::Name(reg, true));
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These shift names are defined in a way to match the native disassembler
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// formatting. See for example the command "objdump -d <binary file>".
20369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const shift_names[kNumberOfShifts] = {
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "lsl", "lsr", "asr", "ror"
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the register shift operands for the instruction. Generally used for
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// data processing instructions.
2101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftRm(Instruction* instr) {
2111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ShiftOp shift = instr->ShiftField();
2121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int shift_index = instr->ShiftValue();
2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int shift_amount = instr->ShiftAmountValue();
2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int rm = instr->RmValue();
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintRegister(rm);
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) {
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Special case for using rm only.
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (instr->RegShiftValue() == 0) {
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // by immediate
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((shift == ROR) && (shift_amount == 0)) {
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Print(", RRX");
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      shift_amount = 32;
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    ", %s #%d",
2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    shift_names[shift_index],
2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    shift_amount);
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // by register
2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int rs = instr->RsValue();
2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    ", %s ", shift_names[shift_index]);
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintRegister(rs);
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print the immediate operand for the instruction. Generally used for data
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// processing instructions.
2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftImm(Instruction* instr) {
2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int rotate = instr->RotateValue() * 2;
2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int immed8 = instr->Immed8Value();
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                  "#%d", imm);
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Print the optional shift and immediate used by saturating instructions.
2561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintShiftSat(Instruction* instr) {
25750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  int shift = instr->Bits(11, 7);
25850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (shift > 0) {
2591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
2601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    ", %s #%d",
2611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    shift_names[instr->Bit(6) * 2],
2621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    instr->Bits(11, 7));
26350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
26450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
26550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
26650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print PU formatting to reduce complexity of FormatOption.
2681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintPU(Instruction* instr) {
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (instr->PUField()) {
2701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case da_x: {
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Print("da");
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case ia_x: {
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Print("ia");
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case db_x: {
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Print("db");
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case ib_x: {
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Print("ib");
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the FormatOption method.
2963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
2973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  switch (svc) {
2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case kCallRtRedirected:
2991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Print("call rt redirected");
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
3011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case kBreakpoint:
3021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Print("breakpoint");
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (svc >= kStopCode) {
3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        "%d - 0x%x",
3081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        svc & kStopCodeMask,
3091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        svc & kStopCodeMask);
3103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      } else {
3111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        "%d",
3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        svc);
3143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle all register based formatting in this function to reduce the
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// complexity of FormatOption.
3221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatRegister(Instruction* instr, const char* format) {
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(format[0] == 'r');
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (format[1] == 'n') {  // 'rn: Rn register
3251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int reg = instr->RnValue();
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintRegister(reg);
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (format[1] == 'd') {  // 'rd: Rd register
3291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int reg = instr->RdValue();
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintRegister(reg);
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (format[1] == 's') {  // 'rs: Rs register
3331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int reg = instr->RsValue();
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintRegister(reg);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (format[1] == 'm') {  // 'rm: Rm register
3371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int reg = instr->RmValue();
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintRegister(reg);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (format[1] == 't') {  // 'rt: Rt register
3411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int reg = instr->RtValue();
342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    PrintRegister(reg);
343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return 2;
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (format[1] == 'l') {
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 'rlist: register list for load and store multiple instructions
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(STRING_STARTS_WITH(format, "rlist"));
3471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int rlist = instr->RlistValue();
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int reg = 0;
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Print("{");
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Print register list in ascending order, by scanning the bit mask.
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (rlist != 0) {
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((rlist & 1) != 0) {
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintRegister(reg);
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if ((rlist >> 1) != 0) {
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Print(", ");
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      reg++;
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      rlist >>= 1;
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Print("}");
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 5;
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Handle all VFP register based formatting in this function to reduce the
370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// complexity of FormatOption.
3711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatVFPRegister(Instruction* instr, const char* format) {
372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT((format[0] == 'S') || (format[0] == 'D'));
373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  VFPRegPrecision precision =
3758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      format[0] == 'D' ? kDoublePrecision : kSinglePrecision;
3768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int retval = 2;
3788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int reg = -1;
379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (format[1] == 'n') {
3808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    reg = instr->VFPNRegValue(precision);
381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (format[1] == 'm') {
3828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    reg = instr->VFPMRegValue(precision);
383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (format[1] == 'd') {
3848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    reg = instr->VFPDRegValue(precision);
3858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (format[2] == '+') {
3868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      int immed8 = instr->Immed8Value();
3878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (format[0] == 'S') reg += immed8 - 1;
3888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (format[0] == 'D') reg += (immed8 / 2 - 1);
3898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
3908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (format[2] == '+') retval = 3;
3918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
3928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    UNREACHABLE();
393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (precision == kSinglePrecision) {
3968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrintSRegister(reg);
3978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
3988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrintDRegister(reg);
3998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
4008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return retval;
402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatVFPinstruction(Instruction* instr, const char* format) {
406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Print(format);
407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return 0;
408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Print the movw or movt instruction.
4121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::PrintMovwMovt(Instruction* instr) {
4131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int imm = instr->ImmedMovwMovtValue();
4141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int rd = instr->RdValue();
4159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  PrintRegister(rd);
4161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
4171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                  ", #%d", imm);
4189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
4199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// FormatOption takes a formatting string and interprets it based on
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the current instructions. The format string points to the first
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// character of the option string (the option escape has already been
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// consumed by the caller.)  FormatOption returns the number of
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// characters that were consumed from the formatting string.
4261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::FormatOption(Instruction* instr, const char* format) {
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (format[0]) {
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'a': {  // 'a: accumulate multiplies
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->Bit(21) == 0) {
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("ul");
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("la");
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'b': {  // 'b: byte loads or stores
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->HasB()) {
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("b");
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'c': {  // 'cond: conditional execution
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(STRING_STARTS_WITH(format, "cond"));
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintCondition(instr);
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 4;
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    case 'd': {  // 'd: vmov double immediate.
4483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      double d = instr->DoubleImmedVmov();
4491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
4501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      "#%g", d);
4513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      return 1;
4523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
4537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    case 'f': {  // 'f: bitfield instructions - v7 and above.
4547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      uint32_t lsbit = instr->Bits(11, 7);
4557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      uint32_t width = instr->Bits(20, 16) + 1;
4567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      if (instr->Bit(21) == 0) {
4577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // BFC/BFI:
4587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // Bits 20-16 represent most-significant bit. Covert to width.
4597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        width -= lsbit;
4607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        ASSERT(width > 0);
4617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      }
4627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT((width + lsbit) <= 32);
4631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
4641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      "#%d, #%d", lsbit, width);
4657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      return 1;
4667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'h': {  // 'h: halfword operation for extra loads and stores
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->HasH()) {
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("h");
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("b");
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
47550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    case 'i': {  // 'i: immediate value from adjacent bits.
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16
47750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      int width = (format[3] - '0') * 10 + (format[4] - '0');
47850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      int lsb   = (format[6] - '0') * 10 + (format[7] - '0');
47950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
48050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      ASSERT((width >= 1) && (width <= 32));
48150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      ASSERT((lsb >= 0) && (lsb <= 31));
48250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      ASSERT((width + lsb) <= 32);
48350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
4841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
4851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      "%d",
4861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      instr->Bits(width + lsb - 1, lsb));
48750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      return 8;
48850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    }
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'l': {  // 'l: branch and link
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->HasLink()) {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("l");
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'm': {
4969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (format[1] == 'w') {
4979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // 'mw: movt/movw instructions.
4989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        PrintMovwMovt(instr);
4999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        return 2;
5009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
5019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (format[1] == 'e') {  // 'memop: load/store instructions.
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ASSERT(STRING_STARTS_WITH(format, "memop"));
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (instr->HasL()) {
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Print("ldr");
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) &&
507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) {
508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            if (instr->Bit(5) == 1) {
509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Print("strd");
510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            } else {
511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Print("ldrd");
512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            }
513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            return 5;
514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          }
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Print("str");
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 5;
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // 'msg: for simulator break instructions
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(STRING_STARTS_WITH(format, "msg"));
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* str =
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
5231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
5241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      "%s", converter_.NameInCode(str));
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 3;
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'o': {
5283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      if ((format[3] == '1') && (format[4] == '2')) {
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // 'off12: 12-bit offset for load and store instructions
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ASSERT(STRING_STARTS_WITH(format, "off12"));
5311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
5321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        "%d", instr->Offset12Value());
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 5;
5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else if (format[3] == '0') {
5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19"));
5371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
5381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        "%d",
5391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        (instr->Bits(19, 8) << 4) +
5401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        instr->Bits(3, 0));
5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return 15;
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // 'off8: 8-bit offset for extra load and store instructions
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(STRING_STARTS_WITH(format, "off8"));
5451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
5461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
5471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      "%d", offs8);
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 4;
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'p': {  // 'pu: P and U bits for load and store instructions
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(STRING_STARTS_WITH(format, "pu"));
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintPU(instr);
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 2;
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'r': {
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return FormatRegister(instr, format);
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 's': {
55950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      if (format[1] == 'h') {  // 'shift_op or 'shift_rm or 'shift_sat.
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (format[6] == 'o') {  // 'shift_op
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ASSERT(STRING_STARTS_WITH(format, "shift_op"));
5621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          if (instr->TypeValue() == 0) {
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            PrintShiftRm(instr);
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
5651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            ASSERT(instr->TypeValue() == 1);
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            PrintShiftImm(instr);
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 8;
56950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen        } else if (format[6] == 's') {  // 'shift_sat.
57050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen          ASSERT(STRING_STARTS_WITH(format, "shift_sat"));
57150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen          PrintShiftSat(instr);
57250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen          return 9;
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {  // 'shift_rm
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          PrintShiftRm(instr);
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 8;
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      } else if (format[1] == 'v') {  // 'svc
5793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        ASSERT(STRING_STARTS_WITH(format, "svc"));
5801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PrintSoftwareInterrupt(instr->SvcValue());
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 3;
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ASSERT(STRING_STARTS_WITH(format, "sign"));
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (instr->HasSign()) {
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Print("s");
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 4;
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // 's: S field of data processing instructions
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->HasS()) {
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("s");
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 't': {  // 'target: target of branch instructions
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(STRING_STARTS_WITH(format, "target"));
5971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      int off = (instr->SImmed24Value() << 2) + 8;
5981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
5991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      "%+d -> %s",
6001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      off,
6011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      converter_.NameOfAddress(
6021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        reinterpret_cast<byte*>(instr) + off));
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 6;
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'u': {  // 'u: signed or unsigned multiplies
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The manual gets the meaning of bit 22 backwards in the multiply
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // instruction overview on page A3.16.2.  The instructions that
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // exist in u and s variants are the following:
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // smull A4.1.87
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // umull A4.1.129
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // umlal A4.1.128
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // smlal A4.1.76
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // For these 0 means u and 1 means s.  As can be seen on their individual
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // pages.  The other 18 mul instructions have the bit set or unset in
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // arbitrary ways that are unrelated to the signedness of the instruction.
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // None of these 18 instructions exist in both a 'u' and an 's' variant.
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->Bit(22) == 0) {
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("u");
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("s");
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 'v': {
626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      return FormatVFPinstruction(instr, format);
627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 'S':
629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 'D': {
630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      return FormatVFPRegister(instr, format);
631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'w': {  // 'w: W field of load and store instructions
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->HasW()) {
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Print("!");
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Format takes a formatting string for a whole instruction and prints it into
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the output buffer. All escaped options are handed to FormatOption to be
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// parsed further.
6511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::Format(Instruction* instr, const char* format) {
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char cur = *format++;
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (cur == '\'') {  // Single quote is used as the formatting escape.
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      format += FormatOption(instr, format);
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      out_buffer_[out_buffer_pos_++] = cur;
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cur = *format++;
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  out_buffer_[out_buffer_pos_]  = '\0';
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The disassembler may end up decoding data inlined in the code. We do not want
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// it to crash if the data does not ressemble any known instruction.
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define VERIFY(condition) \
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochif(!(condition)) {        \
6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Unknown(instr);         \
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return;                 \
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// For currently unimplemented decodings the disassembler calls Unknown(instr)
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// which will just print "unknown" of the instruction bits.
6761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::Unknown(Instruction* instr) {
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Format(instr, "unknown");
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType01(Instruction* instr) {
6821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int type = instr->TypeValue();
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((type == 0) && instr->IsSpecialType0()) {
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // multiply instruction or extra loads and stores
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (instr->Bits(7, 4) == 9) {
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->Bit(24) == 0) {
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // multiply instructions
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (instr->Bit(23) == 0) {
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (instr->Bit(21) == 0) {
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // The MUL instruction description (A 4.1.33) refers to Rd as being
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // the destination for the operation, but it confusingly uses the
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // Rn field to encode it.
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "mul'cond's 'rn, 'rm, 'rs");
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // The MLA instruction description (A 4.1.28) refers to the order
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // Rn field to encode the Rd register and the Rd field to encode
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // the Rn register.
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // The signed/long multiply instructions use the terms RdHi and RdLo
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // when referring to the target registers. They are mapped to the Rn
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // and Rd fields as follows:
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // RdLo == Rd field
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // RdHi == Rn field
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Unknown(instr);  // not used by V8
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
71325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
71425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      // ldrd, strd
71525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      switch (instr->PUField()) {
7161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        case da_x: {
71725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          if (instr->Bit(22) == 0) {
71825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
71925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          } else {
72025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
72125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          }
72225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          break;
72325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        }
7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        case ia_x: {
72525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          if (instr->Bit(22) == 0) {
72625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
72725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          } else {
72825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
72925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          }
73025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          break;
73125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        }
7321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        case db_x: {
73325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          if (instr->Bit(22) == 0) {
73425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
73525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          } else {
73625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
73725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          }
73825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          break;
73925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        }
7401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        case ib_x: {
74125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          if (instr->Bit(22) == 0) {
74225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
74325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          } else {
74425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
74525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          }
74625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          break;
74725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        }
74825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        default: {
74925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          // The PU field is a 2-bit field.
75025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          UNREACHABLE();
75125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          break;
75225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        }
75325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      }
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // extra load/store instructions
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      switch (instr->PUField()) {
7571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        case da_x: {
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (instr->Bit(22) == 0) {
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
7651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        case ia_x: {
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (instr->Bit(22) == 0) {
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
7731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        case db_x: {
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (instr->Bit(22) == 0) {
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
7811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        case ib_x: {
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (instr->Bit(22) == 0) {
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default: {
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // The PU field is a 2-bit field.
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UNREACHABLE();
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if ((type == 0) && instr->IsMiscType0()) {
7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (instr->Bits(22, 21) == 1) {
7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      switch (instr->BitField(7, 4)) {
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        case BX:
8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Format(instr, "bx'cond 'rm");
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        case BLX:
8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Format(instr, "blx'cond 'rm");
8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        case BKPT:
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Format(instr, "bkpt 'off0to3and8to19");
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        default:
8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Unknown(instr);  // not used by V8
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else if (instr->Bits(22, 21) == 3) {
8141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      switch (instr->BitField(7, 4)) {
8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        case CLZ:
8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Format(instr, "clz'cond 'rd, 'rm");
8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        default:
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Unknown(instr);  // not used by V8
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Unknown(instr);  // not used by V8
8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (instr->OpcodeField()) {
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case AND: {
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case EOR: {
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case SUB: {
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case RSB: {
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ADD: {
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ADC: {
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case SBC: {
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case RSC: {
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case TST: {
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (instr->HasS()) {
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Format(instr, "tst'cond 'rn, 'shift_op");
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
8639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          Format(instr, "movw'cond 'mw");
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case TEQ: {
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (instr->HasS()) {
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Format(instr, "teq'cond 'rn, 'shift_op");
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          // Other instructions matching this pattern are handled in the
8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          // miscellaneous instructions part above.
8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          UNREACHABLE();
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case CMP: {
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (instr->HasS()) {
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Format(instr, "cmp'cond 'rn, 'shift_op");
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
8819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          Format(instr, "movt'cond 'mw");
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case CMN: {
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (instr->HasS()) {
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Format(instr, "cmn'cond 'rn, 'shift_op");
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
8896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          // Other instructions matching this pattern are handled in the
8906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          // miscellaneous instructions part above.
8916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          UNREACHABLE();
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case ORR: {
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case MOV: {
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "mov'cond's 'rd, 'shift_op");
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case BIC: {
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case MVN: {
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Format(instr, "mvn'cond's 'rd, 'shift_op");
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default: {
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // The Opcode field is a 4-bit field.
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UNREACHABLE();
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType2(Instruction* instr) {
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (instr->PUField()) {
9231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case da_x: {
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->HasW()) {
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Unknown(instr);  // not used in V8
92644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        return;
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case ia_x: {
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (instr->HasW()) {
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Unknown(instr);  // not used in V8
93444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        return;
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case db_x: {
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case ib_x: {
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The PU field is a 2-bit field.
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType3(Instruction* instr) {
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (instr->PUField()) {
9581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case da_x: {
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      VERIFY(!instr->HasW());
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case ia_x: {
96450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      if (instr->HasW()) {
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VERIFY(instr->Bits(5, 4) == 0x1);
96650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen        if (instr->Bit(22) == 0x1) {
96780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
96850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen        } else {
96950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen          UNREACHABLE();  // SSAT.
97050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen        }
97150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      } else {
97250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen        Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
97350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      }
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case db_x: {
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case ib_x: {
9813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
9823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
9837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
9843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        uint32_t msbit = widthminus1 + lsbit;
9853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        if (msbit <= 31) {
9867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          if (instr->Bit(22)) {
9877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Format(instr, "ubfx'cond 'rd, 'rm, 'f");
9887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          } else {
9897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Format(instr, "sbfx'cond 'rd, 'rm, 'f");
9907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          }
9917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        } else {
9927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          UNREACHABLE();
9937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        }
9947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
9957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
9967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
9977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        if (msbit >= lsbit) {
9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          if (instr->RmValue() == 15) {
9997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Format(instr, "bfc'cond 'rd, 'f");
10007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          } else {
10017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Format(instr, "bfi'cond 'rd, 'rm, 'f");
10027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          }
10033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        } else {
10043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          UNREACHABLE();
10053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        }
10063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      } else {
10073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
10083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      }
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The PU field is a 2-bit field.
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType4(Instruction* instr) {
102144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (instr->Bit(22) != 0) {
102244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Privileged mode currently not supported.
102344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Unknown(instr);
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
102544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (instr->HasL()) {
102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
102844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Format(instr, "stm'cond'pu 'rn'w, 'rlist");
102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType5(Instruction* instr) {
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Format(instr, "b'l'cond 'target");
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType6(Instruction* instr) {
1040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DecodeType6CoprocessorIns(instr);
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Decoder::DecodeType7(Instruction* instr) {
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (instr->Bit(24) == 1) {
10461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (instr->SvcValue() >= kStopCode) {
10473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      Format(instr, "stop'cond 'svc");
10483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Also print the stop message. Its address is encoded
10493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // in the following 4 bytes.
10501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
10511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      "\n  %p  %08x       stop message: %s",
10521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      reinterpret_cast<int32_t*>(instr
10531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                                     + Instruction::kInstrSize),
10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      *reinterpret_cast<char**>(instr
10551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                                    + Instruction::kInstrSize),
10561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      *reinterpret_cast<char**>(instr
10571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                                    + Instruction::kInstrSize));
10581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // We have decoded 2 * Instruction::kInstrSize bytes.
10591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return 2 * Instruction::kInstrSize;
10603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    } else {
10613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      Format(instr, "svc'cond 'svc");
10623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    DecodeTypeVFP(instr);
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
10661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return Instruction::kInstrSize;
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// void Decoder::DecodeTypeVFP(Instruction* instr)
1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vmov: Sn = Rt
1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vmov: Rt = Sn
1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vcvt: Dd = Sm
1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// vcvt: Sd = Dm
107544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Dd = vabs(Dm)
107644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Dd = vneg(Dm)
1077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vadd(Dn, Dm)
1078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vsub(Dn, Dm)
1079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vmul(Dn, Dm)
1080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dd = vdiv(Dn, Dm)
1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// vcmp(Dd, Dm)
10828defd9ff6930b4e24729971a61cf7469daf119beSteve Block// vmrs
10838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// vmsr
10848defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Dd = vsqrt(Dm)
10851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeTypeVFP(Instruction* instr) {
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY(instr->Bits(11, 9) == 0x5);
10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (instr->Bit(4) == 0) {
10901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (instr->Opc1Value() == 0x7) {
10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Other data processing instructions
10921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
10938defd9ff6930b4e24729971a61cf7469daf119beSteve Block        // vmov register to register.
10941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (instr->SzValue() == 0x1) {
10958defd9ff6930b4e24729971a61cf7469daf119beSteve Block          Format(instr, "vmov.f64'cond 'Dd, 'Dm");
10968defd9ff6930b4e24729971a61cf7469daf119beSteve Block        } else {
10973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          Format(instr, "vmov.f32'cond 'Sd, 'Sm");
10988defd9ff6930b4e24729971a61cf7469daf119beSteve Block        }
10991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
11001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // vabs
1101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Format(instr, "vabs.f64'cond 'Dd, 'Dm");
110244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
110344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // vneg
1104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Format(instr, "vneg.f64'cond 'Dd, 'Dm");
11051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        DecodeVCVTBetweenDoubleAndSingle(instr);
11071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        DecodeVCVTBetweenFloatingPointAndInteger(instr);
11091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (((instr->Opc2Value() >> 1) == 0x6) &&
11101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 (instr->Opc3Value() & 0x1)) {
11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        DecodeVCVTBetweenFloatingPointAndInteger(instr);
11121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
11131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 (instr->Opc3Value() & 0x1)) {
11146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        DecodeVCMP(instr);
11151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
11168defd9ff6930b4e24729971a61cf7469daf119beSteve Block        Format(instr, "vsqrt.f64'cond 'Dd, 'Dm");
11171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (instr->Opc3Value() == 0x0) {
11181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (instr->SzValue() == 0x1) {
11193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          Format(instr, "vmov.f64'cond 'Dd, 'd");
11203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        } else {
11213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          Unknown(instr);  // Not used by V8.
11223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        }
11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
11246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Unknown(instr);  // Not used by V8.
11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
11261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else if (instr->Opc1Value() == 0x3) {
11271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (instr->SzValue() == 0x1) {
11281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (instr->Opc3Value() & 0x1) {
11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
11306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
11326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Unknown(instr);  // Not used by V8.
11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
11361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
11371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (instr->SzValue() == 0x1) {
11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Unknown(instr);  // Not used by V8.
11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
11421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
11431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (instr->SzValue() == 0x1) {
1144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Unknown(instr);  // Not used by V8.
11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
1149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Unknown(instr);  // Not used by V8.
1150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
11521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if ((instr->VCValue() == 0x0) &&
11531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        (instr->VAValue() == 0x0)) {
11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
11551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else if ((instr->VCValue() == 0x0) &&
11561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block               (instr->VAValue() == 0x7) &&
11576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               (instr->Bits(19, 16) == 0x1)) {
11581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (instr->VLValue() == 0) {
11598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        if (instr->Bits(15, 12) == 0xF) {
11608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          Format(instr, "vmsr'cond FPSCR, APSR");
11618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        } else {
11628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          Format(instr, "vmsr'cond FPSCR, 'rt");
11638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        }
11648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      } else {
11658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        if (instr->Bits(15, 12) == 0xF) {
11668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          Format(instr, "vmrs'cond APSR, FPSCR");
11678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        } else {
11688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          Format(instr, "vmrs'cond 'rt, FPSCR");
11698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        }
11708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
11771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Instruction* instr) {
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         (instr->VAValue() == 0x0));
11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool to_arm_register = (instr->VLValue() == 0x1);
11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (to_arm_register) {
11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Format(instr, "vmov'cond 'rt, 'Sn");
1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Format(instr, "vmov'cond 'Sn, 'rt");
11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCMP(Instruction* instr) {
11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
11941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         (instr->Opc3Value() & 0x1));
11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Comparison.
11971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool dp_operation = (instr->SzValue() == 1);
11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (dp_operation && !raise_exception_for_qnan) {
12011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (instr->Opc2Value() == 0x4) {
1202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
12031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else if (instr->Opc2Value() == 0x5) {
1204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Format(instr, "vcmp.f64'cond 'Dd, #0.0");
1205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
1206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Unknown(instr);  // invalid
1207756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Unknown(instr);  // Not used by V8.
12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
12176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool double_to_single = (instr->SzValue() == 1);
12196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (double_to_single) {
12216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm");
12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm");
12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
12311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool to_integer = (instr->Bit(18) == 1);
12341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool dp_operation = (instr->SzValue() == 1);
12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (to_integer) {
12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool unsigned_integer = (instr->Bit(16) == 0);
12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (dp_operation) {
12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (unsigned_integer) {
12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm");
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (unsigned_integer) {
12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm");
12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm");
12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool unsigned_integer = (instr->Bit(7) == 0);
12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (dp_operation) {
12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (unsigned_integer) {
12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm");
12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
12586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
12596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
12606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
12616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (unsigned_integer) {
12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm");
12636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm");
12656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Decode Type 6 coprocessor instructions.
1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Dm = vmov(Rt, Rt2)
1273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// <Rt, Rt2> = vmov(Dm)
1274d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Ddst = MEM(Rbase + 4*offset).
1275d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// MEM(Rbase + 4*offset) = Dsrc.
12761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VERIFY(instr->TypeValue() == 6);
1278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
12791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (instr->CoprocessorValue() == 0xA) {
12801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    switch (instr->OpcodeValue()) {
12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      case 0x8:
128280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      case 0xA:
12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (instr->HasL()) {
128480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
128680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        break;
12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      case 0xC:
129080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      case 0xE:
12916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (instr->HasL()) {
129280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
12936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
129480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
12956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
12966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        break;
12978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0x4:
12988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0x5:
12998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0x6:
13008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0x7:
13018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0x9:
13028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB: {
13038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        bool to_vfp_register = (instr->VLValue() == 0x1);
13048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (to_vfp_register) {
13058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
13068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        } else {
13078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
13088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        }
13098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        break;
13108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      default:
13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Unknown(instr);  // Not used by V8.
13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (instr->CoprocessorValue() == 0xB) {
13151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    switch (instr->OpcodeValue()) {
1316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      case 0x2:
1317d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        // Load and store double to two GP registers
1318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        if (instr->Bits(7, 4) != 0x1) {
1319d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          Unknown(instr);  // Not used by V8.
1320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        } else if (instr->HasL()) {
1321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        } else {
1323d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1324d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        }
1325d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        break;
1326d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      case 0x8:
1327d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        if (instr->HasL()) {
132880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1329d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        } else {
133080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        }
1332d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        break;
1333d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      case 0xC:
1334d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        if (instr->HasL()) {
133580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        } else {
133780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1338d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        }
1339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        break;
13408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0x4:
13418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0x5:
13428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0x9: {
13438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        bool to_vfp_register = (instr->VLValue() == 0x1);
13448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (to_vfp_register) {
13458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
13468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        } else {
13478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
13488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        }
13498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        break;
13508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
1351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      default:
1352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        Unknown(instr);  // Not used by V8.
1353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
13546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Unknown(instr);  // Not used by V8.
135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef VERIFIY
136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
136144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Decoder::IsConstantPoolAt(byte* instr_ptr) {
136244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
136444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
136544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
136744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
136844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (IsConstantPoolAt(instr_ptr)) {
136944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return instruction_bits & kConstantPoolLengthMask;
137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return -1;
1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassemble the instruction at *instr_ptr into the output buffer.
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Decoder::InstructionDecode(byte* instr_ptr) {
13791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Instruction* instr = Instruction::At(instr_ptr);
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print raw instruction bytes.
13811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
13821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                  "%08x       ",
13831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                  instr->InstructionBits());
13841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (instr->ConditionField() == kSpecialCondition) {
138544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Unknown(instr);
138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Instruction::kInstrSize;
138744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
138844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
138944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
139144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    "constant pool begin (length %d)",
139244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    instruction_bits &
139344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    kConstantPoolLengthMask);
13941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return Instruction::kInstrSize;
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
13961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  switch (instr->TypeValue()) {
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1: {
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DecodeType01(instr);
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2: {
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DecodeType2(instr);
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 3: {
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DecodeType3(instr);
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 4: {
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DecodeType4(instr);
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 5: {
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DecodeType5(instr);
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 6: {
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DecodeType6(instr);
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 7: {
14233e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      return DecodeType7(instr);
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The type field is 3-bits in the ARM encoding.
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
14311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return Instruction::kInstrSize;
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} }  // namespace v8::internal
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm {
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const {
144544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
144644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return tmp_buffer_.start();
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const {
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NameOfAddress(addr);
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const {
14561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return v8::internal::Registers::Name(reg);
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const {
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();  // ARM does not have the concept of a byte register
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "nobytereg";
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const {
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();  // ARM does not have any XMM registers
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noxmmreg";
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const {
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The default name converter is called for unknown code. So we will not try
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to access any memory.
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "";
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter)
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : converter_(converter) {}
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {}
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* instruction) {
14901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  v8::internal::Decoder d(converter_, buffer);
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return d.InstructionDecode(instruction);
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) {
149644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NameConverter converter;
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Disassembler d(converter);
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* pc = begin; pc < end;) {
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::internal::EmbeddedVector<char, 128> buffer;
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer[0] = '\0';
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* prev_pc = pc;
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc += d.InstructionDecode(buffer, pc);
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "%p    %08x      %s\n",
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace disasm
1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
1517