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