• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013, 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 "globals-vixl.h"
28 #include "utils-vixl.h"
29 #include "a64/decoder-a64.h"
30 
31 namespace vixl {
32 // Top-level instruction decode function.
Decode(Instruction * instr)33 void Decoder::Decode(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_.remove(new_visitor);
113   visitors_.push_front(new_visitor);
114 }
115 
116 
PrependVisitor(DecoderVisitor * new_visitor)117 void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
118   visitors_.remove(new_visitor);
119   visitors_.push_back(new_visitor);
120 }
121 
122 
InsertVisitorBefore(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)123 void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
124                                   DecoderVisitor* registered_visitor) {
125   visitors_.remove(new_visitor);
126   std::list<DecoderVisitor*>::iterator it;
127   for (it = visitors_.begin(); it != visitors_.end(); it++) {
128     if (*it == registered_visitor) {
129       visitors_.insert(it, new_visitor);
130       return;
131     }
132   }
133   // We reached the end of the list. The last element must be
134   // registered_visitor.
135   VIXL_ASSERT(*it == registered_visitor);
136   visitors_.insert(it, new_visitor);
137 }
138 
139 
InsertVisitorAfter(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)140 void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
141                                  DecoderVisitor* registered_visitor) {
142   visitors_.remove(new_visitor);
143   std::list<DecoderVisitor*>::iterator it;
144   for (it = visitors_.begin(); it != visitors_.end(); it++) {
145     if (*it == registered_visitor) {
146       it++;
147       visitors_.insert(it, new_visitor);
148       return;
149     }
150   }
151   // We reached the end of the list. The last element must be
152   // registered_visitor.
153   VIXL_ASSERT(*it == registered_visitor);
154   visitors_.push_back(new_visitor);
155 }
156 
157 
RemoveVisitor(DecoderVisitor * visitor)158 void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
159   visitors_.remove(visitor);
160 }
161 
162 
DecodePCRelAddressing(Instruction * instr)163 void Decoder::DecodePCRelAddressing(Instruction* instr) {
164   VIXL_ASSERT(instr->Bits(27, 24) == 0x0);
165   // We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
166   // decode.
167   VIXL_ASSERT(instr->Bit(28) == 0x1);
168   VisitPCRelAddressing(instr);
169 }
170 
171 
DecodeBranchSystemException(Instruction * instr)172 void Decoder::DecodeBranchSystemException(Instruction* instr) {
173   VIXL_ASSERT((instr->Bits(27, 24) == 0x4) ||
174          (instr->Bits(27, 24) == 0x5) ||
175          (instr->Bits(27, 24) == 0x6) ||
176          (instr->Bits(27, 24) == 0x7) );
177 
178   switch (instr->Bits(31, 29)) {
179     case 0:
180     case 4: {
181       VisitUnconditionalBranch(instr);
182       break;
183     }
184     case 1:
185     case 5: {
186       if (instr->Bit(25) == 0) {
187         VisitCompareBranch(instr);
188       } else {
189         VisitTestBranch(instr);
190       }
191       break;
192     }
193     case 2: {
194       if (instr->Bit(25) == 0) {
195         if ((instr->Bit(24) == 0x1) ||
196             (instr->Mask(0x01000010) == 0x00000010)) {
197           VisitUnallocated(instr);
198         } else {
199           VisitConditionalBranch(instr);
200         }
201       } else {
202         VisitUnallocated(instr);
203       }
204       break;
205     }
206     case 6: {
207       if (instr->Bit(25) == 0) {
208         if (instr->Bit(24) == 0) {
209           if ((instr->Bits(4, 2) != 0) ||
210               (instr->Mask(0x00E0001D) == 0x00200001) ||
211               (instr->Mask(0x00E0001D) == 0x00400001) ||
212               (instr->Mask(0x00E0001E) == 0x00200002) ||
213               (instr->Mask(0x00E0001E) == 0x00400002) ||
214               (instr->Mask(0x00E0001C) == 0x00600000) ||
215               (instr->Mask(0x00E0001C) == 0x00800000) ||
216               (instr->Mask(0x00E0001F) == 0x00A00000) ||
217               (instr->Mask(0x00C0001C) == 0x00C00000)) {
218             VisitUnallocated(instr);
219           } else {
220             VisitException(instr);
221           }
222         } else {
223           if (instr->Bits(23, 22) == 0) {
224             const Instr masked_003FF0E0 = instr->Mask(0x003FF0E0);
225             if ((instr->Bits(21, 19) == 0x4) ||
226                 (masked_003FF0E0 == 0x00033000) ||
227                 (masked_003FF0E0 == 0x003FF020) ||
228                 (masked_003FF0E0 == 0x003FF060) ||
229                 (masked_003FF0E0 == 0x003FF0E0) ||
230                 (instr->Mask(0x00388000) == 0x00008000) ||
231                 (instr->Mask(0x0038E000) == 0x00000000) ||
232                 (instr->Mask(0x0039E000) == 0x00002000) ||
233                 (instr->Mask(0x003AE000) == 0x00002000) ||
234                 (instr->Mask(0x003CE000) == 0x00042000) ||
235                 (instr->Mask(0x003FFFC0) == 0x000320C0) ||
236                 (instr->Mask(0x003FF100) == 0x00032100) ||
237                 (instr->Mask(0x003FF200) == 0x00032200) ||
238                 (instr->Mask(0x003FF400) == 0x00032400) ||
239                 (instr->Mask(0x003FF800) == 0x00032800) ||
240                 (instr->Mask(0x0038F000) == 0x00005000) ||
241                 (instr->Mask(0x0038E000) == 0x00006000)) {
242               VisitUnallocated(instr);
243             } else {
244               VisitSystem(instr);
245             }
246           } else {
247             VisitUnallocated(instr);
248           }
249         }
250       } else {
251         if ((instr->Bit(24) == 0x1) ||
252             (instr->Bits(20, 16) != 0x1F) ||
253             (instr->Bits(15, 10) != 0) ||
254             (instr->Bits(4, 0) != 0) ||
255             (instr->Bits(24, 21) == 0x3) ||
256             (instr->Bits(24, 22) == 0x3)) {
257           VisitUnallocated(instr);
258         } else {
259           VisitUnconditionalBranchToRegister(instr);
260         }
261       }
262       break;
263     }
264     case 3:
265     case 7: {
266       VisitUnallocated(instr);
267       break;
268     }
269   }
270 }
271 
272 
DecodeLoadStore(Instruction * instr)273 void Decoder::DecodeLoadStore(Instruction* instr) {
274   VIXL_ASSERT((instr->Bits(27, 24) == 0x8) ||
275          (instr->Bits(27, 24) == 0x9) ||
276          (instr->Bits(27, 24) == 0xC) ||
277          (instr->Bits(27, 24) == 0xD) );
278 
279   if (instr->Bit(24) == 0) {
280     if (instr->Bit(28) == 0) {
281       if (instr->Bit(29) == 0) {
282         if (instr->Bit(26) == 0) {
283           // TODO: VisitLoadStoreExclusive.
284           VisitUnimplemented(instr);
285         } else {
286           DecodeAdvSIMDLoadStore(instr);
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(Instruction * instr)392 void Decoder::DecodeLogical(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(Instruction * instr)411 void Decoder::DecodeBitfieldExtract(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(Instruction * instr)436 void Decoder::DecodeAddSubImmediate(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(Instruction * instr)446 void Decoder::DecodeDataProcessing(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           } else {
492             if (instr->Bit(30) == 0) {
493               if ((instr->Bit(15) == 0x1) ||
494                   (instr->Bits(15, 11) == 0) ||
495                   (instr->Bits(15, 12) == 0x1) ||
496                   (instr->Bits(15, 12) == 0x3) ||
497                   (instr->Bits(15, 13) == 0x3) ||
498                   (instr->Mask(0x8000EC00) == 0x00004C00) ||
499                   (instr->Mask(0x8000E800) == 0x80004000) ||
500                   (instr->Mask(0x8000E400) == 0x80004000)) {
501                 VisitUnallocated(instr);
502               } else {
503                 VisitDataProcessing2Source(instr);
504               }
505             } else {
506               if ((instr->Bit(13) == 1) ||
507                   (instr->Bits(20, 16) != 0) ||
508                   (instr->Bits(15, 14) != 0) ||
509                   (instr->Mask(0xA01FFC00) == 0x00000C00) ||
510                   (instr->Mask(0x201FF800) == 0x00001800)) {
511                 VisitUnallocated(instr);
512               } else {
513                 VisitDataProcessing1Source(instr);
514               }
515             }
516             break;
517           }
518         }
519         case 1:
520         case 3:
521         case 5:
522         case 7: VisitUnallocated(instr); break;
523       }
524     }
525   } else {
526     if (instr->Bit(28) == 0) {
527      if (instr->Bit(21) == 0) {
528         if ((instr->Bits(23, 22) == 0x3) ||
529             (instr->Mask(0x80008000) == 0x00008000)) {
530           VisitUnallocated(instr);
531         } else {
532           VisitAddSubShifted(instr);
533         }
534       } else {
535         if ((instr->Mask(0x00C00000) != 0x00000000) ||
536             (instr->Mask(0x00001400) == 0x00001400) ||
537             (instr->Mask(0x00001800) == 0x00001800)) {
538           VisitUnallocated(instr);
539         } else {
540           VisitAddSubExtended(instr);
541         }
542       }
543     } else {
544       if ((instr->Bit(30) == 0x1) ||
545           (instr->Bits(30, 29) == 0x1) ||
546           (instr->Mask(0xE0600000) == 0x00200000) ||
547           (instr->Mask(0xE0608000) == 0x00400000) ||
548           (instr->Mask(0x60608000) == 0x00408000) ||
549           (instr->Mask(0x60E00000) == 0x00E00000) ||
550           (instr->Mask(0x60E00000) == 0x00800000) ||
551           (instr->Mask(0x60E00000) == 0x00600000)) {
552         VisitUnallocated(instr);
553       } else {
554         VisitDataProcessing3Source(instr);
555       }
556     }
557   }
558 }
559 
560 
DecodeFP(Instruction * instr)561 void Decoder::DecodeFP(Instruction* instr) {
562   VIXL_ASSERT((instr->Bits(27, 24) == 0xE) ||
563               (instr->Bits(27, 24) == 0xF));
564 
565   if (instr->Bit(28) == 0) {
566     DecodeAdvSIMDDataProcessing(instr);
567   } else {
568     if (instr->Bit(29) == 1) {
569       VisitUnallocated(instr);
570     } else {
571       if (instr->Bits(31, 30) == 0x3) {
572         VisitUnallocated(instr);
573       } else if (instr->Bits(31, 30) == 0x1) {
574         DecodeAdvSIMDDataProcessing(instr);
575       } else {
576         if (instr->Bit(24) == 0) {
577           if (instr->Bit(21) == 0) {
578             if ((instr->Bit(23) == 1) ||
579                 (instr->Bit(18) == 1) ||
580                 (instr->Mask(0x80008000) == 0x00000000) ||
581                 (instr->Mask(0x000E0000) == 0x00000000) ||
582                 (instr->Mask(0x000E0000) == 0x000A0000) ||
583                 (instr->Mask(0x00160000) == 0x00000000) ||
584                 (instr->Mask(0x00160000) == 0x00120000)) {
585               VisitUnallocated(instr);
586             } else {
587               VisitFPFixedPointConvert(instr);
588             }
589           } else {
590             if (instr->Bits(15, 10) == 32) {
591               VisitUnallocated(instr);
592             } else if (instr->Bits(15, 10) == 0) {
593               if ((instr->Bits(23, 22) == 0x3) ||
594                   (instr->Mask(0x000E0000) == 0x000A0000) ||
595                   (instr->Mask(0x000E0000) == 0x000C0000) ||
596                   (instr->Mask(0x00160000) == 0x00120000) ||
597                   (instr->Mask(0x00160000) == 0x00140000) ||
598                   (instr->Mask(0x20C40000) == 0x00800000) ||
599                   (instr->Mask(0x20C60000) == 0x00840000) ||
600                   (instr->Mask(0xA0C60000) == 0x80060000) ||
601                   (instr->Mask(0xA0C60000) == 0x00860000) ||
602                   (instr->Mask(0xA0C60000) == 0x00460000) ||
603                   (instr->Mask(0xA0CE0000) == 0x80860000) ||
604                   (instr->Mask(0xA0CE0000) == 0x804E0000) ||
605                   (instr->Mask(0xA0CE0000) == 0x000E0000) ||
606                   (instr->Mask(0xA0D60000) == 0x00160000) ||
607                   (instr->Mask(0xA0D60000) == 0x80560000) ||
608                   (instr->Mask(0xA0D60000) == 0x80960000)) {
609                 VisitUnallocated(instr);
610               } else {
611                 VisitFPIntegerConvert(instr);
612               }
613             } else if (instr->Bits(14, 10) == 16) {
614               const Instr masked_A0DF8000 = instr->Mask(0xA0DF8000);
615               if ((instr->Mask(0x80180000) != 0) ||
616                   (masked_A0DF8000 == 0x00020000) ||
617                   (masked_A0DF8000 == 0x00030000) ||
618                   (masked_A0DF8000 == 0x00068000) ||
619                   (masked_A0DF8000 == 0x00428000) ||
620                   (masked_A0DF8000 == 0x00430000) ||
621                   (masked_A0DF8000 == 0x00468000) ||
622                   (instr->Mask(0xA0D80000) == 0x00800000) ||
623                   (instr->Mask(0xA0DE0000) == 0x00C00000) ||
624                   (instr->Mask(0xA0DF0000) == 0x00C30000) ||
625                   (instr->Mask(0xA0DC0000) == 0x00C40000)) {
626                 VisitUnallocated(instr);
627               } else {
628                 VisitFPDataProcessing1Source(instr);
629               }
630             } else if (instr->Bits(13, 10) == 8) {
631               if ((instr->Bits(15, 14) != 0) ||
632                   (instr->Bits(2, 0) != 0) ||
633                   (instr->Mask(0x80800000) != 0x00000000)) {
634                 VisitUnallocated(instr);
635               } else {
636                 VisitFPCompare(instr);
637               }
638             } else if (instr->Bits(12, 10) == 4) {
639               if ((instr->Bits(9, 5) != 0) ||
640                   (instr->Mask(0x80800000) != 0x00000000)) {
641                 VisitUnallocated(instr);
642               } else {
643                 VisitFPImmediate(instr);
644               }
645             } else {
646               if (instr->Mask(0x80800000) != 0x00000000) {
647                 VisitUnallocated(instr);
648               } else {
649                 switch (instr->Bits(11, 10)) {
650                   case 1: {
651                     VisitFPConditionalCompare(instr);
652                     break;
653                   }
654                   case 2: {
655                     if ((instr->Bits(15, 14) == 0x3) ||
656                         (instr->Mask(0x00009000) == 0x00009000) ||
657                         (instr->Mask(0x0000A000) == 0x0000A000)) {
658                       VisitUnallocated(instr);
659                     } else {
660                       VisitFPDataProcessing2Source(instr);
661                     }
662                     break;
663                   }
664                   case 3: {
665                     VisitFPConditionalSelect(instr);
666                     break;
667                   }
668                   default: VIXL_UNREACHABLE();
669                 }
670               }
671             }
672           }
673         } else {
674           // Bit 30 == 1 has been handled earlier.
675           VIXL_ASSERT(instr->Bit(30) == 0);
676           if (instr->Mask(0xA0800000) != 0) {
677             VisitUnallocated(instr);
678           } else {
679             VisitFPDataProcessing3Source(instr);
680           }
681         }
682       }
683     }
684   }
685 }
686 
687 
DecodeAdvSIMDLoadStore(Instruction * instr)688 void Decoder::DecodeAdvSIMDLoadStore(Instruction* instr) {
689   // TODO: Implement Advanced SIMD load/store instruction decode.
690   VIXL_ASSERT(instr->Bits(29, 25) == 0x6);
691   VisitUnimplemented(instr);
692 }
693 
694 
DecodeAdvSIMDDataProcessing(Instruction * instr)695 void Decoder::DecodeAdvSIMDDataProcessing(Instruction* instr) {
696   // TODO: Implement Advanced SIMD data processing instruction decode.
697   VIXL_ASSERT(instr->Bits(27, 25) == 0x7);
698   VisitUnimplemented(instr);
699 }
700 
701 
702 #define DEFINE_VISITOR_CALLERS(A)                                              \
703   void Decoder::Visit##A(Instruction *instr) {                                 \
704     VIXL_ASSERT(instr->Mask(A##FMask) == A##Fixed);                            \
705     std::list<DecoderVisitor*>::iterator it;                                   \
706     for (it = visitors_.begin(); it != visitors_.end(); it++) {                \
707       (*it)->Visit##A(instr);                                                  \
708     }                                                                          \
709   }
710 VISITOR_LIST(DEFINE_VISITOR_CALLERS)
711 #undef DEFINE_VISITOR_CALLERS
712 }  // namespace vixl
713