/ disassembler / ARM64 / A64DOpcode.cpp
A64DOpcode.cpp
   1  /*
   2   * Copyright (C) 2012, 2016 Apple Inc. 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
   6   * are met:
   7   * 1. Redistributions of source code must retain the above copyright
   8   *    notice, this list of conditions and the following disclaimer.
   9   * 2. Redistributions in binary form must reproduce the above copyright
  10   *    notice, this list of conditions and the following disclaimer in the
  11   *    documentation and/or other materials provided with the distribution.
  12   *
  13   * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  17   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24   */
  25  
  26  #include "config.h"
  27  
  28  #if ENABLE(ARM64_DISASSEMBLER)
  29  
  30  #include "A64DOpcode.h"
  31  
  32  #include <stdarg.h>
  33  #include <stdint.h>
  34  #include <stdio.h>
  35  
  36  namespace JSC { namespace ARM64Disassembler {
  37  
  38  A64DOpcode::OpcodeGroup* A64DOpcode::opcodeTable[32];
  39  
  40  const char* const A64DOpcode::s_conditionNames[16] = {
  41      "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
  42      "hi", "ls", "ge", "lt", "gt", "le", "al", "ne"
  43  };
  44  
  45  const char* const A64DOpcode::s_optionName[8] = {
  46      "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"
  47  };
  48  
  49  const char* const A64DOpcode::s_shiftNames[4] = {
  50      "lsl", "lsr", "asl", "ror"
  51  };
  52  
  53  const char A64DOpcode::s_FPRegisterPrefix[5] = {
  54      'b', 'h', 's', 'd', 'q'
  55  };
  56  
  57  struct OpcodeGroupInitializer {
  58      unsigned m_opcodeGroupNumber;
  59      uint32_t m_mask;
  60      uint32_t m_pattern;
  61      const char* (*m_format)(A64DOpcode*);
  62  };
  63  
  64  #define OPCODE_GROUP_ENTRY(groupIndex, groupClass) \
  65  { groupIndex, groupClass::mask, groupClass::pattern, groupClass::format }
  66  
  67  static const OpcodeGroupInitializer opcodeGroupList[] = {
  68      OPCODE_GROUP_ENTRY(0x08, A64DOpcodeCAS),
  69      OPCODE_GROUP_ENTRY(0x08, A64DOpcodeLoadStoreRegisterPair),
  70      OPCODE_GROUP_ENTRY(0x08, A64DOpcodeLoadStoreExclusive),
  71      OPCODE_GROUP_ENTRY(0x09, A64DOpcodeLoadStoreRegisterPair),
  72      OPCODE_GROUP_ENTRY(0x0a, A64DOpcodeLogicalShiftedRegister),
  73      OPCODE_GROUP_ENTRY(0x0b, A64DOpcodeAddSubtractExtendedRegister),
  74      OPCODE_GROUP_ENTRY(0x0b, A64DOpcodeAddSubtractShiftedRegister),
  75      OPCODE_GROUP_ENTRY(0x11, A64DOpcodeAddSubtractImmediate),
  76      OPCODE_GROUP_ENTRY(0x12, A64DOpcodeMoveWide),
  77      OPCODE_GROUP_ENTRY(0x12, A64DOpcodeLogicalImmediate),
  78      OPCODE_GROUP_ENTRY(0x13, A64DOpcodeBitfield),
  79      OPCODE_GROUP_ENTRY(0x13, A64DOpcodeExtract),
  80      OPCODE_GROUP_ENTRY(0x14, A64DOpcodeUnconditionalBranchImmediate),
  81      OPCODE_GROUP_ENTRY(0x14, A64DOpcodeConditionalBranchImmediate),
  82      OPCODE_GROUP_ENTRY(0x14, A64DOpcodeCompareAndBranchImmediate),
  83      OPCODE_GROUP_ENTRY(0x14, A64OpcodeExceptionGeneration),
  84      OPCODE_GROUP_ENTRY(0x15, A64DOpcodeUnconditionalBranchImmediate),
  85      OPCODE_GROUP_ENTRY(0x15, A64DOpcodeConditionalBranchImmediate),
  86      OPCODE_GROUP_ENTRY(0x15, A64DOpcodeCompareAndBranchImmediate),
  87      OPCODE_GROUP_ENTRY(0x15, A64DOpcodeHint),
  88      OPCODE_GROUP_ENTRY(0x15, A64DOpcodeSystemSync),
  89      OPCODE_GROUP_ENTRY(0x15, A64DOpcodeMSRImmediate),
  90      OPCODE_GROUP_ENTRY(0x15, A64DOpcodeMSROrMRSRegister),
  91      OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchImmediate),
  92      OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchRegister),
  93      OPCODE_GROUP_ENTRY(0x16, A64DOpcodeTestAndBranchImmediate),
  94      OPCODE_GROUP_ENTRY(0x17, A64DOpcodeUnconditionalBranchImmediate),
  95      OPCODE_GROUP_ENTRY(0x17, A64DOpcodeUnconditionalBranchRegister),
  96      OPCODE_GROUP_ENTRY(0x17, A64DOpcodeTestAndBranchImmediate),
  97      OPCODE_GROUP_ENTRY(0x18, A64DOpcodeLoadStoreImmediate),
  98      OPCODE_GROUP_ENTRY(0x18, A64DOpcodeLoadStoreRegisterOffset),
  99      OPCODE_GROUP_ENTRY(0x18, A64DOpcodeLoadStoreAuthenticated),
 100      OPCODE_GROUP_ENTRY(0x18, A64DOpcodeLoadAtomic),
 101      OPCODE_GROUP_ENTRY(0x18, A64DOpcodeSwapAtomic),
 102      OPCODE_GROUP_ENTRY(0x19, A64DOpcodeLoadStoreUnsignedImmediate),
 103      OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeConditionalSelect),
 104      OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeDataProcessing1Source),
 105      OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeDataProcessing2Source),
 106      OPCODE_GROUP_ENTRY(0x1b, A64DOpcodeDataProcessing3Source),
 107      OPCODE_GROUP_ENTRY(0x1c, A64DOpcodeLoadStoreImmediate),
 108      OPCODE_GROUP_ENTRY(0x1c, A64DOpcodeLoadStoreRegisterOffset),
 109      OPCODE_GROUP_ENTRY(0x1d, A64DOpcodeLoadStoreUnsignedImmediate),
 110      OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointCompare),
 111      OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointConditionalSelect),
 112      OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointDataProcessing2Source),
 113      OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointDataProcessing1Source),
 114      OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingFixedPointConversions),
 115      OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointIntegerConversions),
 116  };
 117  
 118  bool A64DOpcode::s_initialized = false;
 119  
 120  void A64DOpcode::init()
 121  {
 122      if (s_initialized)
 123          return;
 124  
 125      OpcodeGroup* lastGroups[32];
 126  
 127      for (unsigned i = 0; i < 32; i++) {
 128          opcodeTable[i] = 0;
 129          lastGroups[i] = 0;
 130      }
 131  
 132      for (unsigned i = 0; i < sizeof(opcodeGroupList) / sizeof(struct OpcodeGroupInitializer); i++) {
 133          OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcodeGroupList[i].m_mask, opcodeGroupList[i].m_pattern, opcodeGroupList[i].m_format);
 134          uint32_t opcodeGroupNumber = opcodeGroupList[i].m_opcodeGroupNumber;
 135  
 136          if (!opcodeTable[opcodeGroupNumber])
 137              opcodeTable[opcodeGroupNumber] = newOpcodeGroup;
 138          else
 139              lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup);
 140          lastGroups[opcodeGroupNumber] = newOpcodeGroup;
 141      }
 142  
 143      s_initialized = true;
 144  }
 145  
 146  void A64DOpcode::setPCAndOpcode(uint32_t* newPC, uint32_t newOpcode)
 147  {
 148      m_currentPC = newPC;
 149      m_opcode = newOpcode;
 150      m_bufferOffset = 0;
 151      m_formatBuffer[0] = '\0';
 152  }
 153  
 154  const char* A64DOpcode::disassemble(uint32_t* currentPC)
 155  {
 156      setPCAndOpcode(currentPC, *currentPC);
 157  
 158      OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)];
 159  
 160      while (opGroup) {
 161          if (opGroup->matches(m_opcode))
 162              return opGroup->format(this);
 163          opGroup = opGroup->next();
 164      }
 165  
 166      return A64DOpcode::format();
 167  }
 168  
 169  void A64DOpcode::bufferPrintf(const char* format, ...)
 170  {
 171      if (m_bufferOffset >= bufferSize)
 172          return;
 173  
 174      va_list argList;
 175      va_start(argList, format);
 176  
 177      m_bufferOffset += vsnprintf(m_formatBuffer + m_bufferOffset, bufferSize - m_bufferOffset, format, argList);
 178  
 179      va_end(argList);
 180  }
 181  
 182  const char* A64DOpcode::format()
 183  {
 184      bufferPrintf("   .long  %08x", m_opcode);
 185      return m_formatBuffer;
 186  }
 187  
 188  void A64DOpcode::appendRegisterName(unsigned registerNumber, bool is64Bit)
 189  {
 190      if (registerNumber == 29) {
 191          bufferPrintf(is64Bit ? "fp" : "wfp");
 192          return;
 193      }
 194  
 195      if (registerNumber == 30) {
 196          bufferPrintf(is64Bit ? "lr" : "wlr");
 197          return;
 198      }
 199  
 200      bufferPrintf("%c%u", is64Bit ? 'x' : 'w', registerNumber);
 201  }
 202  
 203  void A64DOpcode::appendFPRegisterName(unsigned registerNumber, unsigned registerSize)
 204  {
 205      bufferPrintf("%c%u", FPRegisterPrefix(registerSize), registerNumber);
 206  }
 207  
 208  const char* const A64DOpcodeAddSubtract::s_opNames[4] = { "add", "adds", "sub", "subs" };
 209  
 210  const char* A64DOpcodeAddSubtractImmediate::format()
 211  {
 212      if (isCMP())
 213          appendInstructionName(cmpName());
 214      else {
 215          if (isMovSP())
 216              appendInstructionName("mov");
 217          else
 218              appendInstructionName(opName());
 219          appendSPOrRegisterName(rd(), is64Bit());
 220          appendSeparator();
 221      }
 222      appendSPOrRegisterName(rn(), is64Bit());
 223  
 224      if (!isMovSP()) {
 225          appendSeparator();
 226          appendUnsignedImmediate(immed12());
 227          if (shift()) {
 228              appendSeparator();
 229              appendString(shift() == 1 ? "lsl" : "reserved");
 230          }
 231      }
 232      return m_formatBuffer;
 233  }
 234  
 235  const char* A64DOpcodeAddSubtractExtendedRegister::format()
 236  {
 237      if (immediate3() > 4)
 238          return A64DOpcode::format();
 239  
 240      if (isCMP())
 241          appendInstructionName(cmpName());
 242      else {
 243          appendInstructionName(opName());
 244          appendSPOrRegisterName(rd(), is64Bit());
 245          appendSeparator();
 246      }
 247      appendSPOrRegisterName(rn(), is64Bit());
 248      appendSeparator();
 249      appendZROrRegisterName(rm(), is64Bit() && ((option() & 0x3) == 0x3));
 250      appendSeparator();
 251      if (option() == 0x2 && ((rd() == 31) || (rn() == 31)))
 252          appendString("lsl");
 253      else
 254          appendString(optionName());
 255      if (immediate3()) {
 256          appendCharacter(' ');
 257          appendUnsignedImmediate(immediate3());
 258      }
 259  
 260      return m_formatBuffer;
 261  }
 262  
 263  const char* A64DOpcodeAddSubtractShiftedRegister::format()
 264  {
 265      if (!is64Bit() && immediate6() & 0x20)
 266          return A64DOpcode::format();
 267  
 268      if (shift() == 0x3)
 269          return A64DOpcode::format();
 270  
 271      if (isCMP())
 272          appendInstructionName(cmpName());
 273      else {
 274          if (isNeg())
 275              appendInstructionName(cmpName());
 276          else
 277              appendInstructionName(opName());
 278          appendSPOrRegisterName(rd(), is64Bit());
 279          appendSeparator();
 280      }
 281      if (!isNeg()) {
 282          appendRegisterName(rn(), is64Bit());
 283          appendSeparator();
 284      }
 285      appendZROrRegisterName(rm(), is64Bit());
 286      if (immediate6()) {
 287          appendSeparator();
 288          appendShiftType(shift());
 289          appendUnsignedImmediate(immediate6());
 290      }
 291  
 292      return m_formatBuffer;
 293  }
 294  
 295  const char* const A64DOpcodeBitfield::s_opNames[3] = { "sbfm", "bfm", "ubfm" };
 296  const char* const A64DOpcodeBitfield::s_extendPseudoOpNames[3][3] = {
 297      { "sxtb", "sxth", "sxtw" }, { 0, 0, 0} , { "uxtb", "uxth", "uxtw" } };
 298  const char* const A64DOpcodeBitfield::s_insertOpNames[3] = { "sbfiz", "bfi", "ubfiz" };
 299  const char* const A64DOpcodeBitfield::s_extractOpNames[3] = { "sbfx", "bfxil", "ubfx" };
 300  
 301  const char* A64DOpcodeBitfield::format()
 302  {
 303      if (opc() == 0x3)
 304          return A64DOpcode::format();
 305  
 306      if (is64Bit() != nBit())
 307          return A64DOpcode::format();
 308  
 309      if (!is64Bit() && ((immediateR() & 0x20) || (immediateS() & 0x20)))
 310          return A64DOpcode::format();
 311  
 312      if (!(opc() & 0x1) && !immediateR()) {
 313          // [un]signed {btye,half-word,word} extend
 314          bool isSTXType = false;
 315          if (immediateS() == 7) {
 316              appendInstructionName(extendPseudoOpNames(0));
 317              isSTXType = true;
 318          } else if (immediateS() == 15) {
 319              appendInstructionName(extendPseudoOpNames(1));
 320              isSTXType = true;
 321          } else if (immediateS() == 31 && is64Bit() && !opc()) {
 322              appendInstructionName(extendPseudoOpNames(2));
 323              isSTXType = true;
 324          }
 325  
 326          if (isSTXType) {
 327              appendRegisterName(rd(), is64Bit());
 328              appendSeparator();
 329              appendRegisterName(rn(), false);
 330  
 331              return m_formatBuffer;
 332          }
 333      }
 334  
 335      if (!(opc() & 0x1) && ((immediateS() & 0x1f) == 0x1f) && (is64Bit() == (immediateS() >> 5))) {
 336          // asr/lsr
 337          appendInstructionName(!opc() ? "asr" : "lsr");
 338  
 339          appendRegisterName(rd(), is64Bit());
 340          appendSeparator();
 341          appendRegisterName(rn(), is64Bit());
 342          appendSeparator();
 343          appendUnsignedImmediate(immediateR());
 344  
 345          return m_formatBuffer;
 346      }
 347  
 348      if (opc() == 0x2 && (immediateS() + 1) == immediateR()) {
 349          // lsl
 350          appendInstructionName("lsl");
 351          appendRegisterName(rd(), is64Bit());
 352          appendSeparator();
 353          appendRegisterName(rn(), is64Bit());
 354          appendSeparator();
 355          appendUnsignedImmediate((is64Bit() ? 64u : 32u) - immediateR());
 356          
 357          return m_formatBuffer;
 358      }
 359      
 360      if (immediateS() < immediateR()) {
 361          if (opc() != 1 || rn() != 0x1f) {
 362              // bit field insert
 363              appendInstructionName(insertOpNames());
 364  
 365              appendRegisterName(rd(), is64Bit());
 366              appendSeparator();
 367              appendRegisterName(rn(), is64Bit());
 368              appendSeparator();
 369              appendUnsignedImmediate((is64Bit() ? 64u : 32u) - immediateR());
 370              appendSeparator();
 371              appendUnsignedImmediate(immediateS() + 1);
 372  
 373              return m_formatBuffer;
 374          }
 375          
 376          appendInstructionName(opName());
 377          appendRegisterName(rd(), is64Bit());
 378          appendSeparator();
 379          appendRegisterName(rn(), is64Bit());
 380          appendSeparator();
 381          appendUnsignedImmediate(immediateR());
 382          appendSeparator();
 383          appendUnsignedImmediate(immediateS());
 384          
 385          return m_formatBuffer;
 386      }
 387      
 388      // bit field extract
 389      appendInstructionName(extractOpNames());
 390  
 391      appendRegisterName(rd(), is64Bit());
 392      appendSeparator();
 393      appendRegisterName(rn(), is64Bit());
 394      appendSeparator();
 395      appendUnsignedImmediate(immediateR());
 396      appendSeparator();
 397      appendUnsignedImmediate(immediateS() - immediateR() + 1);
 398  
 399      return m_formatBuffer;
 400  }
 401  
 402  const char* A64DOpcodeCompareAndBranchImmediate::format()
 403  {
 404      appendInstructionName(opBit() ? "cbnz" : "cbz");
 405      appendRegisterName(rt(), is64Bit());
 406      appendSeparator();    
 407      appendPCRelativeOffset(m_currentPC, static_cast<int32_t>(immediate19()));
 408      return m_formatBuffer;
 409  }
 410  
 411  const char* A64DOpcodeConditionalBranchImmediate::format()
 412  {
 413      bufferPrintf("   b.%-5.5s", conditionName(condition()));
 414      appendPCRelativeOffset(m_currentPC, static_cast<int32_t>(immediate19()));
 415      return m_formatBuffer;
 416  }
 417  
 418  const char* const A64DOpcodeConditionalSelect::s_opNames[4] = {
 419      "csel", "csinc", "csinv", "csneg"
 420  };
 421  
 422  const char* A64DOpcodeConditionalSelect::format()
 423  {
 424      if (sBit())
 425          return A64DOpcode::format();
 426  
 427      if (op2() & 0x2)
 428          return A64DOpcode::format();
 429  
 430      if (rn() == rm() && (opNum() == 1 || opNum() == 2)) {
 431          if (rn() == 31) {
 432              appendInstructionName((opNum() == 1) ? "cset" : "csetm");
 433              appendRegisterName(rd(), is64Bit());
 434          } else {
 435              appendInstructionName((opNum() == 1) ? "cinc" : "cinv");
 436              appendRegisterName(rd(), is64Bit());
 437              appendSeparator();
 438              appendZROrRegisterName(rn(), is64Bit());
 439          }
 440          appendSeparator();
 441          appendString(conditionName(condition() ^ 0x1));
 442  
 443          return m_formatBuffer;
 444      }
 445  
 446      appendInstructionName(opName());
 447      appendRegisterName(rd(), is64Bit());
 448      appendSeparator();
 449      appendZROrRegisterName(rn(), is64Bit());
 450      appendSeparator();
 451      appendZROrRegisterName(rm(), is64Bit());
 452      appendSeparator();
 453      appendString(conditionName(condition()));
 454  
 455      return m_formatBuffer;
 456  
 457  }
 458  
 459  const char* const A64DOpcodeDataProcessing1Source::s_opNames[8] = {
 460      "rbit", "rev16", "rev32", "rev", "clz", "cls", 0, 0
 461  };
 462      
 463  const char* const A64DOpcodeDataProcessing1Source::s_pacAutOpNames[18] = {
 464      "pacia", "pacib", "pacda", "pacdb", "autia", "autib", "autda", "autdb",
 465      "paciza", "pacizb", "pacdza", "pacdzb", "autiza", "autizb", "autdza", "autdzb",
 466      "xpaci", "xpacd"
 467  };
 468  
 469  const char* A64DOpcodeDataProcessing1Source::format()
 470  {
 471      if (sBit())
 472          return A64DOpcode::format();
 473  
 474      if (opCode2() == 1 && is64Bit() && opCode() <= 0x1001) {
 475          if (opCode() <= 0x00111 || rt() == 0x11111) {
 476              appendInstructionName(s_pacAutOpNames[opCode()]);
 477              appendZROrRegisterName(rd(), is64Bit());
 478              if (opCode() <= 0x00111) {
 479                  appendSeparator();
 480                  appendZROrRegisterName(rn(), is64Bit());
 481              }
 482              return m_formatBuffer;
 483          }
 484          return A64DOpcode::format();
 485      }
 486  
 487      if (opCode2())
 488          return A64DOpcode::format();
 489  
 490      if (opCode() & 0x38)
 491          return A64DOpcode::format();
 492  
 493      if ((opCode() & 0x3e) == 0x6)
 494          return A64DOpcode::format();
 495  
 496      if (is64Bit() && opCode() == 0x3)
 497          return A64DOpcode::format();
 498  
 499      if (!is64Bit() && opCode() == 0x2)
 500          appendInstructionName("rev");
 501      else
 502          appendInstructionName(opName());
 503      appendZROrRegisterName(rd(), is64Bit());
 504      appendSeparator();
 505      appendZROrRegisterName(rn(), is64Bit());
 506      
 507      return m_formatBuffer;
 508  }
 509  
 510  const char* const A64DOpcodeDataProcessing2Source::s_opNames[16] = {
 511      // We use the pseudo-op names for the shift/rotate instructions
 512      0, 0, "udiv", "sdiv", 0, 0, 0, 0,
 513      "lsl", "lsr", "asr", "ror", 0, "pacga", 0, 0
 514  };
 515  
 516  const char* A64DOpcodeDataProcessing2Source::format()
 517  {
 518      if (sBit())
 519          return A64DOpcode::format();
 520  
 521      if (!(opCode() & 0x3e))
 522          return A64DOpcode::format();
 523  
 524      if (opCode() & 0x30)
 525          return A64DOpcode::format();
 526  
 527      if ((opCode() & 0x3c) == 0x4)
 528          return A64DOpcode::format();
 529  
 530      const char* opcodeName = opName();
 531      if (!opcodeName)
 532          return A64DOpcode::format();
 533  
 534      appendInstructionName(opcodeName);
 535      appendZROrRegisterName(rd(), is64Bit());
 536      appendSeparator();
 537      appendZROrRegisterName(rn(), is64Bit());
 538      appendSeparator();
 539      appendZROrRegisterName(rm(), is64Bit());
 540  
 541      return m_formatBuffer;
 542  }
 543  
 544  const char* const A64DOpcodeDataProcessing3Source::s_opNames[16] = {
 545      "madd", "msub", "smaddl", "smsubl", "smulh", 0, 0, 0,
 546      0, 0, "umaddl", "umsubl", "umulh", 0, 0, 0
 547  };
 548  
 549  const char* const A64DOpcodeDataProcessing3Source::s_pseudoOpNames[16] = {
 550      "mul", "mneg", "smull", "smnegl", "smulh", 0, 0, 0,
 551      0, 0, "umull", "umnegl", "umulh", 0, 0, 0
 552  };
 553  
 554  const char* A64DOpcodeDataProcessing3Source::format()
 555  {
 556      if (op54())
 557          return A64DOpcode::format();
 558  
 559      if (opNum() > 12)
 560          return A64DOpcode::format();
 561  
 562      if (!is64Bit() && opNum() > 1)
 563          return A64DOpcode::format();
 564  
 565      if (!opName())
 566          return A64DOpcode::format();
 567  
 568      if ((opNum() & 0x4) && (ra() != 31))
 569          return A64DOpcode::format();
 570  
 571      appendInstructionName(opName());
 572      appendZROrRegisterName(rd(), is64Bit());
 573      appendSeparator();
 574      bool srcOneAndTwoAre64Bit = is64Bit() & !(opNum() & 0x2);
 575      appendZROrRegisterName(rn(), srcOneAndTwoAre64Bit);
 576      appendSeparator();
 577      appendZROrRegisterName(rm(), srcOneAndTwoAre64Bit);
 578  
 579      if (ra() != 31) {
 580          appendSeparator();
 581          appendRegisterName(ra(), is64Bit());
 582      }
 583  
 584      return m_formatBuffer;
 585  }
 586  
 587  const char* A64OpcodeExceptionGeneration::format()
 588  {
 589      const char* opname = 0;
 590      if (!op2()) {
 591          switch (opc()) {
 592          case 0x0: // SVC, HVC & SMC
 593              switch (ll()) {
 594              case 0x1:
 595                  opname = "svc";
 596                  break;
 597              case 0x2:
 598                  opname = "hvc";
 599                  break;
 600              case 0x3:
 601                  opname = "smc";
 602                  break;
 603              }
 604              break;
 605          case 0x1: // BRK
 606              if (!ll())
 607                  opname = "brk";
 608              break;
 609          case 0x2: // HLT
 610              if (!ll())
 611                  opname = "hlt";
 612              break;
 613          case 0x5: // DPCS1-3
 614              switch (ll()) {
 615              case 0x1:
 616                  opname = "dpcs1";
 617                  break;
 618              case 0x2:
 619                  opname = "dpcs2";
 620                  break;
 621              case 0x3:
 622                  opname = "dpcs3";
 623                  break;
 624              }
 625              break;
 626          }
 627      }
 628  
 629      if (!opname)
 630          return A64DOpcode::format();
 631  
 632      appendInstructionName(opname);
 633      appendUnsignedImmediate(immediate16());
 634      return m_formatBuffer;
 635  }
 636  
 637  const char* A64DOpcodeExtract::format()
 638  {
 639      if (op21() || o0Bit())
 640          return A64DOpcode::format();
 641  
 642      if (is64Bit() != nBit())
 643          return A64DOpcode::format();
 644  
 645      if (!is64Bit() && (immediateS() & 0x20))
 646          return A64DOpcode::format();
 647  
 648      bool isROR = rn() == rm();
 649      const char* opName = (isROR) ? "ror" : "extr";
 650  
 651      appendInstructionName(opName);
 652      appendZROrRegisterName(rd(), is64Bit());
 653      appendSeparator();
 654      appendZROrRegisterName(rn(), is64Bit());
 655      if (!isROR) {
 656          appendSeparator();
 657          appendZROrRegisterName(rm(), is64Bit());
 658      }
 659      appendSeparator();
 660      appendUnsignedImmediate(immediateS());
 661  
 662      return m_formatBuffer;
 663  }
 664  
 665  const char* A64DOpcodeFloatingPointCompare::format()
 666  {
 667      if (mBit())
 668          return A64DOpcode::format();
 669  
 670      if (sBit())
 671          return A64DOpcode::format();
 672  
 673      if (type() & 0x2)
 674          return A64DOpcode::format();
 675  
 676      if (op())
 677          return A64DOpcode::format();
 678  
 679      if (opCode2() & 0x7)
 680          return A64DOpcode::format();
 681  
 682      appendInstructionName(opName());
 683      unsigned registerSize = type() + 2;
 684      appendFPRegisterName(rn(), registerSize);
 685      appendSeparator();
 686      if (opCode2() & 0x8)
 687          bufferPrintf("#0.0");
 688      else
 689          appendFPRegisterName(rm(), registerSize);
 690      
 691      return m_formatBuffer;
 692  }
 693  
 694  const char* A64DOpcodeFloatingPointConditionalSelect::format()
 695  {
 696      if (mBit())
 697          return A64DOpcode::format();
 698      
 699      if (sBit())
 700          return A64DOpcode::format();
 701      
 702      if (type() & 0x2)
 703          return A64DOpcode::format();
 704  
 705      appendInstructionName(opName());
 706      unsigned registerSize = type() + 2;
 707      appendFPRegisterName(rd(), registerSize);
 708      appendSeparator();
 709      appendFPRegisterName(rn(), registerSize);
 710      appendSeparator();
 711      appendFPRegisterName(rm(), registerSize);
 712      appendSeparator();
 713      appendString(conditionName(condition()));
 714      
 715      return m_formatBuffer;
 716  }
 717  
 718  const char* const A64DOpcodeFloatingPointDataProcessing1Source::s_opNames[16] = {
 719      "fmov", "fabs", "fneg", "fsqrt", "fcvt", "fcvt", 0, "fcvt",
 720      "frintn", "frintp", "frintm", "frintz", "frinta", 0, "frintx", "frinti"
 721  };
 722  
 723  const char* A64DOpcodeFloatingPointDataProcessing1Source::format()
 724  {
 725      if (mBit())
 726          return A64DOpcode::format();
 727  
 728      if (sBit())
 729          return A64DOpcode::format();
 730  
 731      if (opNum() > 16)
 732          return A64DOpcode::format();
 733  
 734      switch (type()) {
 735      case 0:
 736          if ((opNum() == 0x4) || (opNum() == 0x6) || (opNum() == 0xd))
 737              return A64DOpcode::format();
 738          break;
 739      case 1:
 740          if ((opNum() == 0x5) || (opNum() == 0x6) || (opNum() == 0xd))
 741              return A64DOpcode::format();
 742          break;
 743      case 2:
 744          return A64DOpcode::format();
 745      case 3:
 746          if ((opNum() < 0x4) || (opNum() > 0x5))
 747              return A64DOpcode::format();
 748          break;
 749      }
 750  
 751      appendInstructionName(opName());
 752      if ((opNum() >= 0x4) && (opNum() <= 0x7)) {
 753          unsigned srcRegisterSize = type() ^ 0x2; // 0:s, 1:d & 3:h
 754          unsigned destRegisterSize = (opNum() & 0x3) ^ 0x2;
 755          appendFPRegisterName(rd(), destRegisterSize);
 756          appendSeparator();
 757          appendFPRegisterName(rn(), srcRegisterSize);
 758      } else {
 759          unsigned registerSize = type() + 2;
 760          appendFPRegisterName(rd(), registerSize);
 761          appendSeparator();
 762          appendFPRegisterName(rn(), registerSize);
 763      }
 764  
 765      return m_formatBuffer;
 766  }
 767  
 768  const char* const A64DOpcodeFloatingPointDataProcessing2Source::s_opNames[16] = {
 769      "fmul", "fdiv", "fadd", "fsub", "fmax", "fmin", "fmaxnm", "fminnm", "fnmul"
 770  };
 771  
 772  const char* A64DOpcodeFloatingPointDataProcessing2Source::format()
 773  {
 774      if (mBit())
 775          return A64DOpcode::format();
 776  
 777      if (sBit())
 778          return A64DOpcode::format();
 779  
 780      if (type() & 0x2)
 781          return A64DOpcode::format();
 782  
 783      if (opNum() > 8)
 784          return A64DOpcode::format();
 785  
 786      appendInstructionName(opName());
 787      unsigned registerSize = type() + 2;
 788      appendFPRegisterName(rd(), registerSize);
 789      appendSeparator();
 790      appendFPRegisterName(rn(), registerSize);
 791      appendSeparator();
 792      appendFPRegisterName(rm(), registerSize);
 793  
 794      return m_formatBuffer;
 795  }
 796  
 797  const char* const A64DOpcodeFloatingFixedPointConversions::s_opNames[4] = {
 798      "fcvtzs", "fcvtzu", "scvtf", "ucvtf"
 799  };
 800  
 801  const char* A64DOpcodeFloatingFixedPointConversions::format()
 802  {
 803      if (sBit())
 804          return A64DOpcode::format();
 805  
 806      if (type() & 0x2)
 807          return A64DOpcode::format();
 808  
 809      if (opcode() & 0x4)
 810          return A64DOpcode::format();
 811  
 812      if (!(rmode() & 0x1) && !(opcode() & 0x6))
 813          return A64DOpcode::format();
 814  
 815      if ((rmode() & 0x1) && (opcode() & 0x6) == 0x2)
 816          return A64DOpcode::format();
 817  
 818      if (!(rmode() & 0x2) && !(opcode() & 0x6))
 819          return A64DOpcode::format();
 820  
 821      if ((rmode() & 0x2) && (opcode() & 0x6) == 0x2)
 822          return A64DOpcode::format();
 823  
 824      if (!is64Bit() && scale() >= 32)
 825          return A64DOpcode::format();
 826  
 827      appendInstructionName(opName());
 828      unsigned FPRegisterSize = type() + 2;
 829      bool destIsFP = !rmode();
 830      
 831      if (destIsFP) {
 832          appendFPRegisterName(rd(), FPRegisterSize);
 833          appendSeparator();
 834          appendRegisterName(rn(), is64Bit());
 835      } else {
 836          appendRegisterName(rd(), is64Bit());
 837          appendSeparator();
 838          appendFPRegisterName(rn(), FPRegisterSize);
 839      }
 840      appendSeparator();
 841      appendUnsignedImmediate(64 - scale());
 842      
 843      return m_formatBuffer;
 844  }
 845  
 846  const char* const A64DOpcodeFloatingPointIntegerConversions::s_opNames[32] = {
 847      "fcvtns", "fcvtnu", "scvtf", "ucvtf", "fcvtas", "fcvtau", "fmov", "fmov",
 848      "fcvtps", "fcvtpu", 0, 0, 0, 0, "fmov", "fmov",
 849      "fcvtms", "fcvtmu", 0, 0, 0, 0, 0, 0,
 850      "fcvtzs", "fcvtzu", 0, 0, 0, 0, "fjcvtzs", 0
 851  };
 852  
 853  const char* A64DOpcodeFloatingPointIntegerConversions::format()
 854  {
 855      if (sBit())
 856          return A64DOpcode::format();
 857  
 858      if (type() == 0x3)
 859          return A64DOpcode::format();
 860  
 861      if (((rmode() & 0x1) || (rmode() & 0x2)) && (((opcode() & 0x6) == 0x2) || ((opcode() & 0x6) == 0x4)))
 862          return A64DOpcode::format();
 863  
 864      if ((type() == 0x2) && (!(opcode() & 0x4) || ((opcode() & 0x6) == 0x4)))
 865          return A64DOpcode::format();
 866  
 867      if (!type() && (rmode() & 0x1) && ((opcode() & 0x6) == 0x6))
 868          return A64DOpcode::format();
 869  
 870      if (is64Bit() && type() == 0x2 && ((opNum() & 0xe) == 0x6))
 871          return A64DOpcode::format();
 872  
 873      if (!opName())
 874          return A64DOpcode::format();
 875  
 876      if ((opNum() & 0x1e) == 0xe) {
 877          // Handle fmov to/from upper half of quad separately
 878          if (!is64Bit() || (type() != 0x2))
 879              return A64DOpcode::format();
 880  
 881          appendInstructionName(opName());
 882          if (opcode() & 0x1) {
 883              // fmov Vd.D[1], Xn
 884              bufferPrintf("V%u.D[1]", rd());
 885              appendSeparator();
 886              appendZROrRegisterName(rn());
 887          } else {
 888              // fmov Xd, Vn.D[1]
 889              appendZROrRegisterName(rd());
 890              appendSeparator();
 891              bufferPrintf("V%u.D[1]", rn());
 892          }
 893  
 894          return m_formatBuffer;
 895      }
 896  
 897      appendInstructionName(opName());
 898      unsigned FPRegisterSize = type() + 2;
 899      bool destIsFP = ((opNum() == 2) || (opNum() == 3) || (opNum() == 7));
 900  
 901      if (destIsFP) {
 902          appendFPRegisterName(rd(), FPRegisterSize);
 903          appendSeparator();
 904          appendZROrRegisterName(rn(), is64Bit());
 905      } else {
 906          appendZROrRegisterName(rd(), is64Bit());
 907          appendSeparator();
 908          appendFPRegisterName(rn(), FPRegisterSize);
 909      }
 910  
 911      return m_formatBuffer;
 912  }
 913  
 914  const char* A64DOpcodeMSRImmediate::format()
 915  {
 916      const char* pstateField = nullptr;
 917  
 918      if (!op1() && (op2() == 0x5))
 919          pstateField = "spsel";
 920  
 921      if ((op1() == 0x3) && (op2() == 0x6))
 922          pstateField = "daifset";
 923  
 924      if ((op1() == 0x3) && (op2() == 0x7))
 925          pstateField = "daifclr";
 926  
 927      if (!!op1() && !(op2() & 0x4))
 928          return A64DOpcode::format();
 929  
 930      if (!pstateField)
 931          return A64DOpcode::format();
 932  
 933      appendInstructionName("msr");
 934      appendString(pstateField);
 935      appendSeparator();
 936      appendUnsignedImmediate(crM());
 937  
 938      return m_formatBuffer;
 939  }
 940  
 941  const char* A64DOpcodeMSROrMRSRegister::format()
 942  {
 943      appendInstructionName(opName());
 944  
 945      if (lBit()) {
 946          appendZROrRegisterName(rt());
 947          appendSeparator();
 948      }
 949  
 950      bufferPrintf("S%u_%u_C%u_C%u_%u", op0(), op1(), crN(), crM(), op2());
 951  
 952      if (!lBit()) {
 953          appendSeparator();
 954          appendZROrRegisterName(rt());
 955      }
 956  
 957      const char* systemRegisterName = nullptr;
 958  
 959      switch (systemRegister()) {
 960      case 0b1101100000000001:
 961          systemRegisterName = "ctr_el0";
 962          break;
 963      case 0b1101101000010000:
 964          systemRegisterName = "nzcv";
 965          break;
 966      case 0b1101101000010001:
 967          systemRegisterName = "daif";
 968          break;
 969      case 0b1101101000100000:
 970          systemRegisterName = "fpcr";
 971          break;
 972      case 0b1101101000100001:
 973          systemRegisterName = "fpsr";
 974          break;
 975      case 0b1101111010000010:
 976          systemRegisterName = "tpidr_el0";
 977          break;
 978      case 0b1101111010000011:
 979          systemRegisterName = "tpidrr0_el0";
 980          break;
 981      }
 982  
 983      if (systemRegisterName) {
 984          appendString("  ; ");
 985          appendString(systemRegisterName);
 986      }
 987      return m_formatBuffer;
 988  }
 989  
 990  const char* const A64DOpcodeHint::s_opNames[32] = {
 991      "nop", "yield", "wfe", "wfi", "sev", "sevl", 0, "xpaclri",
 992      "pacia1716", 0, "pacib1716", 0, "autia1716", 0, "autib1716", 0,
 993      0, 0, 0, 0, 0, 0, 0, 0,
 994      "paciaz", "paciasp", "pacibz", "pacibsp", "autiaz", "autiasp", "autibz", "autibsp"
 995  };
 996  
 997  const char* A64DOpcodeHint::format()
 998  {
 999      appendInstructionName(opName());
1000  
1001      if (immediate7() >= 32 || !s_opNames[immediate7()])
1002          appendUnsignedImmediate(immediate7());
1003  
1004      return m_formatBuffer;
1005  }
1006  
1007  const char* A64DOpcodeHint::opName()
1008  {
1009      const char* opName = (immediate7() < 32 ? s_opNames[immediate7()] : 0);
1010      if (!opName)
1011          return "hint";
1012  
1013      return opName;
1014  }
1015  
1016  const char* const A64DOpcodeSystemSync::s_opNames[8] = {
1017      0, 0, "clrex", 0, "dsb", "dmb", "isb", 0
1018  };
1019  
1020  const char* const A64DOpcodeSystemSync::s_optionNames[16] = {
1021      0, "oshld", "oshst", "osh", 0, "nshld", "nshst", "nsh",
1022      0, "ishld", "ishst", "ish", 0, "ld", "st", "sy"
1023  };
1024  
1025  const char* A64DOpcodeSystemSync::format()
1026  {
1027      const char* thisOpName = opName();
1028  
1029      if (!thisOpName)
1030          return A64DOpcode::format();
1031  
1032      appendInstructionName(thisOpName);
1033  
1034      if (op2() & 0x2) {
1035          if (crM() != 0xf) {
1036              appendCharacter('#');
1037              appendUnsignedImmediate(crM());
1038          }
1039      } else {
1040          const char* thisOption = option();
1041          if (thisOption)
1042              appendString(thisOption);
1043          else
1044              appendUnsignedImmediate(crM());
1045      }
1046  
1047      return m_formatBuffer;
1048  }
1049  
1050  const char* const A64DOpcodeLoadStoreExclusive::s_opNames[64] = {
1051      "stxrb", "stlxrb", 0, 0, "ldxrb", "ldaxrb", 0, 0,
1052      0, "stlrb", 0, 0, 0, "ldarb", 0, 0,
1053      "stxrh", "stlxrh", 0, 0, "ldxrh", "ldaxrh", 0, 0,
1054      0, "stlrh", 0, 0, 0, "ldarh", 0, 0,
1055      "stxr", "stlxr", "stxp", "stlxp", "ldxr", "ldaxr", "ldxp", "ldaxp",
1056      0, "stlr", 0, 0, 0, "ldar", 0, 0,
1057      "stxr", "stlxr", "stxp", "stlxp", "ldxr", "ldaxr", "ldxp", "ldaxp",
1058      0, "stlr", 0, 0, 0, "ldar", 0, 0
1059  };
1060  
1061  const char* A64DOpcodeLoadStoreExclusive::format()
1062  {
1063      if (o2() && !o1() && !o0())
1064          return A64DOpcode::format();
1065  
1066      if (o2() && o1())
1067          return A64DOpcode::format();
1068  
1069      if ((size() < 2) && o1())
1070          return A64DOpcode::format();
1071  
1072      if (loadBit() && (rs() != 0x1f))
1073          return A64DOpcode::format();
1074  
1075      if (!isPairOp() && (rt2() != 0x1f))
1076          return A64DOpcode::format();
1077  
1078      const char* thisOpName = opName();
1079  
1080      if (!thisOpName)
1081          return A64DOpcode::format();
1082  
1083      appendInstructionName(thisOpName);
1084  
1085      if (!loadBit()) {
1086          appendZROrRegisterName(rs(), size() == 0x3);
1087          appendSeparator();
1088      }
1089  
1090      appendZROrRegisterName(rt(), size() == 0x3);
1091      appendSeparator();
1092      if (isPairOp()) {
1093          appendZROrRegisterName(rt2(), size() == 0x3);
1094          appendSeparator();
1095      }
1096      appendCharacter('[');
1097      appendSPOrRegisterName(rn());
1098      appendCharacter(']');
1099  
1100      return m_formatBuffer;
1101  }
1102  
1103  // A zero in an entry of the table means the instruction is Unallocated
1104  const char* const A64DOpcodeLoadStore::s_opNames[32] = {
1105      "strb", "ldrb", "ldrsb", "ldrsb", "str", "ldr", "str", "ldr",
1106      "strh", "ldrh", "ldrsh", "ldrsh", "str", "ldr", 0, 0,
1107      "str", "ldr", "ldrsw", 0, "str", "ldr", 0, 0,
1108      "str", "ldr", 0, 0, "str", "ldr", 0, 0
1109  };
1110  
1111  // A zero in an entry of the table means the instruction is Unallocated
1112  const char* const A64DOpcodeLoadStoreImmediate::s_unprivilegedOpNames[32] = {
1113      "sttrb", "ldtrb", "ldtrsb", "ldtrsb", 0, 0, 0, 0,
1114      "sttrh", "ldtrh", "ldtrsh", "ldtrsh", 0, 0, 0, 0,
1115      "sttr", "ldtr", "ldtrsw", 0, 0, 0, 0, 0,
1116      "sttr", "ldtr", 0, 0, 0, 0, 0, 0
1117  };
1118  
1119  // A zero in an entry of the table means the instruction is Unallocated
1120  const char* const A64DOpcodeLoadStoreImmediate::s_unscaledOpNames[32] = {
1121      "sturb", "ldurb", "ldursb", "ldursb", "stur", "ldur", "stur", "ldur",
1122      "sturh", "ldurh", "ldursh", "ldursh", "stur", "ldur", 0, 0,
1123      "stur", "ldur", "ldursw", 0, "stur", "ldur", 0, 0,
1124      "stur", "ldur", "prfum", 0, "stur", "ldur", 0, 0
1125  };
1126  
1127  const char* A64DOpcodeLoadStoreImmediate::format()
1128  {
1129      const char* thisOpName;
1130  
1131      if (type() & 0x1)
1132          thisOpName = opName();
1133      else if (!type())
1134          thisOpName = unscaledOpName();
1135      else
1136          thisOpName = unprivilegedOpName();
1137  
1138      if (!thisOpName)
1139          return A64DOpcode::format();
1140  
1141      appendInstructionName(thisOpName);
1142      if (vBit())
1143          appendFPRegisterName(rt(), size());
1144      else if (!opc())
1145          appendZROrRegisterName(rt(), is64BitRT());
1146      else
1147          appendRegisterName(rt(), is64BitRT());
1148      appendSeparator();
1149      appendCharacter('[');
1150      appendSPOrRegisterName(rn());
1151  
1152      switch (type()) {
1153      case 0: // Unscaled Immediate
1154          if (immediate9()) {
1155              appendSeparator();
1156              appendSignedImmediate(immediate9());
1157          }
1158          appendCharacter(']');
1159          break;
1160      case 1: // Immediate Post-Indexed
1161          appendCharacter(']');
1162          if (immediate9()) {
1163              appendSeparator();
1164              appendSignedImmediate(immediate9());
1165          }
1166          break;
1167      case 2: // Unprivileged
1168          if (immediate9()) {
1169              appendSeparator();
1170              appendSignedImmediate(immediate9());
1171          }
1172          appendCharacter(']');
1173          break;
1174      case 3: // Immediate Pre-Indexed
1175          if (immediate9()) {
1176              appendSeparator();
1177              appendSignedImmediate(immediate9());
1178          }
1179          appendCharacter(']');
1180          appendCharacter('!');
1181          break;
1182      }
1183  
1184      return m_formatBuffer;
1185  }
1186  
1187  const char* A64DOpcodeLoadStoreRegisterOffset::format()
1188  {
1189      const char* thisOpName = opName();
1190  
1191      if (!thisOpName)
1192          return A64DOpcode::format();
1193  
1194      if (!(option() & 0x2))
1195          return A64DOpcode::format();
1196  
1197      appendInstructionName(thisOpName);
1198      unsigned scale;
1199      if (vBit()) {
1200          appendFPRegisterName(rt(), size());
1201          scale = ((opc() & 2)<<1) | size();
1202      } else {
1203          if (!opc())
1204              appendZROrRegisterName(rt(), is64BitRT());
1205          else
1206              appendRegisterName(rt(), is64BitRT());
1207          scale = size();
1208      }
1209      appendSeparator();
1210      appendCharacter('[');
1211      appendSPOrRegisterName(rn());
1212      if (rm() != 31) {
1213          appendSeparator();
1214          appendRegisterName(rm(), (option() & 0x3) == 0x3);
1215  
1216          unsigned shift = sBit() ? scale : 0;
1217  
1218          if (option() == 0x3) {
1219              if (shift) {
1220                  appendSeparator();
1221                  appendString("lsl ");
1222                  appendUnsignedImmediate(shift);
1223              }
1224          } else {
1225              appendSeparator();
1226              appendString(optionName());
1227              if (shift)
1228                  appendUnsignedImmediate(shift);
1229          }
1230      }
1231  
1232      appendCharacter(']');
1233  
1234      return m_formatBuffer;
1235  }
1236  
1237  const char* const A64DOpcodeLoadStoreAuthenticated::s_opNames[2] = {
1238      "ldraa", "ldrab"
1239  };
1240  
1241  const char* A64DOpcodeLoadStoreAuthenticated::format()
1242  {
1243      appendInstructionName(opName());
1244      appendRegisterName(rt());
1245      appendSeparator();
1246      appendCharacter('[');
1247      appendSPOrRegisterName(rn());
1248  
1249      if (wBit() || immediate10()) {
1250          appendSeparator();
1251          appendSignedImmediate(immediate10() << size());
1252      }
1253      appendCharacter(']');
1254  
1255      if (wBit())
1256          appendCharacter('!');
1257      
1258      return m_formatBuffer;
1259  }
1260  
1261  const char* const A64DOpcodeLoadAtomic::s_opNames[64] = {
1262      "ldaddb", "ldaddlb", "ldaddab", "ldaddalb",
1263      "ldaddh", "ldaddlh", "ldaddah", "ldaddalh",
1264      "ldadd", "ldaddl", "ldadda", "ldaddal",
1265      "ldadd", "ldaddl", "ldadda", "ldaddal",
1266  
1267      "ldclrb", "ldclrlb", "ldclrab", "ldclralb",
1268      "ldclrh", "ldclrlh", "ldclrah", "ldclralh",
1269      "ldclr", "ldclrl", "ldclra", "ldclral",
1270      "ldclr", "ldclrl", "ldclra", "ldclral",
1271  
1272      "ldeorb", "ldeorlb", "ldeorab", "ldeoralb",
1273      "ldeorh", "ldeorlh", "ldeorah", "ldeoralh",
1274      "ldeor", "ldeorl", "ldeora", "ldeoral",
1275      "ldeor", "ldeorl", "ldeora", "ldeoral",
1276  
1277      "ldsetb", "ldsetlb", "ldsetab", "ldsetalb",
1278      "ldseth", "ldsetlh", "ldsetah", "ldsetalh",
1279      "ldset", "ldsetl", "ldseta", "ldsetal",
1280      "ldset", "ldsetl", "ldseta", "ldsetal",
1281  };
1282  
1283  const char* A64DOpcodeLoadAtomic::format()
1284  {
1285      const auto* name = opName();
1286      if (!name)
1287          return A64DOpcode::format();
1288      appendInstructionName(name);
1289      appendSPOrRegisterName(rs(), is64Bit());
1290      appendSeparator();
1291      appendSPOrRegisterName(rt(), is64Bit());
1292      appendSeparator();
1293      appendCharacter('[');
1294      appendSPOrRegisterName(rn(), is64Bit());
1295      appendCharacter(']');
1296      return m_formatBuffer;
1297  }
1298  
1299  const char* const A64DOpcodeSwapAtomic::s_opNames[16] = {
1300      "swpb", "swplb", "swpab", "swpalb",
1301      "swph", "swplh", "swpah", "swpalh",
1302      "swp", "swpl", "swpa", "swpal",
1303      "swp", "swpl", "swpa", "swpal",
1304  };
1305  
1306  const char* A64DOpcodeSwapAtomic::format()
1307  {
1308      const auto* name = opName();
1309      appendInstructionName(name);
1310      appendSPOrRegisterName(rs(), is64Bit());
1311      appendSeparator();
1312      appendSPOrRegisterName(rt(), is64Bit());
1313      appendSeparator();
1314      appendCharacter('[');
1315      appendSPOrRegisterName(rn(), is64Bit());
1316      appendCharacter(']');
1317      return m_formatBuffer;
1318  }
1319  
1320  const char* const A64DOpcodeCAS::s_opNames[16] = {
1321      "casb", "caslb", "casab", "casalb",
1322      "cash", "caslh", "casah", "casalh",
1323      "cas", "casl", "casa", "casal",
1324      "cas", "casl", "casa", "casal",
1325  };
1326  
1327  const char* A64DOpcodeCAS::format()
1328  {
1329      const auto* name = opName();
1330      appendInstructionName(name);
1331      appendSPOrRegisterName(rs(), is64Bit());
1332      appendSeparator();
1333      appendSPOrRegisterName(rt(), is64Bit());
1334      appendSeparator();
1335      appendCharacter('[');
1336      appendSPOrRegisterName(rn(), is64Bit());
1337      appendCharacter(']');
1338      return m_formatBuffer;
1339  }
1340  
1341  const char* A64DOpcodeLoadStoreRegisterPair::opName()
1342  {
1343      if (!vBit() && lBit() && size() == 0x1)
1344          return "ldpsw";
1345      if (lBit())
1346          return "ldp";
1347      return "stp";
1348  }
1349  
1350  const char* A64DOpcodeLoadStoreRegisterPair::format()
1351  {
1352      const char* thisOpName = opName();
1353      
1354      if (size() == 0x3)
1355          return A64DOpcode::format();
1356  
1357      if ((offsetMode() < 0x1) || (offsetMode() > 0x3))
1358          return A64DOpcode::format();
1359  
1360      if ((offsetMode() == 0x1) && !vBit() && !lBit())
1361          return A64DOpcode::format();
1362  
1363      appendInstructionName(thisOpName);
1364      unsigned offsetShift;
1365      if (vBit()) {
1366          appendFPRegisterName(rt(), size());
1367          appendSeparator();
1368          appendFPRegisterName(rt2(), size());
1369          offsetShift = size() + 2;
1370      } else {
1371          if (!lBit())
1372              appendZROrRegisterName(rt(), is64Bit());
1373          else
1374              appendRegisterName(rt(), is64Bit());
1375          appendSeparator();
1376          if (!lBit())
1377              appendZROrRegisterName(rt2(), is64Bit());
1378          else
1379              appendRegisterName(rt2(), is64Bit());
1380          offsetShift = (size() >> 1) + 2;
1381      }
1382  
1383      appendSeparator();
1384      appendCharacter('[');
1385      appendSPOrRegisterName(rn());
1386  
1387      int offset = immediate7() << offsetShift;
1388  
1389      if (offsetMode() == 1) {
1390          appendCharacter(']');
1391          appendSeparator();
1392          appendSignedImmediate(offset);
1393      } else {
1394          appendSeparator();
1395          appendSignedImmediate(offset);
1396          appendCharacter(']');
1397          if (offsetMode() == 0x3)
1398              appendCharacter('!');
1399      }
1400  
1401      return m_formatBuffer;
1402  }
1403  
1404  const char* A64DOpcodeLoadStoreUnsignedImmediate::format()
1405  {
1406      const char* thisOpName = opName();
1407  
1408      if (!thisOpName)
1409          return A64DOpcode::format();
1410  
1411      appendInstructionName(thisOpName);
1412      unsigned scale;
1413      if (vBit()) {
1414          appendFPRegisterName(rt(), size());
1415          scale = ((opc() & 2)<<1) | size();
1416      } else {
1417          if (!opc())
1418              appendZROrRegisterName(rt(), is64BitRT());
1419          else
1420              appendRegisterName(rt(), is64BitRT());
1421          scale = size();
1422      }
1423      appendSeparator();
1424      appendCharacter('[');
1425      appendSPOrRegisterName(rn());
1426  
1427      if (immediate12()) {
1428          appendSeparator();
1429          appendUnsignedImmediate(immediate12() << scale);
1430      }
1431  
1432      appendCharacter(']');
1433  
1434      return m_formatBuffer;
1435  }
1436  
1437  // A zero in an entry of the table means the instruction is Unallocated
1438  const char* const A64DOpcodeLogical::s_opNames[8] = {
1439      "and", "bic", "orr", "orn", "eor", "eon", "ands", "bics"
1440  };
1441  
1442  const char* A64DOpcodeLogicalShiftedRegister::format()
1443  {
1444      if (!is64Bit() && immediate6() & 0x20)
1445          return A64DOpcode::format();
1446  
1447      if (isTst())
1448          appendInstructionName("tst");
1449      else {
1450          if (isMov())
1451              appendInstructionName(nBit() ? "mvn" : "mov");
1452          else
1453              appendInstructionName(opName(opNumber()));
1454          appendZROrRegisterName(rd(), is64Bit());
1455          appendSeparator();
1456      }
1457  
1458      if (!isMov()) {
1459          appendZROrRegisterName(rn(), is64Bit());
1460          appendSeparator();
1461      }
1462  
1463      appendZROrRegisterName(rm(), is64Bit());
1464      if (immediate6()) {
1465          appendSeparator();
1466          appendShiftType(shift());
1467          appendUnsignedImmediate(immediate6());
1468      }
1469  
1470      return m_formatBuffer;
1471  }
1472  
1473  static unsigned highestBitSet(unsigned value)
1474  {
1475      unsigned result = 0;
1476  
1477      while (value >>= 1)
1478          result++;
1479  
1480      return result;
1481  }
1482  
1483  static uint64_t rotateRight(uint64_t value, unsigned width, unsigned shift)
1484  {
1485      uint64_t result = value;
1486  
1487      if (shift)
1488          result = (value >> (shift % width)) | (value << (width - shift));
1489  
1490      return result;
1491  }
1492  
1493  static uint64_t replicate(uint64_t value, unsigned width)
1494  {
1495      uint64_t result = 0;
1496  
1497      for (unsigned totalBits = 0; totalBits < 64; totalBits += width)
1498          result = (result << width) | value;
1499  
1500      return result;
1501  }
1502  
1503  const char* A64DOpcodeLogicalImmediate::format()
1504  {
1505      if (!is64Bit() && nBit())
1506          return A64DOpcode::format();
1507  
1508      unsigned len = highestBitSet(nBit() << 6 | (immediateS() ^ 0x3f));
1509      unsigned levels = (1 << len) - 1; // len number of 1 bits starting at LSB
1510  
1511      if ((immediateS() & levels) == levels)
1512          return A64DOpcode::format();
1513  
1514      unsigned r = immediateR() & levels;
1515      unsigned s = immediateS() & levels;
1516      unsigned eSize = 1 << len;
1517      uint64_t pattern = rotateRight((1ull << (s + 1)) - 1, eSize, r);
1518  
1519      uint64_t immediate = replicate(pattern, eSize);
1520  
1521      if (!is64Bit())
1522          immediate &= 0xffffffffull;
1523  
1524      if (isTst())
1525          appendInstructionName("tst");
1526      else {
1527          if (isMov())
1528              appendInstructionName("mov");
1529          else
1530              appendInstructionName(opName(opNumber()));
1531          appendRegisterName(rd(), is64Bit());
1532          appendSeparator();
1533      }
1534      if (!isMov()) {
1535          appendRegisterName(rn(), is64Bit());
1536          appendSeparator();
1537      }
1538      appendUnsignedImmediate64(immediate);
1539  
1540      return m_formatBuffer;
1541  }
1542  
1543  const char* const A64DOpcodeMoveWide::s_opNames[4] = { "movn", 0, "movz", "movk" };
1544  
1545  const char* A64DOpcodeMoveWide::format()
1546  {
1547      if (opc() == 1)
1548          return A64DOpcode::format();
1549      if (!is64Bit() && hw() >= 2)
1550          return A64DOpcode::format();
1551  
1552      if (!opc() && (!immediate16() || !hw()) && (is64Bit() || immediate16() != 0xffff)) {
1553          // MOV pseudo op for MOVN
1554          appendInstructionName("mov");
1555          appendRegisterName(rd(), is64Bit());
1556          appendSeparator();
1557  
1558          if (is64Bit()) {
1559              int64_t amount = immediate16() << (hw() * 16);
1560              amount = ~amount;
1561              appendSignedImmediate64(amount);
1562          } else {
1563              int32_t amount = immediate16() << (hw() * 16);
1564              amount = ~amount;
1565              appendSignedImmediate(amount);
1566          }
1567      } else {
1568          appendInstructionName(opName());
1569          appendRegisterName(rd(), is64Bit());
1570          appendSeparator();
1571          appendUnsignedHexImmediate(immediate16());
1572          if (hw()) {
1573              appendSeparator();
1574              appendShiftAmount(hw());
1575          }
1576      }
1577  
1578      return m_formatBuffer;
1579  }
1580  
1581  const char* A64DOpcodeTestAndBranchImmediate::format()
1582  {
1583      appendInstructionName(opBit() ? "tbnz" : "tbz");
1584      appendRegisterName(rt());
1585      appendSeparator();
1586      appendUnsignedImmediate(bitNumber());
1587      appendSeparator();
1588      appendPCRelativeOffset(m_currentPC, static_cast<int32_t>(immediate14()));
1589      return m_formatBuffer;
1590  }
1591  
1592  const char* A64DOpcodeUnconditionalBranchImmediate::format()
1593  {
1594      appendInstructionName(op() ? "bl" : "b");
1595      appendPCRelativeOffset(m_currentPC, static_cast<int32_t>(immediate26()));
1596      return m_formatBuffer;
1597  }
1598  
1599  const char* const A64DOpcodeUnconditionalBranchRegister::s_opNames[8] = { "br", "blr", "ret", "", "eret", "drps", "", "" };
1600  const char* const A64DOpcodeUnconditionalBranchRegister::s_AuthOpNames[20] = {
1601      "braaz", "brabz", "blraaz", "blrabz", "retaa", "retab", 0, 0,
1602      "eretaa", "eretab", 0, 0, 0, 0, 0, 0,
1603      "braa", "brab", "blraa", "blrab"
1604  };
1605  
1606  const char* A64DOpcodeUnconditionalBranchRegister::authOpName()
1607  {
1608      unsigned opCode = authOpCode();
1609      if (opCode >= 20)
1610          return 0;
1611      return s_AuthOpNames[opCode];
1612  }
1613  
1614  const char* A64DOpcodeUnconditionalBranchRegister::format()
1615  {
1616      unsigned opcValue = opc();
1617      if (op2() == 0x1f && (op3() & 0x3e) == 0x2) {
1618          const char* opName = authOpName();
1619          if (!opName)
1620              return A64DOpcode::format();
1621          if (rn() != 0x1f && (opcValue == 0x2 || opcValue == 0x4))
1622              return A64DOpcode::format();
1623  
1624          appendInstructionName(opName);
1625          if ((opcValue & 0x7) <= 0x1)
1626              appendRegisterName(rn());
1627          if (opcValue & 0x8) {
1628              appendSeparator();
1629              appendRegisterName(rm());
1630          }
1631  
1632          return m_formatBuffer;
1633      }
1634      if (opcValue == 3 || opcValue > 5)
1635          return A64DOpcode::format();
1636      if (((opcValue & 0xe) == 0x4) && rn() != 0x1f)
1637          return A64DOpcode::format();
1638      appendInstructionName(opName());
1639      if (opcValue <= 2)
1640          appendRegisterName(rn());
1641      return m_formatBuffer;
1642  }
1643  
1644  } } // namespace JSC::ARM64Disassembler
1645  
1646  #endif // ENABLE(ARM64_DISASSEMBLER)