10cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Copyright 2014, 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
270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#include "vixl/globals.h"
280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#include "vixl/utils.h"
290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#include "vixl/a64/decoder-a64.h"
30ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
31ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl {
3239ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixl
3339ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodeInstruction(const Instruction *instr) {
34578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (instr->Bits(28, 27) == 0) {
35578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    VisitUnallocated(instr);
36578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
37578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    switch (instr->Bits(27, 24)) {
38578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // 0:   PC relative addressing.
39578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x0: DecodePCRelAddressing(instr); break;
40578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
41578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // 1:   Add/sub immediate.
42578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x1: DecodeAddSubImmediate(instr); break;
43578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
44578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // A:   Logical shifted register.
45578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Add/sub with carry.
46578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Conditional compare register.
47578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Conditional compare immediate.
48578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Conditional select.
49578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Data processing 1 source.
50578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Data processing 2 source.
51578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // B:   Add/sub shifted register.
52578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Add/sub extended register.
53578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Data processing 3 source.
54578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0xA:
55578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0xB: DecodeDataProcessing(instr); break;
56578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
57578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // 2:   Logical immediate.
58578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Move wide immediate.
59578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x2: DecodeLogical(instr); break;
60578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
61578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // 3:   Bitfield.
62578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Extract.
63578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x3: DecodeBitfieldExtract(instr); break;
64578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
65578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // 4:   Unconditional branch immediate.
66578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Exception generation.
67578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Compare and branch immediate.
68578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // 5:   Compare and branch immediate.
69578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Conditional branch.
70578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      System.
71578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // 6,7: Unconditional branch.
72578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Test and branch immediate.
73578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x4:
74578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x5:
75578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x6:
76578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x7: DecodeBranchSystemException(instr); break;
77578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
78578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // 8,9: Load/store register pair post-index.
79578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Load register literal.
80578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Load/store register unscaled immediate.
81578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Load/store register immediate post-index.
82578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Load/store register immediate pre-index.
83578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Load/store register offset.
84578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Load/store exclusive.
85578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // C,D: Load/store register pair offset.
86578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Load/store register pair pre-index.
87578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Load/store register unsigned immediate.
88578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Advanced SIMD.
89578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x8:
90578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0x9:
91578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0xC:
92578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0xD: DecodeLoadStore(instr); break;
93578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
94578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // E:   FP fixed point conversion.
95578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      FP integer conversion.
96578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      FP data processing 1 source.
97578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      FP compare.
98578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      FP immediate.
99578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      FP data processing 2 source.
100578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      FP conditional compare.
101578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      FP conditional select.
102578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Advanced SIMD.
103578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // F:   FP data processing 3 source.
104578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //      Advanced SIMD.
105578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0xE:
106578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      case 0xF: DecodeFP(instr); break;
107578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
11239ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixl  visitors_.push_back(new_visitor);
113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
11739ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixl  visitors_.push_front(new_visitor);
118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  DecoderVisitor* registered_visitor) {
123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  std::list<DecoderVisitor*>::iterator it;
124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (it = visitors_.begin(); it != visitors_.end(); it++) {
125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (*it == registered_visitor) {
126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      visitors_.insert(it, new_visitor);
127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return;
128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We reached the end of the list. The last element must be
131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // registered_visitor.
1321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(*it == registered_visitor);
133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  visitors_.insert(it, new_visitor);
134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 DecoderVisitor* registered_visitor) {
139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  std::list<DecoderVisitor*>::iterator it;
140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (it = visitors_.begin(); it != visitors_.end(); it++) {
141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (*it == registered_visitor) {
142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      it++;
143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      visitors_.insert(it, new_visitor);
144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return;
145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We reached the end of the list. The last element must be
148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // registered_visitor.
1491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(*it == registered_visitor);
150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  visitors_.push_back(new_visitor);
151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Decoder::RemoveVisitor(DecoderVisitor* visitor) {
155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  visitors_.remove(visitor);
156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
15939ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodePCRelAddressing(const Instruction* instr) {
1601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->Bits(27, 24) == 0x0);
161578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
162578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // decode.
1631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->Bit(28) == 0x1);
164578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  VisitPCRelAddressing(instr);
165578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
166578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
167578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
16839ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodeBranchSystemException(const Instruction* instr) {
1691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((instr->Bits(27, 24) == 0x4) ||
17090b0414b6c794be58f34813f84c2c06e6a15be91armvixl              (instr->Bits(27, 24) == 0x5) ||
17190b0414b6c794be58f34813f84c2c06e6a15be91armvixl              (instr->Bits(27, 24) == 0x6) ||
17290b0414b6c794be58f34813f84c2c06e6a15be91armvixl              (instr->Bits(27, 24) == 0x7) );
173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
174578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  switch (instr->Bits(31, 29)) {
175578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case 0:
176578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case 4: {
177578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      VisitUnconditionalBranch(instr);
178578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
179578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
180578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case 1:
181578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case 5: {
182578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (instr->Bit(25) == 0) {
183578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitCompareBranch(instr);
184578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else {
185578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitTestBranch(instr);
186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
187578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
188578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
189578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case 2: {
190578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (instr->Bit(25) == 0) {
191578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if ((instr->Bit(24) == 0x1) ||
192578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0x01000010) == 0x00000010)) {
193578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
195578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitConditionalBranch(instr);
196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
197578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else {
198578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitUnallocated(instr);
199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
200578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
201578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
202578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case 6: {
203578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (instr->Bit(25) == 0) {
204578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if (instr->Bit(24) == 0) {
205578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if ((instr->Bits(4, 2) != 0) ||
206578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00E0001D) == 0x00200001) ||
207578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00E0001D) == 0x00400001) ||
208578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00E0001E) == 0x00200002) ||
209578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00E0001E) == 0x00400002) ||
210578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00E0001C) == 0x00600000) ||
211578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00E0001C) == 0x00800000) ||
212578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00E0001F) == 0x00A00000) ||
213578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00C0001C) == 0x00C00000)) {
214578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitUnallocated(instr);
215578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          } else {
216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            VisitException(instr);
217578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          }
218578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        } else {
219578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Bits(23, 22) == 0) {
220578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            const Instr masked_003FF0E0 = instr->Mask(0x003FF0E0);
221578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            if ((instr->Bits(21, 19) == 0x4) ||
222578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (masked_003FF0E0 == 0x00033000) ||
223578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (masked_003FF0E0 == 0x003FF020) ||
224578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (masked_003FF0E0 == 0x003FF060) ||
225578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (masked_003FF0E0 == 0x003FF0E0) ||
226578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x00388000) == 0x00008000) ||
227578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x0038E000) == 0x00000000) ||
228578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x0039E000) == 0x00002000) ||
229578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x003AE000) == 0x00002000) ||
230578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x003CE000) == 0x00042000) ||
231578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x003FFFC0) == 0x000320C0) ||
232578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x003FF100) == 0x00032100) ||
233578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x003FF200) == 0x00032200) ||
234578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x003FF400) == 0x00032400) ||
235578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x003FF800) == 0x00032800) ||
236578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x0038F000) == 0x00005000) ||
237578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x0038E000) == 0x00006000)) {
238578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitUnallocated(instr);
239578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else {
240578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitSystem(instr);
241578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            }
242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          } else {
243578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitUnallocated(instr);
244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
245578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        }
246578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else {
247578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if ((instr->Bit(24) == 0x1) ||
248578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Bits(20, 16) != 0x1F) ||
249578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Bits(15, 10) != 0) ||
250578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Bits(4, 0) != 0) ||
251578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Bits(24, 21) == 0x3) ||
252578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Bits(24, 22) == 0x3)) {
253578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
255ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          VisitUnconditionalBranchToRegister(instr);
256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
258578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
259578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
260578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case 3:
261578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case 7: {
262578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      VisitUnallocated(instr);
263578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
264ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
266ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
267ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
268ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
26939ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodeLoadStore(const Instruction* instr) {
2701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((instr->Bits(27, 24) == 0x8) ||
27190b0414b6c794be58f34813f84c2c06e6a15be91armvixl              (instr->Bits(27, 24) == 0x9) ||
27290b0414b6c794be58f34813f84c2c06e6a15be91armvixl              (instr->Bits(27, 24) == 0xC) ||
27390b0414b6c794be58f34813f84c2c06e6a15be91armvixl              (instr->Bits(27, 24) == 0xD) );
2740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // TODO(all): rearrange the tree to integrate this branch.
2750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((instr->Bit(28) == 0) && (instr->Bit(29) == 0) && (instr->Bit(26) == 1)) {
2760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    DecodeNEONLoadStore(instr);
2770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    return;
2780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (instr->Bit(24) == 0) {
281ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (instr->Bit(28) == 0) {
282ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (instr->Bit(29) == 0) {
283ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        if (instr->Bit(26) == 0) {
28490b0414b6c794be58f34813f84c2c06e6a15be91armvixl          VisitLoadStoreExclusive(instr);
285ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
2860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VIXL_UNREACHABLE();
287ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
288ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
289578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if ((instr->Bits(31, 30) == 0x3) ||
290578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0xC4400000) == 0x40000000)) {
291578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
293578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Bit(23) == 0) {
294578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            if (instr->Mask(0xC4400000) == 0xC0400000) {
295578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitUnallocated(instr);
296578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else {
297578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitLoadStorePairNonTemporal(instr);
298578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            }
299578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          } else {
300578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitLoadStorePairPostIndex(instr);
301578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          }
302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
303ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
304ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
305ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (instr->Bit(29) == 0) {
306578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if (instr->Mask(0xC4000000) == 0xC4000000) {
307578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
308578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        } else {
309578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitLoadLiteral(instr);
310578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        }
311ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
312578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if ((instr->Mask(0x84C00000) == 0x80C00000) ||
313578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0x44800000) == 0x44800000) ||
314578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0x84800000) == 0x84800000)) {
315578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
316578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        } else {
317578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Bit(21) == 0) {
318578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            switch (instr->Bits(11, 10)) {
319578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              case 0: {
320578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitLoadStoreUnscaledOffset(instr);
321578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                break;
322578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
323578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              case 1: {
324578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                if (instr->Mask(0xC4C00000) == 0xC0800000) {
325578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  VisitUnallocated(instr);
326578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                } else {
327578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  VisitLoadStorePostIndex(instr);
328578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                }
329578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                break;
330578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
331578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              case 2: {
332578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                // TODO: VisitLoadStoreRegisterOffsetUnpriv.
333578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnimplemented(instr);
334578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                break;
335578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
336578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              case 3: {
337578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                if (instr->Mask(0xC4C00000) == 0xC0800000) {
338578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  VisitUnallocated(instr);
339578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                } else {
340578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  VisitLoadStorePreIndex(instr);
341578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                }
342578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                break;
343578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            }
345578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          } else {
346578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            if (instr->Bits(11, 10) == 0x2) {
347578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              if (instr->Bit(14) == 0) {
348578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnallocated(instr);
349578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              } else {
350578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitLoadStoreRegisterOffset(instr);
351578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
352578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else {
353578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitUnallocated(instr);
354ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            }
355ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
356ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
357ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
359ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
360ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (instr->Bit(28) == 0) {
361578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (instr->Bit(29) == 0) {
362578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitUnallocated(instr);
363ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
364578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if ((instr->Bits(31, 30) == 0x3) ||
365578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0xC4400000) == 0x40000000)) {
366578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
367578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        } else {
368578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Bit(23) == 0) {
369578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitLoadStorePairOffset(instr);
370578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          } else {
371578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitLoadStorePairPreIndex(instr);
372578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          }
373578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        }
374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
375ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
376578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (instr->Bit(29) == 0) {
377578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitUnallocated(instr);
378578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else {
379578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if ((instr->Mask(0x84C00000) == 0x80C00000) ||
380578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0x44800000) == 0x44800000) ||
381578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0x84800000) == 0x84800000)) {
382578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
383578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        } else {
384578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitLoadStoreUnsignedOffset(instr);
385578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        }
386578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      }
387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
39239ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodeLogical(const Instruction* instr) {
3931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->Bits(27, 24) == 0x2);
394ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
395578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (instr->Mask(0x80400000) == 0x00400000) {
396578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    VisitUnallocated(instr);
397ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
398578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    if (instr->Bit(23) == 0) {
399578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      VisitLogicalImmediate(instr);
400578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    } else {
401578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (instr->Bits(30, 29) == 0x1) {
402578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitUnallocated(instr);
403578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else {
404578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitMoveWideImmediate(instr);
405578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      }
406578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
41139ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodeBitfieldExtract(const Instruction* instr) {
4121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->Bits(27, 24) == 0x3);
413ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
414578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if ((instr->Mask(0x80400000) == 0x80000000) ||
415578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      (instr->Mask(0x80400000) == 0x00400000) ||
416578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      (instr->Mask(0x80008000) == 0x00008000)) {
417578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    VisitUnallocated(instr);
418578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else if (instr->Bit(23) == 0) {
419578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    if ((instr->Mask(0x80200000) == 0x00200000) ||
420578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        (instr->Mask(0x60000000) == 0x60000000)) {
421578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      VisitUnallocated(instr);
422578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    } else {
423578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      VisitBitfield(instr);
424578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
425ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
426578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    if ((instr->Mask(0x60200000) == 0x00200000) ||
427578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        (instr->Mask(0x60000000) != 0x00000000)) {
428578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      VisitUnallocated(instr);
429578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    } else {
430578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      VisitExtract(instr);
431578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
432ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
433ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
434ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
435ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
43639ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodeAddSubImmediate(const Instruction* instr) {
4371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->Bits(27, 24) == 0x1);
438578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (instr->Bit(23) == 1) {
439578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    VisitUnallocated(instr);
440578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
441578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    VisitAddSubImmediate(instr);
442578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
443578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
444578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
445578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
44639ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodeDataProcessing(const Instruction* instr) {
4471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((instr->Bits(27, 24) == 0xA) ||
4481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              (instr->Bits(27, 24) == 0xB));
449ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
450578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (instr->Bit(24) == 0) {
451ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (instr->Bit(28) == 0) {
452578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if (instr->Mask(0x80008000) == 0x00008000) {
453578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitUnallocated(instr);
454578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else {
455578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitLogicalShifted(instr);
456578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      }
457ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (instr->Bits(23, 21)) {
459ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case 0: {
460578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Mask(0x0000FC00) != 0) {
461578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitUnallocated(instr);
462578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          } else {
463578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitAddSubWithCarry(instr);
464578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          }
465ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
466ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
467ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case 2: {
468578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if ((instr->Bit(29) == 0) ||
469578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              (instr->Mask(0x00000410) != 0)) {
470578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitUnallocated(instr);
471ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          } else {
472578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            if (instr->Bit(11) == 0) {
473578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitConditionalCompareRegister(instr);
474578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else {
475578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitConditionalCompareImmediate(instr);
476578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            }
477ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
478ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
479ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
480ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case 4: {
481578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Mask(0x20000800) != 0x00000000) {
482578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitUnallocated(instr);
483578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          } else {
484578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitConditionalSelect(instr);
485578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          }
486ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
487ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
488ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case 6: {
489578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Bit(29) == 0x1) {
490578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitUnallocated(instr);
4910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VIXL_FALLTHROUGH();
492ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          } else {
493578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            if (instr->Bit(30) == 0) {
494578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              if ((instr->Bit(15) == 0x1) ||
495578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Bits(15, 11) == 0) ||
496578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Bits(15, 12) == 0x1) ||
497578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Bits(15, 12) == 0x3) ||
498578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Bits(15, 13) == 0x3) ||
499578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x8000EC00) == 0x00004C00) ||
500578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x8000E800) == 0x80004000) ||
501578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x8000E400) == 0x80004000)) {
502578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnallocated(instr);
503578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              } else {
504578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitDataProcessing2Source(instr);
505578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
506578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else {
507578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              if ((instr->Bit(13) == 1) ||
508578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Bits(20, 16) != 0) ||
509578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Bits(15, 14) != 0) ||
510578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA01FFC00) == 0x00000C00) ||
511578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x201FF800) == 0x00001800)) {
512578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnallocated(instr);
513578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              } else {
514578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitDataProcessing1Source(instr);
515578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
516578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            }
517578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            break;
518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
519ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
520578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        case 1:
521578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        case 3:
522578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        case 5:
523578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        case 7: VisitUnallocated(instr); break;
524ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
525ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
526ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
527ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (instr->Bit(28) == 0) {
528578645f14e122d2b87d907e298cda7e7d0babf1farmvixl     if (instr->Bit(21) == 0) {
529578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if ((instr->Bits(23, 22) == 0x3) ||
530578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0x80008000) == 0x00008000)) {
531578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
532578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        } else {
533578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitAddSubShifted(instr);
534578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        }
535ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
536578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if ((instr->Mask(0x00C00000) != 0x00000000) ||
537578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0x00001400) == 0x00001400) ||
538578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            (instr->Mask(0x00001800) == 0x00001800)) {
539578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitUnallocated(instr);
540578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        } else {
541578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          VisitAddSubExtended(instr);
542578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        }
543ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
544ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
545578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      if ((instr->Bit(30) == 0x1) ||
546578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          (instr->Bits(30, 29) == 0x1) ||
547578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          (instr->Mask(0xE0600000) == 0x00200000) ||
548578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          (instr->Mask(0xE0608000) == 0x00400000) ||
549578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          (instr->Mask(0x60608000) == 0x00408000) ||
550578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          (instr->Mask(0x60E00000) == 0x00E00000) ||
551578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          (instr->Mask(0x60E00000) == 0x00800000) ||
552578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          (instr->Mask(0x60E00000) == 0x00600000)) {
553578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitUnallocated(instr);
554578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      } else {
555578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        VisitDataProcessing3Source(instr);
556578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      }
557ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
558ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
559ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
560ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
561ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
56239ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixlvoid Decoder::DecodeFP(const Instruction* instr) {
5631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((instr->Bits(27, 24) == 0xE) ||
5641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              (instr->Bits(27, 24) == 0xF));
565578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (instr->Bit(28) == 0) {
5660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    DecodeNEONVectorDataProcessing(instr);
567578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
5680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (instr->Bits(31, 30) == 0x3) {
569578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      VisitUnallocated(instr);
5700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else if (instr->Bits(31, 30) == 0x1) {
5710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      DecodeNEONScalarDataProcessing(instr);
572ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
5730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Bit(29) == 0) {
574578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        if (instr->Bit(24) == 0) {
575578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Bit(21) == 0) {
576578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            if ((instr->Bit(23) == 1) ||
577578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Bit(18) == 1) ||
578578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x80008000) == 0x00000000) ||
579578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x000E0000) == 0x00000000) ||
580578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x000E0000) == 0x000A0000) ||
581578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x00160000) == 0x00000000) ||
582578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                (instr->Mask(0x00160000) == 0x00120000)) {
583578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitUnallocated(instr);
584578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else {
585578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitFPFixedPointConvert(instr);
586578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            }
587578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          } else {
588578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            if (instr->Bits(15, 10) == 32) {
589578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              VisitUnallocated(instr);
590578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else if (instr->Bits(15, 10) == 0) {
591578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              if ((instr->Bits(23, 22) == 0x3) ||
592578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x000E0000) == 0x000A0000) ||
593578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x000E0000) == 0x000C0000) ||
594578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x00160000) == 0x00120000) ||
595578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x00160000) == 0x00140000) ||
596578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x20C40000) == 0x00800000) ||
597578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x20C60000) == 0x00840000) ||
598578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0C60000) == 0x80060000) ||
599578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0C60000) == 0x00860000) ||
600578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0C60000) == 0x00460000) ||
601578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0CE0000) == 0x80860000) ||
602578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0CE0000) == 0x804E0000) ||
603578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0CE0000) == 0x000E0000) ||
604578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0D60000) == 0x00160000) ||
605578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0D60000) == 0x80560000) ||
606578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0D60000) == 0x80960000)) {
607578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnallocated(instr);
608578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              } else {
609578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitFPIntegerConvert(instr);
610578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
611578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else if (instr->Bits(14, 10) == 16) {
612578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              const Instr masked_A0DF8000 = instr->Mask(0xA0DF8000);
613578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              if ((instr->Mask(0x80180000) != 0) ||
614578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (masked_A0DF8000 == 0x00020000) ||
615578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (masked_A0DF8000 == 0x00030000) ||
616578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (masked_A0DF8000 == 0x00068000) ||
617578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (masked_A0DF8000 == 0x00428000) ||
618578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (masked_A0DF8000 == 0x00430000) ||
619578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (masked_A0DF8000 == 0x00468000) ||
620578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0D80000) == 0x00800000) ||
621578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0DE0000) == 0x00C00000) ||
622578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0DF0000) == 0x00C30000) ||
623578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0xA0DC0000) == 0x00C40000)) {
624578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnallocated(instr);
625578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              } else {
626578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitFPDataProcessing1Source(instr);
627578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
628578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else if (instr->Bits(13, 10) == 8) {
629578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              if ((instr->Bits(15, 14) != 0) ||
630578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Bits(2, 0) != 0) ||
631578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x80800000) != 0x00000000)) {
632578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnallocated(instr);
633578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              } else {
634578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitFPCompare(instr);
635578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
636578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else if (instr->Bits(12, 10) == 4) {
637578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              if ((instr->Bits(9, 5) != 0) ||
638578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  (instr->Mask(0x80800000) != 0x00000000)) {
639578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnallocated(instr);
640578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              } else {
641578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitFPImmediate(instr);
642578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
643578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            } else {
644578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              if (instr->Mask(0x80800000) != 0x00000000) {
645578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                VisitUnallocated(instr);
646578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              } else {
647578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                switch (instr->Bits(11, 10)) {
648578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  case 1: {
649578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                    VisitFPConditionalCompare(instr);
650578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                    break;
651578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  }
652578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  case 2: {
653578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                    if ((instr->Bits(15, 14) == 0x3) ||
654578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                        (instr->Mask(0x00009000) == 0x00009000) ||
655578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                        (instr->Mask(0x0000A000) == 0x0000A000)) {
656578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                      VisitUnallocated(instr);
657578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                    } else {
658578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                      VisitFPDataProcessing2Source(instr);
659578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                    }
660578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                    break;
661578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  }
662578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  case 3: {
663578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                    VisitFPConditionalSelect(instr);
664578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                    break;
665578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                  }
6661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                  default: VIXL_UNREACHABLE();
667578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                }
668578645f14e122d2b87d907e298cda7e7d0babf1farmvixl              }
669578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            }
670ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
671578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        } else {
672578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          // Bit 30 == 1 has been handled earlier.
6731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          VIXL_ASSERT(instr->Bit(30) == 0);
674578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          if (instr->Mask(0xA0800000) != 0) {
675578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitUnallocated(instr);
676578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          } else {
677578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            VisitFPDataProcessing3Source(instr);
678ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          }
679ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
6800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
6810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitUnallocated(instr);
682ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
683ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
684ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
685ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
686ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
687578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
6880cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Decoder::DecodeNEONLoadStore(const Instruction* instr) {
6891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->Bits(29, 25) == 0x6);
6900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Bit(31) == 0) {
6910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if ((instr->Bit(24) == 0) && (instr->Bit(21) == 1)) {
6920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VisitUnallocated(instr);
6930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return;
6940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
6950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (instr->Bit(23) == 0) {
6970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Bits(20, 16) == 0) {
6980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Bit(24) == 0) {
6990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VisitNEONLoadStoreMultiStruct(instr);
7000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
7010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VisitNEONLoadStoreSingleStruct(instr);
7020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
7030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
7040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitUnallocated(instr);
7050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
7060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
7070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Bit(24) == 0) {
7080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitNEONLoadStoreMultiStructPostIndex(instr);
7090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
7100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitNEONLoadStoreSingleStructPostIndex(instr);
7110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
7120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
7130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
7140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VisitUnallocated(instr);
7150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
7160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
7170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7190cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Decoder::DecodeNEONVectorDataProcessing(const Instruction* instr) {
7200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(instr->Bits(28, 25) == 0x7);
7210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Bit(31) == 0) {
7220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (instr->Bit(24) == 0) {
7230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Bit(21) == 0) {
7240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Bit(15) == 0) {
7250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          if (instr->Bit(10) == 0) {
7260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            if (instr->Bit(29) == 0) {
7270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              if (instr->Bit(11) == 0) {
7280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                VisitNEONTable(instr);
7290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              } else {
7300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                VisitNEONPerm(instr);
7310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              }
7320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            } else {
7330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              VisitNEONExtract(instr);
7340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            }
7350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          } else {
7360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            if (instr->Bits(23, 22) == 0) {
7370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              VisitNEONCopy(instr);
7380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            } else {
7390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              VisitUnallocated(instr);
7400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            }
7410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          }
7420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
7430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VisitUnallocated(instr);
7440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
7450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
7460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Bit(10) == 0) {
7470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          if (instr->Bit(11) == 0) {
7480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VisitNEON3Different(instr);
7490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          } else {
7500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            if (instr->Bits(18, 17) == 0) {
7510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              if (instr->Bit(20) == 0) {
7520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                if (instr->Bit(19) == 0) {
7530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                  VisitNEON2RegMisc(instr);
7540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                } else {
7550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                  if (instr->Bits(30, 29) == 0x2) {
7560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                    VisitCryptoAES(instr);
7570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                  } else {
7580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                    VisitUnallocated(instr);
7590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                  }
7600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                }
7610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              } else {
7620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                if (instr->Bit(19) == 0) {
7630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                  VisitNEONAcrossLanes(instr);
7640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                } else {
7650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                  VisitUnallocated(instr);
7660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                }
7670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              }
7680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            } else {
7690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              VisitUnallocated(instr);
7700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            }
7710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          }
7720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
7730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VisitNEON3Same(instr);
7740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
7750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
7760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
7770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Bit(10) == 0) {
7780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitNEONByIndexedElement(instr);
7790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
7800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Bit(23) == 0) {
7810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          if (instr->Bits(22, 19) == 0) {
7820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VisitNEONModifiedImmediate(instr);
7830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          } else {
7840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VisitNEONShiftImmediate(instr);
7850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          }
7860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
7870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VisitUnallocated(instr);
7880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
7890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
7900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
7910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
7920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VisitUnallocated(instr);
7930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
794578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
795578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
796578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
7970cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Decoder::DecodeNEONScalarDataProcessing(const Instruction* instr) {
7980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(instr->Bits(28, 25) == 0xF);
7990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Bit(24) == 0) {
8000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (instr->Bit(21) == 0) {
8010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Bit(15) == 0) {
8020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Bit(10) == 0) {
8030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          if (instr->Bit(29) == 0) {
8040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            if (instr->Bit(11) == 0) {
8050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              VisitCrypto3RegSHA(instr);
8060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            } else {
8070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              VisitUnallocated(instr);
8080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            }
8090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          } else {
8100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VisitUnallocated(instr);
8110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          }
8120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
8130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          if (instr->Bits(23, 22) == 0) {
8140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VisitNEONScalarCopy(instr);
8150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          } else {
8160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VisitUnallocated(instr);
8170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          }
8180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
8190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
8200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitUnallocated(instr);
8210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
8220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
8230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Bit(10) == 0) {
8240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Bit(11) == 0) {
8250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VisitNEONScalar3Diff(instr);
8260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
8270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          if (instr->Bits(18, 17) == 0) {
8280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            if (instr->Bit(20) == 0) {
8290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              if (instr->Bit(19) == 0) {
8300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                VisitNEONScalar2RegMisc(instr);
8310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              } else {
8320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                if (instr->Bit(29) == 0) {
8330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                  VisitCrypto2RegSHA(instr);
8340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                } else {
8350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                  VisitUnallocated(instr);
8360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                }
8370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              }
8380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            } else {
8390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              if (instr->Bit(19) == 0) {
8400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                VisitNEONScalarPairwise(instr);
8410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              } else {
8420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                VisitUnallocated(instr);
8430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              }
8440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            }
8450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          } else {
8460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VisitUnallocated(instr);
8470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          }
8480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
8490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
8500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitNEONScalar3Same(instr);
8510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
8520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
8530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
8540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (instr->Bit(10) == 0) {
8550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VisitNEONScalarByIndexedElement(instr);
8560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
8570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Bit(23) == 0) {
8580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitNEONScalarShiftImmediate(instr);
8590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
8600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VisitUnallocated(instr);
8610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
8620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
8630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
864578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
865578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
866578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#define DEFINE_VISITOR_CALLERS(A)                                              \
86839ee1f4b336c7e6b25be0df6375c18dcbd577c09armvixl  void Decoder::Visit##A(const Instruction *instr) {                           \
8691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(instr->Mask(A##FMask) == A##Fixed);                            \
870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    std::list<DecoderVisitor*>::iterator it;                                   \
871ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    for (it = visitors_.begin(); it != visitors_.end(); it++) {                \
872ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (*it)->Visit##A(instr);                                                  \
873ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }                                                                          \
874ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
875ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlVISITOR_LIST(DEFINE_VISITOR_CALLERS)
876ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#undef DEFINE_VISITOR_CALLERS
877ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
878