1// Copyright 2014, ARM Limited
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7//   * Redistributions of source code must retain the above copyright notice,
8//     this list of conditions and the following disclaimer.
9//   * Redistributions in binary form must reproduce the above copyright notice,
10//     this list of conditions and the following disclaimer in the documentation
11//     and/or other materials provided with the distribution.
12//   * Neither the name of ARM Limited nor the names of its contributors may be
13//     used to endorse or promote products derived from this software without
14//     specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#include "vixl/globals.h"
28#include "vixl/utils.h"
29#include "vixl/a64/decoder-a64.h"
30
31namespace vixl {
32
33void Decoder::DecodeInstruction(const Instruction *instr) {
34  if (instr->Bits(28, 27) == 0) {
35    VisitUnallocated(instr);
36  } else {
37    switch (instr->Bits(27, 24)) {
38      // 0:   PC relative addressing.
39      case 0x0: DecodePCRelAddressing(instr); break;
40
41      // 1:   Add/sub immediate.
42      case 0x1: DecodeAddSubImmediate(instr); break;
43
44      // A:   Logical shifted register.
45      //      Add/sub with carry.
46      //      Conditional compare register.
47      //      Conditional compare immediate.
48      //      Conditional select.
49      //      Data processing 1 source.
50      //      Data processing 2 source.
51      // B:   Add/sub shifted register.
52      //      Add/sub extended register.
53      //      Data processing 3 source.
54      case 0xA:
55      case 0xB: DecodeDataProcessing(instr); break;
56
57      // 2:   Logical immediate.
58      //      Move wide immediate.
59      case 0x2: DecodeLogical(instr); break;
60
61      // 3:   Bitfield.
62      //      Extract.
63      case 0x3: DecodeBitfieldExtract(instr); break;
64
65      // 4:   Unconditional branch immediate.
66      //      Exception generation.
67      //      Compare and branch immediate.
68      // 5:   Compare and branch immediate.
69      //      Conditional branch.
70      //      System.
71      // 6,7: Unconditional branch.
72      //      Test and branch immediate.
73      case 0x4:
74      case 0x5:
75      case 0x6:
76      case 0x7: DecodeBranchSystemException(instr); break;
77
78      // 8,9: Load/store register pair post-index.
79      //      Load register literal.
80      //      Load/store register unscaled immediate.
81      //      Load/store register immediate post-index.
82      //      Load/store register immediate pre-index.
83      //      Load/store register offset.
84      //      Load/store exclusive.
85      // C,D: Load/store register pair offset.
86      //      Load/store register pair pre-index.
87      //      Load/store register unsigned immediate.
88      //      Advanced SIMD.
89      case 0x8:
90      case 0x9:
91      case 0xC:
92      case 0xD: DecodeLoadStore(instr); break;
93
94      // E:   FP fixed point conversion.
95      //      FP integer conversion.
96      //      FP data processing 1 source.
97      //      FP compare.
98      //      FP immediate.
99      //      FP data processing 2 source.
100      //      FP conditional compare.
101      //      FP conditional select.
102      //      Advanced SIMD.
103      // F:   FP data processing 3 source.
104      //      Advanced SIMD.
105      case 0xE:
106      case 0xF: DecodeFP(instr); break;
107    }
108  }
109}
110
111void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
112  visitors_.push_back(new_visitor);
113}
114
115
116void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
117  visitors_.push_front(new_visitor);
118}
119
120
121void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
122                                  DecoderVisitor* registered_visitor) {
123  std::list<DecoderVisitor*>::iterator it;
124  for (it = visitors_.begin(); it != visitors_.end(); it++) {
125    if (*it == registered_visitor) {
126      visitors_.insert(it, new_visitor);
127      return;
128    }
129  }
130  // We reached the end of the list. The last element must be
131  // registered_visitor.
132  VIXL_ASSERT(*it == registered_visitor);
133  visitors_.insert(it, new_visitor);
134}
135
136
137void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
138                                 DecoderVisitor* registered_visitor) {
139  std::list<DecoderVisitor*>::iterator it;
140  for (it = visitors_.begin(); it != visitors_.end(); it++) {
141    if (*it == registered_visitor) {
142      it++;
143      visitors_.insert(it, new_visitor);
144      return;
145    }
146  }
147  // We reached the end of the list. The last element must be
148  // registered_visitor.
149  VIXL_ASSERT(*it == registered_visitor);
150  visitors_.push_back(new_visitor);
151}
152
153
154void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
155  visitors_.remove(visitor);
156}
157
158
159void Decoder::DecodePCRelAddressing(const Instruction* instr) {
160  VIXL_ASSERT(instr->Bits(27, 24) == 0x0);
161  // We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
162  // decode.
163  VIXL_ASSERT(instr->Bit(28) == 0x1);
164  VisitPCRelAddressing(instr);
165}
166
167
168void Decoder::DecodeBranchSystemException(const Instruction* instr) {
169  VIXL_ASSERT((instr->Bits(27, 24) == 0x4) ||
170              (instr->Bits(27, 24) == 0x5) ||
171              (instr->Bits(27, 24) == 0x6) ||
172              (instr->Bits(27, 24) == 0x7) );
173
174  switch (instr->Bits(31, 29)) {
175    case 0:
176    case 4: {
177      VisitUnconditionalBranch(instr);
178      break;
179    }
180    case 1:
181    case 5: {
182      if (instr->Bit(25) == 0) {
183        VisitCompareBranch(instr);
184      } else {
185        VisitTestBranch(instr);
186      }
187      break;
188    }
189    case 2: {
190      if (instr->Bit(25) == 0) {
191        if ((instr->Bit(24) == 0x1) ||
192            (instr->Mask(0x01000010) == 0x00000010)) {
193          VisitUnallocated(instr);
194        } else {
195          VisitConditionalBranch(instr);
196        }
197      } else {
198        VisitUnallocated(instr);
199      }
200      break;
201    }
202    case 6: {
203      if (instr->Bit(25) == 0) {
204        if (instr->Bit(24) == 0) {
205          if ((instr->Bits(4, 2) != 0) ||
206              (instr->Mask(0x00E0001D) == 0x00200001) ||
207              (instr->Mask(0x00E0001D) == 0x00400001) ||
208              (instr->Mask(0x00E0001E) == 0x00200002) ||
209              (instr->Mask(0x00E0001E) == 0x00400002) ||
210              (instr->Mask(0x00E0001C) == 0x00600000) ||
211              (instr->Mask(0x00E0001C) == 0x00800000) ||
212              (instr->Mask(0x00E0001F) == 0x00A00000) ||
213              (instr->Mask(0x00C0001C) == 0x00C00000)) {
214            VisitUnallocated(instr);
215          } else {
216            VisitException(instr);
217          }
218        } else {
219          if (instr->Bits(23, 22) == 0) {
220            const Instr masked_003FF0E0 = instr->Mask(0x003FF0E0);
221            if ((instr->Bits(21, 19) == 0x4) ||
222                (masked_003FF0E0 == 0x00033000) ||
223                (masked_003FF0E0 == 0x003FF020) ||
224                (masked_003FF0E0 == 0x003FF060) ||
225                (masked_003FF0E0 == 0x003FF0E0) ||
226                (instr->Mask(0x00388000) == 0x00008000) ||
227                (instr->Mask(0x0038E000) == 0x00000000) ||
228                (instr->Mask(0x0039E000) == 0x00002000) ||
229                (instr->Mask(0x003AE000) == 0x00002000) ||
230                (instr->Mask(0x003CE000) == 0x00042000) ||
231                (instr->Mask(0x003FFFC0) == 0x000320C0) ||
232                (instr->Mask(0x003FF100) == 0x00032100) ||
233                (instr->Mask(0x003FF200) == 0x00032200) ||
234                (instr->Mask(0x003FF400) == 0x00032400) ||
235                (instr->Mask(0x003FF800) == 0x00032800) ||
236                (instr->Mask(0x0038F000) == 0x00005000) ||
237                (instr->Mask(0x0038E000) == 0x00006000)) {
238              VisitUnallocated(instr);
239            } else {
240              VisitSystem(instr);
241            }
242          } else {
243            VisitUnallocated(instr);
244          }
245        }
246      } else {
247        if ((instr->Bit(24) == 0x1) ||
248            (instr->Bits(20, 16) != 0x1F) ||
249            (instr->Bits(15, 10) != 0) ||
250            (instr->Bits(4, 0) != 0) ||
251            (instr->Bits(24, 21) == 0x3) ||
252            (instr->Bits(24, 22) == 0x3)) {
253          VisitUnallocated(instr);
254        } else {
255          VisitUnconditionalBranchToRegister(instr);
256        }
257      }
258      break;
259    }
260    case 3:
261    case 7: {
262      VisitUnallocated(instr);
263      break;
264    }
265  }
266}
267
268
269void Decoder::DecodeLoadStore(const Instruction* instr) {
270  VIXL_ASSERT((instr->Bits(27, 24) == 0x8) ||
271              (instr->Bits(27, 24) == 0x9) ||
272              (instr->Bits(27, 24) == 0xC) ||
273              (instr->Bits(27, 24) == 0xD) );
274  // TODO(all): rearrange the tree to integrate this branch.
275  if ((instr->Bit(28) == 0) && (instr->Bit(29) == 0) && (instr->Bit(26) == 1)) {
276    DecodeNEONLoadStore(instr);
277    return;
278  }
279
280  if (instr->Bit(24) == 0) {
281    if (instr->Bit(28) == 0) {
282      if (instr->Bit(29) == 0) {
283        if (instr->Bit(26) == 0) {
284          VisitLoadStoreExclusive(instr);
285        } else {
286          VIXL_UNREACHABLE();
287        }
288      } else {
289        if ((instr->Bits(31, 30) == 0x3) ||
290            (instr->Mask(0xC4400000) == 0x40000000)) {
291          VisitUnallocated(instr);
292        } else {
293          if (instr->Bit(23) == 0) {
294            if (instr->Mask(0xC4400000) == 0xC0400000) {
295              VisitUnallocated(instr);
296            } else {
297              VisitLoadStorePairNonTemporal(instr);
298            }
299          } else {
300            VisitLoadStorePairPostIndex(instr);
301          }
302        }
303      }
304    } else {
305      if (instr->Bit(29) == 0) {
306        if (instr->Mask(0xC4000000) == 0xC4000000) {
307          VisitUnallocated(instr);
308        } else {
309          VisitLoadLiteral(instr);
310        }
311      } else {
312        if ((instr->Mask(0x84C00000) == 0x80C00000) ||
313            (instr->Mask(0x44800000) == 0x44800000) ||
314            (instr->Mask(0x84800000) == 0x84800000)) {
315          VisitUnallocated(instr);
316        } else {
317          if (instr->Bit(21) == 0) {
318            switch (instr->Bits(11, 10)) {
319              case 0: {
320                VisitLoadStoreUnscaledOffset(instr);
321                break;
322              }
323              case 1: {
324                if (instr->Mask(0xC4C00000) == 0xC0800000) {
325                  VisitUnallocated(instr);
326                } else {
327                  VisitLoadStorePostIndex(instr);
328                }
329                break;
330              }
331              case 2: {
332                // TODO: VisitLoadStoreRegisterOffsetUnpriv.
333                VisitUnimplemented(instr);
334                break;
335              }
336              case 3: {
337                if (instr->Mask(0xC4C00000) == 0xC0800000) {
338                  VisitUnallocated(instr);
339                } else {
340                  VisitLoadStorePreIndex(instr);
341                }
342                break;
343              }
344            }
345          } else {
346            if (instr->Bits(11, 10) == 0x2) {
347              if (instr->Bit(14) == 0) {
348                VisitUnallocated(instr);
349              } else {
350                VisitLoadStoreRegisterOffset(instr);
351              }
352            } else {
353              VisitUnallocated(instr);
354            }
355          }
356        }
357      }
358    }
359  } else {
360    if (instr->Bit(28) == 0) {
361      if (instr->Bit(29) == 0) {
362        VisitUnallocated(instr);
363      } else {
364        if ((instr->Bits(31, 30) == 0x3) ||
365            (instr->Mask(0xC4400000) == 0x40000000)) {
366          VisitUnallocated(instr);
367        } else {
368          if (instr->Bit(23) == 0) {
369            VisitLoadStorePairOffset(instr);
370          } else {
371            VisitLoadStorePairPreIndex(instr);
372          }
373        }
374      }
375    } else {
376      if (instr->Bit(29) == 0) {
377        VisitUnallocated(instr);
378      } else {
379        if ((instr->Mask(0x84C00000) == 0x80C00000) ||
380            (instr->Mask(0x44800000) == 0x44800000) ||
381            (instr->Mask(0x84800000) == 0x84800000)) {
382          VisitUnallocated(instr);
383        } else {
384          VisitLoadStoreUnsignedOffset(instr);
385        }
386      }
387    }
388  }
389}
390
391
392void Decoder::DecodeLogical(const Instruction* instr) {
393  VIXL_ASSERT(instr->Bits(27, 24) == 0x2);
394
395  if (instr->Mask(0x80400000) == 0x00400000) {
396    VisitUnallocated(instr);
397  } else {
398    if (instr->Bit(23) == 0) {
399      VisitLogicalImmediate(instr);
400    } else {
401      if (instr->Bits(30, 29) == 0x1) {
402        VisitUnallocated(instr);
403      } else {
404        VisitMoveWideImmediate(instr);
405      }
406    }
407  }
408}
409
410
411void Decoder::DecodeBitfieldExtract(const Instruction* instr) {
412  VIXL_ASSERT(instr->Bits(27, 24) == 0x3);
413
414  if ((instr->Mask(0x80400000) == 0x80000000) ||
415      (instr->Mask(0x80400000) == 0x00400000) ||
416      (instr->Mask(0x80008000) == 0x00008000)) {
417    VisitUnallocated(instr);
418  } else if (instr->Bit(23) == 0) {
419    if ((instr->Mask(0x80200000) == 0x00200000) ||
420        (instr->Mask(0x60000000) == 0x60000000)) {
421      VisitUnallocated(instr);
422    } else {
423      VisitBitfield(instr);
424    }
425  } else {
426    if ((instr->Mask(0x60200000) == 0x00200000) ||
427        (instr->Mask(0x60000000) != 0x00000000)) {
428      VisitUnallocated(instr);
429    } else {
430      VisitExtract(instr);
431    }
432  }
433}
434
435
436void Decoder::DecodeAddSubImmediate(const Instruction* instr) {
437  VIXL_ASSERT(instr->Bits(27, 24) == 0x1);
438  if (instr->Bit(23) == 1) {
439    VisitUnallocated(instr);
440  } else {
441    VisitAddSubImmediate(instr);
442  }
443}
444
445
446void Decoder::DecodeDataProcessing(const Instruction* instr) {
447  VIXL_ASSERT((instr->Bits(27, 24) == 0xA) ||
448              (instr->Bits(27, 24) == 0xB));
449
450  if (instr->Bit(24) == 0) {
451    if (instr->Bit(28) == 0) {
452      if (instr->Mask(0x80008000) == 0x00008000) {
453        VisitUnallocated(instr);
454      } else {
455        VisitLogicalShifted(instr);
456      }
457    } else {
458      switch (instr->Bits(23, 21)) {
459        case 0: {
460          if (instr->Mask(0x0000FC00) != 0) {
461            VisitUnallocated(instr);
462          } else {
463            VisitAddSubWithCarry(instr);
464          }
465          break;
466        }
467        case 2: {
468          if ((instr->Bit(29) == 0) ||
469              (instr->Mask(0x00000410) != 0)) {
470            VisitUnallocated(instr);
471          } else {
472            if (instr->Bit(11) == 0) {
473              VisitConditionalCompareRegister(instr);
474            } else {
475              VisitConditionalCompareImmediate(instr);
476            }
477          }
478          break;
479        }
480        case 4: {
481          if (instr->Mask(0x20000800) != 0x00000000) {
482            VisitUnallocated(instr);
483          } else {
484            VisitConditionalSelect(instr);
485          }
486          break;
487        }
488        case 6: {
489          if (instr->Bit(29) == 0x1) {
490            VisitUnallocated(instr);
491            VIXL_FALLTHROUGH();
492          } else {
493            if (instr->Bit(30) == 0) {
494              if ((instr->Bit(15) == 0x1) ||
495                  (instr->Bits(15, 11) == 0) ||
496                  (instr->Bits(15, 12) == 0x1) ||
497                  (instr->Bits(15, 12) == 0x3) ||
498                  (instr->Bits(15, 13) == 0x3) ||
499                  (instr->Mask(0x8000EC00) == 0x00004C00) ||
500                  (instr->Mask(0x8000E800) == 0x80004000) ||
501                  (instr->Mask(0x8000E400) == 0x80004000)) {
502                VisitUnallocated(instr);
503              } else {
504                VisitDataProcessing2Source(instr);
505              }
506            } else {
507              if ((instr->Bit(13) == 1) ||
508                  (instr->Bits(20, 16) != 0) ||
509                  (instr->Bits(15, 14) != 0) ||
510                  (instr->Mask(0xA01FFC00) == 0x00000C00) ||
511                  (instr->Mask(0x201FF800) == 0x00001800)) {
512                VisitUnallocated(instr);
513              } else {
514                VisitDataProcessing1Source(instr);
515              }
516            }
517            break;
518          }
519        }
520        case 1:
521        case 3:
522        case 5:
523        case 7: VisitUnallocated(instr); break;
524      }
525    }
526  } else {
527    if (instr->Bit(28) == 0) {
528     if (instr->Bit(21) == 0) {
529        if ((instr->Bits(23, 22) == 0x3) ||
530            (instr->Mask(0x80008000) == 0x00008000)) {
531          VisitUnallocated(instr);
532        } else {
533          VisitAddSubShifted(instr);
534        }
535      } else {
536        if ((instr->Mask(0x00C00000) != 0x00000000) ||
537            (instr->Mask(0x00001400) == 0x00001400) ||
538            (instr->Mask(0x00001800) == 0x00001800)) {
539          VisitUnallocated(instr);
540        } else {
541          VisitAddSubExtended(instr);
542        }
543      }
544    } else {
545      if ((instr->Bit(30) == 0x1) ||
546          (instr->Bits(30, 29) == 0x1) ||
547          (instr->Mask(0xE0600000) == 0x00200000) ||
548          (instr->Mask(0xE0608000) == 0x00400000) ||
549          (instr->Mask(0x60608000) == 0x00408000) ||
550          (instr->Mask(0x60E00000) == 0x00E00000) ||
551          (instr->Mask(0x60E00000) == 0x00800000) ||
552          (instr->Mask(0x60E00000) == 0x00600000)) {
553        VisitUnallocated(instr);
554      } else {
555        VisitDataProcessing3Source(instr);
556      }
557    }
558  }
559}
560
561
562void Decoder::DecodeFP(const Instruction* instr) {
563  VIXL_ASSERT((instr->Bits(27, 24) == 0xE) ||
564              (instr->Bits(27, 24) == 0xF));
565  if (instr->Bit(28) == 0) {
566    DecodeNEONVectorDataProcessing(instr);
567  } else {
568    if (instr->Bits(31, 30) == 0x3) {
569      VisitUnallocated(instr);
570    } else if (instr->Bits(31, 30) == 0x1) {
571      DecodeNEONScalarDataProcessing(instr);
572    } else {
573      if (instr->Bit(29) == 0) {
574        if (instr->Bit(24) == 0) {
575          if (instr->Bit(21) == 0) {
576            if ((instr->Bit(23) == 1) ||
577                (instr->Bit(18) == 1) ||
578                (instr->Mask(0x80008000) == 0x00000000) ||
579                (instr->Mask(0x000E0000) == 0x00000000) ||
580                (instr->Mask(0x000E0000) == 0x000A0000) ||
581                (instr->Mask(0x00160000) == 0x00000000) ||
582                (instr->Mask(0x00160000) == 0x00120000)) {
583              VisitUnallocated(instr);
584            } else {
585              VisitFPFixedPointConvert(instr);
586            }
587          } else {
588            if (instr->Bits(15, 10) == 32) {
589              VisitUnallocated(instr);
590            } else if (instr->Bits(15, 10) == 0) {
591              if ((instr->Bits(23, 22) == 0x3) ||
592                  (instr->Mask(0x000E0000) == 0x000A0000) ||
593                  (instr->Mask(0x000E0000) == 0x000C0000) ||
594                  (instr->Mask(0x00160000) == 0x00120000) ||
595                  (instr->Mask(0x00160000) == 0x00140000) ||
596                  (instr->Mask(0x20C40000) == 0x00800000) ||
597                  (instr->Mask(0x20C60000) == 0x00840000) ||
598                  (instr->Mask(0xA0C60000) == 0x80060000) ||
599                  (instr->Mask(0xA0C60000) == 0x00860000) ||
600                  (instr->Mask(0xA0C60000) == 0x00460000) ||
601                  (instr->Mask(0xA0CE0000) == 0x80860000) ||
602                  (instr->Mask(0xA0CE0000) == 0x804E0000) ||
603                  (instr->Mask(0xA0CE0000) == 0x000E0000) ||
604                  (instr->Mask(0xA0D60000) == 0x00160000) ||
605                  (instr->Mask(0xA0D60000) == 0x80560000) ||
606                  (instr->Mask(0xA0D60000) == 0x80960000)) {
607                VisitUnallocated(instr);
608              } else {
609                VisitFPIntegerConvert(instr);
610              }
611            } else if (instr->Bits(14, 10) == 16) {
612              const Instr masked_A0DF8000 = instr->Mask(0xA0DF8000);
613              if ((instr->Mask(0x80180000) != 0) ||
614                  (masked_A0DF8000 == 0x00020000) ||
615                  (masked_A0DF8000 == 0x00030000) ||
616                  (masked_A0DF8000 == 0x00068000) ||
617                  (masked_A0DF8000 == 0x00428000) ||
618                  (masked_A0DF8000 == 0x00430000) ||
619                  (masked_A0DF8000 == 0x00468000) ||
620                  (instr->Mask(0xA0D80000) == 0x00800000) ||
621                  (instr->Mask(0xA0DE0000) == 0x00C00000) ||
622                  (instr->Mask(0xA0DF0000) == 0x00C30000) ||
623                  (instr->Mask(0xA0DC0000) == 0x00C40000)) {
624                VisitUnallocated(instr);
625              } else {
626                VisitFPDataProcessing1Source(instr);
627              }
628            } else if (instr->Bits(13, 10) == 8) {
629              if ((instr->Bits(15, 14) != 0) ||
630                  (instr->Bits(2, 0) != 0) ||
631                  (instr->Mask(0x80800000) != 0x00000000)) {
632                VisitUnallocated(instr);
633              } else {
634                VisitFPCompare(instr);
635              }
636            } else if (instr->Bits(12, 10) == 4) {
637              if ((instr->Bits(9, 5) != 0) ||
638                  (instr->Mask(0x80800000) != 0x00000000)) {
639                VisitUnallocated(instr);
640              } else {
641                VisitFPImmediate(instr);
642              }
643            } else {
644              if (instr->Mask(0x80800000) != 0x00000000) {
645                VisitUnallocated(instr);
646              } else {
647                switch (instr->Bits(11, 10)) {
648                  case 1: {
649                    VisitFPConditionalCompare(instr);
650                    break;
651                  }
652                  case 2: {
653                    if ((instr->Bits(15, 14) == 0x3) ||
654                        (instr->Mask(0x00009000) == 0x00009000) ||
655                        (instr->Mask(0x0000A000) == 0x0000A000)) {
656                      VisitUnallocated(instr);
657                    } else {
658                      VisitFPDataProcessing2Source(instr);
659                    }
660                    break;
661                  }
662                  case 3: {
663                    VisitFPConditionalSelect(instr);
664                    break;
665                  }
666                  default: VIXL_UNREACHABLE();
667                }
668              }
669            }
670          }
671        } else {
672          // Bit 30 == 1 has been handled earlier.
673          VIXL_ASSERT(instr->Bit(30) == 0);
674          if (instr->Mask(0xA0800000) != 0) {
675            VisitUnallocated(instr);
676          } else {
677            VisitFPDataProcessing3Source(instr);
678          }
679        }
680      } else {
681        VisitUnallocated(instr);
682      }
683    }
684  }
685}
686
687
688void Decoder::DecodeNEONLoadStore(const Instruction* instr) {
689  VIXL_ASSERT(instr->Bits(29, 25) == 0x6);
690  if (instr->Bit(31) == 0) {
691    if ((instr->Bit(24) == 0) && (instr->Bit(21) == 1)) {
692      VisitUnallocated(instr);
693      return;
694    }
695
696    if (instr->Bit(23) == 0) {
697      if (instr->Bits(20, 16) == 0) {
698        if (instr->Bit(24) == 0) {
699          VisitNEONLoadStoreMultiStruct(instr);
700        } else {
701          VisitNEONLoadStoreSingleStruct(instr);
702        }
703      } else {
704        VisitUnallocated(instr);
705      }
706    } else {
707      if (instr->Bit(24) == 0) {
708        VisitNEONLoadStoreMultiStructPostIndex(instr);
709      } else {
710        VisitNEONLoadStoreSingleStructPostIndex(instr);
711      }
712    }
713  } else {
714    VisitUnallocated(instr);
715  }
716}
717
718
719void Decoder::DecodeNEONVectorDataProcessing(const Instruction* instr) {
720  VIXL_ASSERT(instr->Bits(28, 25) == 0x7);
721  if (instr->Bit(31) == 0) {
722    if (instr->Bit(24) == 0) {
723      if (instr->Bit(21) == 0) {
724        if (instr->Bit(15) == 0) {
725          if (instr->Bit(10) == 0) {
726            if (instr->Bit(29) == 0) {
727              if (instr->Bit(11) == 0) {
728                VisitNEONTable(instr);
729              } else {
730                VisitNEONPerm(instr);
731              }
732            } else {
733              VisitNEONExtract(instr);
734            }
735          } else {
736            if (instr->Bits(23, 22) == 0) {
737              VisitNEONCopy(instr);
738            } else {
739              VisitUnallocated(instr);
740            }
741          }
742        } else {
743          VisitUnallocated(instr);
744        }
745      } else {
746        if (instr->Bit(10) == 0) {
747          if (instr->Bit(11) == 0) {
748            VisitNEON3Different(instr);
749          } else {
750            if (instr->Bits(18, 17) == 0) {
751              if (instr->Bit(20) == 0) {
752                if (instr->Bit(19) == 0) {
753                  VisitNEON2RegMisc(instr);
754                } else {
755                  if (instr->Bits(30, 29) == 0x2) {
756                    VisitCryptoAES(instr);
757                  } else {
758                    VisitUnallocated(instr);
759                  }
760                }
761              } else {
762                if (instr->Bit(19) == 0) {
763                  VisitNEONAcrossLanes(instr);
764                } else {
765                  VisitUnallocated(instr);
766                }
767              }
768            } else {
769              VisitUnallocated(instr);
770            }
771          }
772        } else {
773          VisitNEON3Same(instr);
774        }
775      }
776    } else {
777      if (instr->Bit(10) == 0) {
778        VisitNEONByIndexedElement(instr);
779      } else {
780        if (instr->Bit(23) == 0) {
781          if (instr->Bits(22, 19) == 0) {
782            VisitNEONModifiedImmediate(instr);
783          } else {
784            VisitNEONShiftImmediate(instr);
785          }
786        } else {
787          VisitUnallocated(instr);
788        }
789      }
790    }
791  } else {
792    VisitUnallocated(instr);
793  }
794}
795
796
797void Decoder::DecodeNEONScalarDataProcessing(const Instruction* instr) {
798  VIXL_ASSERT(instr->Bits(28, 25) == 0xF);
799  if (instr->Bit(24) == 0) {
800    if (instr->Bit(21) == 0) {
801      if (instr->Bit(15) == 0) {
802        if (instr->Bit(10) == 0) {
803          if (instr->Bit(29) == 0) {
804            if (instr->Bit(11) == 0) {
805              VisitCrypto3RegSHA(instr);
806            } else {
807              VisitUnallocated(instr);
808            }
809          } else {
810            VisitUnallocated(instr);
811          }
812        } else {
813          if (instr->Bits(23, 22) == 0) {
814            VisitNEONScalarCopy(instr);
815          } else {
816            VisitUnallocated(instr);
817          }
818        }
819      } else {
820        VisitUnallocated(instr);
821      }
822    } else {
823      if (instr->Bit(10) == 0) {
824        if (instr->Bit(11) == 0) {
825          VisitNEONScalar3Diff(instr);
826        } else {
827          if (instr->Bits(18, 17) == 0) {
828            if (instr->Bit(20) == 0) {
829              if (instr->Bit(19) == 0) {
830                VisitNEONScalar2RegMisc(instr);
831              } else {
832                if (instr->Bit(29) == 0) {
833                  VisitCrypto2RegSHA(instr);
834                } else {
835                  VisitUnallocated(instr);
836                }
837              }
838            } else {
839              if (instr->Bit(19) == 0) {
840                VisitNEONScalarPairwise(instr);
841              } else {
842                VisitUnallocated(instr);
843              }
844            }
845          } else {
846            VisitUnallocated(instr);
847          }
848        }
849      } else {
850        VisitNEONScalar3Same(instr);
851      }
852    }
853  } else {
854    if (instr->Bit(10) == 0) {
855      VisitNEONScalarByIndexedElement(instr);
856    } else {
857      if (instr->Bit(23) == 0) {
858        VisitNEONScalarShiftImmediate(instr);
859      } else {
860        VisitUnallocated(instr);
861      }
862    }
863  }
864}
865
866
867#define DEFINE_VISITOR_CALLERS(A)                                              \
868  void Decoder::Visit##A(const Instruction *instr) {                           \
869    VIXL_ASSERT(instr->Mask(A##FMask) == A##Fixed);                            \
870    std::list<DecoderVisitor*>::iterator it;                                   \
871    for (it = visitors_.begin(); it != visitors_.end(); it++) {                \
872      (*it)->Visit##A(instr);                                                  \
873    }                                                                          \
874  }
875VISITOR_LIST(DEFINE_VISITOR_CALLERS)
876#undef DEFINE_VISITOR_CALLERS
877}  // namespace vixl
878