Home | History | Annotate | Download | only in a64
      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.
     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 
    111 void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
    112   visitors_.remove(new_visitor);
    113   visitors_.push_front(new_visitor);
    114 }
    115 
    116 
    117 void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
    118   visitors_.remove(new_visitor);
    119   visitors_.push_back(new_visitor);
    120 }
    121 
    122 
    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 
    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 
    158 void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
    159   visitors_.remove(visitor);
    160 }
    161 
    162 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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