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(0x0038F000) == 0x00005000) ||
250                 (instr->Mask(0x0038E000) == 0x00006000)) {
251               VisitUnallocated(instr);
252             } else {
253               VisitSystem(instr);
254             }
255           } else {
256             VisitUnallocated(instr);
257           }
258         }
259       } else {
260         if (((instr->ExtractBit(24) == 0x1) &&
261              (instr->ExtractBits(23, 21) > 0x1)) ||
262             (instr->ExtractBits(20, 16) != 0x1F) ||
263             (instr->ExtractBits(15, 10) == 0x1) ||
264             (instr->ExtractBits(15, 10) > 0x3) ||
265             (instr->ExtractBits(24, 21) == 0x3) ||
266             (instr->ExtractBits(24, 22) == 0x3)) {
267           VisitUnallocated(instr);
268         } else {
269           VisitUnconditionalBranchToRegister(instr);
270         }
271       }
272       break;
273     }
274     case 3:
275     case 7: {
276       VisitUnallocated(instr);
277       break;
278     }
279   }
280 }
281 
282 
DecodeLoadStore(const Instruction * instr)283 void Decoder::DecodeLoadStore(const Instruction* instr) {
284   VIXL_ASSERT((instr->ExtractBits(27, 24) == 0x8) ||
285               (instr->ExtractBits(27, 24) == 0x9) ||
286               (instr->ExtractBits(27, 24) == 0xC) ||
287               (instr->ExtractBits(27, 24) == 0xD));
288   // TODO(all): rearrange the tree to integrate this branch.
289   if ((instr->ExtractBit(28) == 0) && (instr->ExtractBit(29) == 0) &&
290       (instr->ExtractBit(26) == 1)) {
291     DecodeNEONLoadStore(instr);
292     return;
293   }
294 
295   if (instr->ExtractBit(24) == 0) {
296     if (instr->ExtractBit(28) == 0) {
297       if (instr->ExtractBit(29) == 0) {
298         if (instr->ExtractBit(26) == 0) {
299           VisitLoadStoreExclusive(instr);
300         } else {
301           VIXL_UNREACHABLE();
302         }
303       } else {
304         if ((instr->ExtractBits(31, 30) == 0x3) ||
305             (instr->Mask(0xC4400000) == 0x40000000)) {
306           VisitUnallocated(instr);
307         } else {
308           if (instr->ExtractBit(23) == 0) {
309             if (instr->Mask(0xC4400000) == 0xC0400000) {
310               VisitUnallocated(instr);
311             } else {
312               VisitLoadStorePairNonTemporal(instr);
313             }
314           } else {
315             VisitLoadStorePairPostIndex(instr);
316           }
317         }
318       }
319     } else {
320       if (instr->ExtractBit(29) == 0) {
321         if (instr->Mask(0xC4000000) == 0xC4000000) {
322           VisitUnallocated(instr);
323         } else {
324           VisitLoadLiteral(instr);
325         }
326       } else {
327         if ((instr->Mask(0x44800000) == 0x44800000) ||
328             (instr->Mask(0x84800000) == 0x84800000)) {
329           VisitUnallocated(instr);
330         } else {
331           if (instr->ExtractBit(21) == 0) {
332             switch (instr->ExtractBits(11, 10)) {
333               case 0: {
334                 VisitLoadStoreUnscaledOffset(instr);
335                 break;
336               }
337               case 1: {
338                 if (instr->Mask(0xC4C00000) == 0xC0800000) {
339                   VisitUnallocated(instr);
340                 } else {
341                   VisitLoadStorePostIndex(instr);
342                 }
343                 break;
344               }
345               case 2: {
346                 // TODO: VisitLoadStoreRegisterOffsetUnpriv.
347                 VisitUnimplemented(instr);
348                 break;
349               }
350               case 3: {
351                 if (instr->Mask(0xC4C00000) == 0xC0800000) {
352                   VisitUnallocated(instr);
353                 } else {
354                   VisitLoadStorePreIndex(instr);
355                 }
356                 break;
357               }
358             }
359           } else {
360             if (instr->ExtractBits(11, 10) == 0x2) {
361               if (instr->ExtractBit(14) == 0) {
362                 VisitUnallocated(instr);
363               } else {
364                 VisitLoadStoreRegisterOffset(instr);
365               }
366             } else {
367               if (instr->ExtractBits(11, 10) == 0x0) {
368                 if (instr->ExtractBit(25) == 0) {
369                   if (instr->ExtractBit(26) == 0) {
370                     if ((instr->ExtractBit(15) == 1) &&
371                         ((instr->ExtractBits(14, 12) == 0x1) ||
372                          (instr->ExtractBit(13) == 1) ||
373                          (instr->ExtractBits(14, 12) == 0x5) ||
374                          ((instr->ExtractBits(14, 12) == 0x4) &&
375                           ((instr->ExtractBit(23) == 0) ||
376                            (instr->ExtractBits(23, 22) == 0x3))))) {
377                       VisitUnallocated(instr);
378                     } else {
379                       VisitAtomicMemory(instr);
380                     }
381                   } else {
382                     VisitUnallocated(instr);
383                   }
384                 } else {
385                   VisitUnallocated(instr);
386                 }
387               } else {
388                 VisitUnallocated(instr);
389               }
390             }
391           }
392         }
393       }
394     }
395   } else {
396     if (instr->ExtractBit(28) == 0) {
397       if (instr->ExtractBit(29) == 0) {
398         VisitUnallocated(instr);
399       } else {
400         if ((instr->ExtractBits(31, 30) == 0x3) ||
401             (instr->Mask(0xC4400000) == 0x40000000)) {
402           VisitUnallocated(instr);
403         } else {
404           if (instr->ExtractBit(23) == 0) {
405             VisitLoadStorePairOffset(instr);
406           } else {
407             VisitLoadStorePairPreIndex(instr);
408           }
409         }
410       }
411     } else {
412       if (instr->ExtractBit(29) == 0) {
413         VisitUnallocated(instr);
414       } else {
415         if ((instr->Mask(0x84C00000) == 0x80C00000) ||
416             (instr->Mask(0x44800000) == 0x44800000) ||
417             (instr->Mask(0x84800000) == 0x84800000)) {
418           VisitUnallocated(instr);
419         } else {
420           VisitLoadStoreUnsignedOffset(instr);
421         }
422       }
423     }
424   }
425 }
426 
427 
DecodeLogical(const Instruction * instr)428 void Decoder::DecodeLogical(const Instruction* instr) {
429   VIXL_ASSERT(instr->ExtractBits(27, 24) == 0x2);
430 
431   if (instr->Mask(0x80400000) == 0x00400000) {
432     VisitUnallocated(instr);
433   } else {
434     if (instr->ExtractBit(23) == 0) {
435       VisitLogicalImmediate(instr);
436     } else {
437       if (instr->ExtractBits(30, 29) == 0x1) {
438         VisitUnallocated(instr);
439       } else {
440         VisitMoveWideImmediate(instr);
441       }
442     }
443   }
444 }
445 
446 
DecodeBitfieldExtract(const Instruction * instr)447 void Decoder::DecodeBitfieldExtract(const Instruction* instr) {
448   VIXL_ASSERT(instr->ExtractBits(27, 24) == 0x3);
449 
450   if ((instr->Mask(0x80400000) == 0x80000000) ||
451       (instr->Mask(0x80400000) == 0x00400000) ||
452       (instr->Mask(0x80008000) == 0x00008000)) {
453     VisitUnallocated(instr);
454   } else if (instr->ExtractBit(23) == 0) {
455     if ((instr->Mask(0x80200000) == 0x00200000) ||
456         (instr->Mask(0x60000000) == 0x60000000)) {
457       VisitUnallocated(instr);
458     } else {
459       VisitBitfield(instr);
460     }
461   } else {
462     if ((instr->Mask(0x60200000) == 0x00200000) ||
463         (instr->Mask(0x60000000) != 0x00000000)) {
464       VisitUnallocated(instr);
465     } else {
466       VisitExtract(instr);
467     }
468   }
469 }
470 
471 
DecodeAddSubImmediate(const Instruction * instr)472 void Decoder::DecodeAddSubImmediate(const Instruction* instr) {
473   VIXL_ASSERT(instr->ExtractBits(27, 24) == 0x1);
474   if (instr->ExtractBit(23) == 1) {
475     VisitUnallocated(instr);
476   } else {
477     VisitAddSubImmediate(instr);
478   }
479 }
480 
481 
DecodeDataProcessing(const Instruction * instr)482 void Decoder::DecodeDataProcessing(const Instruction* instr) {
483   VIXL_ASSERT((instr->ExtractBits(27, 24) == 0xA) ||
484               (instr->ExtractBits(27, 24) == 0xB));
485 
486   if (instr->ExtractBit(24) == 0) {
487     if (instr->ExtractBit(28) == 0) {
488       if (instr->Mask(0x80008000) == 0x00008000) {
489         VisitUnallocated(instr);
490       } else {
491         VisitLogicalShifted(instr);
492       }
493     } else {
494       switch (instr->ExtractBits(23, 21)) {
495         case 0: {
496           if (instr->Mask(0x0000FC00) != 0) {
497             VisitUnallocated(instr);
498           } else {
499             VisitAddSubWithCarry(instr);
500           }
501           break;
502         }
503         case 2: {
504           if ((instr->ExtractBit(29) == 0) || (instr->Mask(0x00000410) != 0)) {
505             VisitUnallocated(instr);
506           } else {
507             if (instr->ExtractBit(11) == 0) {
508               VisitConditionalCompareRegister(instr);
509             } else {
510               VisitConditionalCompareImmediate(instr);
511             }
512           }
513           break;
514         }
515         case 4: {
516           if (instr->Mask(0x20000800) != 0x00000000) {
517             VisitUnallocated(instr);
518           } else {
519             VisitConditionalSelect(instr);
520           }
521           break;
522         }
523         case 6: {
524           if (instr->ExtractBit(29) == 0x1) {
525             VisitUnallocated(instr);
526             VIXL_FALLTHROUGH();
527           } else {
528             if (instr->ExtractBit(30) == 0) {
529               if ((instr->ExtractBit(15) == 0x1) ||
530                   (instr->ExtractBits(15, 11) == 0) ||
531                   (instr->ExtractBits(15, 12) == 0x1) ||
532                   ((instr->ExtractBits(15, 12) == 0x3) &&
533                    (instr->ExtractBit(31) == 0)) ||
534                   (instr->ExtractBits(15, 13) == 0x3) ||
535                   (instr->Mask(0x8000EC00) == 0x00004C00) ||
536                   (instr->Mask(0x8000E800) == 0x80004000) ||
537                   (instr->Mask(0x8000E400) == 0x80004000)) {
538                 VisitUnallocated(instr);
539               } else {
540                 VisitDataProcessing2Source(instr);
541               }
542             } else {
543               if ((instr->ExtractBits(20, 17) != 0) ||
544                   (instr->ExtractBit(15) == 1) ||
545                   ((instr->ExtractBit(16) == 1) &&
546                    ((instr->ExtractBits(14, 10) > 17) ||
547                     (instr->ExtractBit(31) == 0))) ||
548                   ((instr->ExtractBit(16) == 0) &&
549                    ((instr->ExtractBits(14, 13) != 0) ||
550                     (instr->Mask(0xA01FFC00) == 0x00000C00) ||
551                     (instr->Mask(0x201FF800) == 0x00001800)))) {
552                 VisitUnallocated(instr);
553               } else {
554                 VisitDataProcessing1Source(instr);
555               }
556             }
557             break;
558           }
559         }
560         case 1:
561         case 3:
562         case 5:
563         case 7:
564           VisitUnallocated(instr);
565           break;
566       }
567     }
568   } else {
569     if (instr->ExtractBit(28) == 0) {
570       if (instr->ExtractBit(21) == 0) {
571         if ((instr->ExtractBits(23, 22) == 0x3) ||
572             (instr->Mask(0x80008000) == 0x00008000)) {
573           VisitUnallocated(instr);
574         } else {
575           VisitAddSubShifted(instr);
576         }
577       } else {
578         if ((instr->Mask(0x00C00000) != 0x00000000) ||
579             (instr->Mask(0x00001400) == 0x00001400) ||
580             (instr->Mask(0x00001800) == 0x00001800)) {
581           VisitUnallocated(instr);
582         } else {
583           VisitAddSubExtended(instr);
584         }
585       }
586     } else {
587       if ((instr->ExtractBit(30) == 0x1) ||
588           (instr->ExtractBits(30, 29) == 0x1) ||
589           (instr->Mask(0xE0600000) == 0x00200000) ||
590           (instr->Mask(0xE0608000) == 0x00400000) ||
591           (instr->Mask(0x60608000) == 0x00408000) ||
592           (instr->Mask(0x60E00000) == 0x00E00000) ||
593           (instr->Mask(0x60E00000) == 0x00800000) ||
594           (instr->Mask(0x60E00000) == 0x00600000)) {
595         VisitUnallocated(instr);
596       } else {
597         VisitDataProcessing3Source(instr);
598       }
599     }
600   }
601 }
602 
603 
DecodeFP(const Instruction * instr)604 void Decoder::DecodeFP(const Instruction* instr) {
605   VIXL_ASSERT((instr->ExtractBits(27, 24) == 0xE) ||
606               (instr->ExtractBits(27, 24) == 0xF));
607   if (instr->ExtractBit(28) == 0) {
608     DecodeNEONVectorDataProcessing(instr);
609   } else {
610     if (instr->ExtractBits(31, 30) == 0x3) {
611       VisitUnallocated(instr);
612     } else if (instr->ExtractBits(31, 30) == 0x1) {
613       DecodeNEONScalarDataProcessing(instr);
614     } else {
615       if (instr->ExtractBit(29) == 0) {
616         if (instr->ExtractBit(24) == 0) {
617           if (instr->ExtractBit(21) == 0) {
618             if ((instr->ExtractBits(23, 22) == 0x2) ||
619                 (instr->ExtractBit(18) == 1) ||
620                 (instr->Mask(0x80008000) == 0x00000000) ||
621                 (instr->Mask(0x000E0000) == 0x00000000) ||
622                 (instr->Mask(0x000E0000) == 0x000A0000) ||
623                 (instr->Mask(0x00160000) == 0x00000000) ||
624                 (instr->Mask(0x00160000) == 0x00120000)) {
625               VisitUnallocated(instr);
626             } else {
627               VisitFPFixedPointConvert(instr);
628             }
629           } else {
630             if (instr->ExtractBits(15, 10) == 32) {
631               VisitUnallocated(instr);
632             } else if (instr->ExtractBits(15, 10) == 0) {
633               if ((instr->Mask(0x000E0000) == 0x000A0000) ||
634                   (instr->Mask(0x000E0000) == 0x000C0000) ||
635                   (instr->Mask(0x00160000) == 0x00120000) ||
636                   (instr->Mask(0x00160000) == 0x00140000) ||
637                   (instr->Mask(0x20C40000) == 0x00800000) ||
638                   (instr->Mask(0x20C60000) == 0x00840000) ||
639                   (instr->Mask(0xA0C60000) == 0x80060000) ||
640                   (instr->Mask(0xA0C60000) == 0x00860000) ||
641                   (instr->Mask(0xA0CE0000) == 0x80860000) ||
642                   (instr->Mask(0xA0CE0000) == 0x804E0000) ||
643                   (instr->Mask(0xA0CE0000) == 0x000E0000) ||
644                   (instr->Mask(0xA0D60000) == 0x00160000) ||
645                   (instr->Mask(0xA0D60000) == 0x80560000) ||
646                   (instr->Mask(0xA0D60000) == 0x80960000)) {
647                 VisitUnallocated(instr);
648               } else {
649                 VisitFPIntegerConvert(instr);
650               }
651             } else if (instr->ExtractBits(14, 10) == 16) {
652               const Instr masked_A0DF8000 = instr->Mask(0xA0DF8000);
653               if ((instr->Mask(0x80180000) != 0) ||
654                   (masked_A0DF8000 == 0x00020000) ||
655                   (masked_A0DF8000 == 0x00030000) ||
656                   (masked_A0DF8000 == 0x00068000) ||
657                   (masked_A0DF8000 == 0x00428000) ||
658                   (masked_A0DF8000 == 0x00430000) ||
659                   (masked_A0DF8000 == 0x00468000) ||
660                   (instr->Mask(0xA0D80000) == 0x00800000) ||
661                   (instr->Mask(0xA0DF0000) == 0x00C30000) ||
662                   (instr->Mask(0xA0DF8000) == 0x00C68000)) {
663                 VisitUnallocated(instr);
664               } else {
665                 VisitFPDataProcessing1Source(instr);
666               }
667             } else if (instr->ExtractBits(13, 10) == 8) {
668               if ((instr->ExtractBits(15, 14) != 0) ||
669                   (instr->ExtractBits(2, 0) != 0) ||
670                   (instr->ExtractBit(31) == 1) ||
671                   (instr->ExtractBits(23, 22) == 0x2)) {
672                 VisitUnallocated(instr);
673               } else {
674                 VisitFPCompare(instr);
675               }
676             } else if (instr->ExtractBits(12, 10) == 4) {
677               if ((instr->ExtractBits(9, 5) != 0) ||
678                   // Valid enc: 01d, 00s, 11h.
679                   (instr->ExtractBits(23, 22) == 0x2) ||
680                   (instr->ExtractBit(31) == 1)) {
681                 VisitUnallocated(instr);
682               } else {
683                 VisitFPImmediate(instr);
684               }
685             } else {
686               if ((instr->ExtractBits(23, 22) == 0x2) ||
687                   (instr->ExtractBit(31) == 1)) {
688                 VisitUnallocated(instr);
689               } else {
690                 switch (instr->ExtractBits(11, 10)) {
691                   case 1: {
692                     VisitFPConditionalCompare(instr);
693                     break;
694                   }
695                   case 2: {
696                     if (instr->ExtractBits(15, 12) > 0x8) {
697                       VisitUnallocated(instr);
698                     } else {
699                       VisitFPDataProcessing2Source(instr);
700                     }
701                     break;
702                   }
703                   case 3: {
704                     VisitFPConditionalSelect(instr);
705                     break;
706                   }
707                   default:
708                     VIXL_UNREACHABLE();
709                 }
710               }
711             }
712           }
713         } else {
714           // Bit 30 == 1 has been handled earlier.
715           VIXL_ASSERT(instr->ExtractBit(30) == 0);
716           if ((instr->Mask(0xA0000000) != 0) ||
717               (instr->ExtractBits(23, 22) == 0x2)) {
718             VisitUnallocated(instr);
719           } else {
720             VisitFPDataProcessing3Source(instr);
721           }
722         }
723       } else {
724         VisitUnallocated(instr);
725       }
726     }
727   }
728 }
729 
730 
DecodeNEONLoadStore(const Instruction * instr)731 void Decoder::DecodeNEONLoadStore(const Instruction* instr) {
732   VIXL_ASSERT(instr->ExtractBits(29, 25) == 0x6);
733   if (instr->ExtractBit(31) == 0) {
734     if ((instr->ExtractBit(24) == 0) && (instr->ExtractBit(21) == 1)) {
735       VisitUnallocated(instr);
736       return;
737     }
738 
739     if (instr->ExtractBit(23) == 0) {
740       if (instr->ExtractBits(20, 16) == 0) {
741         if (instr->ExtractBit(24) == 0) {
742           VisitNEONLoadStoreMultiStruct(instr);
743         } else {
744           VisitNEONLoadStoreSingleStruct(instr);
745         }
746       } else {
747         VisitUnallocated(instr);
748       }
749     } else {
750       if (instr->ExtractBit(24) == 0) {
751         VisitNEONLoadStoreMultiStructPostIndex(instr);
752       } else {
753         VisitNEONLoadStoreSingleStructPostIndex(instr);
754       }
755     }
756   } else {
757     VisitUnallocated(instr);
758   }
759 }
760 
761 
DecodeNEONVectorDataProcessing(const Instruction * instr)762 void Decoder::DecodeNEONVectorDataProcessing(const Instruction* instr) {
763   VIXL_ASSERT(instr->ExtractBits(28, 25) == 0x7);
764   if (instr->ExtractBit(31) == 0) {
765     if (instr->ExtractBit(24) == 0) {
766       if (instr->ExtractBit(21) == 0) {
767         if (instr->ExtractBit(15) == 0) {
768           if (instr->ExtractBit(10) == 0) {
769             if (instr->ExtractBit(29) == 0) {
770               if (instr->ExtractBit(11) == 0) {
771                 VisitNEONTable(instr);
772               } else {
773                 VisitNEONPerm(instr);
774               }
775             } else {
776               VisitNEONExtract(instr);
777             }
778           } else {
779             if (instr->ExtractBits(23, 22) == 0) {
780               VisitNEONCopy(instr);
781             } else if (instr->ExtractBit(14) == 0x0 &&
782                        instr->ExtractBit(22) == 0x1) {
783               // U + a + opcode.
784               uint8_t decode_field =
785                   (instr->ExtractBit(29) << 1) | instr->ExtractBit(23);
786               decode_field = (decode_field << 3) | instr->ExtractBits(13, 11);
787               switch (decode_field) {
788                 case 0x5:
789                 case 0xB:
790                 case 0xC:
791                 case 0xD:
792                 case 0x11:
793                 case 0x19:
794                 case 0x1B:
795                 case 0x1F:
796                   VisitUnallocated(instr);
797                   break;
798                 default:
799                   VisitNEON3SameFP16(instr);
800                   break;
801               }
802             } else {
803               VisitUnallocated(instr);
804             }
805           }
806         } else if (instr->ExtractBit(10) == 0) {
807           VisitUnallocated(instr);
808         } else if ((instr->ExtractBits(14, 11) == 0x3) ||
809                    (instr->ExtractBits(14, 13) == 0x1)) {
810           // opcode = 0b0011
811           // opcode = 0b01xx
812           VisitUnallocated(instr);
813         } else if (instr->ExtractBit(29) == 0) {
814           // U == 0
815           if (instr->ExtractBits(14, 11) == 0x2) {
816             // opcode = 0b0010
817             VisitNEON3SameExtra(instr);
818           } else {
819             VisitUnallocated(instr);
820           }
821         } else {
822           // U == 1
823           if ((instr->ExtractBits(14, 11) == 0xd) ||
824               (instr->ExtractBits(14, 11) == 0xf)) {
825             // opcode = 0b11x1
826             VisitUnallocated(instr);
827           } else {
828             VisitNEON3SameExtra(instr);
829           }
830         }
831       } else {
832         if (instr->ExtractBit(10) == 0) {
833           if (instr->ExtractBit(11) == 0) {
834             VisitNEON3Different(instr);
835           } else {
836             if (instr->ExtractBits(18, 17) == 0) {
837               if (instr->ExtractBit(20) == 0) {
838                 if (instr->ExtractBit(19) == 0) {
839                   VisitNEON2RegMisc(instr);
840                 } else {
841                   if (instr->ExtractBits(30, 29) == 0x2) {
842                     VisitCryptoAES(instr);
843                   } else {
844                     VisitUnallocated(instr);
845                   }
846                 }
847               } else {
848                 if (instr->ExtractBit(19) == 0) {
849                   VisitNEONAcrossLanes(instr);
850                 } else {
851                   if (instr->ExtractBit(22) == 0) {
852                     VisitUnallocated(instr);
853                   } else {
854                     if ((instr->ExtractBits(16, 15) == 0x0) ||
855                         (instr->ExtractBits(16, 14) == 0x2) ||
856                         (instr->ExtractBits(16, 15) == 0x2) ||
857                         (instr->ExtractBits(16, 12) == 0x1e) ||
858                         ((instr->ExtractBit(23) == 0) &&
859                          ((instr->ExtractBits(16, 14) == 0x3) ||
860                           (instr->ExtractBits(16, 12) == 0x1f))) ||
861                         ((instr->ExtractBit(23) == 1) &&
862                          (instr->ExtractBits(16, 12) == 0x1c))) {
863                       VisitUnallocated(instr);
864                     } else {
865                       VisitNEON2RegMiscFP16(instr);
866                     }
867                   }
868                 }
869               }
870             } else {
871               VisitUnallocated(instr);
872             }
873           }
874         } else {
875           VisitNEON3Same(instr);
876         }
877       }
878     } else {
879       if (instr->ExtractBit(10) == 0) {
880         VisitNEONByIndexedElement(instr);
881       } else {
882         if (instr->ExtractBit(23) == 0) {
883           if (instr->ExtractBits(22, 19) == 0) {
884             VisitNEONModifiedImmediate(instr);
885           } else {
886             VisitNEONShiftImmediate(instr);
887           }
888         } else {
889           VisitUnallocated(instr);
890         }
891       }
892     }
893   } else {
894     VisitUnallocated(instr);
895   }
896 }
897 
898 
DecodeNEONScalarDataProcessing(const Instruction * instr)899 void Decoder::DecodeNEONScalarDataProcessing(const Instruction* instr) {
900   VIXL_ASSERT(instr->ExtractBits(28, 25) == 0xF);
901   if (instr->ExtractBit(24) == 0) {
902     if (instr->ExtractBit(21) == 0) {
903       if (instr->ExtractBit(15) == 0) {
904         if (instr->ExtractBit(10) == 0) {
905           if (instr->ExtractBit(29) == 0) {
906             if (instr->ExtractBit(11) == 0) {
907               VisitCrypto3RegSHA(instr);
908             } else {
909               VisitUnallocated(instr);
910             }
911           } else {
912             VisitUnallocated(instr);
913           }
914         } else {
915           if (instr->ExtractBits(23, 22) == 0) {
916             VisitNEONScalarCopy(instr);
917           } else {
918             if (instr->Mask(0x00404000) == 0x00400000) {
919               if ((instr->ExtractBits(13, 11) == 0x6) ||
920                   (instr->ExtractBits(13, 11) < 2) ||
921                   ((instr->Mask(0x20800000) == 0x00000000) &&
922                    ((instr->ExtractBits(13, 11) < 0x3) ||
923                     (instr->ExtractBits(13, 11) == 0x5))) ||
924                   ((instr->Mask(0x20800000) == 0x00800000) &&
925                    (instr->ExtractBits(13, 11) < 0x7)) ||
926                   ((instr->Mask(0x20800000) == 0x20000000) &&
927                    ((instr->ExtractBits(13, 11) < 0x4) ||
928                     (instr->ExtractBits(13, 11) == 0x7))) ||
929                   ((instr->Mask(0x20800000) == 0x20800000) &&
930                    (instr->ExtractBits(12, 11) == 0x3))) {
931                 VisitUnallocated(instr);
932               } else {
933                 VisitNEONScalar3SameFP16(instr);
934               }
935             } else {
936               VisitUnallocated(instr);
937             }
938           }
939         }
940       } else {
941         if (instr->ExtractBit(29) == 0) {
942           VisitUnallocated(instr);
943         } else {
944           if (instr->ExtractBit(10) == 0) {
945             VisitUnallocated(instr);
946           } else {
947             VisitNEONScalar3SameExtra(instr);
948           }
949         }
950       }
951     } else {
952       if (instr->ExtractBit(10) == 0) {
953         if (instr->ExtractBit(11) == 0) {
954           VisitNEONScalar3Diff(instr);
955         } else {
956           if (instr->ExtractBits(18, 17) == 0) {
957             if (instr->ExtractBit(20) == 0) {
958               if (instr->ExtractBit(19) == 0) {
959                 VisitNEONScalar2RegMisc(instr);
960               } else {
961                 if (instr->ExtractBit(29) == 0) {
962                   VisitCrypto2RegSHA(instr);
963                 } else {
964                   VisitUnallocated(instr);
965                 }
966               }
967             } else {
968               if (instr->ExtractBit(19) == 0) {
969                 VisitNEONScalarPairwise(instr);
970               } else {
971                 if (instr->ExtractBit(22) == 0) {
972                   VisitUnallocated(instr);
973                 } else {
974                   if ((instr->ExtractBits(16, 15) == 0x0) ||
975                       (instr->ExtractBits(16, 14) == 0x2) ||
976                       (instr->ExtractBits(16, 15) == 0x2) ||
977                       (instr->ExtractBits(16, 13) == 0xc) ||
978                       (instr->ExtractBits(16, 12) == 0x1e) ||
979                       ((instr->ExtractBit(23) == 0) &&
980                        ((instr->ExtractBits(16, 14) == 0x3) ||
981                         (instr->ExtractBits(16, 12) == 0x1f))) ||
982                       ((instr->ExtractBit(23) == 1) &&
983                        ((instr->ExtractBits(16, 12) == 0xf) ||
984                         (instr->ExtractBits(16, 12) == 0x1c) ||
985                         ((instr->ExtractBit(29) == 1) &&
986                          ((instr->ExtractBits(16, 12) == 0xe) ||
987                           (instr->ExtractBits(16, 12) == 0x1f)))))) {
988                     VisitUnallocated(instr);
989                   } else {
990                     VisitNEONScalar2RegMiscFP16(instr);
991                   }
992                 }
993               }
994             }
995           } else {
996             VisitUnallocated(instr);
997           }
998         }
999       } else {
1000         VisitNEONScalar3Same(instr);
1001       }
1002     }
1003   } else {
1004     if (instr->ExtractBit(10) == 0) {
1005       VisitNEONScalarByIndexedElement(instr);
1006     } else {
1007       if (instr->ExtractBit(23) == 0) {
1008         VisitNEONScalarShiftImmediate(instr);
1009       } else {
1010         VisitUnallocated(instr);
1011       }
1012     }
1013   }
1014 }
1015 
1016 
1017 #define DEFINE_VISITOR_CALLERS(A)                               \
1018   void Decoder::Visit##A(const Instruction* instr) {            \
1019     VIXL_ASSERT(((A##FMask == 0) && (A##Fixed == 0)) ||         \
1020                 (instr->Mask(A##FMask) == A##Fixed));           \
1021     std::list<DecoderVisitor*>::iterator it;                    \
1022     for (it = visitors_.begin(); it != visitors_.end(); it++) { \
1023       (*it)->Visit##A(instr);                                   \
1024     }                                                           \
1025   }
1026 VISITOR_LIST(DEFINE_VISITOR_CALLERS)
1027 #undef DEFINE_VISITOR_CALLERS
1028 }  // namespace aarch64
1029 }  // namespace vixl
1030