tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Decoder-vixl.cpp (28979B)


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