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
31namespace vixl {
32// Top-level instruction decode function.
33void 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
111void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
112  visitors_.remove(new_visitor);
113  visitors_.push_front(new_visitor);
114}
115
116
117void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
118  visitors_.remove(new_visitor);
119  visitors_.push_back(new_visitor);
120}
121
122
123void 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
140void 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
158void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
159  visitors_.remove(visitor);
160}
161
162
163void 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
172void 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
273void 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
392void 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
411void 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
436void 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
446void 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
561void 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
688void 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
695void 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  }
710VISITOR_LIST(DEFINE_VISITOR_CALLERS)
711#undef DEFINE_VISITOR_CALLERS
712}  // namespace vixl
713