11cb0ef41Sopenharmony_ci// Copyright 2011 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// A Disassembler object is used to disassemble a block of code instruction by
61cb0ef41Sopenharmony_ci// instruction. The default implementation of the NameConverter object can be
71cb0ef41Sopenharmony_ci// overriden to modify register names or to do symbol lookup on addresses.
81cb0ef41Sopenharmony_ci//
91cb0ef41Sopenharmony_ci// The example below will disassemble a block of code and print it to stdout.
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci//   NameConverter converter;
121cb0ef41Sopenharmony_ci//   Disassembler d(converter);
131cb0ef41Sopenharmony_ci//   for (byte* pc = begin; pc < end;) {
141cb0ef41Sopenharmony_ci//     v8::base::EmbeddedVector<char, 256> buffer;
151cb0ef41Sopenharmony_ci//     byte* prev_pc = pc;
161cb0ef41Sopenharmony_ci//     pc += d.InstructionDecode(buffer, pc);
171cb0ef41Sopenharmony_ci//     printf("%p    %08x      %s\n",
181cb0ef41Sopenharmony_ci//            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
191cb0ef41Sopenharmony_ci//   }
201cb0ef41Sopenharmony_ci//
211cb0ef41Sopenharmony_ci// The Disassembler class also has a convenience method to disassemble a block
221cb0ef41Sopenharmony_ci// of code into a FILE*, meaning that the above functionality could also be
231cb0ef41Sopenharmony_ci// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci#include <cassert>
261cb0ef41Sopenharmony_ci#include <cinttypes>
271cb0ef41Sopenharmony_ci#include <cstdarg>
281cb0ef41Sopenharmony_ci#include <cstdio>
291cb0ef41Sopenharmony_ci#include <cstring>
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_ARM
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci#include "src/base/bits.h"
341cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h"
351cb0ef41Sopenharmony_ci#include "src/base/strings.h"
361cb0ef41Sopenharmony_ci#include "src/base/vector.h"
371cb0ef41Sopenharmony_ci#include "src/codegen/arm/assembler-arm.h"
381cb0ef41Sopenharmony_ci#include "src/codegen/arm/constants-arm.h"
391cb0ef41Sopenharmony_ci#include "src/codegen/arm/register-arm.h"
401cb0ef41Sopenharmony_ci#include "src/diagnostics/disasm.h"
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cinamespace v8 {
431cb0ef41Sopenharmony_cinamespace internal {
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci//------------------------------------------------------------------------------
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci// Decoder decodes and disassembles instructions into an output buffer.
481cb0ef41Sopenharmony_ci// It uses the converter to convert register names and call destinations into
491cb0ef41Sopenharmony_ci// more informative description.
501cb0ef41Sopenharmony_ciclass Decoder {
511cb0ef41Sopenharmony_ci public:
521cb0ef41Sopenharmony_ci  Decoder(const disasm::NameConverter& converter, base::Vector<char> out_buffer)
531cb0ef41Sopenharmony_ci      : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) {
541cb0ef41Sopenharmony_ci    out_buffer_[out_buffer_pos_] = '\0';
551cb0ef41Sopenharmony_ci  }
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  ~Decoder() {}
581cb0ef41Sopenharmony_ci  Decoder(const Decoder&) = delete;
591cb0ef41Sopenharmony_ci  Decoder& operator=(const Decoder&) = delete;
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  // Writes one disassembled instruction into 'buffer' (0-terminated).
621cb0ef41Sopenharmony_ci  // Returns the length of the disassembled machine instruction in bytes.
631cb0ef41Sopenharmony_ci  int InstructionDecode(byte* instruction);
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  static bool IsConstantPoolAt(byte* instr_ptr);
661cb0ef41Sopenharmony_ci  static int ConstantPoolSizeAt(byte* instr_ptr);
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci private:
691cb0ef41Sopenharmony_ci  // Bottleneck functions to print into the out_buffer.
701cb0ef41Sopenharmony_ci  void PrintChar(const char ch);
711cb0ef41Sopenharmony_ci  void Print(const char* str);
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  // Printing of common values.
741cb0ef41Sopenharmony_ci  void PrintRegister(int reg);
751cb0ef41Sopenharmony_ci  void PrintSRegister(int reg);
761cb0ef41Sopenharmony_ci  void PrintDRegister(int reg);
771cb0ef41Sopenharmony_ci  void PrintQRegister(int reg);
781cb0ef41Sopenharmony_ci  int FormatVFPRegister(Instruction* instr, const char* format,
791cb0ef41Sopenharmony_ci                        VFPRegPrecision precision);
801cb0ef41Sopenharmony_ci  void PrintMovwMovt(Instruction* instr);
811cb0ef41Sopenharmony_ci  int FormatVFPinstruction(Instruction* instr, const char* format);
821cb0ef41Sopenharmony_ci  void PrintCondition(Instruction* instr);
831cb0ef41Sopenharmony_ci  void PrintShiftRm(Instruction* instr);
841cb0ef41Sopenharmony_ci  void PrintShiftImm(Instruction* instr);
851cb0ef41Sopenharmony_ci  void PrintShiftSat(Instruction* instr);
861cb0ef41Sopenharmony_ci  void PrintPU(Instruction* instr);
871cb0ef41Sopenharmony_ci  void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  // Handle formatting of instructions and their options.
901cb0ef41Sopenharmony_ci  int FormatRegister(Instruction* instr, const char* option);
911cb0ef41Sopenharmony_ci  void FormatNeonList(int Vd, int type);
921cb0ef41Sopenharmony_ci  void FormatNeonMemory(int Rn, int align, int Rm);
931cb0ef41Sopenharmony_ci  int FormatOption(Instruction* instr, const char* option);
941cb0ef41Sopenharmony_ci  void Format(Instruction* instr, const char* format);
951cb0ef41Sopenharmony_ci  void Unknown(Instruction* instr);
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  // Each of these functions decodes one particular instruction type, a 3-bit
981cb0ef41Sopenharmony_ci  // field in the instruction encoding.
991cb0ef41Sopenharmony_ci  // Types 0 and 1 are combined as they are largely the same except for the way
1001cb0ef41Sopenharmony_ci  // they interpret the shifter operand.
1011cb0ef41Sopenharmony_ci  void DecodeType01(Instruction* instr);
1021cb0ef41Sopenharmony_ci  void DecodeType2(Instruction* instr);
1031cb0ef41Sopenharmony_ci  void DecodeType3(Instruction* instr);
1041cb0ef41Sopenharmony_ci  void DecodeType4(Instruction* instr);
1051cb0ef41Sopenharmony_ci  void DecodeType5(Instruction* instr);
1061cb0ef41Sopenharmony_ci  void DecodeType6(Instruction* instr);
1071cb0ef41Sopenharmony_ci  // Type 7 includes special Debugger instructions.
1081cb0ef41Sopenharmony_ci  int DecodeType7(Instruction* instr);
1091cb0ef41Sopenharmony_ci  // CP15 coprocessor instructions.
1101cb0ef41Sopenharmony_ci  void DecodeTypeCP15(Instruction* instr);
1111cb0ef41Sopenharmony_ci  // For VFP support.
1121cb0ef41Sopenharmony_ci  void DecodeTypeVFP(Instruction* instr);
1131cb0ef41Sopenharmony_ci  void DecodeType6CoprocessorIns(Instruction* instr);
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  void DecodeSpecialCondition(Instruction* instr);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  // F4.1.14 Floating-point data-processing.
1181cb0ef41Sopenharmony_ci  void DecodeFloatingPointDataProcessing(Instruction* instr);
1191cb0ef41Sopenharmony_ci  // F4.1.18 Unconditional instructions.
1201cb0ef41Sopenharmony_ci  void DecodeUnconditional(Instruction* instr);
1211cb0ef41Sopenharmony_ci  // F4.1.20 Advanced SIMD data-processing.
1221cb0ef41Sopenharmony_ci  void DecodeAdvancedSIMDDataProcessing(Instruction* instr);
1231cb0ef41Sopenharmony_ci  // F4.1.21 Advanced SIMD two registers, or three registers of different
1241cb0ef41Sopenharmony_ci  // lengths.
1251cb0ef41Sopenharmony_ci  void DecodeAdvancedSIMDTwoOrThreeRegisters(Instruction* instr);
1261cb0ef41Sopenharmony_ci  // F4.1.23 Memory hints and barriers.
1271cb0ef41Sopenharmony_ci  void DecodeMemoryHintsAndBarriers(Instruction* instr);
1281cb0ef41Sopenharmony_ci  // F4.1.24 Advanced SIMD element or structure load/store.
1291cb0ef41Sopenharmony_ci  void DecodeAdvancedSIMDElementOrStructureLoadStore(Instruction* instr);
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
1321cb0ef41Sopenharmony_ci  void DecodeVCMP(Instruction* instr);
1331cb0ef41Sopenharmony_ci  void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
1341cb0ef41Sopenharmony_ci  void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
1351cb0ef41Sopenharmony_ci  void DecodeVmovImmediate(Instruction* instr);
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  const disasm::NameConverter& converter_;
1381cb0ef41Sopenharmony_ci  base::Vector<char> out_buffer_;
1391cb0ef41Sopenharmony_ci  int out_buffer_pos_;
1401cb0ef41Sopenharmony_ci};
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci// Support for assertions in the Decoder formatting functions.
1431cb0ef41Sopenharmony_ci#define STRING_STARTS_WITH(string, compare_string) \
1441cb0ef41Sopenharmony_ci  (strncmp(string, compare_string, strlen(compare_string)) == 0)
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci// Append the ch to the output buffer.
1471cb0ef41Sopenharmony_civoid Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; }
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci// Append the str to the output buffer.
1501cb0ef41Sopenharmony_civoid Decoder::Print(const char* str) {
1511cb0ef41Sopenharmony_ci  char cur = *str++;
1521cb0ef41Sopenharmony_ci  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
1531cb0ef41Sopenharmony_ci    PrintChar(cur);
1541cb0ef41Sopenharmony_ci    cur = *str++;
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci  out_buffer_[out_buffer_pos_] = 0;
1571cb0ef41Sopenharmony_ci}
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci// These condition names are defined in a way to match the native disassembler
1601cb0ef41Sopenharmony_ci// formatting. See for example the command "objdump -d <binary file>".
1611cb0ef41Sopenharmony_cistatic const char* const cond_names[kNumberOfConditions] = {
1621cb0ef41Sopenharmony_ci    "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
1631cb0ef41Sopenharmony_ci    "hi", "ls", "ge", "lt", "gt", "le", "",   "invalid",
1641cb0ef41Sopenharmony_ci};
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci// Print the condition guarding the instruction.
1671cb0ef41Sopenharmony_civoid Decoder::PrintCondition(Instruction* instr) {
1681cb0ef41Sopenharmony_ci  Print(cond_names[instr->ConditionValue()]);
1691cb0ef41Sopenharmony_ci}
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci// Print the register name according to the active name converter.
1721cb0ef41Sopenharmony_civoid Decoder::PrintRegister(int reg) {
1731cb0ef41Sopenharmony_ci  Print(converter_.NameOfCPURegister(reg));
1741cb0ef41Sopenharmony_ci}
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci// Print the VFP S register name according to the active name converter.
1771cb0ef41Sopenharmony_civoid Decoder::PrintSRegister(int reg) { Print(VFPRegisters::Name(reg, false)); }
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci// Print the VFP D register name according to the active name converter.
1801cb0ef41Sopenharmony_civoid Decoder::PrintDRegister(int reg) { Print(VFPRegisters::Name(reg, true)); }
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci// Print the VFP Q register name according to the active name converter.
1831cb0ef41Sopenharmony_civoid Decoder::PrintQRegister(int reg) {
1841cb0ef41Sopenharmony_ci  Print(RegisterName(QwNeonRegister::from_code(reg)));
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci// These shift names are defined in a way to match the native disassembler
1881cb0ef41Sopenharmony_ci// formatting. See for example the command "objdump -d <binary file>".
1891cb0ef41Sopenharmony_cistatic const char* const shift_names[kNumberOfShifts] = {"lsl", "lsr", "asr",
1901cb0ef41Sopenharmony_ci                                                         "ror"};
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci// Print the register shift operands for the instruction. Generally used for
1931cb0ef41Sopenharmony_ci// data processing instructions.
1941cb0ef41Sopenharmony_civoid Decoder::PrintShiftRm(Instruction* instr) {
1951cb0ef41Sopenharmony_ci  ShiftOp shift = instr->ShiftField();
1961cb0ef41Sopenharmony_ci  int shift_index = instr->ShiftValue();
1971cb0ef41Sopenharmony_ci  int shift_amount = instr->ShiftAmountValue();
1981cb0ef41Sopenharmony_ci  int rm = instr->RmValue();
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  PrintRegister(rm);
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) {
2031cb0ef41Sopenharmony_ci    // Special case for using rm only.
2041cb0ef41Sopenharmony_ci    return;
2051cb0ef41Sopenharmony_ci  }
2061cb0ef41Sopenharmony_ci  if (instr->RegShiftValue() == 0) {
2071cb0ef41Sopenharmony_ci    // by immediate
2081cb0ef41Sopenharmony_ci    if ((shift == ROR) && (shift_amount == 0)) {
2091cb0ef41Sopenharmony_ci      Print(", RRX");
2101cb0ef41Sopenharmony_ci      return;
2111cb0ef41Sopenharmony_ci    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
2121cb0ef41Sopenharmony_ci      shift_amount = 32;
2131cb0ef41Sopenharmony_ci    }
2141cb0ef41Sopenharmony_ci    out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, ", %s #%d",
2151cb0ef41Sopenharmony_ci                                      shift_names[shift_index], shift_amount);
2161cb0ef41Sopenharmony_ci  } else {
2171cb0ef41Sopenharmony_ci    // by register
2181cb0ef41Sopenharmony_ci    int rs = instr->RsValue();
2191cb0ef41Sopenharmony_ci    out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, ", %s ",
2201cb0ef41Sopenharmony_ci                                      shift_names[shift_index]);
2211cb0ef41Sopenharmony_ci    PrintRegister(rs);
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci}
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci// Print the immediate operand for the instruction. Generally used for data
2261cb0ef41Sopenharmony_ci// processing instructions.
2271cb0ef41Sopenharmony_civoid Decoder::PrintShiftImm(Instruction* instr) {
2281cb0ef41Sopenharmony_ci  int rotate = instr->RotateValue() * 2;
2291cb0ef41Sopenharmony_ci  int immed8 = instr->Immed8Value();
2301cb0ef41Sopenharmony_ci  int imm = base::bits::RotateRight32(immed8, rotate);
2311cb0ef41Sopenharmony_ci  out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm);
2321cb0ef41Sopenharmony_ci}
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci// Print the optional shift and immediate used by saturating instructions.
2351cb0ef41Sopenharmony_civoid Decoder::PrintShiftSat(Instruction* instr) {
2361cb0ef41Sopenharmony_ci  int shift = instr->Bits(11, 7);
2371cb0ef41Sopenharmony_ci  if (shift > 0) {
2381cb0ef41Sopenharmony_ci    out_buffer_pos_ +=
2391cb0ef41Sopenharmony_ci        base::SNPrintF(out_buffer_ + out_buffer_pos_, ", %s #%d",
2401cb0ef41Sopenharmony_ci                       shift_names[instr->Bit(6) * 2], instr->Bits(11, 7));
2411cb0ef41Sopenharmony_ci  }
2421cb0ef41Sopenharmony_ci}
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci// Print PU formatting to reduce complexity of FormatOption.
2451cb0ef41Sopenharmony_civoid Decoder::PrintPU(Instruction* instr) {
2461cb0ef41Sopenharmony_ci  switch (instr->PUField()) {
2471cb0ef41Sopenharmony_ci    case da_x: {
2481cb0ef41Sopenharmony_ci      Print("da");
2491cb0ef41Sopenharmony_ci      break;
2501cb0ef41Sopenharmony_ci    }
2511cb0ef41Sopenharmony_ci    case ia_x: {
2521cb0ef41Sopenharmony_ci      Print("ia");
2531cb0ef41Sopenharmony_ci      break;
2541cb0ef41Sopenharmony_ci    }
2551cb0ef41Sopenharmony_ci    case db_x: {
2561cb0ef41Sopenharmony_ci      Print("db");
2571cb0ef41Sopenharmony_ci      break;
2581cb0ef41Sopenharmony_ci    }
2591cb0ef41Sopenharmony_ci    case ib_x: {
2601cb0ef41Sopenharmony_ci      Print("ib");
2611cb0ef41Sopenharmony_ci      break;
2621cb0ef41Sopenharmony_ci    }
2631cb0ef41Sopenharmony_ci    default: {
2641cb0ef41Sopenharmony_ci      UNREACHABLE();
2651cb0ef41Sopenharmony_ci    }
2661cb0ef41Sopenharmony_ci  }
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
2701cb0ef41Sopenharmony_ci// the FormatOption method.
2711cb0ef41Sopenharmony_civoid Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
2721cb0ef41Sopenharmony_ci  switch (svc) {
2731cb0ef41Sopenharmony_ci    case kCallRtRedirected:
2741cb0ef41Sopenharmony_ci      Print("call rt redirected");
2751cb0ef41Sopenharmony_ci      return;
2761cb0ef41Sopenharmony_ci    case kBreakpoint:
2771cb0ef41Sopenharmony_ci      Print("breakpoint");
2781cb0ef41Sopenharmony_ci      return;
2791cb0ef41Sopenharmony_ci    default:
2801cb0ef41Sopenharmony_ci      if (svc >= kStopCode) {
2811cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
2821cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d - 0x%x",
2831cb0ef41Sopenharmony_ci                           svc & kStopCodeMask, svc & kStopCodeMask);
2841cb0ef41Sopenharmony_ci      } else {
2851cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
2861cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", svc);
2871cb0ef41Sopenharmony_ci      }
2881cb0ef41Sopenharmony_ci      return;
2891cb0ef41Sopenharmony_ci  }
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci// Handle all register based formatting in this function to reduce the
2931cb0ef41Sopenharmony_ci// complexity of FormatOption.
2941cb0ef41Sopenharmony_ciint Decoder::FormatRegister(Instruction* instr, const char* format) {
2951cb0ef41Sopenharmony_ci  DCHECK_EQ(format[0], 'r');
2961cb0ef41Sopenharmony_ci  if (format[1] == 'n') {  // 'rn: Rn register
2971cb0ef41Sopenharmony_ci    int reg = instr->RnValue();
2981cb0ef41Sopenharmony_ci    PrintRegister(reg);
2991cb0ef41Sopenharmony_ci    return 2;
3001cb0ef41Sopenharmony_ci  } else if (format[1] == 'd') {  // 'rd: Rd register
3011cb0ef41Sopenharmony_ci    int reg = instr->RdValue();
3021cb0ef41Sopenharmony_ci    PrintRegister(reg);
3031cb0ef41Sopenharmony_ci    return 2;
3041cb0ef41Sopenharmony_ci  } else if (format[1] == 's') {  // 'rs: Rs register
3051cb0ef41Sopenharmony_ci    int reg = instr->RsValue();
3061cb0ef41Sopenharmony_ci    PrintRegister(reg);
3071cb0ef41Sopenharmony_ci    return 2;
3081cb0ef41Sopenharmony_ci  } else if (format[1] == 'm') {  // 'rm: Rm register
3091cb0ef41Sopenharmony_ci    int reg = instr->RmValue();
3101cb0ef41Sopenharmony_ci    PrintRegister(reg);
3111cb0ef41Sopenharmony_ci    return 2;
3121cb0ef41Sopenharmony_ci  } else if (format[1] == 't') {  // 'rt: Rt register
3131cb0ef41Sopenharmony_ci    int reg = instr->RtValue();
3141cb0ef41Sopenharmony_ci    PrintRegister(reg);
3151cb0ef41Sopenharmony_ci    return 2;
3161cb0ef41Sopenharmony_ci  } else if (format[1] == 'l') {
3171cb0ef41Sopenharmony_ci    // 'rlist: register list for load and store multiple instructions
3181cb0ef41Sopenharmony_ci    DCHECK(STRING_STARTS_WITH(format, "rlist"));
3191cb0ef41Sopenharmony_ci    int rlist = instr->RlistValue();
3201cb0ef41Sopenharmony_ci    int reg = 0;
3211cb0ef41Sopenharmony_ci    Print("{");
3221cb0ef41Sopenharmony_ci    // Print register list in ascending order, by scanning the bit mask.
3231cb0ef41Sopenharmony_ci    while (rlist != 0) {
3241cb0ef41Sopenharmony_ci      if ((rlist & 1) != 0) {
3251cb0ef41Sopenharmony_ci        PrintRegister(reg);
3261cb0ef41Sopenharmony_ci        if ((rlist >> 1) != 0) {
3271cb0ef41Sopenharmony_ci          Print(", ");
3281cb0ef41Sopenharmony_ci        }
3291cb0ef41Sopenharmony_ci      }
3301cb0ef41Sopenharmony_ci      reg++;
3311cb0ef41Sopenharmony_ci      rlist >>= 1;
3321cb0ef41Sopenharmony_ci    }
3331cb0ef41Sopenharmony_ci    Print("}");
3341cb0ef41Sopenharmony_ci    return 5;
3351cb0ef41Sopenharmony_ci  }
3361cb0ef41Sopenharmony_ci  UNREACHABLE();
3371cb0ef41Sopenharmony_ci}
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci// Handle all VFP register based formatting in this function to reduce the
3401cb0ef41Sopenharmony_ci// complexity of FormatOption.
3411cb0ef41Sopenharmony_ciint Decoder::FormatVFPRegister(Instruction* instr, const char* format,
3421cb0ef41Sopenharmony_ci                               VFPRegPrecision precision) {
3431cb0ef41Sopenharmony_ci  int retval = 2;
3441cb0ef41Sopenharmony_ci  int reg = -1;
3451cb0ef41Sopenharmony_ci  if (format[1] == 'n') {
3461cb0ef41Sopenharmony_ci    reg = instr->VFPNRegValue(precision);
3471cb0ef41Sopenharmony_ci  } else if (format[1] == 'm') {
3481cb0ef41Sopenharmony_ci    reg = instr->VFPMRegValue(precision);
3491cb0ef41Sopenharmony_ci  } else if (format[1] == 'd') {
3501cb0ef41Sopenharmony_ci    if ((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) &&
3511cb0ef41Sopenharmony_ci        (instr->Bits(11, 9) == 0x5) && (instr->Bit(4) == 0x1)) {
3521cb0ef41Sopenharmony_ci      // vmov.32 has Vd in a different place.
3531cb0ef41Sopenharmony_ci      reg = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3541cb0ef41Sopenharmony_ci    } else {
3551cb0ef41Sopenharmony_ci      reg = instr->VFPDRegValue(precision);
3561cb0ef41Sopenharmony_ci    }
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci    if (format[2] == '+') {
3591cb0ef41Sopenharmony_ci      DCHECK_NE(kSimd128Precision, precision);  // Simd128 unimplemented.
3601cb0ef41Sopenharmony_ci      int immed8 = instr->Immed8Value();
3611cb0ef41Sopenharmony_ci      if (precision == kSinglePrecision) reg += immed8 - 1;
3621cb0ef41Sopenharmony_ci      if (precision == kDoublePrecision) reg += (immed8 / 2 - 1);
3631cb0ef41Sopenharmony_ci    }
3641cb0ef41Sopenharmony_ci    if (format[2] == '+') retval = 3;
3651cb0ef41Sopenharmony_ci  } else {
3661cb0ef41Sopenharmony_ci    UNREACHABLE();
3671cb0ef41Sopenharmony_ci  }
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ci  if (precision == kSinglePrecision) {
3701cb0ef41Sopenharmony_ci    PrintSRegister(reg);
3711cb0ef41Sopenharmony_ci  } else if (precision == kDoublePrecision) {
3721cb0ef41Sopenharmony_ci    PrintDRegister(reg);
3731cb0ef41Sopenharmony_ci  } else {
3741cb0ef41Sopenharmony_ci    DCHECK_EQ(kSimd128Precision, precision);
3751cb0ef41Sopenharmony_ci    PrintQRegister(reg);
3761cb0ef41Sopenharmony_ci  }
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci  return retval;
3791cb0ef41Sopenharmony_ci}
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ciint Decoder::FormatVFPinstruction(Instruction* instr, const char* format) {
3821cb0ef41Sopenharmony_ci  Print(format);
3831cb0ef41Sopenharmony_ci  return 0;
3841cb0ef41Sopenharmony_ci}
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_civoid Decoder::FormatNeonList(int Vd, int type) {
3871cb0ef41Sopenharmony_ci  if (type == nlt_1) {
3881cb0ef41Sopenharmony_ci    out_buffer_pos_ +=
3891cb0ef41Sopenharmony_ci        base::SNPrintF(out_buffer_ + out_buffer_pos_, "{d%d}", Vd);
3901cb0ef41Sopenharmony_ci  } else if (type == nlt_2) {
3911cb0ef41Sopenharmony_ci    out_buffer_pos_ +=
3921cb0ef41Sopenharmony_ci        base::SNPrintF(out_buffer_ + out_buffer_pos_, "{d%d, d%d}", Vd, Vd + 1);
3931cb0ef41Sopenharmony_ci  } else if (type == nlt_3) {
3941cb0ef41Sopenharmony_ci    out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
3951cb0ef41Sopenharmony_ci                                      "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2);
3961cb0ef41Sopenharmony_ci  } else if (type == nlt_4) {
3971cb0ef41Sopenharmony_ci    out_buffer_pos_ +=
3981cb0ef41Sopenharmony_ci        base::SNPrintF(out_buffer_ + out_buffer_pos_, "{d%d, d%d, d%d, d%d}",
3991cb0ef41Sopenharmony_ci                       Vd, Vd + 1, Vd + 2, Vd + 3);
4001cb0ef41Sopenharmony_ci  }
4011cb0ef41Sopenharmony_ci}
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_civoid Decoder::FormatNeonMemory(int Rn, int align, int Rm) {
4041cb0ef41Sopenharmony_ci  out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "[%s",
4051cb0ef41Sopenharmony_ci                                    converter_.NameOfCPURegister(Rn));
4061cb0ef41Sopenharmony_ci  if (align != 0) {
4071cb0ef41Sopenharmony_ci    out_buffer_pos_ +=
4081cb0ef41Sopenharmony_ci        base::SNPrintF(out_buffer_ + out_buffer_pos_, ":%d", (1 << align) << 6);
4091cb0ef41Sopenharmony_ci  }
4101cb0ef41Sopenharmony_ci  if (Rm == 15) {
4111cb0ef41Sopenharmony_ci    Print("]");
4121cb0ef41Sopenharmony_ci  } else if (Rm == 13) {
4131cb0ef41Sopenharmony_ci    Print("]!");
4141cb0ef41Sopenharmony_ci  } else {
4151cb0ef41Sopenharmony_ci    out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "], %s",
4161cb0ef41Sopenharmony_ci                                      converter_.NameOfCPURegister(Rm));
4171cb0ef41Sopenharmony_ci  }
4181cb0ef41Sopenharmony_ci}
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ci// Print the movw or movt instruction.
4211cb0ef41Sopenharmony_civoid Decoder::PrintMovwMovt(Instruction* instr) {
4221cb0ef41Sopenharmony_ci  int imm = instr->ImmedMovwMovtValue();
4231cb0ef41Sopenharmony_ci  int rd = instr->RdValue();
4241cb0ef41Sopenharmony_ci  PrintRegister(rd);
4251cb0ef41Sopenharmony_ci  out_buffer_pos_ +=
4261cb0ef41Sopenharmony_ci      base::SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm);
4271cb0ef41Sopenharmony_ci}
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci// FormatOption takes a formatting string and interprets it based on
4301cb0ef41Sopenharmony_ci// the current instructions. The format string points to the first
4311cb0ef41Sopenharmony_ci// character of the option string (the option escape has already been
4321cb0ef41Sopenharmony_ci// consumed by the caller.)  FormatOption returns the number of
4331cb0ef41Sopenharmony_ci// characters that were consumed from the formatting string.
4341cb0ef41Sopenharmony_ciint Decoder::FormatOption(Instruction* instr, const char* format) {
4351cb0ef41Sopenharmony_ci  switch (format[0]) {
4361cb0ef41Sopenharmony_ci    case 'a': {  // 'a: accumulate multiplies
4371cb0ef41Sopenharmony_ci      if (instr->Bit(21) == 0) {
4381cb0ef41Sopenharmony_ci        Print("ul");
4391cb0ef41Sopenharmony_ci      } else {
4401cb0ef41Sopenharmony_ci        Print("la");
4411cb0ef41Sopenharmony_ci      }
4421cb0ef41Sopenharmony_ci      return 1;
4431cb0ef41Sopenharmony_ci    }
4441cb0ef41Sopenharmony_ci    case 'b': {  // 'b: byte loads or stores
4451cb0ef41Sopenharmony_ci      if (instr->HasB()) {
4461cb0ef41Sopenharmony_ci        Print("b");
4471cb0ef41Sopenharmony_ci      }
4481cb0ef41Sopenharmony_ci      return 1;
4491cb0ef41Sopenharmony_ci    }
4501cb0ef41Sopenharmony_ci    case 'c': {  // 'cond: conditional execution
4511cb0ef41Sopenharmony_ci      DCHECK(STRING_STARTS_WITH(format, "cond"));
4521cb0ef41Sopenharmony_ci      PrintCondition(instr);
4531cb0ef41Sopenharmony_ci      return 4;
4541cb0ef41Sopenharmony_ci    }
4551cb0ef41Sopenharmony_ci    case 'd': {  // 'd: vmov double immediate.
4561cb0ef41Sopenharmony_ci      double d = instr->DoubleImmedVmov().get_scalar();
4571cb0ef41Sopenharmony_ci      out_buffer_pos_ +=
4581cb0ef41Sopenharmony_ci          base::SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d);
4591cb0ef41Sopenharmony_ci      return 1;
4601cb0ef41Sopenharmony_ci    }
4611cb0ef41Sopenharmony_ci    case 'f': {  // 'f: bitfield instructions - v7 and above.
4621cb0ef41Sopenharmony_ci      uint32_t lsbit = instr->Bits(11, 7);
4631cb0ef41Sopenharmony_ci      uint32_t width = instr->Bits(20, 16) + 1;
4641cb0ef41Sopenharmony_ci      if (instr->Bit(21) == 0) {
4651cb0ef41Sopenharmony_ci        // BFC/BFI:
4661cb0ef41Sopenharmony_ci        // Bits 20-16 represent most-significant bit. Covert to width.
4671cb0ef41Sopenharmony_ci        width -= lsbit;
4681cb0ef41Sopenharmony_ci        DCHECK_GT(width, 0);
4691cb0ef41Sopenharmony_ci      }
4701cb0ef41Sopenharmony_ci      DCHECK_LE(width + lsbit, 32);
4711cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
4721cb0ef41Sopenharmony_ci                                        "#%d, #%d", lsbit, width);
4731cb0ef41Sopenharmony_ci      return 1;
4741cb0ef41Sopenharmony_ci    }
4751cb0ef41Sopenharmony_ci    case 'h': {  // 'h: halfword operation for extra loads and stores
4761cb0ef41Sopenharmony_ci      if (instr->HasH()) {
4771cb0ef41Sopenharmony_ci        Print("h");
4781cb0ef41Sopenharmony_ci      } else {
4791cb0ef41Sopenharmony_ci        Print("b");
4801cb0ef41Sopenharmony_ci      }
4811cb0ef41Sopenharmony_ci      return 1;
4821cb0ef41Sopenharmony_ci    }
4831cb0ef41Sopenharmony_ci    case 'i': {  // 'i: immediate value from adjacent bits.
4841cb0ef41Sopenharmony_ci      // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16
4851cb0ef41Sopenharmony_ci      int width = (format[3] - '0') * 10 + (format[4] - '0');
4861cb0ef41Sopenharmony_ci      int lsb = (format[6] - '0') * 10 + (format[7] - '0');
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci      DCHECK((width >= 1) && (width <= 32));
4891cb0ef41Sopenharmony_ci      DCHECK((lsb >= 0) && (lsb <= 31));
4901cb0ef41Sopenharmony_ci      DCHECK_LE(width + lsb, 32);
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d",
4931cb0ef41Sopenharmony_ci                                        instr->Bits(width + lsb - 1, lsb));
4941cb0ef41Sopenharmony_ci      return 8;
4951cb0ef41Sopenharmony_ci    }
4961cb0ef41Sopenharmony_ci    case 'l': {  // 'l: branch and link
4971cb0ef41Sopenharmony_ci      if (instr->HasLink()) {
4981cb0ef41Sopenharmony_ci        Print("l");
4991cb0ef41Sopenharmony_ci      }
5001cb0ef41Sopenharmony_ci      return 1;
5011cb0ef41Sopenharmony_ci    }
5021cb0ef41Sopenharmony_ci    case 'm': {
5031cb0ef41Sopenharmony_ci      if (format[1] == 'w') {
5041cb0ef41Sopenharmony_ci        // 'mw: movt/movw instructions.
5051cb0ef41Sopenharmony_ci        PrintMovwMovt(instr);
5061cb0ef41Sopenharmony_ci        return 2;
5071cb0ef41Sopenharmony_ci      }
5081cb0ef41Sopenharmony_ci      if (format[1] == 'e') {  // 'memop: load/store instructions.
5091cb0ef41Sopenharmony_ci        DCHECK(STRING_STARTS_WITH(format, "memop"));
5101cb0ef41Sopenharmony_ci        if (instr->HasL()) {
5111cb0ef41Sopenharmony_ci          Print("ldr");
5121cb0ef41Sopenharmony_ci        } else {
5131cb0ef41Sopenharmony_ci          if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) &&
5141cb0ef41Sopenharmony_ci              (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) {
5151cb0ef41Sopenharmony_ci            if (instr->Bit(5) == 1) {
5161cb0ef41Sopenharmony_ci              Print("strd");
5171cb0ef41Sopenharmony_ci            } else {
5181cb0ef41Sopenharmony_ci              Print("ldrd");
5191cb0ef41Sopenharmony_ci            }
5201cb0ef41Sopenharmony_ci            return 5;
5211cb0ef41Sopenharmony_ci          }
5221cb0ef41Sopenharmony_ci          Print("str");
5231cb0ef41Sopenharmony_ci        }
5241cb0ef41Sopenharmony_ci        return 5;
5251cb0ef41Sopenharmony_ci      }
5261cb0ef41Sopenharmony_ci      // 'msg: for simulator break instructions
5271cb0ef41Sopenharmony_ci      DCHECK(STRING_STARTS_WITH(format, "msg"));
5281cb0ef41Sopenharmony_ci      byte* str =
5291cb0ef41Sopenharmony_ci          reinterpret_cast<byte*>(instr->InstructionBits() & 0x0FFFFFFF);
5301cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
5311cb0ef41Sopenharmony_ci                                        converter_.NameInCode(str));
5321cb0ef41Sopenharmony_ci      return 3;
5331cb0ef41Sopenharmony_ci    }
5341cb0ef41Sopenharmony_ci    case 'o': {
5351cb0ef41Sopenharmony_ci      if ((format[3] == '1') && (format[4] == '2')) {
5361cb0ef41Sopenharmony_ci        // 'off12: 12-bit offset for load and store instructions
5371cb0ef41Sopenharmony_ci        DCHECK(STRING_STARTS_WITH(format, "off12"));
5381cb0ef41Sopenharmony_ci        out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d",
5391cb0ef41Sopenharmony_ci                                          instr->Offset12Value());
5401cb0ef41Sopenharmony_ci        return 5;
5411cb0ef41Sopenharmony_ci      } else if (format[3] == '0') {
5421cb0ef41Sopenharmony_ci        // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
5431cb0ef41Sopenharmony_ci        DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19"));
5441cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
5451cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d",
5461cb0ef41Sopenharmony_ci                           (instr->Bits(19, 8) << 4) + instr->Bits(3, 0));
5471cb0ef41Sopenharmony_ci        return 15;
5481cb0ef41Sopenharmony_ci      }
5491cb0ef41Sopenharmony_ci      // 'off8: 8-bit offset for extra load and store instructions
5501cb0ef41Sopenharmony_ci      DCHECK(STRING_STARTS_WITH(format, "off8"));
5511cb0ef41Sopenharmony_ci      int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
5521cb0ef41Sopenharmony_ci      out_buffer_pos_ +=
5531cb0ef41Sopenharmony_ci          base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8);
5541cb0ef41Sopenharmony_ci      return 4;
5551cb0ef41Sopenharmony_ci    }
5561cb0ef41Sopenharmony_ci    case 'p': {  // 'pu: P and U bits for load and store instructions
5571cb0ef41Sopenharmony_ci      DCHECK(STRING_STARTS_WITH(format, "pu"));
5581cb0ef41Sopenharmony_ci      PrintPU(instr);
5591cb0ef41Sopenharmony_ci      return 2;
5601cb0ef41Sopenharmony_ci    }
5611cb0ef41Sopenharmony_ci    case 'r': {
5621cb0ef41Sopenharmony_ci      return FormatRegister(instr, format);
5631cb0ef41Sopenharmony_ci    }
5641cb0ef41Sopenharmony_ci    case 's': {
5651cb0ef41Sopenharmony_ci      if (format[1] == 'h') {    // 'shift_op or 'shift_rm or 'shift_sat.
5661cb0ef41Sopenharmony_ci        if (format[6] == 'o') {  // 'shift_op
5671cb0ef41Sopenharmony_ci          DCHECK(STRING_STARTS_WITH(format, "shift_op"));
5681cb0ef41Sopenharmony_ci          if (instr->TypeValue() == 0) {
5691cb0ef41Sopenharmony_ci            PrintShiftRm(instr);
5701cb0ef41Sopenharmony_ci          } else {
5711cb0ef41Sopenharmony_ci            DCHECK_EQ(instr->TypeValue(), 1);
5721cb0ef41Sopenharmony_ci            PrintShiftImm(instr);
5731cb0ef41Sopenharmony_ci          }
5741cb0ef41Sopenharmony_ci          return 8;
5751cb0ef41Sopenharmony_ci        } else if (format[6] == 's') {  // 'shift_sat.
5761cb0ef41Sopenharmony_ci          DCHECK(STRING_STARTS_WITH(format, "shift_sat"));
5771cb0ef41Sopenharmony_ci          PrintShiftSat(instr);
5781cb0ef41Sopenharmony_ci          return 9;
5791cb0ef41Sopenharmony_ci        } else {  // 'shift_rm
5801cb0ef41Sopenharmony_ci          DCHECK(STRING_STARTS_WITH(format, "shift_rm"));
5811cb0ef41Sopenharmony_ci          PrintShiftRm(instr);
5821cb0ef41Sopenharmony_ci          return 8;
5831cb0ef41Sopenharmony_ci        }
5841cb0ef41Sopenharmony_ci      } else if (format[1] == 'v') {  // 'svc
5851cb0ef41Sopenharmony_ci        DCHECK(STRING_STARTS_WITH(format, "svc"));
5861cb0ef41Sopenharmony_ci        PrintSoftwareInterrupt(instr->SvcValue());
5871cb0ef41Sopenharmony_ci        return 3;
5881cb0ef41Sopenharmony_ci      } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
5891cb0ef41Sopenharmony_ci        if (format[2] == 'g') {
5901cb0ef41Sopenharmony_ci          DCHECK(STRING_STARTS_WITH(format, "sign"));
5911cb0ef41Sopenharmony_ci          if (instr->HasSign()) {
5921cb0ef41Sopenharmony_ci            Print("s");
5931cb0ef41Sopenharmony_ci          }
5941cb0ef41Sopenharmony_ci          return 4;
5951cb0ef41Sopenharmony_ci        } else {
5961cb0ef41Sopenharmony_ci          // 'size2 or 'size3, for Advanced SIMD instructions, 2 or 3 registers.
5971cb0ef41Sopenharmony_ci          DCHECK(STRING_STARTS_WITH(format, "size2") ||
5981cb0ef41Sopenharmony_ci                 STRING_STARTS_WITH(format, "size3"));
5991cb0ef41Sopenharmony_ci          int sz = 8 << (format[4] == '2' ? instr->Bits(19, 18)
6001cb0ef41Sopenharmony_ci                                          : instr->Bits(21, 20));
6011cb0ef41Sopenharmony_ci          out_buffer_pos_ +=
6021cb0ef41Sopenharmony_ci              base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sz);
6031cb0ef41Sopenharmony_ci          return 5;
6041cb0ef41Sopenharmony_ci        }
6051cb0ef41Sopenharmony_ci      } else if (format[1] == 'p') {
6061cb0ef41Sopenharmony_ci        if (format[8] == '_') {  // 'spec_reg_fields
6071cb0ef41Sopenharmony_ci          DCHECK(STRING_STARTS_WITH(format, "spec_reg_fields"));
6081cb0ef41Sopenharmony_ci          Print("_");
6091cb0ef41Sopenharmony_ci          int mask = instr->Bits(19, 16);
6101cb0ef41Sopenharmony_ci          if (mask == 0) Print("(none)");
6111cb0ef41Sopenharmony_ci          if ((mask & 0x8) != 0) Print("f");
6121cb0ef41Sopenharmony_ci          if ((mask & 0x4) != 0) Print("s");
6131cb0ef41Sopenharmony_ci          if ((mask & 0x2) != 0) Print("x");
6141cb0ef41Sopenharmony_ci          if ((mask & 0x1) != 0) Print("c");
6151cb0ef41Sopenharmony_ci          return 15;
6161cb0ef41Sopenharmony_ci        } else {  // 'spec_reg
6171cb0ef41Sopenharmony_ci          DCHECK(STRING_STARTS_WITH(format, "spec_reg"));
6181cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
6191cb0ef41Sopenharmony_ci            Print("CPSR");
6201cb0ef41Sopenharmony_ci          } else {
6211cb0ef41Sopenharmony_ci            Print("SPSR");
6221cb0ef41Sopenharmony_ci          }
6231cb0ef41Sopenharmony_ci          return 8;
6241cb0ef41Sopenharmony_ci        }
6251cb0ef41Sopenharmony_ci      }
6261cb0ef41Sopenharmony_ci      // 's: S field of data processing instructions
6271cb0ef41Sopenharmony_ci      if (instr->HasS()) {
6281cb0ef41Sopenharmony_ci        Print("s");
6291cb0ef41Sopenharmony_ci      }
6301cb0ef41Sopenharmony_ci      return 1;
6311cb0ef41Sopenharmony_ci    }
6321cb0ef41Sopenharmony_ci    case 't': {  // 'target: target of branch instructions
6331cb0ef41Sopenharmony_ci      DCHECK(STRING_STARTS_WITH(format, "target"));
6341cb0ef41Sopenharmony_ci      int off = (static_cast<uint32_t>(instr->SImmed24Value()) << 2) + 8u;
6351cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(
6361cb0ef41Sopenharmony_ci          out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
6371cb0ef41Sopenharmony_ci          converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
6381cb0ef41Sopenharmony_ci      return 6;
6391cb0ef41Sopenharmony_ci    }
6401cb0ef41Sopenharmony_ci    case 'u': {  // 'u: signed or unsigned multiplies
6411cb0ef41Sopenharmony_ci      // The manual gets the meaning of bit 22 backwards in the multiply
6421cb0ef41Sopenharmony_ci      // instruction overview on page A3.16.2.  The instructions that
6431cb0ef41Sopenharmony_ci      // exist in u and s variants are the following:
6441cb0ef41Sopenharmony_ci      // smull A4.1.87
6451cb0ef41Sopenharmony_ci      // umull A4.1.129
6461cb0ef41Sopenharmony_ci      // umlal A4.1.128
6471cb0ef41Sopenharmony_ci      // smlal A4.1.76
6481cb0ef41Sopenharmony_ci      // For these 0 means u and 1 means s.  As can be seen on their individual
6491cb0ef41Sopenharmony_ci      // pages.  The other 18 mul instructions have the bit set or unset in
6501cb0ef41Sopenharmony_ci      // arbitrary ways that are unrelated to the signedness of the instruction.
6511cb0ef41Sopenharmony_ci      // None of these 18 instructions exist in both a 'u' and an 's' variant.
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_ci      if (instr->Bit(22) == 0) {
6541cb0ef41Sopenharmony_ci        Print("u");
6551cb0ef41Sopenharmony_ci      } else {
6561cb0ef41Sopenharmony_ci        Print("s");
6571cb0ef41Sopenharmony_ci      }
6581cb0ef41Sopenharmony_ci      return 1;
6591cb0ef41Sopenharmony_ci    }
6601cb0ef41Sopenharmony_ci    case 'v': {
6611cb0ef41Sopenharmony_ci      return FormatVFPinstruction(instr, format);
6621cb0ef41Sopenharmony_ci    }
6631cb0ef41Sopenharmony_ci    case 'A': {
6641cb0ef41Sopenharmony_ci      // Print pc-relative address.
6651cb0ef41Sopenharmony_ci      int offset = instr->Offset12Value();
6661cb0ef41Sopenharmony_ci      byte* pc = reinterpret_cast<byte*>(instr) + Instruction::kPcLoadDelta;
6671cb0ef41Sopenharmony_ci      byte* addr;
6681cb0ef41Sopenharmony_ci      switch (instr->PUField()) {
6691cb0ef41Sopenharmony_ci        case db_x: {
6701cb0ef41Sopenharmony_ci          addr = pc - offset;
6711cb0ef41Sopenharmony_ci          break;
6721cb0ef41Sopenharmony_ci        }
6731cb0ef41Sopenharmony_ci        case ib_x: {
6741cb0ef41Sopenharmony_ci          addr = pc + offset;
6751cb0ef41Sopenharmony_ci          break;
6761cb0ef41Sopenharmony_ci        }
6771cb0ef41Sopenharmony_ci        default: {
6781cb0ef41Sopenharmony_ci          UNREACHABLE();
6791cb0ef41Sopenharmony_ci        }
6801cb0ef41Sopenharmony_ci      }
6811cb0ef41Sopenharmony_ci      out_buffer_pos_ +=
6821cb0ef41Sopenharmony_ci          base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%08" PRIxPTR,
6831cb0ef41Sopenharmony_ci                         reinterpret_cast<uintptr_t>(addr));
6841cb0ef41Sopenharmony_ci      return 1;
6851cb0ef41Sopenharmony_ci    }
6861cb0ef41Sopenharmony_ci    case 'S':
6871cb0ef41Sopenharmony_ci      return FormatVFPRegister(instr, format, kSinglePrecision);
6881cb0ef41Sopenharmony_ci    case 'D':
6891cb0ef41Sopenharmony_ci      return FormatVFPRegister(instr, format, kDoublePrecision);
6901cb0ef41Sopenharmony_ci    case 'Q':
6911cb0ef41Sopenharmony_ci      return FormatVFPRegister(instr, format, kSimd128Precision);
6921cb0ef41Sopenharmony_ci    case 'w': {  // 'w: W field of load and store instructions
6931cb0ef41Sopenharmony_ci      if (instr->HasW()) {
6941cb0ef41Sopenharmony_ci        Print("!");
6951cb0ef41Sopenharmony_ci      }
6961cb0ef41Sopenharmony_ci      return 1;
6971cb0ef41Sopenharmony_ci    }
6981cb0ef41Sopenharmony_ci    default: {
6991cb0ef41Sopenharmony_ci      UNREACHABLE();
7001cb0ef41Sopenharmony_ci    }
7011cb0ef41Sopenharmony_ci  }
7021cb0ef41Sopenharmony_ci  UNREACHABLE();
7031cb0ef41Sopenharmony_ci}
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_ci// Format takes a formatting string for a whole instruction and prints it into
7061cb0ef41Sopenharmony_ci// the output buffer. All escaped options are handed to FormatOption to be
7071cb0ef41Sopenharmony_ci// parsed further.
7081cb0ef41Sopenharmony_civoid Decoder::Format(Instruction* instr, const char* format) {
7091cb0ef41Sopenharmony_ci  char cur = *format++;
7101cb0ef41Sopenharmony_ci  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
7111cb0ef41Sopenharmony_ci    if (cur == '\'') {  // Single quote is used as the formatting escape.
7121cb0ef41Sopenharmony_ci      format += FormatOption(instr, format);
7131cb0ef41Sopenharmony_ci    } else {
7141cb0ef41Sopenharmony_ci      out_buffer_[out_buffer_pos_++] = cur;
7151cb0ef41Sopenharmony_ci    }
7161cb0ef41Sopenharmony_ci    cur = *format++;
7171cb0ef41Sopenharmony_ci  }
7181cb0ef41Sopenharmony_ci  out_buffer_[out_buffer_pos_] = '\0';
7191cb0ef41Sopenharmony_ci}
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci// The disassembler may end up decoding data inlined in the code. We do not want
7221cb0ef41Sopenharmony_ci// it to crash if the data does not resemble any known instruction.
7231cb0ef41Sopenharmony_ci#define VERIFY(condition) \
7241cb0ef41Sopenharmony_ci  if (!(condition)) {     \
7251cb0ef41Sopenharmony_ci    Unknown(instr);       \
7261cb0ef41Sopenharmony_ci    return;               \
7271cb0ef41Sopenharmony_ci  }
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_ci// For currently unimplemented decodings the disassembler calls Unknown(instr)
7301cb0ef41Sopenharmony_ci// which will just print "unknown" of the instruction bits.
7311cb0ef41Sopenharmony_civoid Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); }
7321cb0ef41Sopenharmony_ci
7331cb0ef41Sopenharmony_civoid Decoder::DecodeType01(Instruction* instr) {
7341cb0ef41Sopenharmony_ci  int type = instr->TypeValue();
7351cb0ef41Sopenharmony_ci  if ((type == 0) && instr->IsSpecialType0()) {
7361cb0ef41Sopenharmony_ci    // multiply instruction or extra loads and stores
7371cb0ef41Sopenharmony_ci    if (instr->Bits(7, 4) == 9) {
7381cb0ef41Sopenharmony_ci      if (instr->Bit(24) == 0) {
7391cb0ef41Sopenharmony_ci        // multiply instructions
7401cb0ef41Sopenharmony_ci        if (instr->Bit(23) == 0) {
7411cb0ef41Sopenharmony_ci          if (instr->Bit(21) == 0) {
7421cb0ef41Sopenharmony_ci            // The MUL instruction description (A 4.1.33) refers to Rd as being
7431cb0ef41Sopenharmony_ci            // the destination for the operation, but it confusingly uses the
7441cb0ef41Sopenharmony_ci            // Rn field to encode it.
7451cb0ef41Sopenharmony_ci            Format(instr, "mul'cond's 'rn, 'rm, 'rs");
7461cb0ef41Sopenharmony_ci          } else {
7471cb0ef41Sopenharmony_ci            if (instr->Bit(22) == 0) {
7481cb0ef41Sopenharmony_ci              // The MLA instruction description (A 4.1.28) refers to the order
7491cb0ef41Sopenharmony_ci              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
7501cb0ef41Sopenharmony_ci              // Rn field to encode the Rd register and the Rd field to encode
7511cb0ef41Sopenharmony_ci              // the Rn register.
7521cb0ef41Sopenharmony_ci              Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
7531cb0ef41Sopenharmony_ci            } else {
7541cb0ef41Sopenharmony_ci              // The MLS instruction description (A 4.1.29) refers to the order
7551cb0ef41Sopenharmony_ci              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
7561cb0ef41Sopenharmony_ci              // Rn field to encode the Rd register and the Rd field to encode
7571cb0ef41Sopenharmony_ci              // the Rn register.
7581cb0ef41Sopenharmony_ci              Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
7591cb0ef41Sopenharmony_ci            }
7601cb0ef41Sopenharmony_ci          }
7611cb0ef41Sopenharmony_ci        } else {
7621cb0ef41Sopenharmony_ci          // The signed/long multiply instructions use the terms RdHi and RdLo
7631cb0ef41Sopenharmony_ci          // when referring to the target registers. They are mapped to the Rn
7641cb0ef41Sopenharmony_ci          // and Rd fields as follows:
7651cb0ef41Sopenharmony_ci          // RdLo == Rd field
7661cb0ef41Sopenharmony_ci          // RdHi == Rn field
7671cb0ef41Sopenharmony_ci          // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
7681cb0ef41Sopenharmony_ci          Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
7691cb0ef41Sopenharmony_ci        }
7701cb0ef41Sopenharmony_ci      } else {
7711cb0ef41Sopenharmony_ci        if (instr->Bits(24, 23) == 3) {
7721cb0ef41Sopenharmony_ci          if (instr->Bit(20) == 1) {
7731cb0ef41Sopenharmony_ci            // ldrex
7741cb0ef41Sopenharmony_ci            switch (instr->Bits(22, 21)) {
7751cb0ef41Sopenharmony_ci              case 0:
7761cb0ef41Sopenharmony_ci                Format(instr, "ldrex'cond 'rt, ['rn]");
7771cb0ef41Sopenharmony_ci                break;
7781cb0ef41Sopenharmony_ci              case 1:
7791cb0ef41Sopenharmony_ci                Format(instr, "ldrexd'cond 'rt, ['rn]");
7801cb0ef41Sopenharmony_ci                break;
7811cb0ef41Sopenharmony_ci              case 2:
7821cb0ef41Sopenharmony_ci                Format(instr, "ldrexb'cond 'rt, ['rn]");
7831cb0ef41Sopenharmony_ci                break;
7841cb0ef41Sopenharmony_ci              case 3:
7851cb0ef41Sopenharmony_ci                Format(instr, "ldrexh'cond 'rt, ['rn]");
7861cb0ef41Sopenharmony_ci                break;
7871cb0ef41Sopenharmony_ci              default:
7881cb0ef41Sopenharmony_ci                UNREACHABLE();
7891cb0ef41Sopenharmony_ci            }
7901cb0ef41Sopenharmony_ci          } else {
7911cb0ef41Sopenharmony_ci            // strex
7921cb0ef41Sopenharmony_ci            // The instruction is documented as strex rd, rt, [rn], but the
7931cb0ef41Sopenharmony_ci            // "rt" register is using the rm bits.
7941cb0ef41Sopenharmony_ci            switch (instr->Bits(22, 21)) {
7951cb0ef41Sopenharmony_ci              case 0:
7961cb0ef41Sopenharmony_ci                Format(instr, "strex'cond 'rd, 'rm, ['rn]");
7971cb0ef41Sopenharmony_ci                break;
7981cb0ef41Sopenharmony_ci              case 1:
7991cb0ef41Sopenharmony_ci                Format(instr, "strexd'cond 'rd, 'rm, ['rn]");
8001cb0ef41Sopenharmony_ci                break;
8011cb0ef41Sopenharmony_ci              case 2:
8021cb0ef41Sopenharmony_ci                Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
8031cb0ef41Sopenharmony_ci                break;
8041cb0ef41Sopenharmony_ci              case 3:
8051cb0ef41Sopenharmony_ci                Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
8061cb0ef41Sopenharmony_ci                break;
8071cb0ef41Sopenharmony_ci              default:
8081cb0ef41Sopenharmony_ci                UNREACHABLE();
8091cb0ef41Sopenharmony_ci            }
8101cb0ef41Sopenharmony_ci          }
8111cb0ef41Sopenharmony_ci        } else {
8121cb0ef41Sopenharmony_ci          Unknown(instr);  // not used by V8
8131cb0ef41Sopenharmony_ci        }
8141cb0ef41Sopenharmony_ci      }
8151cb0ef41Sopenharmony_ci    } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xD) == 0xD)) {
8161cb0ef41Sopenharmony_ci      // ldrd, strd
8171cb0ef41Sopenharmony_ci      switch (instr->PUField()) {
8181cb0ef41Sopenharmony_ci        case da_x: {
8191cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
8201cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
8211cb0ef41Sopenharmony_ci          } else {
8221cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
8231cb0ef41Sopenharmony_ci          }
8241cb0ef41Sopenharmony_ci          break;
8251cb0ef41Sopenharmony_ci        }
8261cb0ef41Sopenharmony_ci        case ia_x: {
8271cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
8281cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
8291cb0ef41Sopenharmony_ci          } else {
8301cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
8311cb0ef41Sopenharmony_ci          }
8321cb0ef41Sopenharmony_ci          break;
8331cb0ef41Sopenharmony_ci        }
8341cb0ef41Sopenharmony_ci        case db_x: {
8351cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
8361cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
8371cb0ef41Sopenharmony_ci          } else {
8381cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
8391cb0ef41Sopenharmony_ci          }
8401cb0ef41Sopenharmony_ci          break;
8411cb0ef41Sopenharmony_ci        }
8421cb0ef41Sopenharmony_ci        case ib_x: {
8431cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
8441cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
8451cb0ef41Sopenharmony_ci          } else {
8461cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
8471cb0ef41Sopenharmony_ci          }
8481cb0ef41Sopenharmony_ci          break;
8491cb0ef41Sopenharmony_ci        }
8501cb0ef41Sopenharmony_ci        default: {
8511cb0ef41Sopenharmony_ci          // The PU field is a 2-bit field.
8521cb0ef41Sopenharmony_ci          UNREACHABLE();
8531cb0ef41Sopenharmony_ci        }
8541cb0ef41Sopenharmony_ci      }
8551cb0ef41Sopenharmony_ci    } else {
8561cb0ef41Sopenharmony_ci      // extra load/store instructions
8571cb0ef41Sopenharmony_ci      switch (instr->PUField()) {
8581cb0ef41Sopenharmony_ci        case da_x: {
8591cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
8601cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
8611cb0ef41Sopenharmony_ci          } else {
8621cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
8631cb0ef41Sopenharmony_ci          }
8641cb0ef41Sopenharmony_ci          break;
8651cb0ef41Sopenharmony_ci        }
8661cb0ef41Sopenharmony_ci        case ia_x: {
8671cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
8681cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
8691cb0ef41Sopenharmony_ci          } else {
8701cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
8711cb0ef41Sopenharmony_ci          }
8721cb0ef41Sopenharmony_ci          break;
8731cb0ef41Sopenharmony_ci        }
8741cb0ef41Sopenharmony_ci        case db_x: {
8751cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
8761cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
8771cb0ef41Sopenharmony_ci          } else {
8781cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
8791cb0ef41Sopenharmony_ci          }
8801cb0ef41Sopenharmony_ci          break;
8811cb0ef41Sopenharmony_ci        }
8821cb0ef41Sopenharmony_ci        case ib_x: {
8831cb0ef41Sopenharmony_ci          if (instr->Bit(22) == 0) {
8841cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
8851cb0ef41Sopenharmony_ci          } else {
8861cb0ef41Sopenharmony_ci            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
8871cb0ef41Sopenharmony_ci          }
8881cb0ef41Sopenharmony_ci          break;
8891cb0ef41Sopenharmony_ci        }
8901cb0ef41Sopenharmony_ci        default: {
8911cb0ef41Sopenharmony_ci          // The PU field is a 2-bit field.
8921cb0ef41Sopenharmony_ci          UNREACHABLE();
8931cb0ef41Sopenharmony_ci        }
8941cb0ef41Sopenharmony_ci      }
8951cb0ef41Sopenharmony_ci      return;
8961cb0ef41Sopenharmony_ci    }
8971cb0ef41Sopenharmony_ci  } else if ((type == 0) && instr->IsMiscType0()) {
8981cb0ef41Sopenharmony_ci    if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
8991cb0ef41Sopenharmony_ci        (instr->Bits(15, 4) == 0xF00)) {
9001cb0ef41Sopenharmony_ci      Format(instr, "msr'cond 'spec_reg'spec_reg_fields, 'rm");
9011cb0ef41Sopenharmony_ci    } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
9021cb0ef41Sopenharmony_ci               (instr->Bits(11, 0) == 0)) {
9031cb0ef41Sopenharmony_ci      Format(instr, "mrs'cond 'rd, 'spec_reg");
9041cb0ef41Sopenharmony_ci    } else if (instr->Bits(22, 21) == 1) {
9051cb0ef41Sopenharmony_ci      switch (instr->BitField(7, 4)) {
9061cb0ef41Sopenharmony_ci        case BX:
9071cb0ef41Sopenharmony_ci          Format(instr, "bx'cond 'rm");
9081cb0ef41Sopenharmony_ci          break;
9091cb0ef41Sopenharmony_ci        case BLX:
9101cb0ef41Sopenharmony_ci          Format(instr, "blx'cond 'rm");
9111cb0ef41Sopenharmony_ci          break;
9121cb0ef41Sopenharmony_ci        case BKPT:
9131cb0ef41Sopenharmony_ci          Format(instr, "bkpt 'off0to3and8to19");
9141cb0ef41Sopenharmony_ci          break;
9151cb0ef41Sopenharmony_ci        default:
9161cb0ef41Sopenharmony_ci          Unknown(instr);  // not used by V8
9171cb0ef41Sopenharmony_ci          break;
9181cb0ef41Sopenharmony_ci      }
9191cb0ef41Sopenharmony_ci    } else if (instr->Bits(22, 21) == 3) {
9201cb0ef41Sopenharmony_ci      switch (instr->BitField(7, 4)) {
9211cb0ef41Sopenharmony_ci        case CLZ:
9221cb0ef41Sopenharmony_ci          Format(instr, "clz'cond 'rd, 'rm");
9231cb0ef41Sopenharmony_ci          break;
9241cb0ef41Sopenharmony_ci        default:
9251cb0ef41Sopenharmony_ci          Unknown(instr);  // not used by V8
9261cb0ef41Sopenharmony_ci          break;
9271cb0ef41Sopenharmony_ci      }
9281cb0ef41Sopenharmony_ci    } else {
9291cb0ef41Sopenharmony_ci      Unknown(instr);  // not used by V8
9301cb0ef41Sopenharmony_ci    }
9311cb0ef41Sopenharmony_ci  } else if ((type == 1) && instr->IsNopLikeType1()) {
9321cb0ef41Sopenharmony_ci    if (instr->BitField(7, 0) == 0) {
9331cb0ef41Sopenharmony_ci      Format(instr, "nop'cond");
9341cb0ef41Sopenharmony_ci    } else if (instr->BitField(7, 0) == 20) {
9351cb0ef41Sopenharmony_ci      Format(instr, "csdb");
9361cb0ef41Sopenharmony_ci    } else {
9371cb0ef41Sopenharmony_ci      Unknown(instr);  // Not used in V8.
9381cb0ef41Sopenharmony_ci    }
9391cb0ef41Sopenharmony_ci  } else {
9401cb0ef41Sopenharmony_ci    switch (instr->OpcodeField()) {
9411cb0ef41Sopenharmony_ci      case AND: {
9421cb0ef41Sopenharmony_ci        Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
9431cb0ef41Sopenharmony_ci        break;
9441cb0ef41Sopenharmony_ci      }
9451cb0ef41Sopenharmony_ci      case EOR: {
9461cb0ef41Sopenharmony_ci        Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
9471cb0ef41Sopenharmony_ci        break;
9481cb0ef41Sopenharmony_ci      }
9491cb0ef41Sopenharmony_ci      case SUB: {
9501cb0ef41Sopenharmony_ci        Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
9511cb0ef41Sopenharmony_ci        break;
9521cb0ef41Sopenharmony_ci      }
9531cb0ef41Sopenharmony_ci      case RSB: {
9541cb0ef41Sopenharmony_ci        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
9551cb0ef41Sopenharmony_ci        break;
9561cb0ef41Sopenharmony_ci      }
9571cb0ef41Sopenharmony_ci      case ADD: {
9581cb0ef41Sopenharmony_ci        Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
9591cb0ef41Sopenharmony_ci        break;
9601cb0ef41Sopenharmony_ci      }
9611cb0ef41Sopenharmony_ci      case ADC: {
9621cb0ef41Sopenharmony_ci        Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
9631cb0ef41Sopenharmony_ci        break;
9641cb0ef41Sopenharmony_ci      }
9651cb0ef41Sopenharmony_ci      case SBC: {
9661cb0ef41Sopenharmony_ci        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
9671cb0ef41Sopenharmony_ci        break;
9681cb0ef41Sopenharmony_ci      }
9691cb0ef41Sopenharmony_ci      case RSC: {
9701cb0ef41Sopenharmony_ci        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
9711cb0ef41Sopenharmony_ci        break;
9721cb0ef41Sopenharmony_ci      }
9731cb0ef41Sopenharmony_ci      case TST: {
9741cb0ef41Sopenharmony_ci        if (instr->HasS()) {
9751cb0ef41Sopenharmony_ci          Format(instr, "tst'cond 'rn, 'shift_op");
9761cb0ef41Sopenharmony_ci        } else {
9771cb0ef41Sopenharmony_ci          Format(instr, "movw'cond 'mw");
9781cb0ef41Sopenharmony_ci        }
9791cb0ef41Sopenharmony_ci        break;
9801cb0ef41Sopenharmony_ci      }
9811cb0ef41Sopenharmony_ci      case TEQ: {
9821cb0ef41Sopenharmony_ci        if (instr->HasS()) {
9831cb0ef41Sopenharmony_ci          Format(instr, "teq'cond 'rn, 'shift_op");
9841cb0ef41Sopenharmony_ci        } else {
9851cb0ef41Sopenharmony_ci          // Other instructions matching this pattern are handled in the
9861cb0ef41Sopenharmony_ci          // miscellaneous instructions part above.
9871cb0ef41Sopenharmony_ci          UNREACHABLE();
9881cb0ef41Sopenharmony_ci        }
9891cb0ef41Sopenharmony_ci        break;
9901cb0ef41Sopenharmony_ci      }
9911cb0ef41Sopenharmony_ci      case CMP: {
9921cb0ef41Sopenharmony_ci        if (instr->HasS()) {
9931cb0ef41Sopenharmony_ci          Format(instr, "cmp'cond 'rn, 'shift_op");
9941cb0ef41Sopenharmony_ci        } else {
9951cb0ef41Sopenharmony_ci          Format(instr, "movt'cond 'mw");
9961cb0ef41Sopenharmony_ci        }
9971cb0ef41Sopenharmony_ci        break;
9981cb0ef41Sopenharmony_ci      }
9991cb0ef41Sopenharmony_ci      case CMN: {
10001cb0ef41Sopenharmony_ci        if (instr->HasS()) {
10011cb0ef41Sopenharmony_ci          Format(instr, "cmn'cond 'rn, 'shift_op");
10021cb0ef41Sopenharmony_ci        } else {
10031cb0ef41Sopenharmony_ci          // Other instructions matching this pattern are handled in the
10041cb0ef41Sopenharmony_ci          // miscellaneous instructions part above.
10051cb0ef41Sopenharmony_ci          UNREACHABLE();
10061cb0ef41Sopenharmony_ci        }
10071cb0ef41Sopenharmony_ci        break;
10081cb0ef41Sopenharmony_ci      }
10091cb0ef41Sopenharmony_ci      case ORR: {
10101cb0ef41Sopenharmony_ci        Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
10111cb0ef41Sopenharmony_ci        break;
10121cb0ef41Sopenharmony_ci      }
10131cb0ef41Sopenharmony_ci      case MOV: {
10141cb0ef41Sopenharmony_ci        Format(instr, "mov'cond's 'rd, 'shift_op");
10151cb0ef41Sopenharmony_ci        break;
10161cb0ef41Sopenharmony_ci      }
10171cb0ef41Sopenharmony_ci      case BIC: {
10181cb0ef41Sopenharmony_ci        Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
10191cb0ef41Sopenharmony_ci        break;
10201cb0ef41Sopenharmony_ci      }
10211cb0ef41Sopenharmony_ci      case MVN: {
10221cb0ef41Sopenharmony_ci        Format(instr, "mvn'cond's 'rd, 'shift_op");
10231cb0ef41Sopenharmony_ci        break;
10241cb0ef41Sopenharmony_ci      }
10251cb0ef41Sopenharmony_ci      default: {
10261cb0ef41Sopenharmony_ci        // The Opcode field is a 4-bit field.
10271cb0ef41Sopenharmony_ci        UNREACHABLE();
10281cb0ef41Sopenharmony_ci      }
10291cb0ef41Sopenharmony_ci    }
10301cb0ef41Sopenharmony_ci  }
10311cb0ef41Sopenharmony_ci}
10321cb0ef41Sopenharmony_ci
10331cb0ef41Sopenharmony_civoid Decoder::DecodeType2(Instruction* instr) {
10341cb0ef41Sopenharmony_ci  switch (instr->PUField()) {
10351cb0ef41Sopenharmony_ci    case da_x: {
10361cb0ef41Sopenharmony_ci      if (instr->HasW()) {
10371cb0ef41Sopenharmony_ci        Unknown(instr);  // not used in V8
10381cb0ef41Sopenharmony_ci        return;
10391cb0ef41Sopenharmony_ci      }
10401cb0ef41Sopenharmony_ci      Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
10411cb0ef41Sopenharmony_ci      break;
10421cb0ef41Sopenharmony_ci    }
10431cb0ef41Sopenharmony_ci    case ia_x: {
10441cb0ef41Sopenharmony_ci      if (instr->HasW()) {
10451cb0ef41Sopenharmony_ci        Unknown(instr);  // not used in V8
10461cb0ef41Sopenharmony_ci        return;
10471cb0ef41Sopenharmony_ci      }
10481cb0ef41Sopenharmony_ci      Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
10491cb0ef41Sopenharmony_ci      break;
10501cb0ef41Sopenharmony_ci    }
10511cb0ef41Sopenharmony_ci    case db_x: {
10521cb0ef41Sopenharmony_ci      if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
10531cb0ef41Sopenharmony_ci        Format(instr, "'memop'cond'b 'rd, [pc, #-'off12]'w (addr 'A)");
10541cb0ef41Sopenharmony_ci      } else {
10551cb0ef41Sopenharmony_ci        Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
10561cb0ef41Sopenharmony_ci      }
10571cb0ef41Sopenharmony_ci      break;
10581cb0ef41Sopenharmony_ci    }
10591cb0ef41Sopenharmony_ci    case ib_x: {
10601cb0ef41Sopenharmony_ci      if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
10611cb0ef41Sopenharmony_ci        Format(instr, "'memop'cond'b 'rd, [pc, #+'off12]'w (addr 'A)");
10621cb0ef41Sopenharmony_ci      } else {
10631cb0ef41Sopenharmony_ci        Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
10641cb0ef41Sopenharmony_ci      }
10651cb0ef41Sopenharmony_ci      break;
10661cb0ef41Sopenharmony_ci    }
10671cb0ef41Sopenharmony_ci    default: {
10681cb0ef41Sopenharmony_ci      // The PU field is a 2-bit field.
10691cb0ef41Sopenharmony_ci      UNREACHABLE();
10701cb0ef41Sopenharmony_ci    }
10711cb0ef41Sopenharmony_ci  }
10721cb0ef41Sopenharmony_ci}
10731cb0ef41Sopenharmony_ci
10741cb0ef41Sopenharmony_civoid Decoder::DecodeType3(Instruction* instr) {
10751cb0ef41Sopenharmony_ci  switch (instr->PUField()) {
10761cb0ef41Sopenharmony_ci    case da_x: {
10771cb0ef41Sopenharmony_ci      VERIFY(!instr->HasW());
10781cb0ef41Sopenharmony_ci      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
10791cb0ef41Sopenharmony_ci      break;
10801cb0ef41Sopenharmony_ci    }
10811cb0ef41Sopenharmony_ci    case ia_x: {
10821cb0ef41Sopenharmony_ci      if (instr->Bit(4) == 0) {
10831cb0ef41Sopenharmony_ci        Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
10841cb0ef41Sopenharmony_ci      } else {
10851cb0ef41Sopenharmony_ci        if (instr->Bit(5) == 0) {
10861cb0ef41Sopenharmony_ci          switch (instr->Bits(22, 21)) {
10871cb0ef41Sopenharmony_ci            case 0:
10881cb0ef41Sopenharmony_ci              if (instr->Bit(20) == 0) {
10891cb0ef41Sopenharmony_ci                if (instr->Bit(6) == 0) {
10901cb0ef41Sopenharmony_ci                  Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
10911cb0ef41Sopenharmony_ci                } else {
10921cb0ef41Sopenharmony_ci                  if (instr->Bits(11, 7) == 0) {
10931cb0ef41Sopenharmony_ci                    Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
10941cb0ef41Sopenharmony_ci                  } else {
10951cb0ef41Sopenharmony_ci                    Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
10961cb0ef41Sopenharmony_ci                  }
10971cb0ef41Sopenharmony_ci                }
10981cb0ef41Sopenharmony_ci              } else {
10991cb0ef41Sopenharmony_ci                UNREACHABLE();
11001cb0ef41Sopenharmony_ci              }
11011cb0ef41Sopenharmony_ci              break;
11021cb0ef41Sopenharmony_ci            case 1:
11031cb0ef41Sopenharmony_ci              UNREACHABLE();
11041cb0ef41Sopenharmony_ci            case 2:
11051cb0ef41Sopenharmony_ci              UNREACHABLE();
11061cb0ef41Sopenharmony_ci            case 3:
11071cb0ef41Sopenharmony_ci              Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
11081cb0ef41Sopenharmony_ci              break;
11091cb0ef41Sopenharmony_ci          }
11101cb0ef41Sopenharmony_ci        } else {
11111cb0ef41Sopenharmony_ci          switch (instr->Bits(22, 21)) {
11121cb0ef41Sopenharmony_ci            case 0:
11131cb0ef41Sopenharmony_ci              UNREACHABLE();
11141cb0ef41Sopenharmony_ci            case 1:
11151cb0ef41Sopenharmony_ci              if (instr->Bits(9, 6) == 1) {
11161cb0ef41Sopenharmony_ci                if (instr->Bit(20) == 0) {
11171cb0ef41Sopenharmony_ci                  if (instr->Bits(19, 16) == 0xF) {
11181cb0ef41Sopenharmony_ci                    switch (instr->Bits(11, 10)) {
11191cb0ef41Sopenharmony_ci                      case 0:
11201cb0ef41Sopenharmony_ci                        Format(instr, "sxtb'cond 'rd, 'rm");
11211cb0ef41Sopenharmony_ci                        break;
11221cb0ef41Sopenharmony_ci                      case 1:
11231cb0ef41Sopenharmony_ci                        Format(instr, "sxtb'cond 'rd, 'rm, ror #8");
11241cb0ef41Sopenharmony_ci                        break;
11251cb0ef41Sopenharmony_ci                      case 2:
11261cb0ef41Sopenharmony_ci                        Format(instr, "sxtb'cond 'rd, 'rm, ror #16");
11271cb0ef41Sopenharmony_ci                        break;
11281cb0ef41Sopenharmony_ci                      case 3:
11291cb0ef41Sopenharmony_ci                        Format(instr, "sxtb'cond 'rd, 'rm, ror #24");
11301cb0ef41Sopenharmony_ci                        break;
11311cb0ef41Sopenharmony_ci                    }
11321cb0ef41Sopenharmony_ci                  } else {
11331cb0ef41Sopenharmony_ci                    switch (instr->Bits(11, 10)) {
11341cb0ef41Sopenharmony_ci                      case 0:
11351cb0ef41Sopenharmony_ci                        Format(instr, "sxtab'cond 'rd, 'rn, 'rm");
11361cb0ef41Sopenharmony_ci                        break;
11371cb0ef41Sopenharmony_ci                      case 1:
11381cb0ef41Sopenharmony_ci                        Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8");
11391cb0ef41Sopenharmony_ci                        break;
11401cb0ef41Sopenharmony_ci                      case 2:
11411cb0ef41Sopenharmony_ci                        Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16");
11421cb0ef41Sopenharmony_ci                        break;
11431cb0ef41Sopenharmony_ci                      case 3:
11441cb0ef41Sopenharmony_ci                        Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24");
11451cb0ef41Sopenharmony_ci                        break;
11461cb0ef41Sopenharmony_ci                    }
11471cb0ef41Sopenharmony_ci                  }
11481cb0ef41Sopenharmony_ci                } else {
11491cb0ef41Sopenharmony_ci                  if (instr->Bits(19, 16) == 0xF) {
11501cb0ef41Sopenharmony_ci                    switch (instr->Bits(11, 10)) {
11511cb0ef41Sopenharmony_ci                      case 0:
11521cb0ef41Sopenharmony_ci                        Format(instr, "sxth'cond 'rd, 'rm");
11531cb0ef41Sopenharmony_ci                        break;
11541cb0ef41Sopenharmony_ci                      case 1:
11551cb0ef41Sopenharmony_ci                        Format(instr, "sxth'cond 'rd, 'rm, ror #8");
11561cb0ef41Sopenharmony_ci                        break;
11571cb0ef41Sopenharmony_ci                      case 2:
11581cb0ef41Sopenharmony_ci                        Format(instr, "sxth'cond 'rd, 'rm, ror #16");
11591cb0ef41Sopenharmony_ci                        break;
11601cb0ef41Sopenharmony_ci                      case 3:
11611cb0ef41Sopenharmony_ci                        Format(instr, "sxth'cond 'rd, 'rm, ror #24");
11621cb0ef41Sopenharmony_ci                        break;
11631cb0ef41Sopenharmony_ci                    }
11641cb0ef41Sopenharmony_ci                  } else {
11651cb0ef41Sopenharmony_ci                    switch (instr->Bits(11, 10)) {
11661cb0ef41Sopenharmony_ci                      case 0:
11671cb0ef41Sopenharmony_ci                        Format(instr, "sxtah'cond 'rd, 'rn, 'rm");
11681cb0ef41Sopenharmony_ci                        break;
11691cb0ef41Sopenharmony_ci                      case 1:
11701cb0ef41Sopenharmony_ci                        Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8");
11711cb0ef41Sopenharmony_ci                        break;
11721cb0ef41Sopenharmony_ci                      case 2:
11731cb0ef41Sopenharmony_ci                        Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16");
11741cb0ef41Sopenharmony_ci                        break;
11751cb0ef41Sopenharmony_ci                      case 3:
11761cb0ef41Sopenharmony_ci                        Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24");
11771cb0ef41Sopenharmony_ci                        break;
11781cb0ef41Sopenharmony_ci                    }
11791cb0ef41Sopenharmony_ci                  }
11801cb0ef41Sopenharmony_ci                }
11811cb0ef41Sopenharmony_ci              } else if (instr->Bits(27, 16) == 0x6BF &&
11821cb0ef41Sopenharmony_ci                         instr->Bits(11, 4) == 0xF3) {
11831cb0ef41Sopenharmony_ci                Format(instr, "rev'cond 'rd, 'rm");
11841cb0ef41Sopenharmony_ci              } else {
11851cb0ef41Sopenharmony_ci                UNREACHABLE();
11861cb0ef41Sopenharmony_ci              }
11871cb0ef41Sopenharmony_ci              break;
11881cb0ef41Sopenharmony_ci            case 2:
11891cb0ef41Sopenharmony_ci              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
11901cb0ef41Sopenharmony_ci                if (instr->Bits(19, 16) == 0xF) {
11911cb0ef41Sopenharmony_ci                  switch (instr->Bits(11, 10)) {
11921cb0ef41Sopenharmony_ci                    case 0:
11931cb0ef41Sopenharmony_ci                      Format(instr, "uxtb16'cond 'rd, 'rm");
11941cb0ef41Sopenharmony_ci                      break;
11951cb0ef41Sopenharmony_ci                    case 1:
11961cb0ef41Sopenharmony_ci                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
11971cb0ef41Sopenharmony_ci                      break;
11981cb0ef41Sopenharmony_ci                    case 2:
11991cb0ef41Sopenharmony_ci                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
12001cb0ef41Sopenharmony_ci                      break;
12011cb0ef41Sopenharmony_ci                    case 3:
12021cb0ef41Sopenharmony_ci                      Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
12031cb0ef41Sopenharmony_ci                      break;
12041cb0ef41Sopenharmony_ci                  }
12051cb0ef41Sopenharmony_ci                } else {
12061cb0ef41Sopenharmony_ci                  UNREACHABLE();
12071cb0ef41Sopenharmony_ci                }
12081cb0ef41Sopenharmony_ci              } else {
12091cb0ef41Sopenharmony_ci                UNREACHABLE();
12101cb0ef41Sopenharmony_ci              }
12111cb0ef41Sopenharmony_ci              break;
12121cb0ef41Sopenharmony_ci            case 3:
12131cb0ef41Sopenharmony_ci              if ((instr->Bits(9, 6) == 1)) {
12141cb0ef41Sopenharmony_ci                if ((instr->Bit(20) == 0)) {
12151cb0ef41Sopenharmony_ci                  if (instr->Bits(19, 16) == 0xF) {
12161cb0ef41Sopenharmony_ci                    switch (instr->Bits(11, 10)) {
12171cb0ef41Sopenharmony_ci                      case 0:
12181cb0ef41Sopenharmony_ci                        Format(instr, "uxtb'cond 'rd, 'rm");
12191cb0ef41Sopenharmony_ci                        break;
12201cb0ef41Sopenharmony_ci                      case 1:
12211cb0ef41Sopenharmony_ci                        Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
12221cb0ef41Sopenharmony_ci                        break;
12231cb0ef41Sopenharmony_ci                      case 2:
12241cb0ef41Sopenharmony_ci                        Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
12251cb0ef41Sopenharmony_ci                        break;
12261cb0ef41Sopenharmony_ci                      case 3:
12271cb0ef41Sopenharmony_ci                        Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
12281cb0ef41Sopenharmony_ci                        break;
12291cb0ef41Sopenharmony_ci                    }
12301cb0ef41Sopenharmony_ci                  } else {
12311cb0ef41Sopenharmony_ci                    switch (instr->Bits(11, 10)) {
12321cb0ef41Sopenharmony_ci                      case 0:
12331cb0ef41Sopenharmony_ci                        Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
12341cb0ef41Sopenharmony_ci                        break;
12351cb0ef41Sopenharmony_ci                      case 1:
12361cb0ef41Sopenharmony_ci                        Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
12371cb0ef41Sopenharmony_ci                        break;
12381cb0ef41Sopenharmony_ci                      case 2:
12391cb0ef41Sopenharmony_ci                        Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
12401cb0ef41Sopenharmony_ci                        break;
12411cb0ef41Sopenharmony_ci                      case 3:
12421cb0ef41Sopenharmony_ci                        Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
12431cb0ef41Sopenharmony_ci                        break;
12441cb0ef41Sopenharmony_ci                    }
12451cb0ef41Sopenharmony_ci                  }
12461cb0ef41Sopenharmony_ci                } else {
12471cb0ef41Sopenharmony_ci                  if (instr->Bits(19, 16) == 0xF) {
12481cb0ef41Sopenharmony_ci                    switch (instr->Bits(11, 10)) {
12491cb0ef41Sopenharmony_ci                      case 0:
12501cb0ef41Sopenharmony_ci                        Format(instr, "uxth'cond 'rd, 'rm");
12511cb0ef41Sopenharmony_ci                        break;
12521cb0ef41Sopenharmony_ci                      case 1:
12531cb0ef41Sopenharmony_ci                        Format(instr, "uxth'cond 'rd, 'rm, ror #8");
12541cb0ef41Sopenharmony_ci                        break;
12551cb0ef41Sopenharmony_ci                      case 2:
12561cb0ef41Sopenharmony_ci                        Format(instr, "uxth'cond 'rd, 'rm, ror #16");
12571cb0ef41Sopenharmony_ci                        break;
12581cb0ef41Sopenharmony_ci                      case 3:
12591cb0ef41Sopenharmony_ci                        Format(instr, "uxth'cond 'rd, 'rm, ror #24");
12601cb0ef41Sopenharmony_ci                        break;
12611cb0ef41Sopenharmony_ci                    }
12621cb0ef41Sopenharmony_ci                  } else {
12631cb0ef41Sopenharmony_ci                    switch (instr->Bits(11, 10)) {
12641cb0ef41Sopenharmony_ci                      case 0:
12651cb0ef41Sopenharmony_ci                        Format(instr, "uxtah'cond 'rd, 'rn, 'rm");
12661cb0ef41Sopenharmony_ci                        break;
12671cb0ef41Sopenharmony_ci                      case 1:
12681cb0ef41Sopenharmony_ci                        Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8");
12691cb0ef41Sopenharmony_ci                        break;
12701cb0ef41Sopenharmony_ci                      case 2:
12711cb0ef41Sopenharmony_ci                        Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16");
12721cb0ef41Sopenharmony_ci                        break;
12731cb0ef41Sopenharmony_ci                      case 3:
12741cb0ef41Sopenharmony_ci                        Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24");
12751cb0ef41Sopenharmony_ci                        break;
12761cb0ef41Sopenharmony_ci                    }
12771cb0ef41Sopenharmony_ci                  }
12781cb0ef41Sopenharmony_ci                }
12791cb0ef41Sopenharmony_ci              } else {
12801cb0ef41Sopenharmony_ci                // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001
12811cb0ef41Sopenharmony_ci                if ((instr->Bits(20, 16) == 0x1F) &&
12821cb0ef41Sopenharmony_ci                    (instr->Bits(11, 4) == 0xF3)) {
12831cb0ef41Sopenharmony_ci                  Format(instr, "rbit'cond 'rd, 'rm");
12841cb0ef41Sopenharmony_ci                } else {
12851cb0ef41Sopenharmony_ci                  UNREACHABLE();
12861cb0ef41Sopenharmony_ci                }
12871cb0ef41Sopenharmony_ci              }
12881cb0ef41Sopenharmony_ci              break;
12891cb0ef41Sopenharmony_ci          }
12901cb0ef41Sopenharmony_ci        }
12911cb0ef41Sopenharmony_ci      }
12921cb0ef41Sopenharmony_ci      break;
12931cb0ef41Sopenharmony_ci    }
12941cb0ef41Sopenharmony_ci    case db_x: {
12951cb0ef41Sopenharmony_ci      if (instr->Bits(22, 20) == 0x5) {
12961cb0ef41Sopenharmony_ci        if (instr->Bits(7, 4) == 0x1) {
12971cb0ef41Sopenharmony_ci          if (instr->Bits(15, 12) == 0xF) {
12981cb0ef41Sopenharmony_ci            Format(instr, "smmul'cond 'rn, 'rm, 'rs");
12991cb0ef41Sopenharmony_ci          } else {
13001cb0ef41Sopenharmony_ci            // SMMLA (in V8 notation matching ARM ISA format)
13011cb0ef41Sopenharmony_ci            Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
13021cb0ef41Sopenharmony_ci          }
13031cb0ef41Sopenharmony_ci          break;
13041cb0ef41Sopenharmony_ci        }
13051cb0ef41Sopenharmony_ci      }
13061cb0ef41Sopenharmony_ci      if (instr->Bits(5, 4) == 0x1) {
13071cb0ef41Sopenharmony_ci        if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
13081cb0ef41Sopenharmony_ci          if (instr->Bit(21) == 0x1) {
13091cb0ef41Sopenharmony_ci            // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
13101cb0ef41Sopenharmony_ci            Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
13111cb0ef41Sopenharmony_ci          } else {
13121cb0ef41Sopenharmony_ci            // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
13131cb0ef41Sopenharmony_ci            Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
13141cb0ef41Sopenharmony_ci          }
13151cb0ef41Sopenharmony_ci          break;
13161cb0ef41Sopenharmony_ci        }
13171cb0ef41Sopenharmony_ci      }
13181cb0ef41Sopenharmony_ci      Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
13191cb0ef41Sopenharmony_ci      break;
13201cb0ef41Sopenharmony_ci    }
13211cb0ef41Sopenharmony_ci    case ib_x: {
13221cb0ef41Sopenharmony_ci      if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
13231cb0ef41Sopenharmony_ci        uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
13241cb0ef41Sopenharmony_ci        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
13251cb0ef41Sopenharmony_ci        uint32_t msbit = widthminus1 + lsbit;
13261cb0ef41Sopenharmony_ci        if (msbit <= 31) {
13271cb0ef41Sopenharmony_ci          if (instr->Bit(22)) {
13281cb0ef41Sopenharmony_ci            Format(instr, "ubfx'cond 'rd, 'rm, 'f");
13291cb0ef41Sopenharmony_ci          } else {
13301cb0ef41Sopenharmony_ci            Format(instr, "sbfx'cond 'rd, 'rm, 'f");
13311cb0ef41Sopenharmony_ci          }
13321cb0ef41Sopenharmony_ci        } else {
13331cb0ef41Sopenharmony_ci          UNREACHABLE();
13341cb0ef41Sopenharmony_ci        }
13351cb0ef41Sopenharmony_ci      } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
13361cb0ef41Sopenharmony_ci        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
13371cb0ef41Sopenharmony_ci        uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
13381cb0ef41Sopenharmony_ci        if (msbit >= lsbit) {
13391cb0ef41Sopenharmony_ci          if (instr->RmValue() == 15) {
13401cb0ef41Sopenharmony_ci            Format(instr, "bfc'cond 'rd, 'f");
13411cb0ef41Sopenharmony_ci          } else {
13421cb0ef41Sopenharmony_ci            Format(instr, "bfi'cond 'rd, 'rm, 'f");
13431cb0ef41Sopenharmony_ci          }
13441cb0ef41Sopenharmony_ci        } else {
13451cb0ef41Sopenharmony_ci          UNREACHABLE();
13461cb0ef41Sopenharmony_ci        }
13471cb0ef41Sopenharmony_ci      } else {
13481cb0ef41Sopenharmony_ci        Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
13491cb0ef41Sopenharmony_ci      }
13501cb0ef41Sopenharmony_ci      break;
13511cb0ef41Sopenharmony_ci    }
13521cb0ef41Sopenharmony_ci    default: {
13531cb0ef41Sopenharmony_ci      // The PU field is a 2-bit field.
13541cb0ef41Sopenharmony_ci      UNREACHABLE();
13551cb0ef41Sopenharmony_ci    }
13561cb0ef41Sopenharmony_ci  }
13571cb0ef41Sopenharmony_ci}
13581cb0ef41Sopenharmony_ci
13591cb0ef41Sopenharmony_civoid Decoder::DecodeType4(Instruction* instr) {
13601cb0ef41Sopenharmony_ci  if (instr->Bit(22) != 0) {
13611cb0ef41Sopenharmony_ci    // Privileged mode currently not supported.
13621cb0ef41Sopenharmony_ci    Unknown(instr);
13631cb0ef41Sopenharmony_ci  } else {
13641cb0ef41Sopenharmony_ci    if (instr->HasL()) {
13651cb0ef41Sopenharmony_ci      Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
13661cb0ef41Sopenharmony_ci    } else {
13671cb0ef41Sopenharmony_ci      Format(instr, "stm'cond'pu 'rn'w, 'rlist");
13681cb0ef41Sopenharmony_ci    }
13691cb0ef41Sopenharmony_ci  }
13701cb0ef41Sopenharmony_ci}
13711cb0ef41Sopenharmony_ci
13721cb0ef41Sopenharmony_civoid Decoder::DecodeType5(Instruction* instr) {
13731cb0ef41Sopenharmony_ci  Format(instr, "b'l'cond 'target");
13741cb0ef41Sopenharmony_ci}
13751cb0ef41Sopenharmony_ci
13761cb0ef41Sopenharmony_civoid Decoder::DecodeType6(Instruction* instr) {
13771cb0ef41Sopenharmony_ci  DecodeType6CoprocessorIns(instr);
13781cb0ef41Sopenharmony_ci}
13791cb0ef41Sopenharmony_ci
13801cb0ef41Sopenharmony_ciint Decoder::DecodeType7(Instruction* instr) {
13811cb0ef41Sopenharmony_ci  if (instr->Bit(24) == 1) {
13821cb0ef41Sopenharmony_ci    if (instr->SvcValue() >= kStopCode) {
13831cb0ef41Sopenharmony_ci      Format(instr, "stop'cond 'svc");
13841cb0ef41Sopenharmony_ci    } else {
13851cb0ef41Sopenharmony_ci      Format(instr, "svc'cond 'svc");
13861cb0ef41Sopenharmony_ci    }
13871cb0ef41Sopenharmony_ci  } else {
13881cb0ef41Sopenharmony_ci    switch (instr->CoprocessorValue()) {
13891cb0ef41Sopenharmony_ci      case 10:  // Fall through.
13901cb0ef41Sopenharmony_ci      case 11:
13911cb0ef41Sopenharmony_ci        DecodeTypeVFP(instr);
13921cb0ef41Sopenharmony_ci        break;
13931cb0ef41Sopenharmony_ci      case 15:
13941cb0ef41Sopenharmony_ci        DecodeTypeCP15(instr);
13951cb0ef41Sopenharmony_ci        break;
13961cb0ef41Sopenharmony_ci      default:
13971cb0ef41Sopenharmony_ci        Unknown(instr);
13981cb0ef41Sopenharmony_ci        break;
13991cb0ef41Sopenharmony_ci    }
14001cb0ef41Sopenharmony_ci  }
14011cb0ef41Sopenharmony_ci  return kInstrSize;
14021cb0ef41Sopenharmony_ci}
14031cb0ef41Sopenharmony_ci
14041cb0ef41Sopenharmony_ci// void Decoder::DecodeTypeVFP(Instruction* instr)
14051cb0ef41Sopenharmony_ci// vmov: Sn = Rt
14061cb0ef41Sopenharmony_ci// vmov: Rt = Sn
14071cb0ef41Sopenharmony_ci// vcvt: Dd = Sm
14081cb0ef41Sopenharmony_ci// vcvt: Sd = Dm
14091cb0ef41Sopenharmony_ci// vcvt.f64.s32 Dd, Dd, #<fbits>
14101cb0ef41Sopenharmony_ci// Dd = vabs(Dm)
14111cb0ef41Sopenharmony_ci// Sd = vabs(Sm)
14121cb0ef41Sopenharmony_ci// Dd = vneg(Dm)
14131cb0ef41Sopenharmony_ci// Sd = vneg(Sm)
14141cb0ef41Sopenharmony_ci// Dd = vadd(Dn, Dm)
14151cb0ef41Sopenharmony_ci// Sd = vadd(Sn, Sm)
14161cb0ef41Sopenharmony_ci// Dd = vsub(Dn, Dm)
14171cb0ef41Sopenharmony_ci// Sd = vsub(Sn, Sm)
14181cb0ef41Sopenharmony_ci// Dd = vmul(Dn, Dm)
14191cb0ef41Sopenharmony_ci// Sd = vmul(Sn, Sm)
14201cb0ef41Sopenharmony_ci// Dd = vmla(Dn, Dm)
14211cb0ef41Sopenharmony_ci// Sd = vmla(Sn, Sm)
14221cb0ef41Sopenharmony_ci// Dd = vmls(Dn, Dm)
14231cb0ef41Sopenharmony_ci// Sd = vmls(Sn, Sm)
14241cb0ef41Sopenharmony_ci// Dd = vdiv(Dn, Dm)
14251cb0ef41Sopenharmony_ci// Sd = vdiv(Sn, Sm)
14261cb0ef41Sopenharmony_ci// vcmp(Dd, Dm)
14271cb0ef41Sopenharmony_ci// vcmp(Sd, Sm)
14281cb0ef41Sopenharmony_ci// Dd = vsqrt(Dm)
14291cb0ef41Sopenharmony_ci// Sd = vsqrt(Sm)
14301cb0ef41Sopenharmony_ci// vmrs
14311cb0ef41Sopenharmony_ci// vmsr
14321cb0ef41Sopenharmony_ci// Qd = vdup.size(Qd, Rt)
14331cb0ef41Sopenharmony_ci// vmov.size: Dd[i] = Rt
14341cb0ef41Sopenharmony_ci// vmov.sign.size: Rt = Dn[i]
14351cb0ef41Sopenharmony_civoid Decoder::DecodeTypeVFP(Instruction* instr) {
14361cb0ef41Sopenharmony_ci  VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
14371cb0ef41Sopenharmony_ci  VERIFY(instr->Bits(11, 9) == 0x5);
14381cb0ef41Sopenharmony_ci
14391cb0ef41Sopenharmony_ci  if (instr->Bit(4) == 0) {
14401cb0ef41Sopenharmony_ci    if (instr->Opc1Value() == 0x7) {
14411cb0ef41Sopenharmony_ci      // Other data processing instructions
14421cb0ef41Sopenharmony_ci      if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
14431cb0ef41Sopenharmony_ci        // vmov register to register.
14441cb0ef41Sopenharmony_ci        if (instr->SzValue() == 0x1) {
14451cb0ef41Sopenharmony_ci          Format(instr, "vmov'cond.f64 'Dd, 'Dm");
14461cb0ef41Sopenharmony_ci        } else {
14471cb0ef41Sopenharmony_ci          Format(instr, "vmov'cond.f32 'Sd, 'Sm");
14481cb0ef41Sopenharmony_ci        }
14491cb0ef41Sopenharmony_ci      } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
14501cb0ef41Sopenharmony_ci        // vabs
14511cb0ef41Sopenharmony_ci        if (instr->SzValue() == 0x1) {
14521cb0ef41Sopenharmony_ci          Format(instr, "vabs'cond.f64 'Dd, 'Dm");
14531cb0ef41Sopenharmony_ci        } else {
14541cb0ef41Sopenharmony_ci          Format(instr, "vabs'cond.f32 'Sd, 'Sm");
14551cb0ef41Sopenharmony_ci        }
14561cb0ef41Sopenharmony_ci      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
14571cb0ef41Sopenharmony_ci        // vneg
14581cb0ef41Sopenharmony_ci        if (instr->SzValue() == 0x1) {
14591cb0ef41Sopenharmony_ci          Format(instr, "vneg'cond.f64 'Dd, 'Dm");
14601cb0ef41Sopenharmony_ci        } else {
14611cb0ef41Sopenharmony_ci          Format(instr, "vneg'cond.f32 'Sd, 'Sm");
14621cb0ef41Sopenharmony_ci        }
14631cb0ef41Sopenharmony_ci      } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
14641cb0ef41Sopenharmony_ci        DecodeVCVTBetweenDoubleAndSingle(instr);
14651cb0ef41Sopenharmony_ci      } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
14661cb0ef41Sopenharmony_ci        DecodeVCVTBetweenFloatingPointAndInteger(instr);
14671cb0ef41Sopenharmony_ci      } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
14681cb0ef41Sopenharmony_ci                 (instr->Bit(8) == 1)) {
14691cb0ef41Sopenharmony_ci        // vcvt.f64.s32 Dd, Dd, #<fbits>
14701cb0ef41Sopenharmony_ci        int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
14711cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
14721cb0ef41Sopenharmony_ci        out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
14731cb0ef41Sopenharmony_ci                                          ", #%d", fraction_bits);
14741cb0ef41Sopenharmony_ci      } else if (((instr->Opc2Value() >> 1) == 0x6) &&
14751cb0ef41Sopenharmony_ci                 (instr->Opc3Value() & 0x1)) {
14761cb0ef41Sopenharmony_ci        DecodeVCVTBetweenFloatingPointAndInteger(instr);
14771cb0ef41Sopenharmony_ci      } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
14781cb0ef41Sopenharmony_ci                 (instr->Opc3Value() & 0x1)) {
14791cb0ef41Sopenharmony_ci        DecodeVCMP(instr);
14801cb0ef41Sopenharmony_ci      } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
14811cb0ef41Sopenharmony_ci        if (instr->SzValue() == 0x1) {
14821cb0ef41Sopenharmony_ci          Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
14831cb0ef41Sopenharmony_ci        } else {
14841cb0ef41Sopenharmony_ci          Format(instr, "vsqrt'cond.f32 'Sd, 'Sm");
14851cb0ef41Sopenharmony_ci        }
14861cb0ef41Sopenharmony_ci      } else if (instr->Opc3Value() == 0x0) {
14871cb0ef41Sopenharmony_ci        if (instr->SzValue() == 0x1) {
14881cb0ef41Sopenharmony_ci          Format(instr, "vmov'cond.f64 'Dd, 'd");
14891cb0ef41Sopenharmony_ci        } else {
14901cb0ef41Sopenharmony_ci          Format(instr, "vmov'cond.f32 'Sd, 'd");
14911cb0ef41Sopenharmony_ci        }
14921cb0ef41Sopenharmony_ci      } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) {
14931cb0ef41Sopenharmony_ci        // vrintz - round towards zero (truncate)
14941cb0ef41Sopenharmony_ci        if (instr->SzValue() == 0x1) {
14951cb0ef41Sopenharmony_ci          Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm");
14961cb0ef41Sopenharmony_ci        } else {
14971cb0ef41Sopenharmony_ci          Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm");
14981cb0ef41Sopenharmony_ci        }
14991cb0ef41Sopenharmony_ci      } else {
15001cb0ef41Sopenharmony_ci        Unknown(instr);  // Not used by V8.
15011cb0ef41Sopenharmony_ci      }
15021cb0ef41Sopenharmony_ci    } else if (instr->Opc1Value() == 0x3) {
15031cb0ef41Sopenharmony_ci      if (instr->SzValue() == 0x1) {
15041cb0ef41Sopenharmony_ci        if (instr->Opc3Value() & 0x1) {
15051cb0ef41Sopenharmony_ci          Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
15061cb0ef41Sopenharmony_ci        } else {
15071cb0ef41Sopenharmony_ci          Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
15081cb0ef41Sopenharmony_ci        }
15091cb0ef41Sopenharmony_ci      } else {
15101cb0ef41Sopenharmony_ci        if (instr->Opc3Value() & 0x1) {
15111cb0ef41Sopenharmony_ci          Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm");
15121cb0ef41Sopenharmony_ci        } else {
15131cb0ef41Sopenharmony_ci          Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm");
15141cb0ef41Sopenharmony_ci        }
15151cb0ef41Sopenharmony_ci      }
15161cb0ef41Sopenharmony_ci    } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
15171cb0ef41Sopenharmony_ci      if (instr->SzValue() == 0x1) {
15181cb0ef41Sopenharmony_ci        Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
15191cb0ef41Sopenharmony_ci      } else {
15201cb0ef41Sopenharmony_ci        Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm");
15211cb0ef41Sopenharmony_ci      }
15221cb0ef41Sopenharmony_ci    } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
15231cb0ef41Sopenharmony_ci      if (instr->SzValue() == 0x1) {
15241cb0ef41Sopenharmony_ci        Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
15251cb0ef41Sopenharmony_ci      } else {
15261cb0ef41Sopenharmony_ci        Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm");
15271cb0ef41Sopenharmony_ci      }
15281cb0ef41Sopenharmony_ci    } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
15291cb0ef41Sopenharmony_ci      if (instr->SzValue() == 0x1) {
15301cb0ef41Sopenharmony_ci        Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
15311cb0ef41Sopenharmony_ci      } else {
15321cb0ef41Sopenharmony_ci        Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm");
15331cb0ef41Sopenharmony_ci      }
15341cb0ef41Sopenharmony_ci    } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
15351cb0ef41Sopenharmony_ci      if (instr->SzValue() == 0x1) {
15361cb0ef41Sopenharmony_ci        Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
15371cb0ef41Sopenharmony_ci      } else {
15381cb0ef41Sopenharmony_ci        Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm");
15391cb0ef41Sopenharmony_ci      }
15401cb0ef41Sopenharmony_ci    } else {
15411cb0ef41Sopenharmony_ci      Unknown(instr);  // Not used by V8.
15421cb0ef41Sopenharmony_ci    }
15431cb0ef41Sopenharmony_ci  } else {
15441cb0ef41Sopenharmony_ci    if ((instr->VCValue() == 0x0) && (instr->VAValue() == 0x0)) {
15451cb0ef41Sopenharmony_ci      DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
15461cb0ef41Sopenharmony_ci    } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
15471cb0ef41Sopenharmony_ci      const char* rt_name = converter_.NameOfCPURegister(instr->RtValue());
15481cb0ef41Sopenharmony_ci      if (instr->Bit(23) == 0) {
15491cb0ef41Sopenharmony_ci        int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
15501cb0ef41Sopenharmony_ci        if ((opc1_opc2 & 0xB) == 0) {
15511cb0ef41Sopenharmony_ci          // NeonS32/NeonU32
15521cb0ef41Sopenharmony_ci          if (instr->Bit(21) == 0x0) {
15531cb0ef41Sopenharmony_ci            Format(instr, "vmov'cond.32 'Dd[0], 'rt");
15541cb0ef41Sopenharmony_ci          } else {
15551cb0ef41Sopenharmony_ci            Format(instr, "vmov'cond.32 'Dd[1], 'rt");
15561cb0ef41Sopenharmony_ci          }
15571cb0ef41Sopenharmony_ci        } else {
15581cb0ef41Sopenharmony_ci          int vd = instr->VFPNRegValue(kDoublePrecision);
15591cb0ef41Sopenharmony_ci          if ((opc1_opc2 & 0x8) != 0) {
15601cb0ef41Sopenharmony_ci            // NeonS8 / NeonU8
15611cb0ef41Sopenharmony_ci            int i = opc1_opc2 & 0x7;
15621cb0ef41Sopenharmony_ci            out_buffer_pos_ +=
15631cb0ef41Sopenharmony_ci                base::SNPrintF(out_buffer_ + out_buffer_pos_,
15641cb0ef41Sopenharmony_ci                               "vmov.8 d%d[%d], %s", vd, i, rt_name);
15651cb0ef41Sopenharmony_ci          } else if ((opc1_opc2 & 0x1) != 0) {
15661cb0ef41Sopenharmony_ci            // NeonS16 / NeonU16
15671cb0ef41Sopenharmony_ci            int i = (opc1_opc2 >> 1) & 0x3;
15681cb0ef41Sopenharmony_ci            out_buffer_pos_ +=
15691cb0ef41Sopenharmony_ci                base::SNPrintF(out_buffer_ + out_buffer_pos_,
15701cb0ef41Sopenharmony_ci                               "vmov.16 d%d[%d], %s", vd, i, rt_name);
15711cb0ef41Sopenharmony_ci          } else {
15721cb0ef41Sopenharmony_ci            Unknown(instr);
15731cb0ef41Sopenharmony_ci          }
15741cb0ef41Sopenharmony_ci        }
15751cb0ef41Sopenharmony_ci      } else {
15761cb0ef41Sopenharmony_ci        int size = 32;
15771cb0ef41Sopenharmony_ci        if (instr->Bit(5) != 0) {
15781cb0ef41Sopenharmony_ci          size = 16;
15791cb0ef41Sopenharmony_ci        } else if (instr->Bit(22) != 0) {
15801cb0ef41Sopenharmony_ci          size = 8;
15811cb0ef41Sopenharmony_ci        }
15821cb0ef41Sopenharmony_ci        int Vd = instr->VFPNRegValue(kSimd128Precision);
15831cb0ef41Sopenharmony_ci        out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
15841cb0ef41Sopenharmony_ci                                          "vdup.%i q%d, %s", size, Vd, rt_name);
15851cb0ef41Sopenharmony_ci      }
15861cb0ef41Sopenharmony_ci    } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
15871cb0ef41Sopenharmony_ci      int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
15881cb0ef41Sopenharmony_ci      if ((opc1_opc2 & 0xB) == 0) {
15891cb0ef41Sopenharmony_ci        // NeonS32 / NeonU32
15901cb0ef41Sopenharmony_ci        if (instr->Bit(21) == 0x0) {
15911cb0ef41Sopenharmony_ci          Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
15921cb0ef41Sopenharmony_ci        } else {
15931cb0ef41Sopenharmony_ci          Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
15941cb0ef41Sopenharmony_ci        }
15951cb0ef41Sopenharmony_ci      } else {
15961cb0ef41Sopenharmony_ci        char sign = instr->Bit(23) != 0 ? 'u' : 's';
15971cb0ef41Sopenharmony_ci        const char* rt_name = converter_.NameOfCPURegister(instr->RtValue());
15981cb0ef41Sopenharmony_ci        int vn = instr->VFPNRegValue(kDoublePrecision);
15991cb0ef41Sopenharmony_ci        if ((opc1_opc2 & 0x8) != 0) {
16001cb0ef41Sopenharmony_ci          // NeonS8 / NeonU8
16011cb0ef41Sopenharmony_ci          int i = opc1_opc2 & 0x7;
16021cb0ef41Sopenharmony_ci          out_buffer_pos_ +=
16031cb0ef41Sopenharmony_ci              base::SNPrintF(out_buffer_ + out_buffer_pos_,
16041cb0ef41Sopenharmony_ci                             "vmov.%c8 %s, d%d[%d]", sign, rt_name, vn, i);
16051cb0ef41Sopenharmony_ci        } else if ((opc1_opc2 & 0x1) != 0) {
16061cb0ef41Sopenharmony_ci          // NeonS16 / NeonU16
16071cb0ef41Sopenharmony_ci          int i = (opc1_opc2 >> 1) & 0x3;
16081cb0ef41Sopenharmony_ci          out_buffer_pos_ +=
16091cb0ef41Sopenharmony_ci              base::SNPrintF(out_buffer_ + out_buffer_pos_,
16101cb0ef41Sopenharmony_ci                             "vmov.%c16 %s, d%d[%d]", sign, rt_name, vn, i);
16111cb0ef41Sopenharmony_ci        } else {
16121cb0ef41Sopenharmony_ci          Unknown(instr);
16131cb0ef41Sopenharmony_ci        }
16141cb0ef41Sopenharmony_ci      }
16151cb0ef41Sopenharmony_ci    } else if ((instr->VCValue() == 0x0) && (instr->VAValue() == 0x7) &&
16161cb0ef41Sopenharmony_ci               (instr->Bits(19, 16) == 0x1)) {
16171cb0ef41Sopenharmony_ci      if (instr->VLValue() == 0) {
16181cb0ef41Sopenharmony_ci        if (instr->Bits(15, 12) == 0xF) {
16191cb0ef41Sopenharmony_ci          Format(instr, "vmsr'cond FPSCR, APSR");
16201cb0ef41Sopenharmony_ci        } else {
16211cb0ef41Sopenharmony_ci          Format(instr, "vmsr'cond FPSCR, 'rt");
16221cb0ef41Sopenharmony_ci        }
16231cb0ef41Sopenharmony_ci      } else {
16241cb0ef41Sopenharmony_ci        if (instr->Bits(15, 12) == 0xF) {
16251cb0ef41Sopenharmony_ci          Format(instr, "vmrs'cond APSR, FPSCR");
16261cb0ef41Sopenharmony_ci        } else {
16271cb0ef41Sopenharmony_ci          Format(instr, "vmrs'cond 'rt, FPSCR");
16281cb0ef41Sopenharmony_ci        }
16291cb0ef41Sopenharmony_ci      }
16301cb0ef41Sopenharmony_ci    } else {
16311cb0ef41Sopenharmony_ci      Unknown(instr);  // Not used by V8.
16321cb0ef41Sopenharmony_ci    }
16331cb0ef41Sopenharmony_ci  }
16341cb0ef41Sopenharmony_ci}
16351cb0ef41Sopenharmony_ci
16361cb0ef41Sopenharmony_civoid Decoder::DecodeTypeCP15(Instruction* instr) {
16371cb0ef41Sopenharmony_ci  VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
16381cb0ef41Sopenharmony_ci  VERIFY(instr->CoprocessorValue() == 15);
16391cb0ef41Sopenharmony_ci
16401cb0ef41Sopenharmony_ci  if (instr->Bit(4) == 1) {
16411cb0ef41Sopenharmony_ci    int crn = instr->Bits(19, 16);
16421cb0ef41Sopenharmony_ci    int crm = instr->Bits(3, 0);
16431cb0ef41Sopenharmony_ci    int opc1 = instr->Bits(23, 21);
16441cb0ef41Sopenharmony_ci    int opc2 = instr->Bits(7, 5);
16451cb0ef41Sopenharmony_ci    if ((opc1 == 0) && (crn == 7)) {
16461cb0ef41Sopenharmony_ci      // ARMv6 memory barrier operations.
16471cb0ef41Sopenharmony_ci      // Details available in ARM DDI 0406C.b, B3-1750.
16481cb0ef41Sopenharmony_ci      if ((crm == 10) && (opc2 == 5)) {
16491cb0ef41Sopenharmony_ci        Format(instr, "mcr'cond (CP15DMB)");
16501cb0ef41Sopenharmony_ci      } else if ((crm == 10) && (opc2 == 4)) {
16511cb0ef41Sopenharmony_ci        Format(instr, "mcr'cond (CP15DSB)");
16521cb0ef41Sopenharmony_ci      } else if ((crm == 5) && (opc2 == 4)) {
16531cb0ef41Sopenharmony_ci        Format(instr, "mcr'cond (CP15ISB)");
16541cb0ef41Sopenharmony_ci      } else {
16551cb0ef41Sopenharmony_ci        Unknown(instr);
16561cb0ef41Sopenharmony_ci      }
16571cb0ef41Sopenharmony_ci    } else {
16581cb0ef41Sopenharmony_ci      Unknown(instr);
16591cb0ef41Sopenharmony_ci    }
16601cb0ef41Sopenharmony_ci  } else {
16611cb0ef41Sopenharmony_ci    Unknown(instr);
16621cb0ef41Sopenharmony_ci  }
16631cb0ef41Sopenharmony_ci}
16641cb0ef41Sopenharmony_ci
16651cb0ef41Sopenharmony_civoid Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
16661cb0ef41Sopenharmony_ci    Instruction* instr) {
16671cb0ef41Sopenharmony_ci  VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
16681cb0ef41Sopenharmony_ci         (instr->VAValue() == 0x0));
16691cb0ef41Sopenharmony_ci
16701cb0ef41Sopenharmony_ci  bool to_arm_register = (instr->VLValue() == 0x1);
16711cb0ef41Sopenharmony_ci
16721cb0ef41Sopenharmony_ci  if (to_arm_register) {
16731cb0ef41Sopenharmony_ci    Format(instr, "vmov'cond 'rt, 'Sn");
16741cb0ef41Sopenharmony_ci  } else {
16751cb0ef41Sopenharmony_ci    Format(instr, "vmov'cond 'Sn, 'rt");
16761cb0ef41Sopenharmony_ci  }
16771cb0ef41Sopenharmony_ci}
16781cb0ef41Sopenharmony_ci
16791cb0ef41Sopenharmony_civoid Decoder::DecodeVCMP(Instruction* instr) {
16801cb0ef41Sopenharmony_ci  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
16811cb0ef41Sopenharmony_ci  VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
16821cb0ef41Sopenharmony_ci         (instr->Opc3Value() & 0x1));
16831cb0ef41Sopenharmony_ci
16841cb0ef41Sopenharmony_ci  // Comparison.
16851cb0ef41Sopenharmony_ci  bool dp_operation = (instr->SzValue() == 1);
16861cb0ef41Sopenharmony_ci  bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
16871cb0ef41Sopenharmony_ci
16881cb0ef41Sopenharmony_ci  if (dp_operation && !raise_exception_for_qnan) {
16891cb0ef41Sopenharmony_ci    if (instr->Opc2Value() == 0x4) {
16901cb0ef41Sopenharmony_ci      Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
16911cb0ef41Sopenharmony_ci    } else if (instr->Opc2Value() == 0x5) {
16921cb0ef41Sopenharmony_ci      Format(instr, "vcmp'cond.f64 'Dd, #0.0");
16931cb0ef41Sopenharmony_ci    } else {
16941cb0ef41Sopenharmony_ci      Unknown(instr);  // invalid
16951cb0ef41Sopenharmony_ci    }
16961cb0ef41Sopenharmony_ci  } else if (!raise_exception_for_qnan) {
16971cb0ef41Sopenharmony_ci    if (instr->Opc2Value() == 0x4) {
16981cb0ef41Sopenharmony_ci      Format(instr, "vcmp'cond.f32 'Sd, 'Sm");
16991cb0ef41Sopenharmony_ci    } else if (instr->Opc2Value() == 0x5) {
17001cb0ef41Sopenharmony_ci      Format(instr, "vcmp'cond.f32 'Sd, #0.0");
17011cb0ef41Sopenharmony_ci    } else {
17021cb0ef41Sopenharmony_ci      Unknown(instr);  // invalid
17031cb0ef41Sopenharmony_ci    }
17041cb0ef41Sopenharmony_ci  } else {
17051cb0ef41Sopenharmony_ci    Unknown(instr);  // Not used by V8.
17061cb0ef41Sopenharmony_ci  }
17071cb0ef41Sopenharmony_ci}
17081cb0ef41Sopenharmony_ci
17091cb0ef41Sopenharmony_civoid Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
17101cb0ef41Sopenharmony_ci  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
17111cb0ef41Sopenharmony_ci  VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
17121cb0ef41Sopenharmony_ci
17131cb0ef41Sopenharmony_ci  bool double_to_single = (instr->SzValue() == 1);
17141cb0ef41Sopenharmony_ci
17151cb0ef41Sopenharmony_ci  if (double_to_single) {
17161cb0ef41Sopenharmony_ci    Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
17171cb0ef41Sopenharmony_ci  } else {
17181cb0ef41Sopenharmony_ci    Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
17191cb0ef41Sopenharmony_ci  }
17201cb0ef41Sopenharmony_ci}
17211cb0ef41Sopenharmony_ci
17221cb0ef41Sopenharmony_civoid Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
17231cb0ef41Sopenharmony_ci  VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
17241cb0ef41Sopenharmony_ci  VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
17251cb0ef41Sopenharmony_ci         (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
17261cb0ef41Sopenharmony_ci
17271cb0ef41Sopenharmony_ci  bool to_integer = (instr->Bit(18) == 1);
17281cb0ef41Sopenharmony_ci  bool dp_operation = (instr->SzValue() == 1);
17291cb0ef41Sopenharmony_ci  if (to_integer) {
17301cb0ef41Sopenharmony_ci    bool unsigned_integer = (instr->Bit(16) == 0);
17311cb0ef41Sopenharmony_ci
17321cb0ef41Sopenharmony_ci    if (dp_operation) {
17331cb0ef41Sopenharmony_ci      if (unsigned_integer) {
17341cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
17351cb0ef41Sopenharmony_ci      } else {
17361cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
17371cb0ef41Sopenharmony_ci      }
17381cb0ef41Sopenharmony_ci    } else {
17391cb0ef41Sopenharmony_ci      if (unsigned_integer) {
17401cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
17411cb0ef41Sopenharmony_ci      } else {
17421cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
17431cb0ef41Sopenharmony_ci      }
17441cb0ef41Sopenharmony_ci    }
17451cb0ef41Sopenharmony_ci  } else {
17461cb0ef41Sopenharmony_ci    bool unsigned_integer = (instr->Bit(7) == 0);
17471cb0ef41Sopenharmony_ci
17481cb0ef41Sopenharmony_ci    if (dp_operation) {
17491cb0ef41Sopenharmony_ci      if (unsigned_integer) {
17501cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
17511cb0ef41Sopenharmony_ci      } else {
17521cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
17531cb0ef41Sopenharmony_ci      }
17541cb0ef41Sopenharmony_ci    } else {
17551cb0ef41Sopenharmony_ci      if (unsigned_integer) {
17561cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
17571cb0ef41Sopenharmony_ci      } else {
17581cb0ef41Sopenharmony_ci        Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
17591cb0ef41Sopenharmony_ci      }
17601cb0ef41Sopenharmony_ci    }
17611cb0ef41Sopenharmony_ci  }
17621cb0ef41Sopenharmony_ci}
17631cb0ef41Sopenharmony_ci
17641cb0ef41Sopenharmony_civoid Decoder::DecodeVmovImmediate(Instruction* instr) {
17651cb0ef41Sopenharmony_ci  byte cmode = instr->Bits(11, 8);
17661cb0ef41Sopenharmony_ci  int vd = instr->VFPDRegValue(kSimd128Precision);
17671cb0ef41Sopenharmony_ci  int a = instr->Bit(24);
17681cb0ef41Sopenharmony_ci  int bcd = instr->Bits(18, 16);
17691cb0ef41Sopenharmony_ci  int efgh = instr->Bits(3, 0);
17701cb0ef41Sopenharmony_ci  uint8_t imm = a << 7 | bcd << 4 | efgh;
17711cb0ef41Sopenharmony_ci  switch (cmode) {
17721cb0ef41Sopenharmony_ci    case 0: {
17731cb0ef41Sopenharmony_ci      uint32_t imm32 = imm;
17741cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
17751cb0ef41Sopenharmony_ci                                        "vmov.i32 q%d, %d", vd, imm32);
17761cb0ef41Sopenharmony_ci      break;
17771cb0ef41Sopenharmony_ci    }
17781cb0ef41Sopenharmony_ci    case 0xe: {
17791cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
17801cb0ef41Sopenharmony_ci                                        "vmov.i8 q%d, %d", vd, imm);
17811cb0ef41Sopenharmony_ci      break;
17821cb0ef41Sopenharmony_ci    }
17831cb0ef41Sopenharmony_ci    default:
17841cb0ef41Sopenharmony_ci      Unknown(instr);
17851cb0ef41Sopenharmony_ci  }
17861cb0ef41Sopenharmony_ci}
17871cb0ef41Sopenharmony_ci
17881cb0ef41Sopenharmony_ci// Decode Type 6 coprocessor instructions.
17891cb0ef41Sopenharmony_ci// Dm = vmov(Rt, Rt2)
17901cb0ef41Sopenharmony_ci// <Rt, Rt2> = vmov(Dm)
17911cb0ef41Sopenharmony_ci// Ddst = MEM(Rbase + 4*offset).
17921cb0ef41Sopenharmony_ci// MEM(Rbase + 4*offset) = Dsrc.
17931cb0ef41Sopenharmony_civoid Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
17941cb0ef41Sopenharmony_ci  VERIFY(instr->TypeValue() == 6);
17951cb0ef41Sopenharmony_ci
17961cb0ef41Sopenharmony_ci  if (instr->CoprocessorValue() == 0xA) {
17971cb0ef41Sopenharmony_ci    switch (instr->OpcodeValue()) {
17981cb0ef41Sopenharmony_ci      case 0x8:
17991cb0ef41Sopenharmony_ci      case 0xA:
18001cb0ef41Sopenharmony_ci        if (instr->HasL()) {
18011cb0ef41Sopenharmony_ci          Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
18021cb0ef41Sopenharmony_ci        } else {
18031cb0ef41Sopenharmony_ci          Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
18041cb0ef41Sopenharmony_ci        }
18051cb0ef41Sopenharmony_ci        break;
18061cb0ef41Sopenharmony_ci      case 0xC:
18071cb0ef41Sopenharmony_ci      case 0xE:
18081cb0ef41Sopenharmony_ci        if (instr->HasL()) {
18091cb0ef41Sopenharmony_ci          Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
18101cb0ef41Sopenharmony_ci        } else {
18111cb0ef41Sopenharmony_ci          Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
18121cb0ef41Sopenharmony_ci        }
18131cb0ef41Sopenharmony_ci        break;
18141cb0ef41Sopenharmony_ci      case 0x4:
18151cb0ef41Sopenharmony_ci      case 0x5:
18161cb0ef41Sopenharmony_ci      case 0x6:
18171cb0ef41Sopenharmony_ci      case 0x7:
18181cb0ef41Sopenharmony_ci      case 0x9:
18191cb0ef41Sopenharmony_ci      case 0xB: {
18201cb0ef41Sopenharmony_ci        bool to_vfp_register = (instr->VLValue() == 0x1);
18211cb0ef41Sopenharmony_ci        if (to_vfp_register) {
18221cb0ef41Sopenharmony_ci          Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
18231cb0ef41Sopenharmony_ci        } else {
18241cb0ef41Sopenharmony_ci          Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
18251cb0ef41Sopenharmony_ci        }
18261cb0ef41Sopenharmony_ci        break;
18271cb0ef41Sopenharmony_ci      }
18281cb0ef41Sopenharmony_ci      default:
18291cb0ef41Sopenharmony_ci        Unknown(instr);  // Not used by V8.
18301cb0ef41Sopenharmony_ci    }
18311cb0ef41Sopenharmony_ci  } else if (instr->CoprocessorValue() == 0xB) {
18321cb0ef41Sopenharmony_ci    switch (instr->OpcodeValue()) {
18331cb0ef41Sopenharmony_ci      case 0x2:
18341cb0ef41Sopenharmony_ci        // Load and store double to two GP registers
18351cb0ef41Sopenharmony_ci        if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
18361cb0ef41Sopenharmony_ci          Unknown(instr);  // Not used by V8.
18371cb0ef41Sopenharmony_ci        } else if (instr->HasL()) {
18381cb0ef41Sopenharmony_ci          Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
18391cb0ef41Sopenharmony_ci        } else {
18401cb0ef41Sopenharmony_ci          Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
18411cb0ef41Sopenharmony_ci        }
18421cb0ef41Sopenharmony_ci        break;
18431cb0ef41Sopenharmony_ci      case 0x8:
18441cb0ef41Sopenharmony_ci      case 0xA:
18451cb0ef41Sopenharmony_ci        if (instr->HasL()) {
18461cb0ef41Sopenharmony_ci          Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
18471cb0ef41Sopenharmony_ci        } else {
18481cb0ef41Sopenharmony_ci          Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
18491cb0ef41Sopenharmony_ci        }
18501cb0ef41Sopenharmony_ci        break;
18511cb0ef41Sopenharmony_ci      case 0xC:
18521cb0ef41Sopenharmony_ci      case 0xE:
18531cb0ef41Sopenharmony_ci        if (instr->HasL()) {
18541cb0ef41Sopenharmony_ci          Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
18551cb0ef41Sopenharmony_ci        } else {
18561cb0ef41Sopenharmony_ci          Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
18571cb0ef41Sopenharmony_ci        }
18581cb0ef41Sopenharmony_ci        break;
18591cb0ef41Sopenharmony_ci      case 0x4:
18601cb0ef41Sopenharmony_ci      case 0x5:
18611cb0ef41Sopenharmony_ci      case 0x6:
18621cb0ef41Sopenharmony_ci      case 0x7:
18631cb0ef41Sopenharmony_ci      case 0x9:
18641cb0ef41Sopenharmony_ci      case 0xB: {
18651cb0ef41Sopenharmony_ci        bool to_vfp_register = (instr->VLValue() == 0x1);
18661cb0ef41Sopenharmony_ci        if (to_vfp_register) {
18671cb0ef41Sopenharmony_ci          Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
18681cb0ef41Sopenharmony_ci        } else {
18691cb0ef41Sopenharmony_ci          Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
18701cb0ef41Sopenharmony_ci        }
18711cb0ef41Sopenharmony_ci        break;
18721cb0ef41Sopenharmony_ci      }
18731cb0ef41Sopenharmony_ci      default:
18741cb0ef41Sopenharmony_ci        Unknown(instr);  // Not used by V8.
18751cb0ef41Sopenharmony_ci    }
18761cb0ef41Sopenharmony_ci  } else {
18771cb0ef41Sopenharmony_ci    Unknown(instr);  // Not used by V8.
18781cb0ef41Sopenharmony_ci  }
18791cb0ef41Sopenharmony_ci}
18801cb0ef41Sopenharmony_ci
18811cb0ef41Sopenharmony_cistatic const char* const barrier_option_names[] = {
18821cb0ef41Sopenharmony_ci    "invalid", "oshld", "oshst", "osh", "invalid", "nshld", "nshst", "nsh",
18831cb0ef41Sopenharmony_ci    "invalid", "ishld", "ishst", "ish", "invalid", "ld",    "st",    "sy",
18841cb0ef41Sopenharmony_ci};
18851cb0ef41Sopenharmony_ci
18861cb0ef41Sopenharmony_civoid Decoder::DecodeSpecialCondition(Instruction* instr) {
18871cb0ef41Sopenharmony_ci  int op0 = instr->Bits(25, 24);
18881cb0ef41Sopenharmony_ci  int op1 = instr->Bits(11, 9);
18891cb0ef41Sopenharmony_ci  int op2 = instr->Bit(4);
18901cb0ef41Sopenharmony_ci
18911cb0ef41Sopenharmony_ci  if (instr->Bit(27) == 0) {
18921cb0ef41Sopenharmony_ci    DecodeUnconditional(instr);
18931cb0ef41Sopenharmony_ci  } else if ((instr->Bits(27, 26) == 0b11) && (op0 == 0b10) &&
18941cb0ef41Sopenharmony_ci             ((op1 >> 1) == 0b10) && !op2) {
18951cb0ef41Sopenharmony_ci    DecodeFloatingPointDataProcessing(instr);
18961cb0ef41Sopenharmony_ci  } else {
18971cb0ef41Sopenharmony_ci    Unknown(instr);
18981cb0ef41Sopenharmony_ci  }
18991cb0ef41Sopenharmony_ci}
19001cb0ef41Sopenharmony_ci
19011cb0ef41Sopenharmony_civoid Decoder::DecodeFloatingPointDataProcessing(Instruction* instr) {
19021cb0ef41Sopenharmony_ci  // Floating-point data processing, F4.1.14.
19031cb0ef41Sopenharmony_ci  int op0 = instr->Bits(23, 20);
19041cb0ef41Sopenharmony_ci  int op1 = instr->Bits(19, 16);
19051cb0ef41Sopenharmony_ci  int op2 = instr->Bits(9, 8);
19061cb0ef41Sopenharmony_ci  int op3 = instr->Bit(6);
19071cb0ef41Sopenharmony_ci  if (((op0 & 0b1000) == 0) && op2 && !op3) {
19081cb0ef41Sopenharmony_ci    // Floating-point conditional select.
19091cb0ef41Sopenharmony_ci    // VSEL* (floating-point)
19101cb0ef41Sopenharmony_ci    bool dp_operation = (instr->SzValue() == 1);
19111cb0ef41Sopenharmony_ci    switch (instr->Bits(21, 20)) {
19121cb0ef41Sopenharmony_ci      case 0x0:
19131cb0ef41Sopenharmony_ci        if (dp_operation) {
19141cb0ef41Sopenharmony_ci          Format(instr, "vseleq.f64 'Dd, 'Dn, 'Dm");
19151cb0ef41Sopenharmony_ci        } else {
19161cb0ef41Sopenharmony_ci          Format(instr, "vseleq.f32 'Sd, 'Sn, 'Sm");
19171cb0ef41Sopenharmony_ci        }
19181cb0ef41Sopenharmony_ci        break;
19191cb0ef41Sopenharmony_ci      case 0x1:
19201cb0ef41Sopenharmony_ci        if (dp_operation) {
19211cb0ef41Sopenharmony_ci          Format(instr, "vselvs.f64 'Dd, 'Dn, 'Dm");
19221cb0ef41Sopenharmony_ci        } else {
19231cb0ef41Sopenharmony_ci          Format(instr, "vselvs.f32 'Sd, 'Sn, 'Sm");
19241cb0ef41Sopenharmony_ci        }
19251cb0ef41Sopenharmony_ci        break;
19261cb0ef41Sopenharmony_ci      case 0x2:
19271cb0ef41Sopenharmony_ci        if (dp_operation) {
19281cb0ef41Sopenharmony_ci          Format(instr, "vselge.f64 'Dd, 'Dn, 'Dm");
19291cb0ef41Sopenharmony_ci        } else {
19301cb0ef41Sopenharmony_ci          Format(instr, "vselge.f32 'Sd, 'Sn, 'Sm");
19311cb0ef41Sopenharmony_ci        }
19321cb0ef41Sopenharmony_ci        break;
19331cb0ef41Sopenharmony_ci      case 0x3:
19341cb0ef41Sopenharmony_ci        if (dp_operation) {
19351cb0ef41Sopenharmony_ci          Format(instr, "vselgt.f64 'Dd, 'Dn, 'Dm");
19361cb0ef41Sopenharmony_ci        } else {
19371cb0ef41Sopenharmony_ci          Format(instr, "vselgt.f32 'Sd, 'Sn, 'Sm");
19381cb0ef41Sopenharmony_ci        }
19391cb0ef41Sopenharmony_ci        break;
19401cb0ef41Sopenharmony_ci      default:
19411cb0ef41Sopenharmony_ci        UNREACHABLE();  // Case analysis is exhaustive.
19421cb0ef41Sopenharmony_ci    }
19431cb0ef41Sopenharmony_ci  } else if (instr->Opc1Value() == 0x4 && op2) {
19441cb0ef41Sopenharmony_ci    // Floating-point minNum/maxNum.
19451cb0ef41Sopenharmony_ci    // VMAXNM, VMINNM (floating-point)
19461cb0ef41Sopenharmony_ci    if (instr->SzValue() == 0x1) {
19471cb0ef41Sopenharmony_ci      if (instr->Bit(6) == 0x1) {
19481cb0ef41Sopenharmony_ci        Format(instr, "vminnm.f64 'Dd, 'Dn, 'Dm");
19491cb0ef41Sopenharmony_ci      } else {
19501cb0ef41Sopenharmony_ci        Format(instr, "vmaxnm.f64 'Dd, 'Dn, 'Dm");
19511cb0ef41Sopenharmony_ci      }
19521cb0ef41Sopenharmony_ci    } else {
19531cb0ef41Sopenharmony_ci      if (instr->Bit(6) == 0x1) {
19541cb0ef41Sopenharmony_ci        Format(instr, "vminnm.f32 'Sd, 'Sn, 'Sm");
19551cb0ef41Sopenharmony_ci      } else {
19561cb0ef41Sopenharmony_ci        Format(instr, "vmaxnm.f32 'Sd, 'Sn, 'Sm");
19571cb0ef41Sopenharmony_ci      }
19581cb0ef41Sopenharmony_ci    }
19591cb0ef41Sopenharmony_ci  } else if (instr->Opc1Value() == 0x7 && (op1 >> 3) && op2 && op3) {
19601cb0ef41Sopenharmony_ci    // Floating-point directed convert to integer.
19611cb0ef41Sopenharmony_ci    // VRINTA, VRINTN, VRINTP, VRINTM (floating-point)
19621cb0ef41Sopenharmony_ci    bool dp_operation = (instr->SzValue() == 1);
19631cb0ef41Sopenharmony_ci    int rounding_mode = instr->Bits(17, 16);
19641cb0ef41Sopenharmony_ci    switch (rounding_mode) {
19651cb0ef41Sopenharmony_ci      case 0x0:
19661cb0ef41Sopenharmony_ci        if (dp_operation) {
19671cb0ef41Sopenharmony_ci          Format(instr, "vrinta.f64.f64 'Dd, 'Dm");
19681cb0ef41Sopenharmony_ci        } else {
19691cb0ef41Sopenharmony_ci          Format(instr, "vrinta.f32.f32 'Sd, 'Sm");
19701cb0ef41Sopenharmony_ci        }
19711cb0ef41Sopenharmony_ci        break;
19721cb0ef41Sopenharmony_ci      case 0x1:
19731cb0ef41Sopenharmony_ci        if (dp_operation) {
19741cb0ef41Sopenharmony_ci          Format(instr, "vrintn.f64.f64 'Dd, 'Dm");
19751cb0ef41Sopenharmony_ci        } else {
19761cb0ef41Sopenharmony_ci          Format(instr, "vrintn.f32.f32 'Sd, 'Sm");
19771cb0ef41Sopenharmony_ci        }
19781cb0ef41Sopenharmony_ci        break;
19791cb0ef41Sopenharmony_ci      case 0x2:
19801cb0ef41Sopenharmony_ci        if (dp_operation) {
19811cb0ef41Sopenharmony_ci          Format(instr, "vrintp.f64.f64 'Dd, 'Dm");
19821cb0ef41Sopenharmony_ci        } else {
19831cb0ef41Sopenharmony_ci          Format(instr, "vrintp.f32.f32 'Sd, 'Sm");
19841cb0ef41Sopenharmony_ci        }
19851cb0ef41Sopenharmony_ci        break;
19861cb0ef41Sopenharmony_ci      case 0x3:
19871cb0ef41Sopenharmony_ci        if (dp_operation) {
19881cb0ef41Sopenharmony_ci          Format(instr, "vrintm.f64.f64 'Dd, 'Dm");
19891cb0ef41Sopenharmony_ci        } else {
19901cb0ef41Sopenharmony_ci          Format(instr, "vrintm.f32.f32 'Sd, 'Sm");
19911cb0ef41Sopenharmony_ci        }
19921cb0ef41Sopenharmony_ci        break;
19931cb0ef41Sopenharmony_ci      default:
19941cb0ef41Sopenharmony_ci        UNREACHABLE();  // Case analysis is exhaustive.
19951cb0ef41Sopenharmony_ci    }
19961cb0ef41Sopenharmony_ci  } else {
19971cb0ef41Sopenharmony_ci    Unknown(instr);
19981cb0ef41Sopenharmony_ci  }
19991cb0ef41Sopenharmony_ci  // One class of decoding is missing here: Floating-point extraction and
20001cb0ef41Sopenharmony_ci  // insertion, but it is not used in V8 now, and thus omitted.
20011cb0ef41Sopenharmony_ci}
20021cb0ef41Sopenharmony_ci
20031cb0ef41Sopenharmony_civoid Decoder::DecodeUnconditional(Instruction* instr) {
20041cb0ef41Sopenharmony_ci  // This follows the decoding in F4.1.18 Unconditional instructions.
20051cb0ef41Sopenharmony_ci  int op0 = instr->Bits(26, 25);
20061cb0ef41Sopenharmony_ci  int op1 = instr->Bit(20);
20071cb0ef41Sopenharmony_ci
20081cb0ef41Sopenharmony_ci  // Four classes of decoding:
20091cb0ef41Sopenharmony_ci  // - Miscellaneous (omitted, no instructions used in V8).
20101cb0ef41Sopenharmony_ci  // - Advanced SIMD data-processing.
20111cb0ef41Sopenharmony_ci  // - Memory hints and barriers.
20121cb0ef41Sopenharmony_ci  // - Advanced SIMD element or structure load/store.
20131cb0ef41Sopenharmony_ci  if (op0 == 0b01) {
20141cb0ef41Sopenharmony_ci    DecodeAdvancedSIMDDataProcessing(instr);
20151cb0ef41Sopenharmony_ci  } else if ((op0 & 0b10) == 0b10 && op1) {
20161cb0ef41Sopenharmony_ci    DecodeMemoryHintsAndBarriers(instr);
20171cb0ef41Sopenharmony_ci  } else if (op0 == 0b10 && !op1) {
20181cb0ef41Sopenharmony_ci    DecodeAdvancedSIMDElementOrStructureLoadStore(instr);
20191cb0ef41Sopenharmony_ci  } else {
20201cb0ef41Sopenharmony_ci    Unknown(instr);
20211cb0ef41Sopenharmony_ci  }
20221cb0ef41Sopenharmony_ci}
20231cb0ef41Sopenharmony_ci
20241cb0ef41Sopenharmony_civoid Decoder::DecodeAdvancedSIMDDataProcessing(Instruction* instr) {
20251cb0ef41Sopenharmony_ci  int op0 = instr->Bit(23);
20261cb0ef41Sopenharmony_ci  int op1 = instr->Bit(4);
20271cb0ef41Sopenharmony_ci  if (op0 == 0) {
20281cb0ef41Sopenharmony_ci    // Advanced SIMD three registers of same length.
20291cb0ef41Sopenharmony_ci    int Vm, Vn;
20301cb0ef41Sopenharmony_ci    if (instr->Bit(6) == 0) {
20311cb0ef41Sopenharmony_ci      Vm = instr->VFPMRegValue(kDoublePrecision);
20321cb0ef41Sopenharmony_ci      Vn = instr->VFPNRegValue(kDoublePrecision);
20331cb0ef41Sopenharmony_ci    } else {
20341cb0ef41Sopenharmony_ci      Vm = instr->VFPMRegValue(kSimd128Precision);
20351cb0ef41Sopenharmony_ci      Vn = instr->VFPNRegValue(kSimd128Precision);
20361cb0ef41Sopenharmony_ci    }
20371cb0ef41Sopenharmony_ci
20381cb0ef41Sopenharmony_ci    int u = instr->Bit(24);
20391cb0ef41Sopenharmony_ci    int opc = instr->Bits(11, 8);
20401cb0ef41Sopenharmony_ci    int q = instr->Bit(6);
20411cb0ef41Sopenharmony_ci    int sz = instr->Bits(21, 20);
20421cb0ef41Sopenharmony_ci
20431cb0ef41Sopenharmony_ci    if (!u && opc == 0 && op1) {
20441cb0ef41Sopenharmony_ci      Format(instr, "vqadd.s'size3 'Qd, 'Qn, 'Qm");
20451cb0ef41Sopenharmony_ci    } else if (!u && opc == 1 && sz == 2 && q && op1) {
20461cb0ef41Sopenharmony_ci      if (Vm == Vn) {
20471cb0ef41Sopenharmony_ci        Format(instr, "vmov 'Qd, 'Qm");
20481cb0ef41Sopenharmony_ci      } else {
20491cb0ef41Sopenharmony_ci        Format(instr, "vorr 'Qd, 'Qn, 'Qm");
20501cb0ef41Sopenharmony_ci      }
20511cb0ef41Sopenharmony_ci    } else if (!u && opc == 1 && sz == 1 && q && op1) {
20521cb0ef41Sopenharmony_ci      Format(instr, "vbic 'Qd, 'Qn, 'Qm");
20531cb0ef41Sopenharmony_ci    } else if (!u && opc == 1 && sz == 0 && q && op1) {
20541cb0ef41Sopenharmony_ci      Format(instr, "vand 'Qd, 'Qn, 'Qm");
20551cb0ef41Sopenharmony_ci    } else if (!u && opc == 2 && op1) {
20561cb0ef41Sopenharmony_ci      Format(instr, "vqsub.s'size3 'Qd, 'Qn, 'Qm");
20571cb0ef41Sopenharmony_ci    } else if (!u && opc == 3 && op1) {
20581cb0ef41Sopenharmony_ci      Format(instr, "vcge.s'size3 'Qd, 'Qn, 'Qm");
20591cb0ef41Sopenharmony_ci    } else if (!u && opc == 3 && !op1) {
20601cb0ef41Sopenharmony_ci      Format(instr, "vcgt.s'size3 'Qd, 'Qn, 'Qm");
20611cb0ef41Sopenharmony_ci    } else if (!u && opc == 4 && !op1) {
20621cb0ef41Sopenharmony_ci      Format(instr, "vshl.s'size3 'Qd, 'Qm, 'Qn");
20631cb0ef41Sopenharmony_ci    } else if (!u && opc == 6 && op1) {
20641cb0ef41Sopenharmony_ci      Format(instr, "vmin.s'size3 'Qd, 'Qn, 'Qm");
20651cb0ef41Sopenharmony_ci    } else if (!u && opc == 6 && !op1) {
20661cb0ef41Sopenharmony_ci      Format(instr, "vmax.s'size3 'Qd, 'Qn, 'Qm");
20671cb0ef41Sopenharmony_ci    } else if (!u && opc == 8 && op1) {
20681cb0ef41Sopenharmony_ci      Format(instr, "vtst.i'size3 'Qd, 'Qn, 'Qm");
20691cb0ef41Sopenharmony_ci    } else if (!u && opc == 8 && !op1) {
20701cb0ef41Sopenharmony_ci      Format(instr, "vadd.i'size3 'Qd, 'Qn, 'Qm");
20711cb0ef41Sopenharmony_ci    } else if (opc == 9 && op1) {
20721cb0ef41Sopenharmony_ci      Format(instr, "vmul.i'size3 'Qd, 'Qn, 'Qm");
20731cb0ef41Sopenharmony_ci    } else if (!u && opc == 0xA && op1) {
20741cb0ef41Sopenharmony_ci      Format(instr, "vpmin.s'size3 'Dd, 'Dn, 'Dm");
20751cb0ef41Sopenharmony_ci    } else if (!u && opc == 0xA && !op1) {
20761cb0ef41Sopenharmony_ci      Format(instr, "vpmax.s'size3 'Dd, 'Dn, 'Dm");
20771cb0ef41Sopenharmony_ci    } else if (u && opc == 0XB) {
20781cb0ef41Sopenharmony_ci      Format(instr, "vqrdmulh.s'size3 'Qd, 'Qn, 'Qm");
20791cb0ef41Sopenharmony_ci    } else if (!u && opc == 0xB) {
20801cb0ef41Sopenharmony_ci      Format(instr, "vpadd.i'size3 'Dd, 'Dn, 'Dm");
20811cb0ef41Sopenharmony_ci    } else if (!u && !(sz >> 1) && opc == 0xD && !op1) {
20821cb0ef41Sopenharmony_ci      Format(instr, "vadd.f32 'Qd, 'Qn, 'Qm");
20831cb0ef41Sopenharmony_ci    } else if (!u && (sz >> 1) && opc == 0xD && !op1) {
20841cb0ef41Sopenharmony_ci      Format(instr, "vsub.f32 'Qd, 'Qn, 'Qm");
20851cb0ef41Sopenharmony_ci    } else if (!u && opc == 0xE && !sz && !op1) {
20861cb0ef41Sopenharmony_ci      Format(instr, "vceq.f32 'Qd, 'Qn, 'Qm");
20871cb0ef41Sopenharmony_ci    } else if (!u && !(sz >> 1) && opc == 0xF && op1) {
20881cb0ef41Sopenharmony_ci      Format(instr, "vrecps.f32 'Qd, 'Qn, 'Qm");
20891cb0ef41Sopenharmony_ci    } else if (!u && (sz >> 1) && opc == 0xF && op1) {
20901cb0ef41Sopenharmony_ci      Format(instr, "vrsqrts.f32 'Qd, 'Qn, 'Qm");
20911cb0ef41Sopenharmony_ci    } else if (!u && !(sz >> 1) && opc == 0xF && !op1) {
20921cb0ef41Sopenharmony_ci      Format(instr, "vmax.f32 'Qd, 'Qn, 'Qm");
20931cb0ef41Sopenharmony_ci    } else if (!u && (sz >> 1) && opc == 0xF && !op1) {
20941cb0ef41Sopenharmony_ci      Format(instr, "vmin.f32 'Qd, 'Qn, 'Qm");
20951cb0ef41Sopenharmony_ci    } else if (u && opc == 0 && op1) {
20961cb0ef41Sopenharmony_ci      Format(instr, "vqadd.u'size3 'Qd, 'Qn, 'Qm");
20971cb0ef41Sopenharmony_ci    } else if (u && opc == 1 && sz == 1 && op1) {
20981cb0ef41Sopenharmony_ci      Format(instr, "vbsl 'Qd, 'Qn, 'Qm");
20991cb0ef41Sopenharmony_ci    } else if (u && opc == 1 && sz == 0 && q && op1) {
21001cb0ef41Sopenharmony_ci      Format(instr, "veor 'Qd, 'Qn, 'Qm");
21011cb0ef41Sopenharmony_ci    } else if (u && opc == 1 && sz == 0 && !q && op1) {
21021cb0ef41Sopenharmony_ci      Format(instr, "veor 'Dd, 'Dn, 'Dm");
21031cb0ef41Sopenharmony_ci    } else if (u && opc == 1 && !op1) {
21041cb0ef41Sopenharmony_ci      Format(instr, "vrhadd.u'size3 'Qd, 'Qn, 'Qm");
21051cb0ef41Sopenharmony_ci    } else if (u && opc == 2 && op1) {
21061cb0ef41Sopenharmony_ci      Format(instr, "vqsub.u'size3 'Qd, 'Qn, 'Qm");
21071cb0ef41Sopenharmony_ci    } else if (u && opc == 3 && op1) {
21081cb0ef41Sopenharmony_ci      Format(instr, "vcge.u'size3 'Qd, 'Qn, 'Qm");
21091cb0ef41Sopenharmony_ci    } else if (u && opc == 3 && !op1) {
21101cb0ef41Sopenharmony_ci      Format(instr, "vcgt.u'size3 'Qd, 'Qn, 'Qm");
21111cb0ef41Sopenharmony_ci    } else if (u && opc == 4 && !op1) {
21121cb0ef41Sopenharmony_ci      Format(instr, "vshl.u'size3 'Qd, 'Qm, 'Qn");
21131cb0ef41Sopenharmony_ci    } else if (u && opc == 6 && op1) {
21141cb0ef41Sopenharmony_ci      Format(instr, "vmin.u'size3 'Qd, 'Qn, 'Qm");
21151cb0ef41Sopenharmony_ci    } else if (u && opc == 6 && !op1) {
21161cb0ef41Sopenharmony_ci      Format(instr, "vmax.u'size3 'Qd, 'Qn, 'Qm");
21171cb0ef41Sopenharmony_ci    } else if (u && opc == 8 && op1) {
21181cb0ef41Sopenharmony_ci      Format(instr, "vceq.i'size3 'Qd, 'Qn, 'Qm");
21191cb0ef41Sopenharmony_ci    } else if (u && opc == 8 && !op1) {
21201cb0ef41Sopenharmony_ci      Format(instr, "vsub.i'size3 'Qd, 'Qn, 'Qm");
21211cb0ef41Sopenharmony_ci    } else if (u && opc == 0xA && op1) {
21221cb0ef41Sopenharmony_ci      Format(instr, "vpmin.u'size3 'Dd, 'Dn, 'Dm");
21231cb0ef41Sopenharmony_ci    } else if (u && opc == 0xA && !op1) {
21241cb0ef41Sopenharmony_ci      Format(instr, "vpmax.u'size3 'Dd, 'Dn, 'Dm");
21251cb0ef41Sopenharmony_ci    } else if (u && opc == 0xD && sz == 0 && q && op1) {
21261cb0ef41Sopenharmony_ci      Format(instr, "vmul.f32 'Qd, 'Qn, 'Qm");
21271cb0ef41Sopenharmony_ci    } else if (u && opc == 0xD && sz == 0 && !q && !op1) {
21281cb0ef41Sopenharmony_ci      Format(instr, "vpadd.f32 'Dd, 'Dn, 'Dm");
21291cb0ef41Sopenharmony_ci    } else if (u && opc == 0xE && !(sz >> 1) && !op1) {
21301cb0ef41Sopenharmony_ci      Format(instr, "vcge.f32 'Qd, 'Qn, 'Qm");
21311cb0ef41Sopenharmony_ci    } else if (u && opc == 0xE && (sz >> 1) && !op1) {
21321cb0ef41Sopenharmony_ci      Format(instr, "vcgt.f32 'Qd, 'Qn, 'Qm");
21331cb0ef41Sopenharmony_ci    } else {
21341cb0ef41Sopenharmony_ci      Unknown(instr);
21351cb0ef41Sopenharmony_ci    }
21361cb0ef41Sopenharmony_ci  } else if (op0 == 1 && op1 == 0) {
21371cb0ef41Sopenharmony_ci    DecodeAdvancedSIMDTwoOrThreeRegisters(instr);
21381cb0ef41Sopenharmony_ci  } else if (op0 == 1 && op1 == 1) {
21391cb0ef41Sopenharmony_ci    // Advanced SIMD shifts and immediate generation.
21401cb0ef41Sopenharmony_ci    if (instr->Bits(21, 19) == 0 && instr->Bit(7) == 0) {
21411cb0ef41Sopenharmony_ci      // Advanced SIMD one register and modified immediate.
21421cb0ef41Sopenharmony_ci      DecodeVmovImmediate(instr);
21431cb0ef41Sopenharmony_ci    } else {
21441cb0ef41Sopenharmony_ci      // Advanced SIMD two registers and shift amount.
21451cb0ef41Sopenharmony_ci      int u = instr->Bit(24);
21461cb0ef41Sopenharmony_ci      int imm3H = instr->Bits(21, 19);
21471cb0ef41Sopenharmony_ci      int imm3L = instr->Bits(18, 16);
21481cb0ef41Sopenharmony_ci      int opc = instr->Bits(11, 8);
21491cb0ef41Sopenharmony_ci      int l = instr->Bit(7);
21501cb0ef41Sopenharmony_ci      int q = instr->Bit(6);
21511cb0ef41Sopenharmony_ci      int imm3H_L = imm3H << 1 | l;
21521cb0ef41Sopenharmony_ci
21531cb0ef41Sopenharmony_ci      if (imm3H_L != 0 && opc == 0) {
21541cb0ef41Sopenharmony_ci        // vshr.s<size> Qd, Qm, shift
21551cb0ef41Sopenharmony_ci        int imm7 = (l << 6) | instr->Bits(21, 16);
21561cb0ef41Sopenharmony_ci        int size = base::bits::RoundDownToPowerOfTwo32(imm7);
21571cb0ef41Sopenharmony_ci        int shift = 2 * size - imm7;
21581cb0ef41Sopenharmony_ci        if (q) {
21591cb0ef41Sopenharmony_ci          int Vd = instr->VFPDRegValue(kSimd128Precision);
21601cb0ef41Sopenharmony_ci          int Vm = instr->VFPMRegValue(kSimd128Precision);
21611cb0ef41Sopenharmony_ci          out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
21621cb0ef41Sopenharmony_ci                                            "vshr.%s%d q%d, q%d, #%d",
21631cb0ef41Sopenharmony_ci                                            u ? "u" : "s", size, Vd, Vm, shift);
21641cb0ef41Sopenharmony_ci        } else {
21651cb0ef41Sopenharmony_ci          int Vd = instr->VFPDRegValue(kDoublePrecision);
21661cb0ef41Sopenharmony_ci          int Vm = instr->VFPMRegValue(kDoublePrecision);
21671cb0ef41Sopenharmony_ci          out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
21681cb0ef41Sopenharmony_ci                                            "vshr.%s%d d%d, d%d, #%d",
21691cb0ef41Sopenharmony_ci                                            u ? "u" : "s", size, Vd, Vm, shift);
21701cb0ef41Sopenharmony_ci        }
21711cb0ef41Sopenharmony_ci      } else if (imm3H_L != 0 && opc == 1) {
21721cb0ef41Sopenharmony_ci        // vsra.<type><size> Qd, Qm, shift
21731cb0ef41Sopenharmony_ci        // vsra.<type><size> Dd, Dm, shift
21741cb0ef41Sopenharmony_ci        int imm7 = (l << 6) | instr->Bits(21, 16);
21751cb0ef41Sopenharmony_ci        int size = base::bits::RoundDownToPowerOfTwo32(imm7);
21761cb0ef41Sopenharmony_ci        int shift = 2 * size - imm7;
21771cb0ef41Sopenharmony_ci        if (q) {
21781cb0ef41Sopenharmony_ci          int Vd = instr->VFPDRegValue(kSimd128Precision);
21791cb0ef41Sopenharmony_ci          int Vm = instr->VFPMRegValue(kSimd128Precision);
21801cb0ef41Sopenharmony_ci          out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
21811cb0ef41Sopenharmony_ci                                            "vsra.%s%d q%d, q%d, #%d",
21821cb0ef41Sopenharmony_ci                                            u ? "u" : "s", size, Vd, Vm, shift);
21831cb0ef41Sopenharmony_ci        } else {
21841cb0ef41Sopenharmony_ci          int Vd = instr->VFPDRegValue(kDoublePrecision);
21851cb0ef41Sopenharmony_ci          int Vm = instr->VFPMRegValue(kDoublePrecision);
21861cb0ef41Sopenharmony_ci          out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
21871cb0ef41Sopenharmony_ci                                            "vsra.%s%d d%d, d%d, #%d",
21881cb0ef41Sopenharmony_ci                                            u ? "u" : "s", size, Vd, Vm, shift);
21891cb0ef41Sopenharmony_ci        }
21901cb0ef41Sopenharmony_ci      } else if (imm3H_L != 0 && imm3L == 0 && opc == 0b1010 && !q) {
21911cb0ef41Sopenharmony_ci        // vmovl
21921cb0ef41Sopenharmony_ci        if ((instr->VdValue() & 1) != 0) Unknown(instr);
21931cb0ef41Sopenharmony_ci        int Vd = instr->VFPDRegValue(kSimd128Precision);
21941cb0ef41Sopenharmony_ci        int Vm = instr->VFPMRegValue(kDoublePrecision);
21951cb0ef41Sopenharmony_ci        int imm3H = instr->Bits(21, 19);
21961cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
21971cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_, "vmovl.%s%d q%d, d%d",
21981cb0ef41Sopenharmony_ci                           u ? "u" : "s", imm3H * 8, Vd, Vm);
21991cb0ef41Sopenharmony_ci      } else if (!u && imm3H_L != 0 && opc == 0b0101) {
22001cb0ef41Sopenharmony_ci        // vshl.i<size> Qd, Qm, shift
22011cb0ef41Sopenharmony_ci        int imm7 = (l << 6) | instr->Bits(21, 16);
22021cb0ef41Sopenharmony_ci        int size = base::bits::RoundDownToPowerOfTwo32(imm7);
22031cb0ef41Sopenharmony_ci        int shift = imm7 - size;
22041cb0ef41Sopenharmony_ci        int Vd = instr->VFPDRegValue(kSimd128Precision);
22051cb0ef41Sopenharmony_ci        int Vm = instr->VFPMRegValue(kSimd128Precision);
22061cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
22071cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_,
22081cb0ef41Sopenharmony_ci                           "vshl.i%d q%d, q%d, #%d", size, Vd, Vm, shift);
22091cb0ef41Sopenharmony_ci      } else if (u && imm3H_L != 0 && (opc & 0b1110) == 0b0100) {
22101cb0ef41Sopenharmony_ci        // vsli.<size> Dd, Dm, shift
22111cb0ef41Sopenharmony_ci        // vsri.<size> Dd, Dm, shift
22121cb0ef41Sopenharmony_ci        int imm7 = (l << 6) | instr->Bits(21, 16);
22131cb0ef41Sopenharmony_ci        int size = base::bits::RoundDownToPowerOfTwo32(imm7);
22141cb0ef41Sopenharmony_ci        int shift;
22151cb0ef41Sopenharmony_ci        char direction;
22161cb0ef41Sopenharmony_ci        if (instr->Bit(8) == 1) {
22171cb0ef41Sopenharmony_ci          shift = imm7 - size;
22181cb0ef41Sopenharmony_ci          direction = 'l';  // vsli
22191cb0ef41Sopenharmony_ci        } else {
22201cb0ef41Sopenharmony_ci          shift = 2 * size - imm7;
22211cb0ef41Sopenharmony_ci          direction = 'r';  // vsri
22221cb0ef41Sopenharmony_ci        }
22231cb0ef41Sopenharmony_ci        int Vd = instr->VFPDRegValue(kDoublePrecision);
22241cb0ef41Sopenharmony_ci        int Vm = instr->VFPMRegValue(kDoublePrecision);
22251cb0ef41Sopenharmony_ci        out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
22261cb0ef41Sopenharmony_ci                                          "vs%ci.%d d%d, d%d, #%d", direction,
22271cb0ef41Sopenharmony_ci                                          size, Vd, Vm, shift);
22281cb0ef41Sopenharmony_ci      }
22291cb0ef41Sopenharmony_ci    }
22301cb0ef41Sopenharmony_ci  } else {
22311cb0ef41Sopenharmony_ci    Unknown(instr);
22321cb0ef41Sopenharmony_ci  }
22331cb0ef41Sopenharmony_ci}
22341cb0ef41Sopenharmony_ci
22351cb0ef41Sopenharmony_civoid Decoder::DecodeAdvancedSIMDTwoOrThreeRegisters(Instruction* instr) {
22361cb0ef41Sopenharmony_ci  // Advanced SIMD two registers, or three registers of different lengths.
22371cb0ef41Sopenharmony_ci  int op0 = instr->Bit(24);
22381cb0ef41Sopenharmony_ci  int op1 = instr->Bits(21, 20);
22391cb0ef41Sopenharmony_ci  int op2 = instr->Bits(11, 10);
22401cb0ef41Sopenharmony_ci  int op3 = instr->Bit(6);
22411cb0ef41Sopenharmony_ci  if (!op0 && op1 == 0b11) {
22421cb0ef41Sopenharmony_ci    // vext.8 Qd, Qm, Qn, imm4
22431cb0ef41Sopenharmony_ci    int imm4 = instr->Bits(11, 8);
22441cb0ef41Sopenharmony_ci    int Vd = instr->VFPDRegValue(kSimd128Precision);
22451cb0ef41Sopenharmony_ci    int Vm = instr->VFPMRegValue(kSimd128Precision);
22461cb0ef41Sopenharmony_ci    int Vn = instr->VFPNRegValue(kSimd128Precision);
22471cb0ef41Sopenharmony_ci    out_buffer_pos_ +=
22481cb0ef41Sopenharmony_ci        base::SNPrintF(out_buffer_ + out_buffer_pos_,
22491cb0ef41Sopenharmony_ci                       "vext.8 q%d, q%d, q%d, #%d", Vd, Vn, Vm, imm4);
22501cb0ef41Sopenharmony_ci  } else if (op0 && op1 == 0b11 && ((op2 >> 1) == 0)) {
22511cb0ef41Sopenharmony_ci    // Advanced SIMD two registers misc
22521cb0ef41Sopenharmony_ci    int size = instr->Bits(19, 18);
22531cb0ef41Sopenharmony_ci    int opc1 = instr->Bits(17, 16);
22541cb0ef41Sopenharmony_ci    int opc2 = instr->Bits(10, 7);
22551cb0ef41Sopenharmony_ci    int q = instr->Bit(6);
22561cb0ef41Sopenharmony_ci    int Vd = instr->VFPDRegValue(q ? kSimd128Precision : kDoublePrecision);
22571cb0ef41Sopenharmony_ci    int Vm = instr->VFPMRegValue(q ? kSimd128Precision : kDoublePrecision);
22581cb0ef41Sopenharmony_ci
22591cb0ef41Sopenharmony_ci    int esize = kBitsPerByte * (1 << size);
22601cb0ef41Sopenharmony_ci    if (opc1 == 0 && (opc2 >> 2) == 0) {
22611cb0ef41Sopenharmony_ci      int op = kBitsPerByte << (static_cast<int>(Neon64) - instr->Bits(8, 7));
22621cb0ef41Sopenharmony_ci      // vrev<op>.<esize> Qd, Qm.
22631cb0ef41Sopenharmony_ci      out_buffer_pos_ +=
22641cb0ef41Sopenharmony_ci          base::SNPrintF(out_buffer_ + out_buffer_pos_, "vrev%d.%d q%d, q%d",
22651cb0ef41Sopenharmony_ci                         op, esize, Vd, Vm);
22661cb0ef41Sopenharmony_ci    } else if (opc1 == 0 && opc2 == 0b1100) {
22671cb0ef41Sopenharmony_ci      Format(instr, q ? "vpadal.s'size2 'Qd, 'Qm" : "vpadal.s'size2 'Dd, 'Dm");
22681cb0ef41Sopenharmony_ci    } else if (opc1 == 0 && opc2 == 0b1101) {
22691cb0ef41Sopenharmony_ci      Format(instr, q ? "vpadal.u'size2 'Qd, 'Qm" : "vpadal.u'size2 'Dd, 'Dm");
22701cb0ef41Sopenharmony_ci    } else if (opc1 == 0 && opc2 == 0b0100) {
22711cb0ef41Sopenharmony_ci      Format(instr, q ? "vpaddl.s'size2 'Qd, 'Qm" : "vpaddl.s'size2 'Dd, 'Dm");
22721cb0ef41Sopenharmony_ci    } else if (opc1 == 0 && opc2 == 0b0101) {
22731cb0ef41Sopenharmony_ci      Format(instr, q ? "vpaddl.u'size2 'Qd, 'Qm" : "vpaddl.u'size2 'Dd, 'Dm");
22741cb0ef41Sopenharmony_ci    } else if (size == 0 && opc1 == 0b10 && opc2 == 0) {
22751cb0ef41Sopenharmony_ci      Format(instr, q ? "vswp 'Qd, 'Qm" : "vswp 'Dd, 'Dm");
22761cb0ef41Sopenharmony_ci    } else if (opc1 == 0 && opc2 == 0b1010) {
22771cb0ef41Sopenharmony_ci      DCHECK_EQ(0, size);
22781cb0ef41Sopenharmony_ci      Format(instr, q ? "vcnt.8 'Qd, 'Qm" : "vcnt.8 'Dd, 'Dm");
22791cb0ef41Sopenharmony_ci    } else if (opc1 == 0 && opc2 == 0b1011) {
22801cb0ef41Sopenharmony_ci      Format(instr, "vmvn 'Qd, 'Qm");
22811cb0ef41Sopenharmony_ci    } else if (opc1 == 0b01 && opc2 == 0b0010) {
22821cb0ef41Sopenharmony_ci      DCHECK_NE(0b11, size);
22831cb0ef41Sopenharmony_ci      Format(instr,
22841cb0ef41Sopenharmony_ci             q ? "vceq.s'size2 'Qd, 'Qm, #0" : "vceq.s.'size2 'Dd, 'Dm, #0");
22851cb0ef41Sopenharmony_ci    } else if (opc1 == 0b01 && opc2 == 0b0100) {
22861cb0ef41Sopenharmony_ci      DCHECK_NE(0b11, size);
22871cb0ef41Sopenharmony_ci      Format(instr,
22881cb0ef41Sopenharmony_ci             q ? "vclt.s'size2 'Qd, 'Qm, #0" : "vclt.s.'size2 'Dd, 'Dm, #0");
22891cb0ef41Sopenharmony_ci    } else if (opc1 == 0b01 && opc2 == 0b0110) {
22901cb0ef41Sopenharmony_ci      Format(instr, q ? "vabs.s'size2 'Qd, 'Qm" : "vabs.s.'size2 'Dd, 'Dm");
22911cb0ef41Sopenharmony_ci    } else if (opc1 == 0b01 && opc2 == 0b1110) {
22921cb0ef41Sopenharmony_ci      Format(instr, q ? "vabs.f'size2 'Qd, 'Qm" : "vabs.f.'size2 'Dd, 'Dm");
22931cb0ef41Sopenharmony_ci    } else if (opc1 == 0b01 && opc2 == 0b0111) {
22941cb0ef41Sopenharmony_ci      Format(instr, q ? "vneg.s'size2 'Qd, 'Qm" : "vneg.s.'size2 'Dd, 'Dm");
22951cb0ef41Sopenharmony_ci    } else if (opc1 == 0b01 && opc2 == 0b1111) {
22961cb0ef41Sopenharmony_ci      Format(instr, q ? "vneg.f'size2 'Qd, 'Qm" : "vneg.f.'size2 'Dd, 'Dm");
22971cb0ef41Sopenharmony_ci    } else if (opc1 == 0b10 && opc2 == 0b0001) {
22981cb0ef41Sopenharmony_ci      Format(instr, q ? "vtrn.'size2 'Qd, 'Qm" : "vtrn.'size2 'Dd, 'Dm");
22991cb0ef41Sopenharmony_ci    } else if (opc1 == 0b10 && opc2 == 0b0010) {
23001cb0ef41Sopenharmony_ci      Format(instr, q ? "vuzp.'size2 'Qd, 'Qm" : "vuzp.'size2 'Dd, 'Dm");
23011cb0ef41Sopenharmony_ci    } else if (opc1 == 0b10 && opc2 == 0b0011) {
23021cb0ef41Sopenharmony_ci      Format(instr, q ? "vzip.'size2 'Qd, 'Qm" : "vzip.'size2 'Dd, 'Dm");
23031cb0ef41Sopenharmony_ci    } else if (opc1 == 0b10 && (opc2 & 0b1110) == 0b0100) {
23041cb0ef41Sopenharmony_ci      // vqmov{u}n.<type><esize> Dd, Qm.
23051cb0ef41Sopenharmony_ci      int Vd = instr->VFPDRegValue(kDoublePrecision);
23061cb0ef41Sopenharmony_ci      int Vm = instr->VFPMRegValue(kSimd128Precision);
23071cb0ef41Sopenharmony_ci      int op = instr->Bits(7, 6);
23081cb0ef41Sopenharmony_ci      const char* name = op == 0b01 ? "vqmovun" : "vqmovn";
23091cb0ef41Sopenharmony_ci      char type = op == 0b11 ? 'u' : 's';
23101cb0ef41Sopenharmony_ci      out_buffer_pos_ +=
23111cb0ef41Sopenharmony_ci          base::SNPrintF(out_buffer_ + out_buffer_pos_, "%s.%c%i d%d, q%d",
23121cb0ef41Sopenharmony_ci                         name, type, esize << 1, Vd, Vm);
23131cb0ef41Sopenharmony_ci    } else if (opc1 == 0b10 && opc2 == 0b1000) {
23141cb0ef41Sopenharmony_ci      Format(instr, q ? "vrintn.f32 'Qd, 'Qm" : "vrintn.f32 'Dd, 'Dm");
23151cb0ef41Sopenharmony_ci    } else if (opc1 == 0b10 && opc2 == 0b1011) {
23161cb0ef41Sopenharmony_ci      Format(instr, q ? "vrintz.f32 'Qd, 'Qm" : "vrintz.f32 'Dd, 'Dm");
23171cb0ef41Sopenharmony_ci    } else if (opc1 == 0b10 && opc2 == 0b1101) {
23181cb0ef41Sopenharmony_ci      Format(instr, q ? "vrintm.f32 'Qd, 'Qm" : "vrintm.f32 'Qd, 'Qm");
23191cb0ef41Sopenharmony_ci    } else if (opc1 == 0b10 && opc2 == 0b1111) {
23201cb0ef41Sopenharmony_ci      Format(instr, q ? "vrintp.f32 'Qd, 'Qm" : "vrintp.f32 'Qd, 'Qm");
23211cb0ef41Sopenharmony_ci    } else if (opc1 == 0b11 && (opc2 & 0b1101) == 0b1000) {
23221cb0ef41Sopenharmony_ci      Format(instr, "vrecpe.f32 'Qd, 'Qm");
23231cb0ef41Sopenharmony_ci    } else if (opc1 == 0b11 && (opc2 & 0b1101) == 0b1001) {
23241cb0ef41Sopenharmony_ci      Format(instr, "vrsqrte.f32 'Qd, 'Qm");
23251cb0ef41Sopenharmony_ci    } else if (opc1 == 0b11 && (opc2 & 0b1100) == 0b1100) {
23261cb0ef41Sopenharmony_ci      const char* suffix = nullptr;
23271cb0ef41Sopenharmony_ci      int op = instr->Bits(8, 7);
23281cb0ef41Sopenharmony_ci      switch (op) {
23291cb0ef41Sopenharmony_ci        case 0:
23301cb0ef41Sopenharmony_ci          suffix = "f32.s32";
23311cb0ef41Sopenharmony_ci          break;
23321cb0ef41Sopenharmony_ci        case 1:
23331cb0ef41Sopenharmony_ci          suffix = "f32.u32";
23341cb0ef41Sopenharmony_ci          break;
23351cb0ef41Sopenharmony_ci        case 2:
23361cb0ef41Sopenharmony_ci          suffix = "s32.f32";
23371cb0ef41Sopenharmony_ci          break;
23381cb0ef41Sopenharmony_ci        case 3:
23391cb0ef41Sopenharmony_ci          suffix = "u32.f32";
23401cb0ef41Sopenharmony_ci          break;
23411cb0ef41Sopenharmony_ci      }
23421cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
23431cb0ef41Sopenharmony_ci                                        "vcvt.%s q%d, q%d", suffix, Vd, Vm);
23441cb0ef41Sopenharmony_ci    }
23451cb0ef41Sopenharmony_ci  } else if (op0 && op1 == 0b11 && op2 == 0b10) {
23461cb0ef41Sopenharmony_ci    // VTBL, VTBX
23471cb0ef41Sopenharmony_ci    int Vd = instr->VFPDRegValue(kDoublePrecision);
23481cb0ef41Sopenharmony_ci    int Vn = instr->VFPNRegValue(kDoublePrecision);
23491cb0ef41Sopenharmony_ci    int Vm = instr->VFPMRegValue(kDoublePrecision);
23501cb0ef41Sopenharmony_ci    int len = instr->Bits(9, 8);
23511cb0ef41Sopenharmony_ci    NeonListOperand list(DwVfpRegister::from_code(Vn), len + 1);
23521cb0ef41Sopenharmony_ci    out_buffer_pos_ +=
23531cb0ef41Sopenharmony_ci        base::SNPrintF(out_buffer_ + out_buffer_pos_, "%s d%d, ",
23541cb0ef41Sopenharmony_ci                       instr->Bit(6) == 0 ? "vtbl.8" : "vtbx.8", Vd);
23551cb0ef41Sopenharmony_ci    FormatNeonList(Vn, list.type());
23561cb0ef41Sopenharmony_ci    Print(", ");
23571cb0ef41Sopenharmony_ci    PrintDRegister(Vm);
23581cb0ef41Sopenharmony_ci  } else if (op0 && op1 == 0b11 && op2 == 0b11) {
23591cb0ef41Sopenharmony_ci    // Advanced SIMD duplicate (scalar)
23601cb0ef41Sopenharmony_ci    if (instr->Bits(9, 7) == 0) {
23611cb0ef41Sopenharmony_ci      // VDUP (scalar)
23621cb0ef41Sopenharmony_ci      int Vm = instr->VFPMRegValue(kDoublePrecision);
23631cb0ef41Sopenharmony_ci      int imm4 = instr->Bits(19, 16);
23641cb0ef41Sopenharmony_ci      int esize = 0, index = 0;
23651cb0ef41Sopenharmony_ci      if ((imm4 & 0x1) != 0) {
23661cb0ef41Sopenharmony_ci        esize = 8;
23671cb0ef41Sopenharmony_ci        index = imm4 >> 1;
23681cb0ef41Sopenharmony_ci      } else if ((imm4 & 0x2) != 0) {
23691cb0ef41Sopenharmony_ci        esize = 16;
23701cb0ef41Sopenharmony_ci        index = imm4 >> 2;
23711cb0ef41Sopenharmony_ci      } else {
23721cb0ef41Sopenharmony_ci        esize = 32;
23731cb0ef41Sopenharmony_ci        index = imm4 >> 3;
23741cb0ef41Sopenharmony_ci      }
23751cb0ef41Sopenharmony_ci      if (instr->Bit(6) == 0) {
23761cb0ef41Sopenharmony_ci        int Vd = instr->VFPDRegValue(kDoublePrecision);
23771cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
23781cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_,
23791cb0ef41Sopenharmony_ci                           "vdup.%i d%d, d%d[%d]", esize, Vd, Vm, index);
23801cb0ef41Sopenharmony_ci      } else {
23811cb0ef41Sopenharmony_ci        int Vd = instr->VFPDRegValue(kSimd128Precision);
23821cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
23831cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_,
23841cb0ef41Sopenharmony_ci                           "vdup.%i q%d, d%d[%d]", esize, Vd, Vm, index);
23851cb0ef41Sopenharmony_ci      }
23861cb0ef41Sopenharmony_ci    } else {
23871cb0ef41Sopenharmony_ci      Unknown(instr);
23881cb0ef41Sopenharmony_ci    }
23891cb0ef41Sopenharmony_ci  } else if (op1 != 0b11 && !op3) {
23901cb0ef41Sopenharmony_ci    // Advanced SIMD three registers of different lengths.
23911cb0ef41Sopenharmony_ci    int u = instr->Bit(24);
23921cb0ef41Sopenharmony_ci    int opc = instr->Bits(11, 8);
23931cb0ef41Sopenharmony_ci    if (opc == 0b1000) {
23941cb0ef41Sopenharmony_ci      Format(instr,
23951cb0ef41Sopenharmony_ci             u ? "vmlal.u'size3 'Qd, 'Dn, 'Dm" : "vmlal.s'size3 'Qd, 'Dn, 'Dm");
23961cb0ef41Sopenharmony_ci    } else if (opc == 0b1100) {
23971cb0ef41Sopenharmony_ci      Format(instr,
23981cb0ef41Sopenharmony_ci             u ? "vmull.u'size3 'Qd, 'Dn, 'Dm" : "vmull.s'size3 'Qd, 'Dn, 'Dm");
23991cb0ef41Sopenharmony_ci    }
24001cb0ef41Sopenharmony_ci  } else if (op1 != 0b11 && op3) {
24011cb0ef41Sopenharmony_ci    // The instructions specified by this encoding are not used in V8.
24021cb0ef41Sopenharmony_ci    Unknown(instr);
24031cb0ef41Sopenharmony_ci  } else {
24041cb0ef41Sopenharmony_ci    Unknown(instr);
24051cb0ef41Sopenharmony_ci  }
24061cb0ef41Sopenharmony_ci}
24071cb0ef41Sopenharmony_ci
24081cb0ef41Sopenharmony_civoid Decoder::DecodeMemoryHintsAndBarriers(Instruction* instr) {
24091cb0ef41Sopenharmony_ci  int op0 = instr->Bits(25, 21);
24101cb0ef41Sopenharmony_ci  if (op0 == 0b01011) {
24111cb0ef41Sopenharmony_ci    // Barriers.
24121cb0ef41Sopenharmony_ci    int option = instr->Bits(3, 0);
24131cb0ef41Sopenharmony_ci    switch (instr->Bits(7, 4)) {
24141cb0ef41Sopenharmony_ci      case 4:
24151cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
24161cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_, "dsb %s",
24171cb0ef41Sopenharmony_ci                           barrier_option_names[option]);
24181cb0ef41Sopenharmony_ci        break;
24191cb0ef41Sopenharmony_ci      case 5:
24201cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
24211cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_, "dmb %s",
24221cb0ef41Sopenharmony_ci                           barrier_option_names[option]);
24231cb0ef41Sopenharmony_ci        break;
24241cb0ef41Sopenharmony_ci      case 6:
24251cb0ef41Sopenharmony_ci        out_buffer_pos_ +=
24261cb0ef41Sopenharmony_ci            base::SNPrintF(out_buffer_ + out_buffer_pos_, "isb %s",
24271cb0ef41Sopenharmony_ci                           barrier_option_names[option]);
24281cb0ef41Sopenharmony_ci        break;
24291cb0ef41Sopenharmony_ci      default:
24301cb0ef41Sopenharmony_ci        Unknown(instr);
24311cb0ef41Sopenharmony_ci    }
24321cb0ef41Sopenharmony_ci  } else if ((op0 & 0b10001) == 0b00000 && !instr->Bit(4)) {
24331cb0ef41Sopenharmony_ci    // Preload (immediate).
24341cb0ef41Sopenharmony_ci    const char* rn_name = converter_.NameOfCPURegister(instr->Bits(19, 16));
24351cb0ef41Sopenharmony_ci    int offset = instr->Bits(11, 0);
24361cb0ef41Sopenharmony_ci    if (offset == 0) {
24371cb0ef41Sopenharmony_ci      out_buffer_pos_ +=
24381cb0ef41Sopenharmony_ci          base::SNPrintF(out_buffer_ + out_buffer_pos_, "pld [%s]", rn_name);
24391cb0ef41Sopenharmony_ci    } else if (instr->Bit(23) == 0) {
24401cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
24411cb0ef41Sopenharmony_ci                                        "pld [%s, #-%d]", rn_name, offset);
24421cb0ef41Sopenharmony_ci    } else {
24431cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
24441cb0ef41Sopenharmony_ci                                        "pld [%s, #+%d]", rn_name, offset);
24451cb0ef41Sopenharmony_ci    }
24461cb0ef41Sopenharmony_ci  } else {
24471cb0ef41Sopenharmony_ci    Unknown(instr);
24481cb0ef41Sopenharmony_ci  }
24491cb0ef41Sopenharmony_ci}
24501cb0ef41Sopenharmony_ci
24511cb0ef41Sopenharmony_civoid Decoder::DecodeAdvancedSIMDElementOrStructureLoadStore(
24521cb0ef41Sopenharmony_ci    Instruction* instr) {
24531cb0ef41Sopenharmony_ci  int op0 = instr->Bit(23);
24541cb0ef41Sopenharmony_ci  int op1 = instr->Bits(11, 10);
24551cb0ef41Sopenharmony_ci  int l = instr->Bit(21);
24561cb0ef41Sopenharmony_ci  int n = instr->Bits(9, 8);
24571cb0ef41Sopenharmony_ci  int Vd = instr->VFPDRegValue(kDoublePrecision);
24581cb0ef41Sopenharmony_ci  int Rn = instr->VnValue();
24591cb0ef41Sopenharmony_ci  int Rm = instr->VmValue();
24601cb0ef41Sopenharmony_ci
24611cb0ef41Sopenharmony_ci  if (op0 == 0) {
24621cb0ef41Sopenharmony_ci    // Advanced SIMD load/store multiple structures.
24631cb0ef41Sopenharmony_ci    int itype = instr->Bits(11, 8);
24641cb0ef41Sopenharmony_ci    if (itype == nlt_1 || itype == nlt_2 || itype == nlt_3 || itype == nlt_4) {
24651cb0ef41Sopenharmony_ci      // vld1/vst1
24661cb0ef41Sopenharmony_ci      int size = instr->Bits(7, 6);
24671cb0ef41Sopenharmony_ci      int align = instr->Bits(5, 4);
24681cb0ef41Sopenharmony_ci      const char* op = l ? "vld1.%d " : "vst1.%d ";
24691cb0ef41Sopenharmony_ci      out_buffer_pos_ +=
24701cb0ef41Sopenharmony_ci          base::SNPrintF(out_buffer_ + out_buffer_pos_, op, (1 << size) << 3);
24711cb0ef41Sopenharmony_ci      FormatNeonList(Vd, itype);
24721cb0ef41Sopenharmony_ci      Print(", ");
24731cb0ef41Sopenharmony_ci      FormatNeonMemory(Rn, align, Rm);
24741cb0ef41Sopenharmony_ci    } else {
24751cb0ef41Sopenharmony_ci      Unknown(instr);
24761cb0ef41Sopenharmony_ci    }
24771cb0ef41Sopenharmony_ci  } else if (op1 == 0b11) {
24781cb0ef41Sopenharmony_ci    // Advanced SIMD load single structure to all lanes.
24791cb0ef41Sopenharmony_ci    if (l && n == 0b00) {
24801cb0ef41Sopenharmony_ci      // vld1r(replicate) single element to all lanes.
24811cb0ef41Sopenharmony_ci      int size = instr->Bits(7, 6);
24821cb0ef41Sopenharmony_ci      DCHECK_NE(0b11, size);
24831cb0ef41Sopenharmony_ci      int type = instr->Bit(5) ? nlt_2 : nlt_1;
24841cb0ef41Sopenharmony_ci      out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
24851cb0ef41Sopenharmony_ci                                        "vld1.%d ", (1 << size) << 3);
24861cb0ef41Sopenharmony_ci      FormatNeonList(Vd, type);
24871cb0ef41Sopenharmony_ci      DCHECK_EQ(0, instr->Bit(4));  // Alignment not supported.
24881cb0ef41Sopenharmony_ci      Print(", ");
24891cb0ef41Sopenharmony_ci      FormatNeonMemory(Rn, 0, Rm);
24901cb0ef41Sopenharmony_ci    } else {
24911cb0ef41Sopenharmony_ci      Unknown(instr);
24921cb0ef41Sopenharmony_ci    }
24931cb0ef41Sopenharmony_ci  } else if (op1 != 0b11) {
24941cb0ef41Sopenharmony_ci    // Advanced SIMD load/store single structure to one lane.
24951cb0ef41Sopenharmony_ci    int size = op1;  // size and op1 occupy the same bits in decoding.
24961cb0ef41Sopenharmony_ci    int index_align = instr->Bits(7, 4);
24971cb0ef41Sopenharmony_ci    int index = index_align >> (size + 1);
24981cb0ef41Sopenharmony_ci    if (n == 0b00) {
24991cb0ef41Sopenharmony_ci      // vld1 (single element to one lane) - A1, A2, A3.
25001cb0ef41Sopenharmony_ci      // vst1 (single element to one lane) - A1, A2, A3.
25011cb0ef41Sopenharmony_ci      // Omit alignment.
25021cb0ef41Sopenharmony_ci      out_buffer_pos_ +=
25031cb0ef41Sopenharmony_ci          base::SNPrintF(out_buffer_ + out_buffer_pos_, "v%s1.%d {d%d[%d]}",
25041cb0ef41Sopenharmony_ci                         (l ? "ld" : "st"), (1 << size) << 3, Vd, index);
25051cb0ef41Sopenharmony_ci      Print(", ");
25061cb0ef41Sopenharmony_ci      FormatNeonMemory(Rn, 0, Rm);
25071cb0ef41Sopenharmony_ci    } else {
25081cb0ef41Sopenharmony_ci      Unknown(instr);
25091cb0ef41Sopenharmony_ci    }
25101cb0ef41Sopenharmony_ci  } else {
25111cb0ef41Sopenharmony_ci    Unknown(instr);
25121cb0ef41Sopenharmony_ci  }
25131cb0ef41Sopenharmony_ci}
25141cb0ef41Sopenharmony_ci
25151cb0ef41Sopenharmony_ci#undef VERIFY
25161cb0ef41Sopenharmony_ci
25171cb0ef41Sopenharmony_cibool Decoder::IsConstantPoolAt(byte* instr_ptr) {
25181cb0ef41Sopenharmony_ci  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
25191cb0ef41Sopenharmony_ci  return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
25201cb0ef41Sopenharmony_ci}
25211cb0ef41Sopenharmony_ci
25221cb0ef41Sopenharmony_ciint Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
25231cb0ef41Sopenharmony_ci  if (IsConstantPoolAt(instr_ptr)) {
25241cb0ef41Sopenharmony_ci    int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
25251cb0ef41Sopenharmony_ci    return DecodeConstantPoolLength(instruction_bits);
25261cb0ef41Sopenharmony_ci  } else {
25271cb0ef41Sopenharmony_ci    return -1;
25281cb0ef41Sopenharmony_ci  }
25291cb0ef41Sopenharmony_ci}
25301cb0ef41Sopenharmony_ci
25311cb0ef41Sopenharmony_ci// Disassemble the instruction at *instr_ptr into the output buffer.
25321cb0ef41Sopenharmony_ciint Decoder::InstructionDecode(byte* instr_ptr) {
25331cb0ef41Sopenharmony_ci  Instruction* instr = Instruction::At(reinterpret_cast<Address>(instr_ptr));
25341cb0ef41Sopenharmony_ci  // Print raw instruction bytes.
25351cb0ef41Sopenharmony_ci  out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
25361cb0ef41Sopenharmony_ci                                    "%08x       ", instr->InstructionBits());
25371cb0ef41Sopenharmony_ci  if (instr->ConditionField() == kSpecialCondition) {
25381cb0ef41Sopenharmony_ci    DecodeSpecialCondition(instr);
25391cb0ef41Sopenharmony_ci    return kInstrSize;
25401cb0ef41Sopenharmony_ci  }
25411cb0ef41Sopenharmony_ci  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
25421cb0ef41Sopenharmony_ci  if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
25431cb0ef41Sopenharmony_ci    out_buffer_pos_ += base::SNPrintF(
25441cb0ef41Sopenharmony_ci        out_buffer_ + out_buffer_pos_, "constant pool begin (length %d)",
25451cb0ef41Sopenharmony_ci        DecodeConstantPoolLength(instruction_bits));
25461cb0ef41Sopenharmony_ci    return kInstrSize;
25471cb0ef41Sopenharmony_ci  }
25481cb0ef41Sopenharmony_ci  switch (instr->TypeValue()) {
25491cb0ef41Sopenharmony_ci    case 0:
25501cb0ef41Sopenharmony_ci    case 1: {
25511cb0ef41Sopenharmony_ci      DecodeType01(instr);
25521cb0ef41Sopenharmony_ci      break;
25531cb0ef41Sopenharmony_ci    }
25541cb0ef41Sopenharmony_ci    case 2: {
25551cb0ef41Sopenharmony_ci      DecodeType2(instr);
25561cb0ef41Sopenharmony_ci      break;
25571cb0ef41Sopenharmony_ci    }
25581cb0ef41Sopenharmony_ci    case 3: {
25591cb0ef41Sopenharmony_ci      DecodeType3(instr);
25601cb0ef41Sopenharmony_ci      break;
25611cb0ef41Sopenharmony_ci    }
25621cb0ef41Sopenharmony_ci    case 4: {
25631cb0ef41Sopenharmony_ci      DecodeType4(instr);
25641cb0ef41Sopenharmony_ci      break;
25651cb0ef41Sopenharmony_ci    }
25661cb0ef41Sopenharmony_ci    case 5: {
25671cb0ef41Sopenharmony_ci      DecodeType5(instr);
25681cb0ef41Sopenharmony_ci      break;
25691cb0ef41Sopenharmony_ci    }
25701cb0ef41Sopenharmony_ci    case 6: {
25711cb0ef41Sopenharmony_ci      DecodeType6(instr);
25721cb0ef41Sopenharmony_ci      break;
25731cb0ef41Sopenharmony_ci    }
25741cb0ef41Sopenharmony_ci    case 7: {
25751cb0ef41Sopenharmony_ci      return DecodeType7(instr);
25761cb0ef41Sopenharmony_ci    }
25771cb0ef41Sopenharmony_ci    default: {
25781cb0ef41Sopenharmony_ci      // The type field is 3-bits in the ARM encoding.
25791cb0ef41Sopenharmony_ci      UNREACHABLE();
25801cb0ef41Sopenharmony_ci    }
25811cb0ef41Sopenharmony_ci  }
25821cb0ef41Sopenharmony_ci  return kInstrSize;
25831cb0ef41Sopenharmony_ci}
25841cb0ef41Sopenharmony_ci
25851cb0ef41Sopenharmony_ci}  // namespace internal
25861cb0ef41Sopenharmony_ci}  // namespace v8
25871cb0ef41Sopenharmony_ci
25881cb0ef41Sopenharmony_ci//------------------------------------------------------------------------------
25891cb0ef41Sopenharmony_ci
25901cb0ef41Sopenharmony_cinamespace disasm {
25911cb0ef41Sopenharmony_ci
25921cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfAddress(byte* addr) const {
25931cb0ef41Sopenharmony_ci  v8::base::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
25941cb0ef41Sopenharmony_ci  return tmp_buffer_.begin();
25951cb0ef41Sopenharmony_ci}
25961cb0ef41Sopenharmony_ci
25971cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfConstant(byte* addr) const {
25981cb0ef41Sopenharmony_ci  return NameOfAddress(addr);
25991cb0ef41Sopenharmony_ci}
26001cb0ef41Sopenharmony_ci
26011cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfCPURegister(int reg) const {
26021cb0ef41Sopenharmony_ci  return RegisterName(i::Register::from_code(reg));
26031cb0ef41Sopenharmony_ci}
26041cb0ef41Sopenharmony_ci
26051cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfByteCPURegister(int reg) const {
26061cb0ef41Sopenharmony_ci  UNREACHABLE();  // ARM does not have the concept of a byte register
26071cb0ef41Sopenharmony_ci}
26081cb0ef41Sopenharmony_ci
26091cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfXMMRegister(int reg) const {
26101cb0ef41Sopenharmony_ci  UNREACHABLE();  // ARM does not have any XMM registers
26111cb0ef41Sopenharmony_ci}
26121cb0ef41Sopenharmony_ci
26131cb0ef41Sopenharmony_ciconst char* NameConverter::NameInCode(byte* addr) const {
26141cb0ef41Sopenharmony_ci  // The default name converter is called for unknown code. So we will not try
26151cb0ef41Sopenharmony_ci  // to access any memory.
26161cb0ef41Sopenharmony_ci  return "";
26171cb0ef41Sopenharmony_ci}
26181cb0ef41Sopenharmony_ci
26191cb0ef41Sopenharmony_ci//------------------------------------------------------------------------------
26201cb0ef41Sopenharmony_ci
26211cb0ef41Sopenharmony_ciint Disassembler::InstructionDecode(v8::base::Vector<char> buffer,
26221cb0ef41Sopenharmony_ci                                    byte* instruction) {
26231cb0ef41Sopenharmony_ci  v8::internal::Decoder d(converter_, buffer);
26241cb0ef41Sopenharmony_ci  return d.InstructionDecode(instruction);
26251cb0ef41Sopenharmony_ci}
26261cb0ef41Sopenharmony_ci
26271cb0ef41Sopenharmony_ciint Disassembler::ConstantPoolSizeAt(byte* instruction) {
26281cb0ef41Sopenharmony_ci  return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
26291cb0ef41Sopenharmony_ci}
26301cb0ef41Sopenharmony_ci
26311cb0ef41Sopenharmony_civoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
26321cb0ef41Sopenharmony_ci                               UnimplementedOpcodeAction unimplemented_action) {
26331cb0ef41Sopenharmony_ci  NameConverter converter;
26341cb0ef41Sopenharmony_ci  Disassembler d(converter, unimplemented_action);
26351cb0ef41Sopenharmony_ci  for (byte* pc = begin; pc < end;) {
26361cb0ef41Sopenharmony_ci    v8::base::EmbeddedVector<char, 128> buffer;
26371cb0ef41Sopenharmony_ci    buffer[0] = '\0';
26381cb0ef41Sopenharmony_ci    byte* prev_pc = pc;
26391cb0ef41Sopenharmony_ci    pc += d.InstructionDecode(buffer, pc);
26401cb0ef41Sopenharmony_ci    v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
26411cb0ef41Sopenharmony_ci                         *reinterpret_cast<int32_t*>(prev_pc), buffer.begin());
26421cb0ef41Sopenharmony_ci  }
26431cb0ef41Sopenharmony_ci}
26441cb0ef41Sopenharmony_ci
26451cb0ef41Sopenharmony_ci#undef STRING_STARTS_WITH
26461cb0ef41Sopenharmony_ci
26471cb0ef41Sopenharmony_ci}  // namespace disasm
26481cb0ef41Sopenharmony_ci
26491cb0ef41Sopenharmony_ci#endif  // V8_TARGET_ARCH_ARM
2650