1ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Copyright 2013, ARM Limited
2ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// All rights reserved.
3ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
4ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Redistribution and use in source and binary forms, with or without
5ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// modification, are permitted provided that the following conditions are met:
6ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
7ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions of source code must retain the above copyright notice,
8ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer.
9ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions in binary form must reproduce the above copyright notice,
10ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer in the documentation
11ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     and/or other materials provided with the distribution.
12ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Neither the name of ARM Limited nor the names of its contributors may be
13ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     used to endorse or promote products derived from this software without
14ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     specific prior written permission.
15ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
16ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
27ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/disasm-a64.h"
28ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
29ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl {
30ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
31ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlDisassembler::Disassembler() {
32ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_size_ = 256;
33ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_ = reinterpret_cast<char*>(malloc(buffer_size_));
34ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_pos_ = 0;
35ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  own_buffer_ = true;
36ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
37ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
38ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
39ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlDisassembler::Disassembler(char* text_buffer, int buffer_size) {
40ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_size_ = buffer_size;
41ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_ = text_buffer;
42ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_pos_ = 0;
43ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  own_buffer_ = false;
44ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
45ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
46ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
47ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlDisassembler::~Disassembler() {
48ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (own_buffer_) {
49ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    free(buffer_);
50ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
51ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
52ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
53ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
54ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlchar* Disassembler::GetOutput() {
55ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return buffer_;
56ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
57ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
58ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
59ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitAddSubImmediate(Instruction* instr) {
60ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rd_is_zr = RdIsZROrSP(instr);
61ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
62ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                  (instr->ImmAddSub() == 0) ? true : false;
63578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
64ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rds, 'Rns, 'IAddSub";
65ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_cmp = "'Rns, 'IAddSub";
66ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_mov = "'Rds, 'Rns";
67ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
68ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(AddSubImmediateMask)) {
69ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADD_w_imm:
70ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADD_x_imm: {
71ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "add";
72ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (stack_op) {
73ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "mov";
74ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_mov;
75ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
76ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
77ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
78ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADDS_w_imm:
79ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADDS_x_imm: {
80ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "adds";
81ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd_is_zr) {
82ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cmn";
83ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_cmp;
84ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
85ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
86ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
87ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUB_w_imm:
88ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUB_x_imm: mnemonic = "sub"; break;
89ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUBS_w_imm:
90ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUBS_x_imm: {
91ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "subs";
92ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd_is_zr) {
93ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cmp";
94ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_cmp;
95ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
96ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
97ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
99ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitAddSubShifted(Instruction* instr) {
105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rd_is_zr = RdIsZROrSP(instr);
106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rn_is_zr = RnIsZROrSP(instr);
107578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rd, 'Rn, 'Rm'HDP";
109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_cmp = "'Rn, 'Rm'HDP";
110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_neg = "'Rd, 'Rm'HDP";
111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(AddSubShiftedMask)) {
113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADD_w_shift:
114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADD_x_shift: mnemonic = "add"; break;
115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADDS_w_shift:
116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADDS_x_shift: {
117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "adds";
118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd_is_zr) {
119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cmn";
120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_cmp;
121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUB_w_shift:
125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUB_x_shift: {
126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "sub";
127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rn_is_zr) {
128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "neg";
129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_neg;
130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUBS_w_shift:
134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUBS_x_shift: {
135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "subs";
136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd_is_zr) {
137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cmp";
138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_cmp;
139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else if (rn_is_zr) {
140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "negs";
141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_neg;
142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitAddSubExtended(Instruction* instr) {
152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rd_is_zr = RdIsZROrSP(instr);
153578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Extend mode = static_cast<Extend>(instr->ExtendMode());
155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = ((mode == UXTX) || (mode == SXTX)) ?
156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                     "'Rds, 'Rns, 'Xm'Ext" : "'Rds, 'Rns, 'Wm'Ext";
157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ?
158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(AddSubExtendedMask)) {
161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADD_w_ext:
162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADD_x_ext: mnemonic = "add"; break;
163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADDS_w_ext:
164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADDS_x_ext: {
165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "adds";
166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd_is_zr) {
167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cmn";
168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_cmp;
169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUB_w_ext:
173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUB_x_ext: mnemonic = "sub"; break;
174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUBS_w_ext:
175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUBS_x_ext: {
176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "subs";
177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd_is_zr) {
178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cmp";
179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_cmp;
180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitAddSubWithCarry(Instruction* instr) {
190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rn_is_zr = RnIsZROrSP(instr);
191578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rd, 'Rn, 'Rm";
193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_neg = "'Rd, 'Rm";
194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(AddSubWithCarryMask)) {
196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADC_w:
197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADC_x: mnemonic = "adc"; break;
198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADCS_w:
199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADCS_x: mnemonic = "adcs"; break;
200ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SBC_w:
201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SBC_x: {
202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "sbc";
203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rn_is_zr) {
204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "ngc";
205ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_neg;
206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
208ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
209ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SBCS_w:
210ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SBCS_x: {
211ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "sbcs";
212ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rn_is_zr) {
213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "ngcs";
214ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_neg;
215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
217ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
220ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
224ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLogicalImmediate(Instruction* instr) {
225ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rd_is_zr = RdIsZROrSP(instr);
226ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rn_is_zr = RnIsZROrSP(instr);
227578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
228ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rds, 'Rn, 'ITri";
229ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
230578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (instr->ImmLogical() == 0) {
231578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // The immediate encoded in the instruction is not in the expected format.
232578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    Format(instr, "unallocated", "(LogicalImmediate)");
233578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return;
234578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
235578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
236ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LogicalImmediateMask)) {
237ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case AND_w_imm:
238ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case AND_x_imm: mnemonic = "and"; break;
239ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ORR_w_imm:
240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ORR_x_imm: {
241ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "orr";
2427f2db39dffaca523429c67a71054bb19c108f31fAndreas Gampe      unsigned reg_size = (instr->SixtyFourBits() != 0) ? kXRegSize
243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                                        : kWRegSize;
244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) {
245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "mov";
246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = "'Rds, 'ITri";
247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
248ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
249ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
250ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EOR_w_imm:
251ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EOR_x_imm: mnemonic = "eor"; break;
252ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ANDS_w_imm:
253ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ANDS_x_imm: {
254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "ands";
255ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd_is_zr) {
256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "tst";
257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = "'Rn, 'ITri";
258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
260ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
262ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
263ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
264ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
266ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
267ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
2681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((reg_size == kXRegSize) ||
2691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              ((reg_size == kWRegSize) && (value <= 0xffffffff)));
270ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
271ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Test for movz: 16 bits set at positions 0, 16, 32 or 48.
272ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  if (((value & UINT64_C(0xffffffffffff0000)) == 0) ||
273ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      ((value & UINT64_C(0xffffffff0000ffff)) == 0) ||
274ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      ((value & UINT64_C(0xffff0000ffffffff)) == 0) ||
275ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      ((value & UINT64_C(0x0000ffffffffffff)) == 0)) {
276ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return true;
277ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
278ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((reg_size == kXRegSize) &&
281ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      (((~value & UINT64_C(0xffffffffffff0000)) == 0) ||
282ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl       ((~value & UINT64_C(0xffffffff0000ffff)) == 0) ||
283ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl       ((~value & UINT64_C(0xffff0000ffffffff)) == 0) ||
284ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl       ((~value & UINT64_C(0x0000ffffffffffff)) == 0))) {
285ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return true;
286ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
287ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((reg_size == kWRegSize) &&
288ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (((value & 0xffff0000) == 0xffff0000) ||
289ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl       ((value & 0x0000ffff) == 0x0000ffff))) {
290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return true;
291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return false;
293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLogicalShifted(Instruction* instr) {
297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rd_is_zr = RdIsZROrSP(instr);
298ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rn_is_zr = RnIsZROrSP(instr);
299578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
300ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rd, 'Rn, 'Rm'HLo";
301ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LogicalShiftedMask)) {
303ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case AND_w:
304ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case AND_x: mnemonic = "and"; break;
305ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BIC_w:
306ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BIC_x: mnemonic = "bic"; break;
307ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EOR_w:
308ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EOR_x: mnemonic = "eor"; break;
309ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EON_w:
310ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EON_x: mnemonic = "eon"; break;
311ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BICS_w:
312ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BICS_x: mnemonic = "bics"; break;
313ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ANDS_w:
314ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ANDS_x: {
315ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "ands";
316ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd_is_zr) {
317ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "tst";
318ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = "'Rn, 'Rm'HLo";
319ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
320ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
321ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
322ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ORR_w:
323ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ORR_x: {
324ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "orr";
325ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) {
326ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "mov";
327ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = "'Rd, 'Rm";
328ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
329ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
330ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
331ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ORN_w:
332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ORN_x: {
333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "orn";
334ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rn_is_zr) {
335ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "mvn";
336ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = "'Rd, 'Rm'HLo";
337ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
338ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
339ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
3401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
341ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
342ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
345ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
346ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
347ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitConditionalCompareRegister(Instruction* instr) {
348578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
349ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
350ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
351ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(ConditionalCompareRegisterMask)) {
352ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CCMN_w:
353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CCMN_x: mnemonic = "ccmn"; break;
354ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CCMP_w:
355ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CCMP_x: mnemonic = "ccmp"; break;
3561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
357ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
359ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
360ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
361ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
362ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitConditionalCompareImmediate(Instruction* instr) {
363578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
364ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
365ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
366ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(ConditionalCompareImmediateMask)) {
367ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CCMN_w_imm:
368ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CCMN_x_imm: mnemonic = "ccmn"; break;
369ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CCMP_w_imm:
370ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CCMP_x_imm: mnemonic = "ccmp"; break;
3711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
372ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
373ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
375ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitConditionalSelect(Instruction* instr) {
378ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
379ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool rn_is_rm = (instr->Rn() == instr->Rm());
380578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
381ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
382ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_test = "'Rd, 'CInv";
383ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_update = "'Rd, 'Rn, 'CInv";
384ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
385578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  Condition cond = static_cast<Condition>(instr->Condition());
386578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  bool invertible_cond = (cond != al) && (cond != nv);
387578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(ConditionalSelectMask)) {
389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CSEL_w:
390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CSEL_x: mnemonic = "csel"; break;
391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CSINC_w:
392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CSINC_x: {
393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "csinc";
394578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (rnm_is_zr && invertible_cond) {
395ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cset";
396ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_test;
397578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else if (rn_is_rm && invertible_cond) {
398ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cinc";
399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_update;
400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
401ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CSINV_w:
404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CSINV_x: {
405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "csinv";
406578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (rnm_is_zr && invertible_cond) {
407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "csetm";
408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_test;
409578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else if (rn_is_rm && invertible_cond) {
410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cinv";
411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_update;
412ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
413ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
414ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
415ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CSNEG_w:
416ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CSNEG_x: {
417ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "csneg";
418578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (rn_is_rm && invertible_cond) {
419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "cneg";
420ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_update;
421ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
422ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
4241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
425ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
426ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
427ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
428ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
429ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitBitfield(Instruction* instr) {
431ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned s = instr->ImmS();
432ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned r = instr->ImmR();
433ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned rd_size_minus_1 =
4347f2db39dffaca523429c67a71054bb19c108f31fAndreas Gampe    ((instr->SixtyFourBits() != 0) ? kXRegSize : kWRegSize) - 1;
435578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
436578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *form = "";
437ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_shift_right = "'Rd, 'Rn, 'IBr";
438ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_extend = "'Rd, 'Wn";
439ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
440ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
441ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
442ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
443ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(BitfieldMask)) {
444ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SBFM_w:
445ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SBFM_x: {
446ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "sbfx";
447ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      form = form_bfx;
448ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (r == 0) {
449ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_extend;
450ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        if (s == 7) {
451ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          mnemonic = "sxtb";
452ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else if (s == 15) {
453ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          mnemonic = "sxth";
4547f2db39dffaca523429c67a71054bb19c108f31fAndreas Gampe        } else if ((s == 31) && (instr->SixtyFourBits() != 0)) {
455ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          mnemonic = "sxtw";
456ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
457ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          form = form_bfx;
458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
459ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else if (s == rd_size_minus_1) {
460ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "asr";
461ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_shift_right;
462ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else if (s < r) {
463ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "sbfiz";
464ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_bfiz;
465ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
466ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
467ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
468ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UBFM_w:
469ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UBFM_x: {
470ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "ubfx";
471ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      form = form_bfx;
472ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (r == 0) {
473ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_extend;
474ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        if (s == 7) {
475ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          mnemonic = "uxtb";
476ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else if (s == 15) {
477ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          mnemonic = "uxth";
478ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
479ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          form = form_bfx;
480ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
481ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
482ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (s == rd_size_minus_1) {
483ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "lsr";
484ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_shift_right;
485ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else if (r == s + 1) {
486ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "lsl";
487ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_lsl;
488ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else if (s < r) {
489ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "ubfiz";
490ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_bfiz;
491ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
492ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
493ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
494ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BFM_w:
495ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BFM_x: {
496ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "bfxil";
497ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      form = form_bfx;
498ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (s < r) {
499ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "bfi";
500ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_bfiz;
501ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
502ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
503ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
504ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
505ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
506ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
507ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
508ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitExtract(Instruction* instr) {
509578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
510ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
511ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
512ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(ExtractMask)) {
513ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EXTR_w:
514ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EXTR_x: {
515ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (instr->Rn() == instr->Rm()) {
516ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "ror";
517ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = "'Rd, 'Rn, 'IExtract";
518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
519ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "extr";
520ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
521ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
522ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
5231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
524ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
525ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
526ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
527ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
528ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
529ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitPCRelAddressing(Instruction* instr) {
530ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(PCRelAddressingMask)) {
531ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break;
532ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // ADRP is not implemented.
533578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    default: Format(instr, "unimplemented", "(PCRelAddressing)");
534ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
535ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
536ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
537ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
538ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitConditionalBranch(Instruction* instr) {
539ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(ConditionalBranchMask)) {
540ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
5411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
542ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
543ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
544ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
545ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
546ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitUnconditionalBranchToRegister(Instruction* instr) {
547578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
548ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Xn";
549ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
550ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
551ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BR: mnemonic = "br"; break;
552ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BLR: mnemonic = "blr"; break;
553ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case RET: {
554ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "ret";
555ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (instr->Rn() == kLinkRegCode) {
556ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = NULL;
557ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
558ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
559ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
560ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: form = "(UnconditionalBranchToRegister)";
561ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
562ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
563ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
564ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
565ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
566ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitUnconditionalBranch(Instruction* instr) {
567578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
568ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'BImmUncn";
569ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
570ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(UnconditionalBranchMask)) {
571ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case B: mnemonic = "b"; break;
572ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BL: mnemonic = "bl"; break;
5731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
574ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
575ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
576ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
577ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
578ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
579ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitDataProcessing1Source(Instruction* instr) {
580578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
581ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rd, 'Rn";
582ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
583ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(DataProcessing1SourceMask)) {
584ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define FORMAT(A, B)  \
585ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_w:           \
586ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_x: mnemonic = B; break;
587ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(RBIT, "rbit");
588ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(REV16, "rev16");
589ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(REV, "rev");
590ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(CLZ, "clz");
591ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(CLS, "cls");
592ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef FORMAT
593ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case REV32_x: mnemonic = "rev32"; break;
5941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
595ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
596ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
597ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
598ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
599ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
600ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitDataProcessing2Source(Instruction* instr) {
601578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
602ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rd, 'Rn, 'Rm";
603ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
604ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(DataProcessing2SourceMask)) {
605ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define FORMAT(A, B)  \
606ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_w:           \
607ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_x: mnemonic = B; break;
608ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(UDIV, "udiv");
609ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(SDIV, "sdiv");
610ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(LSLV, "lsl");
611ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(LSRV, "lsr");
612ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(ASRV, "asr");
613ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(RORV, "ror");
614ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef FORMAT
615ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: form = "(DataProcessing2Source)";
616ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
617ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
618ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
619ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
620ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
621ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitDataProcessing3Source(Instruction* instr) {
622ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool ra_is_zr = RaIsZROrSP(instr);
623578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
624ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
625ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_rrr = "'Rd, 'Rn, 'Rm";
626ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
627ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_xww = "'Xd, 'Wn, 'Wm";
628ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_xxx = "'Xd, 'Xn, 'Xm";
629ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
630ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(DataProcessing3SourceMask)) {
631ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MADD_w:
632ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MADD_x: {
633ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "madd";
634ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      form = form_rrrr;
635ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (ra_is_zr) {
636ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "mul";
637ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_rrr;
638ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
639ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
640ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
641ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MSUB_w:
642ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MSUB_x: {
643ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "msub";
644ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      form = form_rrrr;
645ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (ra_is_zr) {
646ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "mneg";
647ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_rrr;
648ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
649ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
650ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
651ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SMADDL_x: {
652ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "smaddl";
653ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (ra_is_zr) {
654ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "smull";
655ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_xww;
656ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
657ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
658ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
659ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SMSUBL_x: {
660ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "smsubl";
661ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (ra_is_zr) {
662ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "smnegl";
663ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_xww;
664ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
665ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
666ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
667ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UMADDL_x: {
668ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "umaddl";
669ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (ra_is_zr) {
670ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "umull";
671ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_xww;
672ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
673ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
674ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
675ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UMSUBL_x: {
676ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "umsubl";
677ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (ra_is_zr) {
678ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "umnegl";
679ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = form_xww;
680ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
681ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
682ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
683ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SMULH_x: {
684ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "smulh";
685ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      form = form_xxx;
686ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
687ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
688ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UMULH_x: {
689ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      mnemonic = "umulh";
690ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      form = form_xxx;
691ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
692ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
6931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
694ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
695ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
696ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
697ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
698ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
699ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitCompareBranch(Instruction* instr) {
700578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
701ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rt, 'BImmCmpa";
702ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
703ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(CompareBranchMask)) {
704ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CBZ_w:
705ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CBZ_x: mnemonic = "cbz"; break;
706ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CBNZ_w:
707ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CBNZ_x: mnemonic = "cbnz"; break;
7081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
709ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
710ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
711ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
712ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
713ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
714ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitTestBranch(Instruction* instr) {
715578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
716578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // If the top bit of the immediate is clear, the tested register is
717578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
718578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // encoded in bit 31 of the instruction, we can reuse the Rt form, which
719578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // uses bit 31 (normally "sf") to choose the register size.
720578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *form = "'Rt, 'IS, 'BImmTest";
721ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
722ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(TestBranchMask)) {
723ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case TBZ: mnemonic = "tbz"; break;
724ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case TBNZ: mnemonic = "tbnz"; break;
7251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
726ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
727ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
728ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
729ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
730ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
731ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitMoveWideImmediate(Instruction* instr) {
732578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
733ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Rd, 'IMoveImm";
734ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
735ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Print the shift separately for movk, to make it clear which half word will
736ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // be overwritten. Movn and movz print the computed immediate, which includes
737ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // shift calculation.
738ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(MoveWideImmediateMask)) {
739ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVN_w:
740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVN_x: mnemonic = "movn"; break;
741ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVZ_w:
742ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVZ_x: mnemonic = "movz"; break;
743ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVK_w:
744ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
7451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
746ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
747ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
748ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
749ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
750ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
751ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#define LOAD_STORE_LIST(V)    \
752ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STRB_w, "strb", "'Wt")    \
753ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STRH_w, "strh", "'Wt")    \
754ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STR_w, "str", "'Wt")      \
755ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STR_x, "str", "'Xt")      \
756ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDRB_w, "ldrb", "'Wt")    \
757ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDRH_w, "ldrh", "'Wt")    \
758ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDR_w, "ldr", "'Wt")      \
759ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDR_x, "ldr", "'Xt")      \
760ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDRSB_x, "ldrsb", "'Xt")  \
761ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDRSH_x, "ldrsh", "'Xt")  \
762ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDRSW_x, "ldrsw", "'Xt")  \
763ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDRSB_w, "ldrsb", "'Wt")  \
764ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDRSH_w, "ldrsh", "'Wt")  \
765ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STR_s, "str", "'St")      \
766ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STR_d, "str", "'Dt")      \
767ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDR_s, "ldr", "'St")      \
768ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDR_d, "ldr", "'Dt")
769ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
770ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStorePreIndex(Instruction* instr) {
771578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
772ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(LoadStorePreIndex)";
773ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
774ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStorePreIndexMask)) {
775ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define LS_PREINDEX(A, B, C) \
776ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break;
777ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LOAD_STORE_LIST(LS_PREINDEX)
778ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef LS_PREINDEX
779ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
780ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
781ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
782ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
783ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
784ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStorePostIndex(Instruction* instr) {
785578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
786ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(LoadStorePostIndex)";
787ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
788ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStorePostIndexMask)) {
789ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define LS_POSTINDEX(A, B, C) \
790ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break;
791ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LOAD_STORE_LIST(LS_POSTINDEX)
792ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef LS_POSTINDEX
793ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
794ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
795ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
796ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
797ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
798ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStoreUnsignedOffset(Instruction* instr) {
799578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
800ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(LoadStoreUnsignedOffset)";
801ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
802ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
803ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define LS_UNSIGNEDOFFSET(A, B, C) \
804ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break;
805ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
806ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef LS_UNSIGNEDOFFSET
807ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case PRFM_unsigned: mnemonic = "prfm"; form = "'PrefOp, ['Xn'ILU]";
808ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
809ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
810ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
811ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
812ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
813ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStoreRegisterOffset(Instruction* instr) {
814578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
815ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(LoadStoreRegisterOffset)";
816ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
817ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
818ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define LS_REGISTEROFFSET(A, B, C) \
819ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break;
820ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LOAD_STORE_LIST(LS_REGISTEROFFSET)
821ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef LS_REGISTEROFFSET
822ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case PRFM_reg: mnemonic = "prfm"; form = "'PrefOp, ['Xns, 'Offsetreg]";
823ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
824ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
825ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
826ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
827ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
828ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStoreUnscaledOffset(Instruction* instr) {
829578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
830ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Wt, ['Xns'ILS]";
831ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_x = "'Xt, ['Xns'ILS]";
832ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_s = "'St, ['Xns'ILS]";
833ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_d = "'Dt, ['Xns'ILS]";
834ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
835ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
836ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STURB_w:  mnemonic = "sturb"; break;
837ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STURH_w:  mnemonic = "sturh"; break;
838ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STUR_w:   mnemonic = "stur"; break;
839ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STUR_x:   mnemonic = "stur"; form = form_x; break;
840ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STUR_s:   mnemonic = "stur"; form = form_s; break;
841ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STUR_d:   mnemonic = "stur"; form = form_d; break;
842ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDURB_w:  mnemonic = "ldurb"; break;
843ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDURH_w:  mnemonic = "ldurh"; break;
844ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDUR_w:   mnemonic = "ldur"; break;
845ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDUR_x:   mnemonic = "ldur"; form = form_x; break;
846ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDUR_s:   mnemonic = "ldur"; form = form_s; break;
847ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDUR_d:   mnemonic = "ldur"; form = form_d; break;
848ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDURSB_x: form = form_x;  // Fall through.
849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDURSB_w: mnemonic = "ldursb"; break;
850ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDURSH_x: form = form_x;  // Fall through.
851ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDURSH_w: mnemonic = "ldursh"; break;
852ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDURSW_x: mnemonic = "ldursw"; form = form_x; break;
853ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: form = "(LoadStoreUnscaledOffset)";
854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
855ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
856ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
858ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
859ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadLiteral(Instruction* instr) {
860ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *mnemonic = "ldr";
861ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(LoadLiteral)";
862ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
863ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadLiteralMask)) {
864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break;
865ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break;
866ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break;
867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break;
868578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    default: mnemonic = "unimplemented";
869ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
871ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
872ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
873ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
874ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#define LOAD_STORE_PAIR_LIST(V)         \
875ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STP_w, "stp", "'Wt, 'Wt2", "4")     \
876ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDP_w, "ldp", "'Wt, 'Wt2", "4")     \
877ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "4") \
878ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STP_x, "stp", "'Xt, 'Xt2", "8")     \
879ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDP_x, "ldp", "'Xt, 'Xt2", "8")     \
880ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STP_s, "stp", "'St, 'St2", "4")     \
881ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDP_s, "ldp", "'St, 'St2", "4")     \
882ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(STP_d, "stp", "'Dt, 'Dt2", "8")     \
883ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  V(LDP_d, "ldp", "'Dt, 'Dt2", "8")
884ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
885ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStorePairPostIndex(Instruction* instr) {
886578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
887ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(LoadStorePairPostIndex)";
888ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
889ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStorePairPostIndexMask)) {
890ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define LSP_POSTINDEX(A, B, C, D) \
891ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break;
892ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
893ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef LSP_POSTINDEX
894ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
895ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
896ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
897ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
898ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
899ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStorePairPreIndex(Instruction* instr) {
900578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
901ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(LoadStorePairPreIndex)";
902ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
903ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStorePairPreIndexMask)) {
904ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define LSP_PREINDEX(A, B, C, D) \
905ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break;
906ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
907ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef LSP_PREINDEX
908ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
909ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
910ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
911ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
912ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
913ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStorePairOffset(Instruction* instr) {
914578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
915ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(LoadStorePairOffset)";
916ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
917ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStorePairOffsetMask)) {
918ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define LSP_OFFSET(A, B, C, D) \
919ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break;
920ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LOAD_STORE_PAIR_LIST(LSP_OFFSET)
921ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef LSP_OFFSET
922ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
923ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
924ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
925ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
926ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
927ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitLoadStorePairNonTemporal(Instruction* instr) {
928578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
929ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form;
930ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
931ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadStorePairNonTemporalMask)) {
932ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STNP_w: mnemonic = "stnp"; form = "'Wt, 'Wt2, ['Xns'ILP4]"; break;
933ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDNP_w: mnemonic = "ldnp"; form = "'Wt, 'Wt2, ['Xns'ILP4]"; break;
934ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STNP_x: mnemonic = "stnp"; form = "'Xt, 'Xt2, ['Xns'ILP8]"; break;
935ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDNP_x: mnemonic = "ldnp"; form = "'Xt, 'Xt2, ['Xns'ILP8]"; break;
936ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STNP_s: mnemonic = "stnp"; form = "'St, 'St2, ['Xns'ILP4]"; break;
937ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDNP_s: mnemonic = "ldnp"; form = "'St, 'St2, ['Xns'ILP4]"; break;
938ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STNP_d: mnemonic = "stnp"; form = "'Dt, 'Dt2, ['Xns'ILP8]"; break;
939ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDNP_d: mnemonic = "ldnp"; form = "'Dt, 'Dt2, ['Xns'ILP8]"; break;
940ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: form = "(LoadStorePairNonTemporal)";
941ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
942ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
943ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
944ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
945ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
946ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPCompare(Instruction* instr) {
947578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
948ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Fn, 'Fm";
949ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_zero = "'Fn, #0.0";
950ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
951ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPCompareMask)) {
952ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCMP_s_zero:
953ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCMP_d_zero: form = form_zero;  // Fall through.
954ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCMP_s:
955ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCMP_d: mnemonic = "fcmp"; break;
956ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: form = "(FPCompare)";
957ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
958ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
959ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
960ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
961ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
962ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPConditionalCompare(Instruction* instr) {
963578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unmplemented";
964ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
965ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
966ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPConditionalCompareMask)) {
967ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCCMP_s:
968ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCCMP_d: mnemonic = "fccmp"; break;
969578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FCCMPE_s:
970578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FCCMPE_d: mnemonic = "fccmpe"; break;
971ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: form = "(FPConditionalCompare)";
972ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
973ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
974ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
975ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
976ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
977ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPConditionalSelect(Instruction* instr) {
978578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
979ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
980ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
981ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPConditionalSelectMask)) {
982ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCSEL_s:
983ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCSEL_d: mnemonic = "fcsel"; break;
9841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
985ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
986ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
987ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
988ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
989ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
990ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPDataProcessing1Source(Instruction* instr) {
991578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
992ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Fd, 'Fn";
993ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
994ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPDataProcessing1SourceMask)) {
995ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define FORMAT(A, B)  \
996ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_s:           \
997ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_d: mnemonic = B; break;
998ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FMOV, "fmov");
999ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FABS, "fabs");
1000ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FNEG, "fneg");
1001ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FSQRT, "fsqrt");
1002ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FRINTN, "frintn");
1003ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FRINTP, "frintp");
1004ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FRINTM, "frintm");
1005ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FRINTZ, "frintz");
1006ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FRINTA, "frinta");
1007ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FRINTX, "frintx");
1008ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FRINTI, "frinti");
1009ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef FORMAT
1010ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break;
1011ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break;
1012ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: form = "(FPDataProcessing1Source)";
1013ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1014ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
1015ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1016ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1017ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1018ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPDataProcessing2Source(Instruction* instr) {
1019578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
1020ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Fd, 'Fn, 'Fm";
1021ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1022ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPDataProcessing2SourceMask)) {
1023ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define FORMAT(A, B)  \
1024ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_s:           \
1025ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_d: mnemonic = B; break;
1026ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FMUL, "fmul");
1027ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FDIV, "fdiv");
1028ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FADD, "fadd");
1029ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FSUB, "fsub");
1030ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FMAX, "fmax");
1031ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FMIN, "fmin");
1032ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FMAXNM, "fmaxnm");
1033ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FMINNM, "fminnm");
1034ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FNMUL, "fnmul");
1035ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef FORMAT
10361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1037ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1038ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
1039ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1040ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1041ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1042ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPDataProcessing3Source(Instruction* instr) {
1043578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
1044ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
1045ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1046ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPDataProcessing3SourceMask)) {
1047ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #define FORMAT(A, B)  \
1048ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_s:           \
1049ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case A##_d: mnemonic = B; break;
1050ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FMADD, "fmadd");
1051ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FMSUB, "fmsub");
1052ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FNMADD, "fnmadd");
1053ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    FORMAT(FNMSUB, "fnmsub");
1054ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    #undef FORMAT
10551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1056ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1057ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
1058ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1059ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1060ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1061ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPImmediate(Instruction* instr) {
1062578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
1063ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(FPImmediate)";
1064ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1065ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPImmediateMask)) {
1066ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
1067ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
10681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1069ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1070ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
1071ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1072ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1073ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1074ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPIntegerConvert(Instruction* instr) {
1075578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
1076ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(FPIntegerConvert)";
1077ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_rf = "'Rd, 'Fn";
1078ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_fr = "'Fd, 'Rn";
1079ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1080ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPIntegerConvertMask)) {
1081ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_ws:
1082ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
1083ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_sw:
1084ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
1085f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAS_ws:
1086f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAS_xs:
1087f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAS_wd:
1088f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break;
1089f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAU_ws:
1090f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAU_xs:
1091f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAU_wd:
1092f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break;
1093ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMS_ws:
1094ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMS_xs:
1095ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMS_wd:
1096ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMS_xd: mnemonic = "fcvtms"; form = form_rf; break;
1097ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMU_ws:
1098ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMU_xs:
1099ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMU_wd:
1100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMU_xd: mnemonic = "fcvtmu"; form = form_rf; break;
1101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNS_ws:
1102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNS_xs:
1103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNS_wd:
1104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNS_xd: mnemonic = "fcvtns"; form = form_rf; break;
1105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNU_ws:
1106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNU_xs:
1107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNU_wd:
1108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break;
1109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_xd:
1110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_ws:
1111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_wd:
1112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break;
1113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_xd:
1114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_wd:
1115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_xs:
1116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break;
1117578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_sw:
1118578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_sx:
1119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SCVTF_dw:
1120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break;
1121578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_sw:
1122578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_sx:
1123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UCVTF_dw:
1124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break;
1125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
1127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitFPFixedPointConvert(Instruction* instr) {
1131578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "";
1132578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *form = "'Rd, 'Fn, 'IFPFBits";
1133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
1134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPFixedPointConvertMask)) {
1136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_ws_fixed:
1137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_xs_fixed:
1138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_wd_fixed:
1139578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FCVTZS_xd_fixed: mnemonic = "fcvtzs"; break;
1140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_ws_fixed:
1141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_xs_fixed:
1142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_wd_fixed:
1143578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FCVTZU_xd_fixed: mnemonic = "fcvtzu"; break;
1144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SCVTF_sw_fixed:
1145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SCVTF_sx_fixed:
1146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SCVTF_dw_fixed:
1147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SCVTF_dx_fixed: mnemonic = "scvtf"; form = form_fr; break;
1148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UCVTF_sw_fixed:
1149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UCVTF_sx_fixed:
1150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UCVTF_dw_fixed:
1151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
11521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
1155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitSystem(Instruction* instr) {
1159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Some system instructions hijack their Op and Cp fields to represent a
1160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // range of immediates instead of indicating a different instruction. This
1161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // makes the decoding tricky.
1162578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
1163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char *form = "(System)";
1164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
1166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    switch (instr->Mask(SystemSysRegMask)) {
1167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case MRS: {
1168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "mrs";
1169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        switch (instr->ImmSystemRegister()) {
1170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          case NZCV: form = "'Xt, nzcv"; break;
1171578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          case FPCR: form = "'Xt, fpcr"; break;
1172578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          default: form = "'Xt, (unknown)"; break;
1173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
1174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        break;
1175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case MSR: {
1177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "msr";
1178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        switch (instr->ImmSystemRegister()) {
1179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          case NZCV: form = "nzcv, 'Xt"; break;
1180578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          case FPCR: form = "fpcr, 'Xt"; break;
1181578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          default: form = "(unknown), 'Xt"; break;
1182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
1183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        break;
1184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
11871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
1188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    switch (instr->ImmHint()) {
1189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case NOP: {
1190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        mnemonic = "nop";
1191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        form = NULL;
1192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        break;
1193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1195f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
1196f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    switch (instr->Mask(MemBarrierMask)) {
1197f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      case DMB: {
1198f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        mnemonic = "dmb";
1199f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        form = "'M";
1200f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        break;
1201f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      }
1202f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      case DSB: {
1203f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        mnemonic = "dsb";
1204f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        form = "'M";
1205f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        break;
1206f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      }
1207f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      case ISB: {
1208f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        mnemonic = "isb";
1209f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        form = NULL;
1210f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        break;
1211f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      }
1212f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    }
1213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1214ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Format(instr, mnemonic, form);
1216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1217ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::VisitException(Instruction* instr) {
1220578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *mnemonic = "unimplemented";
1221578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const char *form = "'IDebug";
1222578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(ExceptionMask)) {
1224578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case HLT: mnemonic = "hlt"; break;
1225578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case BRK: mnemonic = "brk"; break;
1226578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SVC: mnemonic = "svc"; break;
1227578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case HVC: mnemonic = "hvc"; break;
1228578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SMC: mnemonic = "smc"; break;
1229578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break;
1230578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break;
1231578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break;
1232578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    default: form = "(Exception)";
1233ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1234578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  Format(instr, mnemonic, form);
1235578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1236578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1237578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1238578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid Disassembler::VisitUnimplemented(Instruction* instr) {
1239578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  Format(instr, "unimplemented", "(Unimplemented)");
1240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1241ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1243578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid Disassembler::VisitUnallocated(Instruction* instr) {
1244578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  Format(instr, "unallocated", "(Unallocated)");
1245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1248ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::ProcessOutput(Instruction* /*instr*/) {
1249ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The base disasm does nothing more than disassembling into a buffer.
1250ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1251ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1252ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1253ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::Format(Instruction* instr, const char* mnemonic,
1254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const char* format) {
12551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(mnemonic != NULL);
1256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ResetOutput();
1257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Substitute(instr, mnemonic);
1258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (format != NULL) {
1259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    buffer_[buffer_pos_++] = ' ';
1260ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Substitute(instr, format);
1261ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1262ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_[buffer_pos_] = 0;
1263ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ProcessOutput(instr);
1264ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1266ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1267ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::Substitute(Instruction* instr, const char* string) {
1268ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  char chr = *string++;
1269ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (chr != '\0') {
1270ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (chr == '\'') {
1271ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      string += SubstituteField(instr, string);
1272ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
1273ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      buffer_[buffer_pos_++] = chr;
1274ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1275ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    chr = *string++;
1276ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1277ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1278ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteField(Instruction* instr, const char* format) {
1281ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (format[0]) {
1282ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'R':  // Register. X or W, selected by sf bit.
1283ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'F':  // FP Register. S or D, selected by type field.
1284ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'W':
1285ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'X':
1286ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'S':
1287ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'D': return SubstituteRegisterField(instr, format);
1288ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'I': return SubstituteImmediateField(instr, format);
1289ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'L': return SubstituteLiteralField(instr, format);
1290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'H': return SubstituteShiftField(instr, format);
1291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'P': return SubstitutePrefetchField(instr, format);
1292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'C': return SubstituteConditionField(instr, format);
1293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'E': return SubstituteExtendField(instr, format);
1294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'A': return SubstitutePCRelAddressField(instr, format);
1295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'B': return SubstituteBranchTargetField(instr, format);
1296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'O': return SubstituteLSRegOffsetField(instr, format);
1297f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case 'M': return SubstituteBarrierField(instr, format);
1298ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: {
12991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
1300ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 1;
1301ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1303ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1304ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1305ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1306ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteRegisterField(Instruction* instr,
1307ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const char* format) {
1308ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_num = 0;
1309ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned field_len = 2;
1310ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (format[1]) {
1311ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'd': reg_num = instr->Rd(); break;
1312ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'n': reg_num = instr->Rn(); break;
1313ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'm': reg_num = instr->Rm(); break;
1314ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'a': reg_num = instr->Ra(); break;
1315ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 't': {
1316ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (format[2] == '2') {
1317ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        reg_num = instr->Rt2();
1318ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        field_len = 3;
1319ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
1320ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        reg_num = instr->Rt();
1321ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1322ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1323ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
13241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1325ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1326ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1327ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Increase field length for registers tagged as stack.
1328ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (format[2] == 's') {
1329ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    field_len = 3;
1330ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1331ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  char reg_type;
1333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (format[0] == 'R') {
1334ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Register type is R: use sf bit to choose X and W.
1335ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    reg_type = instr->SixtyFourBits() ? 'x' : 'w';
1336ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (format[0] == 'F') {
1337ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Floating-point register: use type field to choose S or D.
1338ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    reg_type = ((instr->FPType() & 1) == 0) ? 's' : 'd';
1339ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1340ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Register type is specified. Make it lower case.
1341ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    reg_type = format[0] + 0x20;
1342ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((reg_num != kZeroRegCode) || (reg_type == 's') || (reg_type == 'd')) {
1345ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31.
1346ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AppendToOutput("%c%d", reg_type, reg_num);
1347ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (format[2] == 's') {
1348ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Disassemble w31/x31 as stack pointer wsp/sp.
1349ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AppendToOutput("%s", (reg_type == 'w') ? "wsp" : "sp");
1350ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1351ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Disassemble w31/x31 as zero register wzr/xzr.
1352ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AppendToOutput("%czr", reg_type);
1353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1354ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1355ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return field_len;
1356ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1357ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1359ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteImmediateField(Instruction* instr,
1360ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                           const char* format) {
13611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(format[0] == 'I');
1362ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1363ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (format[1]) {
1364ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'M': {  // IMoveImm or IMoveLSL.
1365ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (format[5] == 'I') {
1366ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide());
1367ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        AppendToOutput("#0x%" PRIx64, imm);
1368ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
13691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        VIXL_ASSERT(format[5] == 'L');
1370ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
1371ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        if (instr->ShiftMoveWide() > 0) {
1372ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
1373ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
1374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1375ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 8;
1376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'L': {
1378ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (format[2]) {
1379ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case 'L': {  // ILLiteral - Immediate Load Literal.
1380578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          AppendToOutput("pc%+" PRId64,
1381ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         instr->ImmLLiteral() << kLiteralEntrySizeLog2);
1382ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return 9;
1383ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
1384ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case 'S': {  // ILS - Immediate Load/Store.
1385ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          if (instr->ImmLS() != 0) {
1386ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            AppendToOutput(", #%" PRId64, instr->ImmLS());
1387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
1388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return 3;
1389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
1390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
1391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          if (instr->ImmLSPair() != 0) {
1392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            // format[3] is the scale value. Convert to a number.
1393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            int scale = format[3] - 0x30;
1394ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            AppendToOutput(", #%" PRId64, instr->ImmLSPair() * scale);
1395ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
1396ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return 4;
1397ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
1398ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case 'U': {  // ILU - Immediate Load/Store Unsigned.
1399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          if (instr->ImmLSUnsigned() != 0) {
1400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            AppendToOutput(", #%" PRIu64,
1401ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                           instr->ImmLSUnsigned() << instr->SizeLS());
1402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
1403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return 3;
1404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
1405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1406ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'C': {  // ICondB - Immediate Conditional Branch.
1408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      int64_t offset = instr->ImmCondBranch() << 2;
1409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      char sign = (offset >= 0) ? '+' : '-';
1410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#%c0x%" PRIx64, sign, offset);
1411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 6;
1412ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1413ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'A': {  // IAddSub.
14141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(instr->ShiftAddSub() <= 1);
1415ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
1416ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
1417ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 7;
1418ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'F': {  // IFPSingle, IFPDouble or IFPFBits.
1420ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (format[3] == 'F') {  // IFPFbits.
1421ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        AppendToOutput("#%d", 64 - instr->FPScale());
1422ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        return 8;
1423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
1424ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
1425ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                       format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64());
1426ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        return 9;
1427ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1428ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1429ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'T': {  // ITri - Immediate Triangular Encoded.
1430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#0x%" PRIx64, instr->ImmLogical());
1431ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 4;
1432ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1433ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'N': {  // INzcv.
1434ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      int nzcv = (instr->Nzcv() << Flags_offset);
1435ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N',
1436ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
1437ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  ((nzcv & CFlag) == 0) ? 'c' : 'C',
1438ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  ((nzcv & VFlag) == 0) ? 'v' : 'V');
1439ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 5;
1440ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1441ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'P': {  // IP - Conditional compare.
1442ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#%d", instr->ImmCondCmp());
1443ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 2;
1444ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1445ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'B': {  // Bitfields.
1446ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return SubstituteBitfieldImmediateField(instr, format);
1447ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1448ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'E': {  // IExtract.
1449ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#%d", instr->ImmS());
1450ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 8;
1451ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1452ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'S': {  // IS - Test and branch bit.
1453ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
1454ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                            instr->ImmTestBranchBit40());
1455ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 2;
1456ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1457ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'D': {  // IDebug - HLT and BRK instructions.
1458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#0x%x", instr->ImmException());
1459ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 6;
1460ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1461ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: {
14621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNIMPLEMENTED();
1463ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 0;
1464ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1465ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1466ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1467ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1468ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1469ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
1470ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                                   const char* format) {
14711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
1472ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned r = instr->ImmR();
1473ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned s = instr->ImmS();
1474ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1475ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (format[2]) {
1476ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'r': {  // IBr.
1477ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#%d", r);
1478ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 3;
1479ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1480ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 's': {  // IBs+1 or IBs-r+1.
1481ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (format[3] == '+') {
1482ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        AppendToOutput("#%d", s + 1);
1483ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        return 5;
1484ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
14851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        VIXL_ASSERT(format[3] == '-');
1486ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        AppendToOutput("#%d", s - r + 1);
1487ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        return 7;
1488ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1489ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1490ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'Z': {  // IBZ-r.
14911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
14927f2db39dffaca523429c67a71054bb19c108f31fAndreas Gampe      unsigned reg_size = (instr->SixtyFourBits() != 0) ? kXRegSize : kWRegSize;
1493ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput("#%d", reg_size - r);
1494ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 5;
1495ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1496ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: {
14971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
1498ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 0;
1499ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1500ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1501ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1502ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1503ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1504ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteLiteralField(Instruction* instr,
1505ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                         const char* format) {
15061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
1507ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(format);
1508ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1509ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadLiteralMask)) {
1510ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_w_lit:
1511ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_x_lit:
1512578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case LDR_s_lit:
1513578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break;
15141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1515ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1516ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1517ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return 6;
1518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1519ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1520ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1521ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
15221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(format[0] == 'H');
15231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->ShiftDP() <= 0x3);
1524ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1525ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (format[1]) {
1526ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'D': {  // HDP.
15271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(instr->ShiftDP() != ROR);
1528ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }  // Fall through.
1529ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'L': {  // HLo.
1530ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (instr->ImmDPShift() != 0) {
1531ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        const char* shift_type[] = {"lsl", "lsr", "asr", "ror"};
1532ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        AppendToOutput(", %s #%" PRId64, shift_type[instr->ShiftDP()],
1533ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                       instr->ImmDPShift());
1534ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1535ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 3;
1536ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1537ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
15381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNIMPLEMENTED();
1539ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 0;
1540ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1541ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1542ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1543ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1544ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteConditionField(Instruction* instr,
1545ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                           const char* format) {
15461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(format[0] == 'C');
1547ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char* condition_code[] = { "eq", "ne", "hs", "lo",
1548ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                   "mi", "pl", "vs", "vc",
1549ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                   "hi", "ls", "ge", "lt",
1550ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                   "gt", "le", "al", "nv" };
1551ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int cond;
1552ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (format[1]) {
1553ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'B': cond = instr->ConditionBranch(); break;
1554ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'I': {
1555ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      cond = InvertCondition(static_cast<Condition>(instr->Condition()));
1556ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1557ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1558ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default: cond = instr->Condition();
1559ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1560ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  AppendToOutput("%s", condition_code[cond]);
1561ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return 4;
1562ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1563ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1564ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1565ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstitutePCRelAddressField(Instruction* instr,
1566ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                              const char* format) {
1567ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(format);
15681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(strncmp(format, "AddrPCRel", 9) == 0);
1569ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1570ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int offset = instr->ImmPCRel();
1571ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1572ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Only ADR (AddrPCRelByte) is supported.
15731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(strcmp(format, "AddrPCRelByte") == 0);
1574ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1575ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  char sign = '+';
1576ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset < 0) {
1577ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    offset = -offset;
1578ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    sign = '-';
1579ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
15801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
15811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  AppendToOutput("#%c0x%x (addr %p)", sign, offset, instr + offset);
1582ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return 13;
1583ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1584ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1585ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1586ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteBranchTargetField(Instruction* instr,
1587ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                              const char* format) {
15881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(strncmp(format, "BImm", 4) == 0);
1589ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1590ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t offset = 0;
1591ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (format[5]) {
1592ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // BImmUncn - unconditional branch immediate.
1593ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'n': offset = instr->ImmUncondBranch(); break;
1594ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // BImmCond - conditional branch immediate.
1595ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'o': offset = instr->ImmCondBranch(); break;
1596ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // BImmCmpa - compare and branch immediate.
1597ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'm': offset = instr->ImmCmpBranch(); break;
1598ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // BImmTest - test and branch immediate.
1599ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 'e': offset = instr->ImmTestBranch(); break;
16001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1601ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1602ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  offset <<= kInstructionSizeLog2;
1603ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  char sign = '+';
1604ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset < 0) {
1605ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    offset = -offset;
1606ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    sign = '-';
1607ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
16081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
16091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, offset, instr + offset);
1610ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return 8;
1611ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1612ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1613ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1614ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteExtendField(Instruction* instr,
1615ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                        const char* format) {
16161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
16171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->ExtendMode() <= 7);
1618ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(format);
1619ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1620ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
1621ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                "sxtb", "sxth", "sxtw", "sxtx" };
1622ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1623ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
1624ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // registers becomes lsl.
1625ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
1626ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
1627ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl       (instr->ExtendMode() == UXTX))) {
1628ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (instr->ImmExtendShift() > 0) {
1629ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput(", lsl #%d", instr->ImmExtendShift());
1630ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1631ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1632ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
1633ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (instr->ImmExtendShift() > 0) {
1634ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput(" #%d", instr->ImmExtendShift());
1635ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1636ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1637ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return 3;
1638ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1639ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1640ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1641ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
1642ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             const char* format) {
16431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
1644ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
1645ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                "undefined", "undefined", "sxtw", "sxtx" };
1646ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(format);
1647ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1648ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned shift = instr->ImmShiftLS();
1649ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Extend ext = static_cast<Extend>(instr->ExtendMode());
1650ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
1651ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1652ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned rm = instr->Rm();
1653ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (rm == kZeroRegCode) {
1654ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AppendToOutput("%czr", reg_type);
1655ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1656ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AppendToOutput("%c%d", reg_type, rm);
1657ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1658ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1659ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Extend mode UXTX is an alias for shift mode LSL here.
1660ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!((ext == UXTX) && (shift == 0))) {
1661ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AppendToOutput(", %s", extend_mode[ext]);
1662ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (shift != 0) {
1663ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AppendToOutput(" #%d", instr->SizeLS());
1664ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1665ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1666ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return 9;
1667ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1668ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1669ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1670ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint Disassembler::SubstitutePrefetchField(Instruction* instr,
1671ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const char* format) {
16721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(format[0] == 'P');
1673ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  USE(format);
1674ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1675ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int prefetch_mode = instr->PrefetchMode();
1676ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1677ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char* ls = (prefetch_mode & 0x10) ? "st" : "ld";
1678ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int level = (prefetch_mode >> 1) + 1;
1679ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const char* ks = (prefetch_mode & 1) ? "strm" : "keep";
1680ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1681ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  AppendToOutput("p%sl%d%s", ls, level, ks);
1682ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return 6;
1683ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1684ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1685f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlint Disassembler::SubstituteBarrierField(Instruction* instr,
1686f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                                         const char* format) {
16871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(format[0] == 'M');
1688f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  USE(format);
1689f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1690f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  static const char* options[4][4] = {
1691f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    { "sy (0b0000)", "oshld", "oshst", "osh" },
1692f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    { "sy (0b0100)", "nshld", "nshst", "nsh" },
1693f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    { "sy (0b1000)", "ishld", "ishst", "ish" },
1694f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    { "sy (0b1100)", "ld", "st", "sy" }
1695f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  };
1696f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  int domain = instr->ImmBarrierDomain();
1697f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  int type = instr->ImmBarrierType();
1698f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1699f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AppendToOutput("%s", options[domain][type]);
1700f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  return 1;
1701f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1702ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1703ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::ResetOutput() {
1704ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_pos_ = 0;
1705ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_[buffer_pos_] = 0;
1706ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1707ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1708ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1709ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Disassembler::AppendToOutput(const char* format, ...) {
1710ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  va_list args;
1711ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  va_start(args, format);
1712ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args);
1713ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  va_end(args);
1714ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1715ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1716ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1717ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid PrintDisassembler::ProcessOutput(Instruction* instr) {
1718ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  fprintf(stream_, "0x%016" PRIx64 "  %08" PRIx32 "\t\t%s\n",
1719ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          reinterpret_cast<uint64_t>(instr),
1720ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          instr->InstructionBits(),
1721ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          GetOutput());
1722ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1723ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
1724