Home | History | Annotate | Download | only in arm64
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <assert.h>
      6 #include <stdarg.h>
      7 #include <stdio.h>
      8 #include <string.h>
      9 
     10 #if V8_TARGET_ARCH_ARM64
     11 
     12 #include "src/arm64/decoder-arm64-inl.h"
     13 #include "src/arm64/disasm-arm64.h"
     14 #include "src/base/platform/platform.h"
     15 #include "src/disasm.h"
     16 #include "src/macro-assembler.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 
     21 
     22 DisassemblingDecoder::DisassemblingDecoder() {
     23   buffer_size_ = 256;
     24   buffer_ = reinterpret_cast<char*>(malloc(buffer_size_));
     25   buffer_pos_ = 0;
     26   own_buffer_ = true;
     27 }
     28 
     29 
     30 DisassemblingDecoder::DisassemblingDecoder(char* text_buffer, int buffer_size) {
     31   buffer_size_ = buffer_size;
     32   buffer_ = text_buffer;
     33   buffer_pos_ = 0;
     34   own_buffer_ = false;
     35 }
     36 
     37 
     38 DisassemblingDecoder::~DisassemblingDecoder() {
     39   if (own_buffer_) {
     40     free(buffer_);
     41   }
     42 }
     43 
     44 
     45 char* DisassemblingDecoder::GetOutput() { return buffer_; }
     46 
     47 
     48 void DisassemblingDecoder::VisitAddSubImmediate(Instruction* instr) {
     49   bool rd_is_zr = RdIsZROrSP(instr);
     50   bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
     51                   (instr->ImmAddSub() == 0) ? true : false;
     52   const char *mnemonic = "";
     53   const char *form = "'Rds, 'Rns, 'IAddSub";
     54   const char *form_cmp = "'Rns, 'IAddSub";
     55   const char *form_mov = "'Rds, 'Rns";
     56 
     57   switch (instr->Mask(AddSubImmediateMask)) {
     58     case ADD_w_imm:
     59     case ADD_x_imm: {
     60       mnemonic = "add";
     61       if (stack_op) {
     62         mnemonic = "mov";
     63         form = form_mov;
     64       }
     65       break;
     66     }
     67     case ADDS_w_imm:
     68     case ADDS_x_imm: {
     69       mnemonic = "adds";
     70       if (rd_is_zr) {
     71         mnemonic = "cmn";
     72         form = form_cmp;
     73       }
     74       break;
     75     }
     76     case SUB_w_imm:
     77     case SUB_x_imm: mnemonic = "sub"; break;
     78     case SUBS_w_imm:
     79     case SUBS_x_imm: {
     80       mnemonic = "subs";
     81       if (rd_is_zr) {
     82         mnemonic = "cmp";
     83         form = form_cmp;
     84       }
     85       break;
     86     }
     87     default: UNREACHABLE();
     88   }
     89   Format(instr, mnemonic, form);
     90 }
     91 
     92 
     93 void DisassemblingDecoder::VisitAddSubShifted(Instruction* instr) {
     94   bool rd_is_zr = RdIsZROrSP(instr);
     95   bool rn_is_zr = RnIsZROrSP(instr);
     96   const char *mnemonic = "";
     97   const char *form = "'Rd, 'Rn, 'Rm'HDP";
     98   const char *form_cmp = "'Rn, 'Rm'HDP";
     99   const char *form_neg = "'Rd, 'Rm'HDP";
    100 
    101   switch (instr->Mask(AddSubShiftedMask)) {
    102     case ADD_w_shift:
    103     case ADD_x_shift: mnemonic = "add"; break;
    104     case ADDS_w_shift:
    105     case ADDS_x_shift: {
    106       mnemonic = "adds";
    107       if (rd_is_zr) {
    108         mnemonic = "cmn";
    109         form = form_cmp;
    110       }
    111       break;
    112     }
    113     case SUB_w_shift:
    114     case SUB_x_shift: {
    115       mnemonic = "sub";
    116       if (rn_is_zr) {
    117         mnemonic = "neg";
    118         form = form_neg;
    119       }
    120       break;
    121     }
    122     case SUBS_w_shift:
    123     case SUBS_x_shift: {
    124       mnemonic = "subs";
    125       if (rd_is_zr) {
    126         mnemonic = "cmp";
    127         form = form_cmp;
    128       } else if (rn_is_zr) {
    129         mnemonic = "negs";
    130         form = form_neg;
    131       }
    132       break;
    133     }
    134     default: UNREACHABLE();
    135   }
    136   Format(instr, mnemonic, form);
    137 }
    138 
    139 
    140 void DisassemblingDecoder::VisitAddSubExtended(Instruction* instr) {
    141   bool rd_is_zr = RdIsZROrSP(instr);
    142   const char *mnemonic = "";
    143   Extend mode = static_cast<Extend>(instr->ExtendMode());
    144   const char *form = ((mode == UXTX) || (mode == SXTX)) ?
    145                      "'Rds, 'Rns, 'Xm'Ext" : "'Rds, 'Rns, 'Wm'Ext";
    146   const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ?
    147                          "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
    148 
    149   switch (instr->Mask(AddSubExtendedMask)) {
    150     case ADD_w_ext:
    151     case ADD_x_ext: mnemonic = "add"; break;
    152     case ADDS_w_ext:
    153     case ADDS_x_ext: {
    154       mnemonic = "adds";
    155       if (rd_is_zr) {
    156         mnemonic = "cmn";
    157         form = form_cmp;
    158       }
    159       break;
    160     }
    161     case SUB_w_ext:
    162     case SUB_x_ext: mnemonic = "sub"; break;
    163     case SUBS_w_ext:
    164     case SUBS_x_ext: {
    165       mnemonic = "subs";
    166       if (rd_is_zr) {
    167         mnemonic = "cmp";
    168         form = form_cmp;
    169       }
    170       break;
    171     }
    172     default: UNREACHABLE();
    173   }
    174   Format(instr, mnemonic, form);
    175 }
    176 
    177 
    178 void DisassemblingDecoder::VisitAddSubWithCarry(Instruction* instr) {
    179   bool rn_is_zr = RnIsZROrSP(instr);
    180   const char *mnemonic = "";
    181   const char *form = "'Rd, 'Rn, 'Rm";
    182   const char *form_neg = "'Rd, 'Rm";
    183 
    184   switch (instr->Mask(AddSubWithCarryMask)) {
    185     case ADC_w:
    186     case ADC_x: mnemonic = "adc"; break;
    187     case ADCS_w:
    188     case ADCS_x: mnemonic = "adcs"; break;
    189     case SBC_w:
    190     case SBC_x: {
    191       mnemonic = "sbc";
    192       if (rn_is_zr) {
    193         mnemonic = "ngc";
    194         form = form_neg;
    195       }
    196       break;
    197     }
    198     case SBCS_w:
    199     case SBCS_x: {
    200       mnemonic = "sbcs";
    201       if (rn_is_zr) {
    202         mnemonic = "ngcs";
    203         form = form_neg;
    204       }
    205       break;
    206     }
    207     default: UNREACHABLE();
    208   }
    209   Format(instr, mnemonic, form);
    210 }
    211 
    212 
    213 void DisassemblingDecoder::VisitLogicalImmediate(Instruction* instr) {
    214   bool rd_is_zr = RdIsZROrSP(instr);
    215   bool rn_is_zr = RnIsZROrSP(instr);
    216   const char *mnemonic = "";
    217   const char *form = "'Rds, 'Rn, 'ITri";
    218 
    219   if (instr->ImmLogical() == 0) {
    220     // The immediate encoded in the instruction is not in the expected format.
    221     Format(instr, "unallocated", "(LogicalImmediate)");
    222     return;
    223   }
    224 
    225   switch (instr->Mask(LogicalImmediateMask)) {
    226     case AND_w_imm:
    227     case AND_x_imm: mnemonic = "and"; break;
    228     case ORR_w_imm:
    229     case ORR_x_imm: {
    230       mnemonic = "orr";
    231       unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
    232                                                         : kWRegSizeInBits;
    233       if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) {
    234         mnemonic = "mov";
    235         form = "'Rds, 'ITri";
    236       }
    237       break;
    238     }
    239     case EOR_w_imm:
    240     case EOR_x_imm: mnemonic = "eor"; break;
    241     case ANDS_w_imm:
    242     case ANDS_x_imm: {
    243       mnemonic = "ands";
    244       if (rd_is_zr) {
    245         mnemonic = "tst";
    246         form = "'Rn, 'ITri";
    247       }
    248       break;
    249     }
    250     default: UNREACHABLE();
    251   }
    252   Format(instr, mnemonic, form);
    253 }
    254 
    255 
    256 bool DisassemblingDecoder::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
    257   DCHECK((reg_size == kXRegSizeInBits) ||
    258          ((reg_size == kWRegSizeInBits) && (value <= 0xffffffff)));
    259 
    260   // Test for movz: 16-bits set at positions 0, 16, 32 or 48.
    261   if (((value & 0xffffffffffff0000UL) == 0UL) ||
    262       ((value & 0xffffffff0000ffffUL) == 0UL) ||
    263       ((value & 0xffff0000ffffffffUL) == 0UL) ||
    264       ((value & 0x0000ffffffffffffUL) == 0UL)) {
    265     return true;
    266   }
    267 
    268   // Test for movn: NOT(16-bits set at positions 0, 16, 32 or 48).
    269   if ((reg_size == kXRegSizeInBits) &&
    270       (((value & 0xffffffffffff0000UL) == 0xffffffffffff0000UL) ||
    271        ((value & 0xffffffff0000ffffUL) == 0xffffffff0000ffffUL) ||
    272        ((value & 0xffff0000ffffffffUL) == 0xffff0000ffffffffUL) ||
    273        ((value & 0x0000ffffffffffffUL) == 0x0000ffffffffffffUL))) {
    274     return true;
    275   }
    276   if ((reg_size == kWRegSizeInBits) &&
    277       (((value & 0xffff0000) == 0xffff0000) ||
    278        ((value & 0x0000ffff) == 0x0000ffff))) {
    279     return true;
    280   }
    281   return false;
    282 }
    283 
    284 
    285 void DisassemblingDecoder::VisitLogicalShifted(Instruction* instr) {
    286   bool rd_is_zr = RdIsZROrSP(instr);
    287   bool rn_is_zr = RnIsZROrSP(instr);
    288   const char *mnemonic = "";
    289   const char *form = "'Rd, 'Rn, 'Rm'HLo";
    290 
    291   switch (instr->Mask(LogicalShiftedMask)) {
    292     case AND_w:
    293     case AND_x: mnemonic = "and"; break;
    294     case BIC_w:
    295     case BIC_x: mnemonic = "bic"; break;
    296     case EOR_w:
    297     case EOR_x: mnemonic = "eor"; break;
    298     case EON_w:
    299     case EON_x: mnemonic = "eon"; break;
    300     case BICS_w:
    301     case BICS_x: mnemonic = "bics"; break;
    302     case ANDS_w:
    303     case ANDS_x: {
    304       mnemonic = "ands";
    305       if (rd_is_zr) {
    306         mnemonic = "tst";
    307         form = "'Rn, 'Rm'HLo";
    308       }
    309       break;
    310     }
    311     case ORR_w:
    312     case ORR_x: {
    313       mnemonic = "orr";
    314       if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) {
    315         mnemonic = "mov";
    316         form = "'Rd, 'Rm";
    317       }
    318       break;
    319     }
    320     case ORN_w:
    321     case ORN_x: {
    322       mnemonic = "orn";
    323       if (rn_is_zr) {
    324         mnemonic = "mvn";
    325         form = "'Rd, 'Rm'HLo";
    326       }
    327       break;
    328     }
    329     default: UNREACHABLE();
    330   }
    331 
    332   Format(instr, mnemonic, form);
    333 }
    334 
    335 
    336 void DisassemblingDecoder::VisitConditionalCompareRegister(Instruction* instr) {
    337   const char *mnemonic = "";
    338   const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
    339 
    340   switch (instr->Mask(ConditionalCompareRegisterMask)) {
    341     case CCMN_w:
    342     case CCMN_x: mnemonic = "ccmn"; break;
    343     case CCMP_w:
    344     case CCMP_x: mnemonic = "ccmp"; break;
    345     default: UNREACHABLE();
    346   }
    347   Format(instr, mnemonic, form);
    348 }
    349 
    350 
    351 void DisassemblingDecoder::VisitConditionalCompareImmediate(
    352     Instruction* instr) {
    353   const char *mnemonic = "";
    354   const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
    355 
    356   switch (instr->Mask(ConditionalCompareImmediateMask)) {
    357     case CCMN_w_imm:
    358     case CCMN_x_imm: mnemonic = "ccmn"; break;
    359     case CCMP_w_imm:
    360     case CCMP_x_imm: mnemonic = "ccmp"; break;
    361     default: UNREACHABLE();
    362   }
    363   Format(instr, mnemonic, form);
    364 }
    365 
    366 
    367 void DisassemblingDecoder::VisitConditionalSelect(Instruction* instr) {
    368   bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
    369   bool rn_is_rm = (instr->Rn() == instr->Rm());
    370   const char *mnemonic = "";
    371   const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
    372   const char *form_test = "'Rd, 'CInv";
    373   const char *form_update = "'Rd, 'Rn, 'CInv";
    374 
    375   Condition cond = static_cast<Condition>(instr->Condition());
    376   bool invertible_cond = (cond != al) && (cond != nv);
    377 
    378   switch (instr->Mask(ConditionalSelectMask)) {
    379     case CSEL_w:
    380     case CSEL_x: mnemonic = "csel"; break;
    381     case CSINC_w:
    382     case CSINC_x: {
    383       mnemonic = "csinc";
    384       if (rnm_is_zr && invertible_cond) {
    385         mnemonic = "cset";
    386         form = form_test;
    387       } else if (rn_is_rm && invertible_cond) {
    388         mnemonic = "cinc";
    389         form = form_update;
    390       }
    391       break;
    392     }
    393     case CSINV_w:
    394     case CSINV_x: {
    395       mnemonic = "csinv";
    396       if (rnm_is_zr && invertible_cond) {
    397         mnemonic = "csetm";
    398         form = form_test;
    399       } else if (rn_is_rm && invertible_cond) {
    400         mnemonic = "cinv";
    401         form = form_update;
    402       }
    403       break;
    404     }
    405     case CSNEG_w:
    406     case CSNEG_x: {
    407       mnemonic = "csneg";
    408       if (rn_is_rm && invertible_cond) {
    409         mnemonic = "cneg";
    410         form = form_update;
    411       }
    412       break;
    413     }
    414     default: UNREACHABLE();
    415   }
    416   Format(instr, mnemonic, form);
    417 }
    418 
    419 
    420 void DisassemblingDecoder::VisitBitfield(Instruction* instr) {
    421   unsigned s = instr->ImmS();
    422   unsigned r = instr->ImmR();
    423   unsigned rd_size_minus_1 =
    424     ((instr->SixtyFourBits() == 1) ? kXRegSizeInBits : kWRegSizeInBits) - 1;
    425   const char *mnemonic = "";
    426   const char *form = "";
    427   const char *form_shift_right = "'Rd, 'Rn, 'IBr";
    428   const char *form_extend = "'Rd, 'Wn";
    429   const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
    430   const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
    431   const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
    432 
    433   switch (instr->Mask(BitfieldMask)) {
    434     case SBFM_w:
    435     case SBFM_x: {
    436       mnemonic = "sbfx";
    437       form = form_bfx;
    438       if (r == 0) {
    439         form = form_extend;
    440         if (s == 7) {
    441           mnemonic = "sxtb";
    442         } else if (s == 15) {
    443           mnemonic = "sxth";
    444         } else if ((s == 31) && (instr->SixtyFourBits() == 1)) {
    445           mnemonic = "sxtw";
    446         } else {
    447           form = form_bfx;
    448         }
    449       } else if (s == rd_size_minus_1) {
    450         mnemonic = "asr";
    451         form = form_shift_right;
    452       } else if (s < r) {
    453         mnemonic = "sbfiz";
    454         form = form_bfiz;
    455       }
    456       break;
    457     }
    458     case UBFM_w:
    459     case UBFM_x: {
    460       mnemonic = "ubfx";
    461       form = form_bfx;
    462       if (r == 0) {
    463         form = form_extend;
    464         if (s == 7) {
    465           mnemonic = "uxtb";
    466         } else if (s == 15) {
    467           mnemonic = "uxth";
    468         } else {
    469           form = form_bfx;
    470         }
    471       }
    472       if (s == rd_size_minus_1) {
    473         mnemonic = "lsr";
    474         form = form_shift_right;
    475       } else if (r == s + 1) {
    476         mnemonic = "lsl";
    477         form = form_lsl;
    478       } else if (s < r) {
    479         mnemonic = "ubfiz";
    480         form = form_bfiz;
    481       }
    482       break;
    483     }
    484     case BFM_w:
    485     case BFM_x: {
    486       mnemonic = "bfxil";
    487       form = form_bfx;
    488       if (s < r) {
    489         mnemonic = "bfi";
    490         form = form_bfiz;
    491       }
    492     }
    493   }
    494   Format(instr, mnemonic, form);
    495 }
    496 
    497 
    498 void DisassemblingDecoder::VisitExtract(Instruction* instr) {
    499   const char *mnemonic = "";
    500   const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
    501 
    502   switch (instr->Mask(ExtractMask)) {
    503     case EXTR_w:
    504     case EXTR_x: {
    505       if (instr->Rn() == instr->Rm()) {
    506         mnemonic = "ror";
    507         form = "'Rd, 'Rn, 'IExtract";
    508       } else {
    509         mnemonic = "extr";
    510       }
    511       break;
    512     }
    513     default: UNREACHABLE();
    514   }
    515   Format(instr, mnemonic, form);
    516 }
    517 
    518 
    519 void DisassemblingDecoder::VisitPCRelAddressing(Instruction* instr) {
    520   switch (instr->Mask(PCRelAddressingMask)) {
    521     case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break;
    522     // ADRP is not implemented.
    523     default: Format(instr, "unimplemented", "(PCRelAddressing)");
    524   }
    525 }
    526 
    527 
    528 void DisassemblingDecoder::VisitConditionalBranch(Instruction* instr) {
    529   switch (instr->Mask(ConditionalBranchMask)) {
    530     case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
    531     default: UNREACHABLE();
    532   }
    533 }
    534 
    535 
    536 void DisassemblingDecoder::VisitUnconditionalBranchToRegister(
    537     Instruction* instr) {
    538   const char *mnemonic = "unimplemented";
    539   const char *form = "'Xn";
    540 
    541   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
    542     case BR: mnemonic = "br"; break;
    543     case BLR: mnemonic = "blr"; break;
    544     case RET: {
    545       mnemonic = "ret";
    546       if (instr->Rn() == kLinkRegCode) {
    547         form = NULL;
    548       }
    549       break;
    550     }
    551     default: form = "(UnconditionalBranchToRegister)";
    552   }
    553   Format(instr, mnemonic, form);
    554 }
    555 
    556 
    557 void DisassemblingDecoder::VisitUnconditionalBranch(Instruction* instr) {
    558   const char *mnemonic = "";
    559   const char *form = "'BImmUncn";
    560 
    561   switch (instr->Mask(UnconditionalBranchMask)) {
    562     case B: mnemonic = "b"; break;
    563     case BL: mnemonic = "bl"; break;
    564     default: UNREACHABLE();
    565   }
    566   Format(instr, mnemonic, form);
    567 }
    568 
    569 
    570 void DisassemblingDecoder::VisitDataProcessing1Source(Instruction* instr) {
    571   const char *mnemonic = "";
    572   const char *form = "'Rd, 'Rn";
    573 
    574   switch (instr->Mask(DataProcessing1SourceMask)) {
    575     #define FORMAT(A, B)  \
    576     case A##_w:           \
    577     case A##_x: mnemonic = B; break;
    578     FORMAT(RBIT, "rbit");
    579     FORMAT(REV16, "rev16");
    580     FORMAT(REV, "rev");
    581     FORMAT(CLZ, "clz");
    582     FORMAT(CLS, "cls");
    583     #undef FORMAT
    584     case REV32_x: mnemonic = "rev32"; break;
    585     default: UNREACHABLE();
    586   }
    587   Format(instr, mnemonic, form);
    588 }
    589 
    590 
    591 void DisassemblingDecoder::VisitDataProcessing2Source(Instruction* instr) {
    592   const char *mnemonic = "unimplemented";
    593   const char *form = "'Rd, 'Rn, 'Rm";
    594 
    595   switch (instr->Mask(DataProcessing2SourceMask)) {
    596     #define FORMAT(A, B)  \
    597     case A##_w:           \
    598     case A##_x: mnemonic = B; break;
    599     FORMAT(UDIV, "udiv");
    600     FORMAT(SDIV, "sdiv");
    601     FORMAT(LSLV, "lsl");
    602     FORMAT(LSRV, "lsr");
    603     FORMAT(ASRV, "asr");
    604     FORMAT(RORV, "ror");
    605     #undef FORMAT
    606     default: form = "(DataProcessing2Source)";
    607   }
    608   Format(instr, mnemonic, form);
    609 }
    610 
    611 
    612 void DisassemblingDecoder::VisitDataProcessing3Source(Instruction* instr) {
    613   bool ra_is_zr = RaIsZROrSP(instr);
    614   const char *mnemonic = "";
    615   const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
    616   const char *form_rrr = "'Rd, 'Rn, 'Rm";
    617   const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
    618   const char *form_xww = "'Xd, 'Wn, 'Wm";
    619   const char *form_xxx = "'Xd, 'Xn, 'Xm";
    620 
    621   switch (instr->Mask(DataProcessing3SourceMask)) {
    622     case MADD_w:
    623     case MADD_x: {
    624       mnemonic = "madd";
    625       form = form_rrrr;
    626       if (ra_is_zr) {
    627         mnemonic = "mul";
    628         form = form_rrr;
    629       }
    630       break;
    631     }
    632     case MSUB_w:
    633     case MSUB_x: {
    634       mnemonic = "msub";
    635       form = form_rrrr;
    636       if (ra_is_zr) {
    637         mnemonic = "mneg";
    638         form = form_rrr;
    639       }
    640       break;
    641     }
    642     case SMADDL_x: {
    643       mnemonic = "smaddl";
    644       if (ra_is_zr) {
    645         mnemonic = "smull";
    646         form = form_xww;
    647       }
    648       break;
    649     }
    650     case SMSUBL_x: {
    651       mnemonic = "smsubl";
    652       if (ra_is_zr) {
    653         mnemonic = "smnegl";
    654         form = form_xww;
    655       }
    656       break;
    657     }
    658     case UMADDL_x: {
    659       mnemonic = "umaddl";
    660       if (ra_is_zr) {
    661         mnemonic = "umull";
    662         form = form_xww;
    663       }
    664       break;
    665     }
    666     case UMSUBL_x: {
    667       mnemonic = "umsubl";
    668       if (ra_is_zr) {
    669         mnemonic = "umnegl";
    670         form = form_xww;
    671       }
    672       break;
    673     }
    674     case SMULH_x: {
    675       mnemonic = "smulh";
    676       form = form_xxx;
    677       break;
    678     }
    679     case UMULH_x: {
    680       mnemonic = "umulh";
    681       form = form_xxx;
    682       break;
    683     }
    684     default: UNREACHABLE();
    685   }
    686   Format(instr, mnemonic, form);
    687 }
    688 
    689 
    690 void DisassemblingDecoder::VisitCompareBranch(Instruction* instr) {
    691   const char *mnemonic = "";
    692   const char *form = "'Rt, 'BImmCmpa";
    693 
    694   switch (instr->Mask(CompareBranchMask)) {
    695     case CBZ_w:
    696     case CBZ_x: mnemonic = "cbz"; break;
    697     case CBNZ_w:
    698     case CBNZ_x: mnemonic = "cbnz"; break;
    699     default: UNREACHABLE();
    700   }
    701   Format(instr, mnemonic, form);
    702 }
    703 
    704 
    705 void DisassemblingDecoder::VisitTestBranch(Instruction* instr) {
    706   const char *mnemonic = "";
    707   // If the top bit of the immediate is clear, the tested register is
    708   // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
    709   // encoded in bit 31 of the instruction, we can reuse the Rt form, which
    710   // uses bit 31 (normally "sf") to choose the register size.
    711   const char *form = "'Rt, 'IS, 'BImmTest";
    712 
    713   switch (instr->Mask(TestBranchMask)) {
    714     case TBZ: mnemonic = "tbz"; break;
    715     case TBNZ: mnemonic = "tbnz"; break;
    716     default: UNREACHABLE();
    717   }
    718   Format(instr, mnemonic, form);
    719 }
    720 
    721 
    722 void DisassemblingDecoder::VisitMoveWideImmediate(Instruction* instr) {
    723   const char *mnemonic = "";
    724   const char *form = "'Rd, 'IMoveImm";
    725 
    726   // Print the shift separately for movk, to make it clear which half word will
    727   // be overwritten. Movn and movz print the computed immediate, which includes
    728   // shift calculation.
    729   switch (instr->Mask(MoveWideImmediateMask)) {
    730     case MOVN_w:
    731     case MOVN_x: mnemonic = "movn"; break;
    732     case MOVZ_w:
    733     case MOVZ_x: mnemonic = "movz"; break;
    734     case MOVK_w:
    735     case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
    736     default: UNREACHABLE();
    737   }
    738   Format(instr, mnemonic, form);
    739 }
    740 
    741 
    742 #define LOAD_STORE_LIST(V)    \
    743   V(STRB_w, "strb", "'Wt")    \
    744   V(STRH_w, "strh", "'Wt")    \
    745   V(STR_w, "str", "'Wt")      \
    746   V(STR_x, "str", "'Xt")      \
    747   V(LDRB_w, "ldrb", "'Wt")    \
    748   V(LDRH_w, "ldrh", "'Wt")    \
    749   V(LDR_w, "ldr", "'Wt")      \
    750   V(LDR_x, "ldr", "'Xt")      \
    751   V(LDRSB_x, "ldrsb", "'Xt")  \
    752   V(LDRSH_x, "ldrsh", "'Xt")  \
    753   V(LDRSW_x, "ldrsw", "'Xt")  \
    754   V(LDRSB_w, "ldrsb", "'Wt")  \
    755   V(LDRSH_w, "ldrsh", "'Wt")  \
    756   V(STR_s, "str", "'St")      \
    757   V(STR_d, "str", "'Dt")      \
    758   V(LDR_s, "ldr", "'St")      \
    759   V(LDR_d, "ldr", "'Dt")
    760 
    761 void DisassemblingDecoder::VisitLoadStorePreIndex(Instruction* instr) {
    762   const char *mnemonic = "unimplemented";
    763   const char *form = "(LoadStorePreIndex)";
    764 
    765   switch (instr->Mask(LoadStorePreIndexMask)) {
    766     #define LS_PREINDEX(A, B, C) \
    767     case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break;
    768     LOAD_STORE_LIST(LS_PREINDEX)
    769     #undef LS_PREINDEX
    770   }
    771   Format(instr, mnemonic, form);
    772 }
    773 
    774 
    775 void DisassemblingDecoder::VisitLoadStorePostIndex(Instruction* instr) {
    776   const char *mnemonic = "unimplemented";
    777   const char *form = "(LoadStorePostIndex)";
    778 
    779   switch (instr->Mask(LoadStorePostIndexMask)) {
    780     #define LS_POSTINDEX(A, B, C) \
    781     case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break;
    782     LOAD_STORE_LIST(LS_POSTINDEX)
    783     #undef LS_POSTINDEX
    784   }
    785   Format(instr, mnemonic, form);
    786 }
    787 
    788 
    789 void DisassemblingDecoder::VisitLoadStoreUnsignedOffset(Instruction* instr) {
    790   const char *mnemonic = "unimplemented";
    791   const char *form = "(LoadStoreUnsignedOffset)";
    792 
    793   switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
    794     #define LS_UNSIGNEDOFFSET(A, B, C) \
    795     case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break;
    796     LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
    797     #undef LS_UNSIGNEDOFFSET
    798     case PRFM_unsigned: mnemonic = "prfm"; form = "'PrefOp, ['Xn'ILU]";
    799   }
    800   Format(instr, mnemonic, form);
    801 }
    802 
    803 
    804 void DisassemblingDecoder::VisitLoadStoreRegisterOffset(Instruction* instr) {
    805   const char *mnemonic = "unimplemented";
    806   const char *form = "(LoadStoreRegisterOffset)";
    807 
    808   switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
    809     #define LS_REGISTEROFFSET(A, B, C) \
    810     case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break;
    811     LOAD_STORE_LIST(LS_REGISTEROFFSET)
    812     #undef LS_REGISTEROFFSET
    813     case PRFM_reg: mnemonic = "prfm"; form = "'PrefOp, ['Xns, 'Offsetreg]";
    814   }
    815   Format(instr, mnemonic, form);
    816 }
    817 
    818 
    819 void DisassemblingDecoder::VisitLoadStoreUnscaledOffset(Instruction* instr) {
    820   const char *mnemonic = "unimplemented";
    821   const char *form = "'Wt, ['Xns'ILS]";
    822   const char *form_x = "'Xt, ['Xns'ILS]";
    823   const char *form_s = "'St, ['Xns'ILS]";
    824   const char *form_d = "'Dt, ['Xns'ILS]";
    825 
    826   switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
    827     case STURB_w:  mnemonic = "sturb"; break;
    828     case STURH_w:  mnemonic = "sturh"; break;
    829     case STUR_w:   mnemonic = "stur"; break;
    830     case STUR_x:   mnemonic = "stur"; form = form_x; break;
    831     case STUR_s:   mnemonic = "stur"; form = form_s; break;
    832     case STUR_d:   mnemonic = "stur"; form = form_d; break;
    833     case LDURB_w:  mnemonic = "ldurb"; break;
    834     case LDURH_w:  mnemonic = "ldurh"; break;
    835     case LDUR_w:   mnemonic = "ldur"; break;
    836     case LDUR_x:   mnemonic = "ldur"; form = form_x; break;
    837     case LDUR_s:   mnemonic = "ldur"; form = form_s; break;
    838     case LDUR_d:   mnemonic = "ldur"; form = form_d; break;
    839     case LDURSB_x: form = form_x;  // Fall through.
    840     case LDURSB_w: mnemonic = "ldursb"; break;
    841     case LDURSH_x: form = form_x;  // Fall through.
    842     case LDURSH_w: mnemonic = "ldursh"; break;
    843     case LDURSW_x: mnemonic = "ldursw"; form = form_x; break;
    844     default: form = "(LoadStoreUnscaledOffset)";
    845   }
    846   Format(instr, mnemonic, form);
    847 }
    848 
    849 
    850 void DisassemblingDecoder::VisitLoadLiteral(Instruction* instr) {
    851   const char *mnemonic = "ldr";
    852   const char *form = "(LoadLiteral)";
    853 
    854   switch (instr->Mask(LoadLiteralMask)) {
    855     case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break;
    856     case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break;
    857     case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break;
    858     case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break;
    859     default: mnemonic = "unimplemented";
    860   }
    861   Format(instr, mnemonic, form);
    862 }
    863 
    864 
    865 #define LOAD_STORE_PAIR_LIST(V)         \
    866   V(STP_w, "stp", "'Wt, 'Wt2", "4")     \
    867   V(LDP_w, "ldp", "'Wt, 'Wt2", "4")     \
    868   V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "4") \
    869   V(STP_x, "stp", "'Xt, 'Xt2", "8")     \
    870   V(LDP_x, "ldp", "'Xt, 'Xt2", "8")     \
    871   V(STP_s, "stp", "'St, 'St2", "4")     \
    872   V(LDP_s, "ldp", "'St, 'St2", "4")     \
    873   V(STP_d, "stp", "'Dt, 'Dt2", "8")     \
    874   V(LDP_d, "ldp", "'Dt, 'Dt2", "8")
    875 
    876 void DisassemblingDecoder::VisitLoadStorePairPostIndex(Instruction* instr) {
    877   const char *mnemonic = "unimplemented";
    878   const char *form = "(LoadStorePairPostIndex)";
    879 
    880   switch (instr->Mask(LoadStorePairPostIndexMask)) {
    881     #define LSP_POSTINDEX(A, B, C, D) \
    882     case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break;
    883     LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
    884     #undef LSP_POSTINDEX
    885   }
    886   Format(instr, mnemonic, form);
    887 }
    888 
    889 
    890 void DisassemblingDecoder::VisitLoadStorePairPreIndex(Instruction* instr) {
    891   const char *mnemonic = "unimplemented";
    892   const char *form = "(LoadStorePairPreIndex)";
    893 
    894   switch (instr->Mask(LoadStorePairPreIndexMask)) {
    895     #define LSP_PREINDEX(A, B, C, D) \
    896     case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break;
    897     LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
    898     #undef LSP_PREINDEX
    899   }
    900   Format(instr, mnemonic, form);
    901 }
    902 
    903 
    904 void DisassemblingDecoder::VisitLoadStorePairOffset(Instruction* instr) {
    905   const char *mnemonic = "unimplemented";
    906   const char *form = "(LoadStorePairOffset)";
    907 
    908   switch (instr->Mask(LoadStorePairOffsetMask)) {
    909     #define LSP_OFFSET(A, B, C, D) \
    910     case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break;
    911     LOAD_STORE_PAIR_LIST(LSP_OFFSET)
    912     #undef LSP_OFFSET
    913   }
    914   Format(instr, mnemonic, form);
    915 }
    916 
    917 void DisassemblingDecoder::VisitLoadStoreAcquireRelease(Instruction *instr) {
    918   const char *mnemonic = "unimplemented";
    919   const char *form = "'Wt, ['Xn]";
    920   const char *form_x = "'Xt, ['Xn]";
    921   const char *form_stlx = "'Ws, 'Wt, ['Xn]";
    922   const char *form_stlx_x = "'Ws, 'Xt, ['Xn]";
    923 
    924   switch (instr->Mask(LoadStoreAcquireReleaseMask)) {
    925     case LDAXR_b: mnemonic = "ldaxrb"; break;
    926     case STLR_b:  mnemonic = "stlrb"; break;
    927     case LDAR_b:  mnemonic = "ldarb"; break;
    928     case LDAXR_h: mnemonic = "ldaxrh"; break;
    929     case STLR_h:  mnemonic = "stlrh"; break;
    930     case LDAR_h:  mnemonic = "ldarh"; break;
    931     case LDAXR_w: mnemonic = "ldaxr"; break;
    932     case STLR_w:  mnemonic = "stlr"; break;
    933     case LDAR_w:  mnemonic = "ldar"; break;
    934     case LDAXR_x: mnemonic = "ldaxr"; form = form_x; break;
    935     case STLR_x:  mnemonic = "stlr"; form = form_x; break;
    936     case LDAR_x:  mnemonic = "ldar"; form = form_x; break;
    937     case STLXR_h: mnemonic = "stlxrh"; form = form_stlx; break;
    938     case STLXR_b: mnemonic = "stlxrb"; form = form_stlx; break;
    939     case STLXR_w: mnemonic = "stlxr"; form = form_stlx; break;
    940     case STLXR_x: mnemonic = "stlxr"; form = form_stlx_x; break;
    941     default: form = "(LoadStoreAcquireReleaseMask)";
    942   }
    943   Format(instr, mnemonic, form);
    944 }
    945 
    946 void DisassemblingDecoder::VisitFPCompare(Instruction* instr) {
    947   const char *mnemonic = "unimplemented";
    948   const char *form = "'Fn, 'Fm";
    949   const char *form_zero = "'Fn, #0.0";
    950 
    951   switch (instr->Mask(FPCompareMask)) {
    952     case FCMP_s_zero:
    953     case FCMP_d_zero: form = form_zero;  // Fall through.
    954     case FCMP_s:
    955     case FCMP_d: mnemonic = "fcmp"; break;
    956     default: form = "(FPCompare)";
    957   }
    958   Format(instr, mnemonic, form);
    959 }
    960 
    961 
    962 void DisassemblingDecoder::VisitFPConditionalCompare(Instruction* instr) {
    963   const char *mnemonic = "unimplemented";
    964   const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
    965 
    966   switch (instr->Mask(FPConditionalCompareMask)) {
    967     case FCCMP_s:
    968     case FCCMP_d: mnemonic = "fccmp"; break;
    969     case FCCMPE_s:
    970     case FCCMPE_d: mnemonic = "fccmpe"; break;
    971     default: form = "(FPConditionalCompare)";
    972   }
    973   Format(instr, mnemonic, form);
    974 }
    975 
    976 
    977 void DisassemblingDecoder::VisitFPConditionalSelect(Instruction* instr) {
    978   const char *mnemonic = "";
    979   const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
    980 
    981   switch (instr->Mask(FPConditionalSelectMask)) {
    982     case FCSEL_s:
    983     case FCSEL_d: mnemonic = "fcsel"; break;
    984     default: UNREACHABLE();
    985   }
    986   Format(instr, mnemonic, form);
    987 }
    988 
    989 
    990 void DisassemblingDecoder::VisitFPDataProcessing1Source(Instruction* instr) {
    991   const char *mnemonic = "unimplemented";
    992   const char *form = "'Fd, 'Fn";
    993 
    994   switch (instr->Mask(FPDataProcessing1SourceMask)) {
    995     #define FORMAT(A, B)  \
    996     case A##_s:           \
    997     case A##_d: mnemonic = B; break;
    998     FORMAT(FMOV, "fmov");
    999     FORMAT(FABS, "fabs");
   1000     FORMAT(FNEG, "fneg");
   1001     FORMAT(FSQRT, "fsqrt");
   1002     FORMAT(FRINTN, "frintn");
   1003     FORMAT(FRINTP, "frintp");
   1004     FORMAT(FRINTM, "frintm");
   1005     FORMAT(FRINTZ, "frintz");
   1006     FORMAT(FRINTA, "frinta");
   1007     FORMAT(FRINTX, "frintx");
   1008     FORMAT(FRINTI, "frinti");
   1009     #undef FORMAT
   1010     case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break;
   1011     case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break;
   1012     default: form = "(FPDataProcessing1Source)";
   1013   }
   1014   Format(instr, mnemonic, form);
   1015 }
   1016 
   1017 
   1018 void DisassemblingDecoder::VisitFPDataProcessing2Source(Instruction* instr) {
   1019   const char *mnemonic = "";
   1020   const char *form = "'Fd, 'Fn, 'Fm";
   1021 
   1022   switch (instr->Mask(FPDataProcessing2SourceMask)) {
   1023     #define FORMAT(A, B)  \
   1024     case A##_s:           \
   1025     case A##_d: mnemonic = B; break;
   1026     FORMAT(FMUL, "fmul");
   1027     FORMAT(FDIV, "fdiv");
   1028     FORMAT(FADD, "fadd");
   1029     FORMAT(FSUB, "fsub");
   1030     FORMAT(FMAX, "fmax");
   1031     FORMAT(FMIN, "fmin");
   1032     FORMAT(FMAXNM, "fmaxnm");
   1033     FORMAT(FMINNM, "fminnm");
   1034     FORMAT(FNMUL, "fnmul");
   1035     #undef FORMAT
   1036     default: UNREACHABLE();
   1037   }
   1038   Format(instr, mnemonic, form);
   1039 }
   1040 
   1041 
   1042 void DisassemblingDecoder::VisitFPDataProcessing3Source(Instruction* instr) {
   1043   const char *mnemonic = "";
   1044   const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
   1045 
   1046   switch (instr->Mask(FPDataProcessing3SourceMask)) {
   1047     #define FORMAT(A, B)  \
   1048     case A##_s:           \
   1049     case A##_d: mnemonic = B; break;
   1050     FORMAT(FMADD, "fmadd");
   1051     FORMAT(FMSUB, "fmsub");
   1052     FORMAT(FNMADD, "fnmadd");
   1053     FORMAT(FNMSUB, "fnmsub");
   1054     #undef FORMAT
   1055     default: UNREACHABLE();
   1056   }
   1057   Format(instr, mnemonic, form);
   1058 }
   1059 
   1060 
   1061 void DisassemblingDecoder::VisitFPImmediate(Instruction* instr) {
   1062   const char *mnemonic = "";
   1063   const char *form = "(FPImmediate)";
   1064 
   1065   switch (instr->Mask(FPImmediateMask)) {
   1066     case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
   1067     case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
   1068     default: UNREACHABLE();
   1069   }
   1070   Format(instr, mnemonic, form);
   1071 }
   1072 
   1073 
   1074 void DisassemblingDecoder::VisitFPIntegerConvert(Instruction* instr) {
   1075   const char *mnemonic = "unimplemented";
   1076   const char *form = "(FPIntegerConvert)";
   1077   const char *form_rf = "'Rd, 'Fn";
   1078   const char *form_fr = "'Fd, 'Rn";
   1079 
   1080   switch (instr->Mask(FPIntegerConvertMask)) {
   1081     case FMOV_ws:
   1082     case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
   1083     case FMOV_sw:
   1084     case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
   1085     case FCVTAS_ws:
   1086     case FCVTAS_xs:
   1087     case FCVTAS_wd:
   1088     case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break;
   1089     case FCVTAU_ws:
   1090     case FCVTAU_xs:
   1091     case FCVTAU_wd:
   1092     case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break;
   1093     case FCVTMS_ws:
   1094     case FCVTMS_xs:
   1095     case FCVTMS_wd:
   1096     case FCVTMS_xd: mnemonic = "fcvtms"; form = form_rf; break;
   1097     case FCVTMU_ws:
   1098     case FCVTMU_xs:
   1099     case FCVTMU_wd:
   1100     case FCVTMU_xd: mnemonic = "fcvtmu"; form = form_rf; break;
   1101     case FCVTNS_ws:
   1102     case FCVTNS_xs:
   1103     case FCVTNS_wd:
   1104     case FCVTNS_xd: mnemonic = "fcvtns"; form = form_rf; break;
   1105     case FCVTNU_ws:
   1106     case FCVTNU_xs:
   1107     case FCVTNU_wd:
   1108     case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break;
   1109     case FCVTZU_xd:
   1110     case FCVTZU_ws:
   1111     case FCVTZU_wd:
   1112     case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break;
   1113     case FCVTZS_xd:
   1114     case FCVTZS_wd:
   1115     case FCVTZS_xs:
   1116     case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break;
   1117     case SCVTF_sw:
   1118     case SCVTF_sx:
   1119     case SCVTF_dw:
   1120     case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break;
   1121     case UCVTF_sw:
   1122     case UCVTF_sx:
   1123     case UCVTF_dw:
   1124     case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break;
   1125   }
   1126   Format(instr, mnemonic, form);
   1127 }
   1128 
   1129 
   1130 void DisassemblingDecoder::VisitFPFixedPointConvert(Instruction* instr) {
   1131   const char *mnemonic = "";
   1132   const char *form = "'Rd, 'Fn, 'IFPFBits";
   1133   const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
   1134 
   1135   switch (instr->Mask(FPFixedPointConvertMask)) {
   1136     case FCVTZS_ws_fixed:
   1137     case FCVTZS_xs_fixed:
   1138     case FCVTZS_wd_fixed:
   1139     case FCVTZS_xd_fixed: mnemonic = "fcvtzs"; break;
   1140     case FCVTZU_ws_fixed:
   1141     case FCVTZU_xs_fixed:
   1142     case FCVTZU_wd_fixed:
   1143     case FCVTZU_xd_fixed: mnemonic = "fcvtzu"; break;
   1144     case SCVTF_sw_fixed:
   1145     case SCVTF_sx_fixed:
   1146     case SCVTF_dw_fixed:
   1147     case SCVTF_dx_fixed: mnemonic = "scvtf"; form = form_fr; break;
   1148     case UCVTF_sw_fixed:
   1149     case UCVTF_sx_fixed:
   1150     case UCVTF_dw_fixed:
   1151     case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
   1152   }
   1153   Format(instr, mnemonic, form);
   1154 }
   1155 
   1156 
   1157 void DisassemblingDecoder::VisitSystem(Instruction* instr) {
   1158   // Some system instructions hijack their Op and Cp fields to represent a
   1159   // range of immediates instead of indicating a different instruction. This
   1160   // makes the decoding tricky.
   1161   const char *mnemonic = "unimplemented";
   1162   const char *form = "(System)";
   1163 
   1164   if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
   1165     switch (instr->Mask(SystemSysRegMask)) {
   1166       case MRS: {
   1167         mnemonic = "mrs";
   1168         switch (instr->ImmSystemRegister()) {
   1169           case NZCV: form = "'Xt, nzcv"; break;
   1170           case FPCR: form = "'Xt, fpcr"; break;
   1171           default: form = "'Xt, (unknown)"; break;
   1172         }
   1173         break;
   1174       }
   1175       case MSR: {
   1176         mnemonic = "msr";
   1177         switch (instr->ImmSystemRegister()) {
   1178           case NZCV: form = "nzcv, 'Xt"; break;
   1179           case FPCR: form = "fpcr, 'Xt"; break;
   1180           default: form = "(unknown), 'Xt"; break;
   1181         }
   1182         break;
   1183       }
   1184     }
   1185   } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
   1186     DCHECK(instr->Mask(SystemHintMask) == HINT);
   1187     switch (instr->ImmHint()) {
   1188       case NOP: {
   1189         mnemonic = "nop";
   1190         form = NULL;
   1191         break;
   1192       }
   1193     }
   1194   } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
   1195     switch (instr->Mask(MemBarrierMask)) {
   1196       case DMB: {
   1197         mnemonic = "dmb";
   1198         form = "'M";
   1199         break;
   1200       }
   1201       case DSB: {
   1202         mnemonic = "dsb";
   1203         form = "'M";
   1204         break;
   1205       }
   1206       case ISB: {
   1207         mnemonic = "isb";
   1208         form = NULL;
   1209         break;
   1210       }
   1211     }
   1212   }
   1213 
   1214   Format(instr, mnemonic, form);
   1215 }
   1216 
   1217 
   1218 void DisassemblingDecoder::VisitException(Instruction* instr) {
   1219   const char *mnemonic = "unimplemented";
   1220   const char *form = "'IDebug";
   1221 
   1222   switch (instr->Mask(ExceptionMask)) {
   1223     case HLT: mnemonic = "hlt"; break;
   1224     case BRK: mnemonic = "brk"; break;
   1225     case SVC: mnemonic = "svc"; break;
   1226     case HVC: mnemonic = "hvc"; break;
   1227     case SMC: mnemonic = "smc"; break;
   1228     case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break;
   1229     case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break;
   1230     case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break;
   1231     default: form = "(Exception)";
   1232   }
   1233   Format(instr, mnemonic, form);
   1234 }
   1235 
   1236 
   1237 void DisassemblingDecoder::VisitUnimplemented(Instruction* instr) {
   1238   Format(instr, "unimplemented", "(Unimplemented)");
   1239 }
   1240 
   1241 
   1242 void DisassemblingDecoder::VisitUnallocated(Instruction* instr) {
   1243   Format(instr, "unallocated", "(Unallocated)");
   1244 }
   1245 
   1246 
   1247 void DisassemblingDecoder::ProcessOutput(Instruction* /*instr*/) {
   1248   // The base disasm does nothing more than disassembling into a buffer.
   1249 }
   1250 
   1251 
   1252 void DisassemblingDecoder::Format(Instruction* instr, const char* mnemonic,
   1253                                   const char* format) {
   1254   // TODO(mcapewel) don't think I can use the instr address here - there needs
   1255   //                to be a base address too
   1256   DCHECK(mnemonic != NULL);
   1257   ResetOutput();
   1258   Substitute(instr, mnemonic);
   1259   if (format != NULL) {
   1260     buffer_[buffer_pos_++] = ' ';
   1261     Substitute(instr, format);
   1262   }
   1263   buffer_[buffer_pos_] = 0;
   1264   ProcessOutput(instr);
   1265 }
   1266 
   1267 
   1268 void DisassemblingDecoder::Substitute(Instruction* instr, const char* string) {
   1269   char chr = *string++;
   1270   while (chr != '\0') {
   1271     if (chr == '\'') {
   1272       string += SubstituteField(instr, string);
   1273     } else {
   1274       buffer_[buffer_pos_++] = chr;
   1275     }
   1276     chr = *string++;
   1277   }
   1278 }
   1279 
   1280 
   1281 int DisassemblingDecoder::SubstituteField(Instruction* instr,
   1282                                           const char* format) {
   1283   switch (format[0]) {
   1284     case 'R':  // Register. X or W, selected by sf bit.
   1285     case 'F':  // FP Register. S or D, selected by type field.
   1286     case 'W':
   1287     case 'X':
   1288     case 'S':
   1289     case 'D': return SubstituteRegisterField(instr, format);
   1290     case 'I': return SubstituteImmediateField(instr, format);
   1291     case 'L': return SubstituteLiteralField(instr, format);
   1292     case 'H': return SubstituteShiftField(instr, format);
   1293     case 'P': return SubstitutePrefetchField(instr, format);
   1294     case 'C': return SubstituteConditionField(instr, format);
   1295     case 'E': return SubstituteExtendField(instr, format);
   1296     case 'A': return SubstitutePCRelAddressField(instr, format);
   1297     case 'B': return SubstituteBranchTargetField(instr, format);
   1298     case 'O': return SubstituteLSRegOffsetField(instr, format);
   1299     case 'M': return SubstituteBarrierField(instr, format);
   1300     default: {
   1301       UNREACHABLE();
   1302       return 1;
   1303     }
   1304   }
   1305 }
   1306 
   1307 
   1308 int DisassemblingDecoder::SubstituteRegisterField(Instruction* instr,
   1309                                                   const char* format) {
   1310   unsigned reg_num = 0;
   1311   unsigned field_len = 2;
   1312   switch (format[1]) {
   1313     case 'd': reg_num = instr->Rd(); break;
   1314     case 'n': reg_num = instr->Rn(); break;
   1315     case 'm': reg_num = instr->Rm(); break;
   1316     case 'a': reg_num = instr->Ra(); break;
   1317     case 't': {
   1318       if (format[2] == '2') {
   1319         reg_num = instr->Rt2();
   1320         field_len = 3;
   1321       } else {
   1322         reg_num = instr->Rt();
   1323       }
   1324       break;
   1325     }
   1326     case 's':
   1327       reg_num = instr->Rs();
   1328       break;
   1329     default: UNREACHABLE();
   1330   }
   1331 
   1332   // Increase field length for registers tagged as stack.
   1333   if (format[2] == 's') {
   1334     field_len = 3;
   1335   }
   1336 
   1337   char reg_type;
   1338   if (format[0] == 'R') {
   1339     // Register type is R: use sf bit to choose X and W.
   1340     reg_type = instr->SixtyFourBits() ? 'x' : 'w';
   1341   } else if (format[0] == 'F') {
   1342     // Floating-point register: use type field to choose S or D.
   1343     reg_type = ((instr->FPType() & 1) == 0) ? 's' : 'd';
   1344   } else {
   1345     // Register type is specified. Make it lower case.
   1346     reg_type = format[0] + 0x20;
   1347   }
   1348 
   1349   if ((reg_num != kZeroRegCode) || (reg_type == 's') || (reg_type == 'd')) {
   1350     // A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31.
   1351 
   1352     // Filter special registers
   1353     if ((reg_type == 'x') && (reg_num == 27)) {
   1354       AppendToOutput("cp");
   1355     } else if ((reg_type == 'x') && (reg_num == 28)) {
   1356       AppendToOutput("jssp");
   1357     } else if ((reg_type == 'x') && (reg_num == 29)) {
   1358       AppendToOutput("fp");
   1359     } else if ((reg_type == 'x') && (reg_num == 30)) {
   1360       AppendToOutput("lr");
   1361     } else {
   1362       AppendToOutput("%c%d", reg_type, reg_num);
   1363     }
   1364   } else if (format[2] == 's') {
   1365     // Disassemble w31/x31 as stack pointer wcsp/csp.
   1366     AppendToOutput("%s", (reg_type == 'w') ? "wcsp" : "csp");
   1367   } else {
   1368     // Disassemble w31/x31 as zero register wzr/xzr.
   1369     AppendToOutput("%czr", reg_type);
   1370   }
   1371 
   1372   return field_len;
   1373 }
   1374 
   1375 
   1376 int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr,
   1377                                                    const char* format) {
   1378   DCHECK(format[0] == 'I');
   1379 
   1380   switch (format[1]) {
   1381     case 'M': {  // IMoveImm or IMoveLSL.
   1382       if (format[5] == 'I') {
   1383         uint64_t imm = static_cast<uint64_t>(instr->ImmMoveWide())
   1384                        << (16 * instr->ShiftMoveWide());
   1385         AppendToOutput("#0x%" PRIx64, imm);
   1386       } else {
   1387         DCHECK(format[5] == 'L');
   1388         AppendToOutput("#0x%" PRIx32, instr->ImmMoveWide());
   1389         if (instr->ShiftMoveWide() > 0) {
   1390           AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
   1391         }
   1392       }
   1393       return 8;
   1394     }
   1395     case 'L': {
   1396       switch (format[2]) {
   1397         case 'L': {  // ILLiteral - Immediate Load Literal.
   1398           AppendToOutput("pc%+" PRId32, instr->ImmLLiteral()
   1399                                             << kLoadLiteralScaleLog2);
   1400           return 9;
   1401         }
   1402         case 'S': {  // ILS - Immediate Load/Store.
   1403           if (instr->ImmLS() != 0) {
   1404             AppendToOutput(", #%" PRId32, instr->ImmLS());
   1405           }
   1406           return 3;
   1407         }
   1408         case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
   1409           if (instr->ImmLSPair() != 0) {
   1410             // format[3] is the scale value. Convert to a number.
   1411             int scale = format[3] - 0x30;
   1412             AppendToOutput(", #%" PRId32, instr->ImmLSPair() * scale);
   1413           }
   1414           return 4;
   1415         }
   1416         case 'U': {  // ILU - Immediate Load/Store Unsigned.
   1417           if (instr->ImmLSUnsigned() != 0) {
   1418             AppendToOutput(", #%" PRId32, instr->ImmLSUnsigned()
   1419                                               << instr->SizeLS());
   1420           }
   1421           return 3;
   1422         }
   1423       }
   1424     }
   1425     case 'C': {  // ICondB - Immediate Conditional Branch.
   1426       int64_t offset = instr->ImmCondBranch() << 2;
   1427       char sign = (offset >= 0) ? '+' : '-';
   1428       AppendToOutput("#%c0x%" PRIx64, sign, offset);
   1429       return 6;
   1430     }
   1431     case 'A': {  // IAddSub.
   1432       DCHECK(instr->ShiftAddSub() <= 1);
   1433       int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
   1434       AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
   1435       return 7;
   1436     }
   1437     case 'F': {  // IFPSingle, IFPDouble or IFPFBits.
   1438       if (format[3] == 'F') {  // IFPFBits.
   1439         AppendToOutput("#%d", 64 - instr->FPScale());
   1440         return 8;
   1441       } else {
   1442         AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmFP(),
   1443                        format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64());
   1444         return 9;
   1445       }
   1446     }
   1447     case 'T': {  // ITri - Immediate Triangular Encoded.
   1448       AppendToOutput("#0x%" PRIx64, instr->ImmLogical());
   1449       return 4;
   1450     }
   1451     case 'N': {  // INzcv.
   1452       int nzcv = (instr->Nzcv() << Flags_offset);
   1453       AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N',
   1454                                   ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
   1455                                   ((nzcv & CFlag) == 0) ? 'c' : 'C',
   1456                                   ((nzcv & VFlag) == 0) ? 'v' : 'V');
   1457       return 5;
   1458     }
   1459     case 'P': {  // IP - Conditional compare.
   1460       AppendToOutput("#%d", instr->ImmCondCmp());
   1461       return 2;
   1462     }
   1463     case 'B': {  // Bitfields.
   1464       return SubstituteBitfieldImmediateField(instr, format);
   1465     }
   1466     case 'E': {  // IExtract.
   1467       AppendToOutput("#%d", instr->ImmS());
   1468       return 8;
   1469     }
   1470     case 'S': {  // IS - Test and branch bit.
   1471       AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
   1472                             instr->ImmTestBranchBit40());
   1473       return 2;
   1474     }
   1475     case 'D': {  // IDebug - HLT and BRK instructions.
   1476       AppendToOutput("#0x%x", instr->ImmException());
   1477       return 6;
   1478     }
   1479     default: {
   1480       UNREACHABLE();
   1481       return 0;
   1482     }
   1483   }
   1484 }
   1485 
   1486 
   1487 int DisassemblingDecoder::SubstituteBitfieldImmediateField(Instruction* instr,
   1488                                                            const char* format) {
   1489   DCHECK((format[0] == 'I') && (format[1] == 'B'));
   1490   unsigned r = instr->ImmR();
   1491   unsigned s = instr->ImmS();
   1492 
   1493   switch (format[2]) {
   1494     case 'r': {  // IBr.
   1495       AppendToOutput("#%d", r);
   1496       return 3;
   1497     }
   1498     case 's': {  // IBs+1 or IBs-r+1.
   1499       if (format[3] == '+') {
   1500         AppendToOutput("#%d", s + 1);
   1501         return 5;
   1502       } else {
   1503         DCHECK(format[3] == '-');
   1504         AppendToOutput("#%d", s - r + 1);
   1505         return 7;
   1506       }
   1507     }
   1508     case 'Z': {  // IBZ-r.
   1509       DCHECK((format[3] == '-') && (format[4] == 'r'));
   1510       unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
   1511                                                         : kWRegSizeInBits;
   1512       AppendToOutput("#%d", reg_size - r);
   1513       return 5;
   1514     }
   1515     default: {
   1516       UNREACHABLE();
   1517       return 0;
   1518     }
   1519   }
   1520 }
   1521 
   1522 
   1523 int DisassemblingDecoder::SubstituteLiteralField(Instruction* instr,
   1524                                                  const char* format) {
   1525   DCHECK(strncmp(format, "LValue", 6) == 0);
   1526   USE(format);
   1527 
   1528   switch (instr->Mask(LoadLiteralMask)) {
   1529     case LDR_w_lit:
   1530     case LDR_x_lit:
   1531     case LDR_s_lit:
   1532     case LDR_d_lit:
   1533       AppendToOutput("(addr 0x%016" PRIxPTR ")", instr->LiteralAddress());
   1534       break;
   1535     default: UNREACHABLE();
   1536   }
   1537 
   1538   return 6;
   1539 }
   1540 
   1541 
   1542 int DisassemblingDecoder::SubstituteShiftField(Instruction* instr,
   1543                                                const char* format) {
   1544   DCHECK(format[0] == 'H');
   1545   DCHECK(instr->ShiftDP() <= 0x3);
   1546 
   1547   switch (format[1]) {
   1548     case 'D': {  // HDP.
   1549       DCHECK(instr->ShiftDP() != ROR);
   1550     }  // Fall through.
   1551     case 'L': {  // HLo.
   1552       if (instr->ImmDPShift() != 0) {
   1553         const char* shift_type[] = {"lsl", "lsr", "asr", "ror"};
   1554         AppendToOutput(", %s #%" PRId32, shift_type[instr->ShiftDP()],
   1555                        instr->ImmDPShift());
   1556       }
   1557       return 3;
   1558     }
   1559     default:
   1560       UNREACHABLE();
   1561       return 0;
   1562   }
   1563 }
   1564 
   1565 
   1566 int DisassemblingDecoder::SubstituteConditionField(Instruction* instr,
   1567                                                    const char* format) {
   1568   DCHECK(format[0] == 'C');
   1569   const char* condition_code[] = { "eq", "ne", "hs", "lo",
   1570                                    "mi", "pl", "vs", "vc",
   1571                                    "hi", "ls", "ge", "lt",
   1572                                    "gt", "le", "al", "nv" };
   1573   int cond;
   1574   switch (format[1]) {
   1575     case 'B': cond = instr->ConditionBranch(); break;
   1576     case 'I': {
   1577       cond = NegateCondition(static_cast<Condition>(instr->Condition()));
   1578       break;
   1579     }
   1580     default: cond = instr->Condition();
   1581   }
   1582   AppendToOutput("%s", condition_code[cond]);
   1583   return 4;
   1584 }
   1585 
   1586 
   1587 int DisassemblingDecoder::SubstitutePCRelAddressField(Instruction* instr,
   1588                                                       const char* format) {
   1589   USE(format);
   1590   DCHECK(strncmp(format, "AddrPCRel", 9) == 0);
   1591 
   1592   int offset = instr->ImmPCRel();
   1593 
   1594   // Only ADR (AddrPCRelByte) is supported.
   1595   DCHECK(strcmp(format, "AddrPCRelByte") == 0);
   1596 
   1597   char sign = '+';
   1598   if (offset < 0) {
   1599     offset = -offset;
   1600     sign = '-';
   1601   }
   1602   AppendToOutput("#%c0x%x (addr %p)", sign, offset,
   1603                  instr->InstructionAtOffset(offset, Instruction::NO_CHECK));
   1604   return 13;
   1605 }
   1606 
   1607 
   1608 int DisassemblingDecoder::SubstituteBranchTargetField(Instruction* instr,
   1609                                                       const char* format) {
   1610   DCHECK(strncmp(format, "BImm", 4) == 0);
   1611 
   1612   int64_t offset = 0;
   1613   switch (format[5]) {
   1614     // BImmUncn - unconditional branch immediate.
   1615     case 'n': offset = instr->ImmUncondBranch(); break;
   1616     // BImmCond - conditional branch immediate.
   1617     case 'o': offset = instr->ImmCondBranch(); break;
   1618     // BImmCmpa - compare and branch immediate.
   1619     case 'm': offset = instr->ImmCmpBranch(); break;
   1620     // BImmTest - test and branch immediate.
   1621     case 'e': offset = instr->ImmTestBranch(); break;
   1622     default: UNREACHABLE();
   1623   }
   1624   offset <<= kInstructionSizeLog2;
   1625   char sign = '+';
   1626   if (offset < 0) {
   1627     sign = '-';
   1628   }
   1629   AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset),
   1630                  instr->InstructionAtOffset(offset), Instruction::NO_CHECK);
   1631   return 8;
   1632 }
   1633 
   1634 
   1635 int DisassemblingDecoder::SubstituteExtendField(Instruction* instr,
   1636                                                 const char* format) {
   1637   DCHECK(strncmp(format, "Ext", 3) == 0);
   1638   DCHECK(instr->ExtendMode() <= 7);
   1639   USE(format);
   1640 
   1641   const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
   1642                                 "sxtb", "sxth", "sxtw", "sxtx" };
   1643 
   1644   // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
   1645   // registers becomes lsl.
   1646   if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
   1647       (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
   1648        (instr->ExtendMode() == UXTX))) {
   1649     if (instr->ImmExtendShift() > 0) {
   1650       AppendToOutput(", lsl #%d", instr->ImmExtendShift());
   1651     }
   1652   } else {
   1653     AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
   1654     if (instr->ImmExtendShift() > 0) {
   1655       AppendToOutput(" #%d", instr->ImmExtendShift());
   1656     }
   1657   }
   1658   return 3;
   1659 }
   1660 
   1661 
   1662 int DisassemblingDecoder::SubstituteLSRegOffsetField(Instruction* instr,
   1663                                                      const char* format) {
   1664   DCHECK(strncmp(format, "Offsetreg", 9) == 0);
   1665   const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
   1666                                 "undefined", "undefined", "sxtw", "sxtx" };
   1667   USE(format);
   1668 
   1669   unsigned shift = instr->ImmShiftLS();
   1670   Extend ext = static_cast<Extend>(instr->ExtendMode());
   1671   char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
   1672 
   1673   unsigned rm = instr->Rm();
   1674   if (rm == kZeroRegCode) {
   1675     AppendToOutput("%czr", reg_type);
   1676   } else {
   1677     AppendToOutput("%c%d", reg_type, rm);
   1678   }
   1679 
   1680   // Extend mode UXTX is an alias for shift mode LSL here.
   1681   if (!((ext == UXTX) && (shift == 0))) {
   1682     AppendToOutput(", %s", extend_mode[ext]);
   1683     if (shift != 0) {
   1684       AppendToOutput(" #%d", instr->SizeLS());
   1685     }
   1686   }
   1687   return 9;
   1688 }
   1689 
   1690 
   1691 int DisassemblingDecoder::SubstitutePrefetchField(Instruction* instr,
   1692                                                   const char* format) {
   1693   DCHECK(format[0] == 'P');
   1694   USE(format);
   1695 
   1696   int prefetch_mode = instr->PrefetchMode();
   1697 
   1698   const char* ls = (prefetch_mode & 0x10) ? "st" : "ld";
   1699   int level = (prefetch_mode >> 1) + 1;
   1700   const char* ks = (prefetch_mode & 1) ? "strm" : "keep";
   1701 
   1702   AppendToOutput("p%sl%d%s", ls, level, ks);
   1703   return 6;
   1704 }
   1705 
   1706 int DisassemblingDecoder::SubstituteBarrierField(Instruction* instr,
   1707                                                  const char* format) {
   1708   DCHECK(format[0] == 'M');
   1709   USE(format);
   1710 
   1711   static const char* const options[4][4] = {
   1712     { "sy (0b0000)", "oshld", "oshst", "osh" },
   1713     { "sy (0b0100)", "nshld", "nshst", "nsh" },
   1714     { "sy (0b1000)", "ishld", "ishst", "ish" },
   1715     { "sy (0b1100)", "ld", "st", "sy" }
   1716   };
   1717   int domain = instr->ImmBarrierDomain();
   1718   int type = instr->ImmBarrierType();
   1719 
   1720   AppendToOutput("%s", options[domain][type]);
   1721   return 1;
   1722 }
   1723 
   1724 
   1725 void DisassemblingDecoder::ResetOutput() {
   1726   buffer_pos_ = 0;
   1727   buffer_[buffer_pos_] = 0;
   1728 }
   1729 
   1730 
   1731 void DisassemblingDecoder::AppendToOutput(const char* format, ...) {
   1732   va_list args;
   1733   va_start(args, format);
   1734   buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args);
   1735   va_end(args);
   1736 }
   1737 
   1738 
   1739 void PrintDisassembler::ProcessOutput(Instruction* instr) {
   1740   fprintf(stream_, "0x%016" PRIx64 "  %08" PRIx32 "\t\t%s\n",
   1741           reinterpret_cast<uint64_t>(instr), instr->InstructionBits(),
   1742           GetOutput());
   1743 }
   1744 
   1745 }  // namespace internal
   1746 }  // namespace v8
   1747 
   1748 
   1749 namespace disasm {
   1750 
   1751 
   1752 const char* NameConverter::NameOfAddress(byte* addr) const {
   1753   v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void *>(addr));
   1754   return tmp_buffer_.start();
   1755 }
   1756 
   1757 
   1758 const char* NameConverter::NameOfConstant(byte* addr) const {
   1759   return NameOfAddress(addr);
   1760 }
   1761 
   1762 
   1763 const char* NameConverter::NameOfCPURegister(int reg) const {
   1764   unsigned ureg = reg;  // Avoid warnings about signed/unsigned comparisons.
   1765   if (ureg >= v8::internal::kNumberOfRegisters) {
   1766     return "noreg";
   1767   }
   1768   if (ureg == v8::internal::kZeroRegCode) {
   1769     return "xzr";
   1770   }
   1771   v8::internal::SNPrintF(tmp_buffer_, "x%u", ureg);
   1772   return tmp_buffer_.start();
   1773 }
   1774 
   1775 
   1776 const char* NameConverter::NameOfByteCPURegister(int reg) const {
   1777   UNREACHABLE();  // ARM64 does not have the concept of a byte register
   1778   return "nobytereg";
   1779 }
   1780 
   1781 
   1782 const char* NameConverter::NameOfXMMRegister(int reg) const {
   1783   UNREACHABLE();  // ARM64 does not have any XMM registers
   1784   return "noxmmreg";
   1785 }
   1786 
   1787 
   1788 const char* NameConverter::NameInCode(byte* addr) const {
   1789   // The default name converter is called for unknown code, so we will not try
   1790   // to access any memory.
   1791   return "";
   1792 }
   1793 
   1794 
   1795 //------------------------------------------------------------------------------
   1796 
   1797 class BufferDisassembler : public v8::internal::DisassemblingDecoder {
   1798  public:
   1799   explicit BufferDisassembler(v8::internal::Vector<char> out_buffer)
   1800       : out_buffer_(out_buffer) { }
   1801 
   1802   ~BufferDisassembler() { }
   1803 
   1804   virtual void ProcessOutput(v8::internal::Instruction* instr) {
   1805     v8::internal::SNPrintF(out_buffer_, "%08" PRIx32 "       %s",
   1806                            instr->InstructionBits(), GetOutput());
   1807   }
   1808 
   1809  private:
   1810   v8::internal::Vector<char> out_buffer_;
   1811 };
   1812 
   1813 Disassembler::Disassembler(const NameConverter& converter)
   1814     : converter_(converter) {}
   1815 
   1816 
   1817 Disassembler::~Disassembler() { USE(converter_); }
   1818 
   1819 
   1820 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
   1821                                     byte* instr) {
   1822   v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder;
   1823   BufferDisassembler disasm(buffer);
   1824   decoder.AppendVisitor(&disasm);
   1825 
   1826   decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(instr));
   1827   return v8::internal::kInstructionSize;
   1828 }
   1829 
   1830 
   1831 int Disassembler::ConstantPoolSizeAt(byte* instr) {
   1832   return v8::internal::Assembler::ConstantPoolSizeAt(
   1833       reinterpret_cast<v8::internal::Instruction*>(instr));
   1834 }
   1835 
   1836 
   1837 void Disassembler::Disassemble(FILE* file, byte* start, byte* end) {
   1838   v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder;
   1839   v8::internal::PrintDisassembler disasm(file);
   1840   decoder.AppendVisitor(&disasm);
   1841 
   1842   for (byte* pc = start; pc < end; pc += v8::internal::kInstructionSize) {
   1843     decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc));
   1844   }
   1845 }
   1846 
   1847 }  // namespace disasm
   1848 
   1849 #endif  // V8_TARGET_ARCH_ARM64
   1850