qemu/disas/libvixl/vixl/a64/decoder-a64.cc
<<
>>
Prefs
   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
 878