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