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