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