cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

decoder-a64.cc (28131B)


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