• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 namespace vixl {
33 namespace aarch64 {
34 
DecodeInstruction(const Instruction * instr)35 void 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 
AppendVisitor(DecoderVisitor * new_visitor)129 void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
130   visitors_.push_back(new_visitor);
131 }
132 
133 
PrependVisitor(DecoderVisitor * new_visitor)134 void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
135   visitors_.push_front(new_visitor);
136 }
137 
138 
InsertVisitorBefore(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)139 void 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 
InsertVisitorAfter(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)155 void 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 
RemoveVisitor(DecoderVisitor * visitor)172 void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
173   visitors_.remove(visitor);
174 }
175 
176 
DecodePCRelAddressing(const Instruction * instr)177 void 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 
DecodeBranchSystemException(const Instruction * instr)186 void 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 
DecodeLoadStore(const Instruction * instr)287 void 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 
DecodeLogical(const Instruction * instr)411 void 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 
DecodeBitfieldExtract(const Instruction * instr)430 void 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 
DecodeAddSubImmediate(const Instruction * instr)455 void 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 
DecodeDataProcessing(const Instruction * instr)465 void 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 
DecodeFP(const Instruction * instr)582 void 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 
DecodeNEONLoadStore(const Instruction * instr)708 void 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 
DecodeNEONVectorDataProcessing(const Instruction * instr)739 void 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 
DecodeNEONScalarDataProcessing(const Instruction * instr)817 void 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   }
895 VISITOR_LIST(DEFINE_VISITOR_CALLERS)
896 #undef DEFINE_VISITOR_CALLERS
897 }  // namespace aarch64
898 }  // namespace vixl
899