diff options
Diffstat (limited to 'chromium/v8/src/diagnostics')
27 files changed, 3335 insertions, 916 deletions
diff --git a/chromium/v8/src/diagnostics/arm/disasm-arm.cc b/chromium/v8/src/diagnostics/arm/disasm-arm.cc index cf37d12a1f9..01b697b4bb4 100644 --- a/chromium/v8/src/diagnostics/arm/disasm-arm.cc +++ b/chromium/v8/src/diagnostics/arm/disasm-arm.cc @@ -676,7 +676,6 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { } default: { UNREACHABLE(); - return -1; } } out_buffer_pos_ += @@ -787,7 +786,6 @@ void Decoder::DecodeType01(Instruction* instr) { break; default: UNREACHABLE(); - break; } } else { // strex @@ -808,7 +806,6 @@ void Decoder::DecodeType01(Instruction* instr) { break; default: UNREACHABLE(); - break; } } } else { @@ -853,7 +850,6 @@ void Decoder::DecodeType01(Instruction* instr) { default: { // The PU field is a 2-bit field. UNREACHABLE(); - break; } } } else { @@ -894,7 +890,6 @@ void Decoder::DecodeType01(Instruction* instr) { default: { // The PU field is a 2-bit field. UNREACHABLE(); - break; } } return; @@ -1030,7 +1025,6 @@ void Decoder::DecodeType01(Instruction* instr) { default: { // The Opcode field is a 4-bit field. UNREACHABLE(); - break; } } } @@ -1107,10 +1101,8 @@ void Decoder::DecodeType3(Instruction* instr) { break; case 1: UNREACHABLE(); - break; case 2: UNREACHABLE(); - break; case 3: Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); break; @@ -1119,7 +1111,6 @@ void Decoder::DecodeType3(Instruction* instr) { switch (instr->Bits(22, 21)) { case 0: UNREACHABLE(); - break; case 1: if (instr->Bits(9, 6) == 1) { if (instr->Bit(20) == 0) { @@ -1948,7 +1939,6 @@ void Decoder::DecodeFloatingPointDataProcessing(Instruction* instr) { break; default: UNREACHABLE(); // Case analysis is exhaustive. - break; } } else if (instr->Opc1Value() == 0x4 && op2) { // Floating-point minNum/maxNum. @@ -2002,7 +1992,6 @@ void Decoder::DecodeFloatingPointDataProcessing(Instruction* instr) { break; default: UNREACHABLE(); // Case analysis is exhaustive. - break; } } else { Unknown(instr); @@ -2037,13 +2026,11 @@ void Decoder::DecodeAdvancedSIMDDataProcessing(Instruction* instr) { int op1 = instr->Bit(4); if (op0 == 0) { // Advanced SIMD three registers of same length. - int Vd, Vm, Vn; + int Vm, Vn; if (instr->Bit(6) == 0) { - Vd = instr->VFPDRegValue(kDoublePrecision); Vm = instr->VFPMRegValue(kDoublePrecision); Vn = instr->VFPNRegValue(kDoublePrecision); } else { - Vd = instr->VFPDRegValue(kSimd128Precision); Vm = instr->VFPMRegValue(kSimd128Precision); Vn = instr->VFPNRegValue(kSimd128Precision); } @@ -2617,12 +2604,10 @@ const char* NameConverter::NameOfCPURegister(int reg) const { const char* NameConverter::NameOfByteCPURegister(int reg) const { UNREACHABLE(); // ARM does not have the concept of a byte register - return "nobytereg"; } const char* NameConverter::NameOfXMMRegister(int reg) const { UNREACHABLE(); // ARM does not have any XMM registers - return "noxmmreg"; } const char* NameConverter::NameInCode(byte* addr) const { diff --git a/chromium/v8/src/diagnostics/arm/eh-frame-arm.cc b/chromium/v8/src/diagnostics/arm/eh-frame-arm.cc index 7d0dc49155a..ef0a421820b 100644 --- a/chromium/v8/src/diagnostics/arm/eh-frame-arm.cc +++ b/chromium/v8/src/diagnostics/arm/eh-frame-arm.cc @@ -37,7 +37,6 @@ int EhFrameWriter::RegisterToDwarfCode(Register name) { return kR0DwarfCode; default: UNIMPLEMENTED(); - return -1; } } @@ -54,7 +53,6 @@ const char* EhFrameDisassembler::DwarfRegisterCodeToString(int code) { return "lr"; default: UNIMPLEMENTED(); - return nullptr; } } diff --git a/chromium/v8/src/diagnostics/arm/unwinder-arm.cc b/chromium/v8/src/diagnostics/arm/unwinder-arm.cc index e0e2f0e91f4..e51804caea1 100644 --- a/chromium/v8/src/diagnostics/arm/unwinder-arm.cc +++ b/chromium/v8/src/diagnostics/arm/unwinder-arm.cc @@ -5,7 +5,7 @@ #include <memory> #include "include/v8-unwinder-state.h" -#include "include/v8.h" +#include "include/v8-unwinder.h" #include "src/diagnostics/unwinder.h" #include "src/execution/frame-constants.h" diff --git a/chromium/v8/src/diagnostics/arm64/disasm-arm64.cc b/chromium/v8/src/diagnostics/arm64/disasm-arm64.cc index 93b9531bd5d..af6e7f5441e 100644 --- a/chromium/v8/src/diagnostics/arm64/disasm-arm64.cc +++ b/chromium/v8/src/diagnostics/arm64/disasm-arm64.cc @@ -3954,7 +3954,6 @@ int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr, } default: { UNIMPLEMENTED(); - return 0; } } } @@ -3997,7 +3996,6 @@ int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr, return 0; } UNIMPLEMENTED(); - return 0; } case 'L': { // IVLSLane[0123] - suffix indicates access size shift. AppendToOutput("%d", instr->NEONLSIndex(format[8] - '0')); @@ -4042,12 +4040,10 @@ int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr, return static_cast<int>(strlen("IVMIShiftAmt2")); } else { UNIMPLEMENTED(); - return 0; } } default: { UNIMPLEMENTED(); - return 0; } } } @@ -4342,12 +4338,10 @@ const char* NameConverter::NameOfCPURegister(int reg) const { const char* NameConverter::NameOfByteCPURegister(int reg) const { UNREACHABLE(); // ARM64 does not have the concept of a byte register - return "nobytereg"; } const char* NameConverter::NameOfXMMRegister(int reg) const { UNREACHABLE(); // ARM64 does not have any XMM registers - return "noxmmreg"; } const char* NameConverter::NameInCode(byte* addr) const { diff --git a/chromium/v8/src/diagnostics/arm64/eh-frame-arm64.cc b/chromium/v8/src/diagnostics/arm64/eh-frame-arm64.cc index 115d0cc300c..d27827cfc12 100644 --- a/chromium/v8/src/diagnostics/arm64/eh-frame-arm64.cc +++ b/chromium/v8/src/diagnostics/arm64/eh-frame-arm64.cc @@ -38,7 +38,6 @@ int EhFrameWriter::RegisterToDwarfCode(Register name) { return kX0DwarfCode; default: UNIMPLEMENTED(); - return -1; } } @@ -55,7 +54,6 @@ const char* EhFrameDisassembler::DwarfRegisterCodeToString(int code) { return "sp"; // This could be zr as well default: UNIMPLEMENTED(); - return nullptr; } } diff --git a/chromium/v8/src/diagnostics/compilation-statistics.cc b/chromium/v8/src/diagnostics/compilation-statistics.cc index 40bb239b125..74fa232a080 100644 --- a/chromium/v8/src/diagnostics/compilation-statistics.cc +++ b/chromium/v8/src/diagnostics/compilation-statistics.cc @@ -56,6 +56,29 @@ void CompilationStatistics::BasicStats::Accumulate(const BasicStats& stats) { } } +std::string CompilationStatistics::BasicStats::AsJSON() { +// clang-format off +#define DICT(s) "{" << s << "}" +#define QUOTE(s) "\"" << s << "\"" +#define MEMBER(s) QUOTE(s) << ":" + + DCHECK_EQ(function_name_.find("\""), std::string::npos); + + std::stringstream stream; + stream << DICT( + MEMBER("function_name") << QUOTE(function_name_) << "," + MEMBER("total_allocated_bytes") << total_allocated_bytes_ << "," + MEMBER("max_allocated_bytes") << max_allocated_bytes_ << "," + MEMBER("absolute_max_allocated_bytes") << absolute_max_allocated_bytes_); + + return stream.str(); + +#undef DICT +#undef QUOTE +#undef MEMBER + // clang-format on +} + static void WriteLine(std::ostream& os, bool machine_format, const char* name, const CompilationStatistics::BasicStats& stats, const CompilationStatistics::BasicStats& total_stats) { diff --git a/chromium/v8/src/diagnostics/compilation-statistics.h b/chromium/v8/src/diagnostics/compilation-statistics.h index d14e108d078..a6abdf5e89b 100644 --- a/chromium/v8/src/diagnostics/compilation-statistics.h +++ b/chromium/v8/src/diagnostics/compilation-statistics.h @@ -37,6 +37,8 @@ class CompilationStatistics final : public Malloced { void Accumulate(const BasicStats& stats); + std::string AsJSON(); + base::TimeDelta delta_; size_t total_allocated_bytes_; size_t max_allocated_bytes_; diff --git a/chromium/v8/src/diagnostics/disassembler.cc b/chromium/v8/src/diagnostics/disassembler.cc index 596362b351a..928fe1f3576 100644 --- a/chromium/v8/src/diagnostics/disassembler.cc +++ b/chromium/v8/src/diagnostics/disassembler.cc @@ -128,8 +128,11 @@ const char* V8NameConverter::RootRelativeName(int offset) const { const unsigned kRootsTableSize = sizeof(RootsTable); const int kExtRefsTableStart = IsolateData::external_reference_table_offset(); const unsigned kExtRefsTableSize = ExternalReferenceTable::kSizeInBytes; - const int kBuiltinsTableStart = IsolateData::builtins_table_offset(); - const unsigned kBuiltinsTableSize = + const int kBuiltinTier0TableStart = IsolateData::builtin_tier0_table_offset(); + const unsigned kBuiltinTier0TableSize = + Builtins::kBuiltinTier0Count * kSystemPointerSize; + const int kBuiltinTableStart = IsolateData::builtin_table_offset(); + const unsigned kBuiltinTableSize = Builtins::kBuiltinCount * kSystemPointerSize; if (static_cast<unsigned>(offset - kRootsTableStart) < kRootsTableSize) { @@ -143,7 +146,6 @@ const char* V8NameConverter::RootRelativeName(int offset) const { SNPrintF(v8_buffer_, "root (%s)", RootsTable::name(root_index)); return v8_buffer_.begin(); - } else if (static_cast<unsigned>(offset - kExtRefsTableStart) < kExtRefsTableSize) { uint32_t offset_in_extref_table = offset - kExtRefsTableStart; @@ -162,17 +164,24 @@ const char* V8NameConverter::RootRelativeName(int offset) const { isolate_->external_reference_table()->NameFromOffset( offset_in_extref_table)); return v8_buffer_.begin(); - - } else if (static_cast<unsigned>(offset - kBuiltinsTableStart) < - kBuiltinsTableSize) { - uint32_t offset_in_builtins_table = (offset - kBuiltinsTableStart); + } else if (static_cast<unsigned>(offset - kBuiltinTier0TableStart) < + kBuiltinTier0TableSize) { + uint32_t offset_in_builtins_table = (offset - kBuiltinTier0TableStart); Builtin builtin = Builtins::FromInt(offset_in_builtins_table / kSystemPointerSize); const char* name = Builtins::name(builtin); SNPrintF(v8_buffer_, "builtin (%s)", name); return v8_buffer_.begin(); + } else if (static_cast<unsigned>(offset - kBuiltinTableStart) < + kBuiltinTableSize) { + uint32_t offset_in_builtins_table = (offset - kBuiltinTableStart); + Builtin builtin = + Builtins::FromInt(offset_in_builtins_table / kSystemPointerSize); + const char* name = Builtins::name(builtin); + SNPrintF(v8_buffer_, "builtin (%s)", name); + return v8_buffer_.begin(); } else { // It must be a direct access to one of the external values. if (directly_accessed_external_refs_.empty()) { diff --git a/chromium/v8/src/diagnostics/eh-frame.cc b/chromium/v8/src/diagnostics/eh-frame.cc index d53ea7698a0..223e288e6e9 100644 --- a/chromium/v8/src/diagnostics/eh-frame.cc +++ b/chromium/v8/src/diagnostics/eh-frame.cc @@ -27,14 +27,12 @@ void EhFrameWriter::WriteInitialStateInCie() { UNIMPLEMENTED(); } int EhFrameWriter::RegisterToDwarfCode(Register) { UNIMPLEMENTED(); - return -1; } #ifdef ENABLE_DISASSEMBLER const char* EhFrameDisassembler::DwarfRegisterCodeToString(int) { UNIMPLEMENTED(); - return nullptr; } #endif diff --git a/chromium/v8/src/diagnostics/gdb-jit.cc b/chromium/v8/src/diagnostics/gdb-jit.cc index 53c29cfb242..bc03a189cd5 100644 --- a/chromium/v8/src/diagnostics/gdb-jit.cc +++ b/chromium/v8/src/diagnostics/gdb-jit.cc @@ -4,14 +4,17 @@ #include "src/diagnostics/gdb-jit.h" +#include <iterator> #include <map> #include <memory> #include <vector> -#include "include/v8.h" +#include "include/v8-callbacks.h" #include "src/api/api-inl.h" +#include "src/base/address-region.h" #include "src/base/bits.h" #include "src/base/hashmap.h" +#include "src/base/memory.h" #include "src/base/platform/platform.h" #include "src/base/platform/wrappers.h" #include "src/base/strings.h" @@ -63,7 +66,9 @@ class Writer { T* operator->() { return w_->RawSlotAt<T>(offset_); } - void set(const T& value) { *w_->RawSlotAt<T>(offset_) = value; } + void set(const T& value) { + base::WriteUnalignedValue(w_->AddressAt<T>(offset_), value); + } Slot<T> at(int i) { return Slot<T>(w_, offset_ + sizeof(T) * i); } @@ -75,7 +80,7 @@ class Writer { template <typename T> void Write(const T& val) { Ensure(position_ + sizeof(T)); - *RawSlotAt<T>(position_) = val; + base::WriteUnalignedValue(AddressAt<T>(position_), val); position_ += sizeof(T); } @@ -154,6 +159,12 @@ class Writer { friend class Slot; template <typename T> + Address AddressAt(uintptr_t offset) { + DCHECK(offset < capacity_ && offset + sizeof(T) <= capacity_); + return reinterpret_cast<Address>(&buffer_[offset]); + } + + template <typename T> T* RawSlotAt(uintptr_t offset) { DCHECK(offset < capacity_ && offset + sizeof(T) <= capacity_); return reinterpret_cast<T*>(&buffer_[offset]); @@ -896,17 +907,20 @@ class CodeDescription { }; #endif - CodeDescription(const char* name, Code code, SharedFunctionInfo shared, - LineInfo* lineinfo) - : name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {} + CodeDescription(const char* name, base::AddressRegion region, + SharedFunctionInfo shared, LineInfo* lineinfo, + bool is_function) + : name_(name), + shared_info_(shared), + lineinfo_(lineinfo), + is_function_(is_function), + code_region_(region) {} const char* name() const { return name_; } LineInfo* lineinfo() const { return lineinfo_; } - bool is_function() const { - return CodeKindIsOptimizedJSFunction(code_.kind()); - } + bool is_function() const { return is_function_; } bool has_scope_info() const { return !shared_info_.is_null(); } @@ -915,15 +929,11 @@ class CodeDescription { return shared_info_.scope_info(); } - uintptr_t CodeStart() const { - return static_cast<uintptr_t>(code_.InstructionStart()); - } + uintptr_t CodeStart() const { return code_region_.begin(); } - uintptr_t CodeEnd() const { - return static_cast<uintptr_t>(code_.InstructionEnd()); - } + uintptr_t CodeEnd() const { return code_region_.end(); } - uintptr_t CodeSize() const { return CodeEnd() - CodeStart(); } + uintptr_t CodeSize() const { return code_region_.size(); } bool has_script() { return !shared_info_.is_null() && shared_info_.script().IsScript(); @@ -933,6 +943,8 @@ class CodeDescription { bool IsLineInfoAvailable() { return lineinfo_ != nullptr; } + base::AddressRegion region() { return code_region_; } + #if V8_TARGET_ARCH_X64 uintptr_t GetStackStateStartAddress(StackState state) const { DCHECK(state < STACK_STATE_MAX); @@ -946,7 +958,7 @@ class CodeDescription { #endif std::unique_ptr<char[]> GetFilename() { - if (!shared_info_.is_null()) { + if (!shared_info_.is_null() && script().name().IsString()) { return String::cast(script().name()).ToCString(); } else { std::unique_ptr<char[]> result(new char[1]); @@ -965,9 +977,10 @@ class CodeDescription { private: const char* name_; - Code code_; SharedFunctionInfo shared_info_; LineInfo* lineinfo_; + bool is_function_; + base::AddressRegion code_region_; #if V8_TARGET_ARCH_X64 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; #endif @@ -1080,6 +1093,8 @@ class DebugInfoSection : public DebugSection { UNIMPLEMENTED(); #elif V8_TARGET_ARCH_MIPS64 UNIMPLEMENTED(); +#elif V8_TARGET_ARCH_LOONG64 + UNIMPLEMENTED(); #elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX w->Write<uint8_t>(DW_OP_reg31); // The frame pointer is here on PPC64. #elif V8_TARGET_ARCH_S390 @@ -1092,7 +1107,7 @@ class DebugInfoSection : public DebugSection { int params = scope.ParameterCount(); int context_slots = scope.ContextLocalCount(); // The real slot ID is internal_slots + context_slot_id. - int internal_slots = Context::MIN_CONTEXT_SLOTS; + int internal_slots = scope.ContextHeaderLength(); int current_abbreviation = 4; for (int param = 0; param < params; ++param) { @@ -1109,7 +1124,7 @@ class DebugInfoSection : public DebugSection { } // See contexts.h for more information. - DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, 3); + DCHECK(internal_slots == 2 || internal_slots == 3); DCHECK_EQ(Context::SCOPE_INFO_INDEX, 0); DCHECK_EQ(Context::PREVIOUS_INDEX, 1); DCHECK_EQ(Context::EXTENSION_INDEX, 2); @@ -1117,8 +1132,10 @@ class DebugInfoSection : public DebugSection { w->WriteString(".scope_info"); w->WriteULEB128(current_abbreviation++); w->WriteString(".previous"); - w->WriteULEB128(current_abbreviation++); - w->WriteString(".extension"); + if (internal_slots == 3) { + w->WriteULEB128(current_abbreviation++); + w->WriteString(".extension"); + } for (int context_slot = 0; context_slot < context_slots; ++context_slot) { w->WriteULEB128(current_abbreviation++); @@ -1814,26 +1831,17 @@ static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) { return CreateCodeEntry(reinterpret_cast<Address>(w.buffer()), w.position()); } -struct AddressRange { - Address start; - Address end; -}; - -struct AddressRangeLess { - bool operator()(const AddressRange& a, const AddressRange& b) const { - if (a.start == b.start) return a.end < b.end; - return a.start < b.start; +// Like base::AddressRegion::StartAddressLess but also compares |end| when +// |begin| is equal. +struct AddressRegionLess { + bool operator()(const base::AddressRegion& a, + const base::AddressRegion& b) const { + if (a.begin() == b.begin()) return a.end() < b.end(); + return a.begin() < b.begin(); } }; -struct CodeMapConfig { - using Key = AddressRange; - using Value = JITCodeEntry*; - using Less = AddressRangeLess; -}; - -using CodeMap = - std::map<CodeMapConfig::Key, CodeMapConfig::Value, CodeMapConfig::Less>; +using CodeMap = std::map<base::AddressRegion, JITCodeEntry*, AddressRegionLess>; static CodeMap* GetCodeMap() { // TODO(jgruber): Don't leak. @@ -1907,50 +1915,72 @@ static void AddUnwindInfo(CodeDescription* desc) { static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER; -// Remove entries from the map that intersect the given address range, -// and deregister them from GDB. -static void RemoveJITCodeEntries(CodeMap* map, const AddressRange& range) { - DCHECK(range.start < range.end); +static base::Optional<std::pair<CodeMap::iterator, CodeMap::iterator>> +GetOverlappingRegions(CodeMap* map, const base::AddressRegion region) { + DCHECK_LT(region.begin(), region.end()); - if (map->empty()) return; + if (map->empty()) return {}; // Find the first overlapping entry. - // If successful, points to the first element not less than `range`. The + // If successful, points to the first element not less than `region`. The // returned iterator has the key in `first` and the value in `second`. - auto it = map->lower_bound(range); + auto it = map->lower_bound(region); auto start_it = it; if (it == map->end()) { start_it = map->begin(); + // Find the first overlapping entry. + for (; start_it != map->end(); ++start_it) { + if (start_it->first.end() > region.begin()) { + break; + } + } } else if (it != map->begin()) { for (--it; it != map->begin(); --it) { - if ((*it).first.end <= range.start) break; + if ((*it).first.end() <= region.begin()) break; + start_it = it; + } + if (it == map->begin() && it->first.end() > region.begin()) { start_it = it; } } - DCHECK(start_it != map->end()); + if (start_it == map->end()) { + return {}; + } - // Find the first non-overlapping entry after `range`. + // Find the first non-overlapping entry after `region`. - const auto end_it = map->lower_bound({range.end, 0}); + const auto end_it = map->lower_bound({region.end(), 0}); - // Evict intersecting ranges. + // Return a range containing intersecting regions. - if (std::distance(start_it, end_it) < 1) return; // No overlapping entries. + if (std::distance(start_it, end_it) < 1) + return {}; // No overlapping entries. - for (auto it = start_it; it != end_it; it++) { - JITCodeEntry* old_entry = (*it).second; - UnregisterCodeEntry(old_entry); - DestroyCodeEntry(old_entry); - } + return {{start_it, end_it}}; +} + +// Remove entries from the map that intersect the given address region, +// and deregister them from GDB. +static void RemoveJITCodeEntries(CodeMap* map, + const base::AddressRegion region) { + if (auto overlap = GetOverlappingRegions(map, region)) { + auto start_it = overlap->first; + auto end_it = overlap->second; + for (auto it = start_it; it != end_it; it++) { + JITCodeEntry* old_entry = (*it).second; + UnregisterCodeEntry(old_entry); + DestroyCodeEntry(old_entry); + } - map->erase(start_it, end_it); + map->erase(start_it, end_it); + } } // Insert the entry into the map and register it with GDB. -static void AddJITCodeEntry(CodeMap* map, const AddressRange& range, +static void AddJITCodeEntry(CodeMap* map, const base::AddressRegion region, JITCodeEntry* entry, bool dump_if_enabled, const char* name_hint) { #if defined(DEBUG) && !V8_OS_WIN @@ -1967,24 +1997,21 @@ static void AddJITCodeEntry(CodeMap* map, const AddressRange& range, } #endif - auto result = map->emplace(range, entry); + auto result = map->emplace(region, entry); DCHECK(result.second); // Insertion happened. USE(result); RegisterCodeEntry(entry); } -static void AddCode(const char* name, Code code, SharedFunctionInfo shared, - LineInfo* lineinfo) { +static void AddCode(const char* name, base::AddressRegion region, + SharedFunctionInfo shared, LineInfo* lineinfo, + Isolate* isolate, bool is_function) { DisallowGarbageCollection no_gc; + CodeDescription code_desc(name, region, shared, lineinfo, is_function); CodeMap* code_map = GetCodeMap(); - AddressRange range; - range.start = code.address(); - range.end = code.address() + code.CodeSize(); - RemoveJITCodeEntries(code_map, range); - - CodeDescription code_desc(name, code, shared, lineinfo); + RemoveJITCodeEntries(code_map, region); if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { delete lineinfo; @@ -1992,7 +2019,6 @@ static void AddCode(const char* name, Code code, SharedFunctionInfo shared, } AddUnwindInfo(&code_desc); - Isolate* isolate = code.GetIsolate(); JITCodeEntry* entry = CreateELFObject(&code_desc, isolate); delete lineinfo; @@ -2008,25 +2034,40 @@ static void AddCode(const char* name, Code code, SharedFunctionInfo shared, should_dump = (name_hint != nullptr); } } - AddJITCodeEntry(code_map, range, entry, should_dump, name_hint); + AddJITCodeEntry(code_map, region, entry, should_dump, name_hint); } void EventHandler(const v8::JitCodeEvent* event) { if (!FLAG_gdbjit) return; - if (event->code_type != v8::JitCodeEvent::JIT_CODE) return; + if ((event->code_type != v8::JitCodeEvent::JIT_CODE) && + (event->code_type != v8::JitCodeEvent::WASM_CODE)) { + return; + } base::MutexGuard lock_guard(mutex.Pointer()); switch (event->type) { case v8::JitCodeEvent::CODE_ADDED: { Address addr = reinterpret_cast<Address>(event->code_start); - Isolate* isolate = reinterpret_cast<Isolate*>(event->isolate); - Code code = isolate->heap()->GcSafeFindCodeForInnerPointer(addr); LineInfo* lineinfo = GetLineInfo(addr); std::string event_name(event->name.str, event->name.len); // It's called UnboundScript in the API but it's a SharedFunctionInfo. SharedFunctionInfo shared = event->script.IsEmpty() ? SharedFunctionInfo() : *Utils::OpenHandle(*event->script); - AddCode(event_name.c_str(), code, shared, lineinfo); + Isolate* isolate = reinterpret_cast<Isolate*>(event->isolate); + bool is_function = false; + // TODO(zhin): See if we can use event->code_type to determine + // is_function, the difference currently is that JIT_CODE is SparkPlug, + // TurboProp, TurboFan, whereas CodeKindIsOptimizedJSFunction is only + // TurboProp and TurboFan. is_function is used for AddUnwindInfo, and the + // prologue that SP generates probably matches that of TP/TF, so we can + // use event->code_type here instead of finding the Code. + // TODO(zhin): Rename is_function to be more accurate. + if (event->code_type == v8::JitCodeEvent::JIT_CODE) { + Code code = isolate->heap()->GcSafeFindCodeForInnerPointer(addr); + is_function = CodeKindIsOptimizedJSFunction(code.kind()); + } + AddCode(event_name.c_str(), {addr, event->code_len}, shared, lineinfo, + isolate, is_function); break; } case v8::JitCodeEvent::CODE_MOVED: @@ -2056,6 +2097,23 @@ void EventHandler(const v8::JitCodeEvent* event) { } } } + +void AddRegionForTesting(const base::AddressRegion region) { + // For testing purposes we don't care about JITCodeEntry, pass nullptr. + auto result = GetCodeMap()->emplace(region, nullptr); + DCHECK(result.second); // Insertion happened. + USE(result); +} + +void ClearCodeMapForTesting() { GetCodeMap()->clear(); } + +size_t NumOverlapEntriesForTesting(const base::AddressRegion region) { + if (auto overlaps = GetOverlappingRegions(GetCodeMap(), region)) { + return std::distance(overlaps->first, overlaps->second); + } + return 0; +} + #endif } // namespace GDBJITInterface } // namespace internal diff --git a/chromium/v8/src/diagnostics/gdb-jit.h b/chromium/v8/src/diagnostics/gdb-jit.h index 82f5ce892c9..eb4d515a810 100644 --- a/chromium/v8/src/diagnostics/gdb-jit.h +++ b/chromium/v8/src/diagnostics/gdb-jit.h @@ -5,6 +5,8 @@ #ifndef V8_DIAGNOSTICS_GDB_JIT_H_ #define V8_DIAGNOSTICS_GDB_JIT_H_ +#include "src/base/address-region.h" + // // GDB has two ways of interacting with JIT code. With the "JIT compilation // interface", V8 can tell GDB when it emits JIT code. Unfortunately to do so, @@ -29,9 +31,19 @@ struct JitCodeEvent; namespace internal { namespace GDBJITInterface { #ifdef ENABLE_GDB_JIT_INTERFACE + // JitCodeEventHandler that creates ELF/Mach-O objects and registers them with // GDB. void EventHandler(const v8::JitCodeEvent* event); + +// Expose some functions for unittests. These only exercise the logic to add +// AddressRegion to CodeMap, and checking for overlap. It does not touch the +// actual JITCodeEntry at all. +V8_EXPORT_PRIVATE void AddRegionForTesting(const base::AddressRegion region); +V8_EXPORT_PRIVATE void ClearCodeMapForTesting(); +V8_EXPORT_PRIVATE size_t +NumOverlapEntriesForTesting(const base::AddressRegion region); + #endif } // namespace GDBJITInterface } // namespace internal diff --git a/chromium/v8/src/diagnostics/ia32/disasm-ia32.cc b/chromium/v8/src/diagnostics/ia32/disasm-ia32.cc index de124de7474..fbcba1a4b2e 100644 --- a/chromium/v8/src/diagnostics/ia32/disasm-ia32.cc +++ b/chromium/v8/src/diagnostics/ia32/disasm-ia32.cc @@ -89,6 +89,10 @@ static const char* const conditional_move_mnem[] = { /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"}; +static const char* const cmp_pseudo_op[16] = { + "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord", + "eq_uq", "nge", "ngt", "false", "neq_oq", "ge", "gt", "true"}; + enum InstructionType { NO_INSTR, ZERO_OPERANDS_INSTR, @@ -415,13 +419,11 @@ int DisassemblerIA32::PrintRightOperandHelper( UnimplementedInstruction(); return 1; } - } else { - AppendToBuffer("[%s]", (this->*register_name)(rm)); - return 1; } - break; + AppendToBuffer("[%s]", (this->*register_name)(rm)); + return 1; case 1: // fall through - case 2: + case 2: { if (rm == esp) { byte sib = *(modrmp + 1); int scale, index, base; @@ -436,14 +438,13 @@ int DisassemblerIA32::PrintRightOperandHelper( disp < 0 ? "-" : "+", disp < 0 ? -disp : disp); } return mod == 2 ? 6 : 3; - } else { - // No sib. - int disp = mod == 2 ? Imm32(modrmp + 1) : Imm8(modrmp + 1); - AppendToBuffer("[%s%s0x%x]", (this->*register_name)(rm), - disp < 0 ? "-" : "+", disp < 0 ? -disp : disp); - return mod == 2 ? 5 : 2; } - break; + // No sib. + int disp = mod == 2 ? Imm32(modrmp + 1) : Imm8(modrmp + 1); + AppendToBuffer("[%s%s0x%x]", (this->*register_name)(rm), + disp < 0 ? "-" : "+", disp < 0 ? -disp : disp); + return mod == 2 ? 5 : 2; + } case 3: AppendToBuffer("%s", (this->*register_name)(rm)); return 1; @@ -789,6 +790,15 @@ int DisassemblerIA32::AVXInstruction(byte* data) { SSSE3_UNOP_INSTRUCTION_LIST(DECLARE_SSE_AVX_RM_DIS_CASE) SSE4_RM_INSTRUCTION_LIST(DECLARE_SSE_AVX_RM_DIS_CASE) #undef DECLARE_SSE_AVX_RM_DIS_CASE + +#define DISASSEMBLE_AVX2_BROADCAST(instruction, _1, _2, _3, code) \ + case 0x##code: \ + AppendToBuffer("" #instruction " %s,", NameOfXMMRegister(regop)); \ + current += PrintRightXMMOperand(current); \ + break; + AVX2_BROADCAST_LIST(DISASSEMBLE_AVX2_BROADCAST) +#undef DISASSEMBLE_AVX2_BROADCAST + default: UnimplementedInstruction(); } @@ -808,6 +818,20 @@ int DisassemblerIA32::AVXInstruction(byte* data) { AppendToBuffer(",%d", Imm8_U(current)); current++; break; + case 0x0a: + AppendToBuffer("vroundss %s,%s,", NameOfXMMRegister(regop), + NameOfXMMRegister(vvvv)); + current += PrintRightXMMOperand(current); + AppendToBuffer(",%d", Imm8_U(current)); + current++; + break; + case 0x0b: + AppendToBuffer("vroundsd %s,%s,", NameOfXMMRegister(regop), + NameOfXMMRegister(vvvv)); + current += PrintRightXMMOperand(current); + AppendToBuffer(",%d", Imm8_U(current)); + current++; + break; case 0x0E: AppendToBuffer("vpblendw %s,%s,", NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); @@ -900,39 +924,8 @@ int DisassemblerIA32::AVXInstruction(byte* data) { AppendToBuffer("vmovddup %s,", NameOfXMMRegister(regop)); current += PrintRightXMMOperand(current); break; - case 0x51: - AppendToBuffer("vsqrtsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x58: - AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x59: - AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5C: - AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5D: - AppendToBuffer("vminsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5E: - AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5F: - AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); + case 0x2c: + AppendToBuffer("vcvttsd2si %s,", NameOfXMMRegister(regop)); current += PrintRightXMMOperand(current); break; case 0x70: @@ -946,6 +939,14 @@ int DisassemblerIA32::AVXInstruction(byte* data) { NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); break; +#define DISASM_SSE2_INSTRUCTION_LIST_SD(instruction, _1, _2, opcode) \ + case 0x##opcode: \ + AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \ + NameOfXMMRegister(vvvv)); \ + current += PrintRightXMMOperand(current); \ + break; + SSE2_INSTRUCTION_LIST_SD(DISASM_SSE2_INSTRUCTION_LIST_SD) +#undef DISASM_SSE2_INSTRUCTION_LIST_SD default: UnimplementedInstruction(); } @@ -967,6 +968,10 @@ int DisassemblerIA32::AVXInstruction(byte* data) { AppendToBuffer("vmovshdup %s,", NameOfXMMRegister(regop)); current += PrintRightXMMOperand(current); break; + case 0x2c: + AppendToBuffer("vcvttss2si %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + break; case 0x51: AppendToBuffer("vsqrtss %s,%s,", NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); @@ -982,6 +987,11 @@ int DisassemblerIA32::AVXInstruction(byte* data) { NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); break; + case 0x5a: + AppendToBuffer("vcvtss2sd %s,%s,", NameOfXMMRegister(regop), + NameOfXMMRegister(vvvv)); + current += PrintRightXMMOperand(current); + break; case 0x5B: AppendToBuffer("vcvttps2dq %s,", NameOfXMMRegister(regop)); current += PrintRightXMMOperand(current); @@ -1167,6 +1177,10 @@ int DisassemblerIA32::AVXInstruction(byte* data) { AppendToBuffer("vmovaps %s,", NameOfXMMRegister(regop)); current += PrintRightXMMOperand(current); break; + case 0x2e: + AppendToBuffer("vucomiss %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + break; case 0x50: AppendToBuffer("vmovmskps %s,%s", NameOfCPURegister(regop), NameOfXMMRegister(rm)); @@ -1243,12 +1257,10 @@ int DisassemblerIA32::AVXInstruction(byte* data) { current += PrintRightXMMOperand(current); break; case 0xC2: { - const char* const pseudo_op[] = {"eq", "lt", "le", "unord", - "neq", "nlt", "nle", "ord"}; AppendToBuffer("vcmpps %s,%s,", NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); - AppendToBuffer(", (%s)", pseudo_op[*current]); + AppendToBuffer(", (%s)", cmp_pseudo_op[*current]); current++; break; } @@ -1274,6 +1286,10 @@ int DisassemblerIA32::AVXInstruction(byte* data) { AppendToBuffer("vmovapd %s,", NameOfXMMRegister(regop)); current += PrintRightXMMOperand(current); break; + case 0x2e: + AppendToBuffer("vucomisd %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + break; case 0x50: AppendToBuffer("vmovmskpd %s,%s", NameOfCPURegister(regop), NameOfXMMRegister(rm)); @@ -1371,11 +1387,10 @@ int DisassemblerIA32::AVXInstruction(byte* data) { AppendToBuffer(",%s", NameOfXMMRegister(regop)); break; case 0xC2: { - const char* const pseudo_op[] = {"eq", "lt", "le", "unord", "neq"}; AppendToBuffer("vcmppd %s,%s,", NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); - AppendToBuffer(", (%s)", pseudo_op[*current]); + AppendToBuffer(", (%s)", cmp_pseudo_op[*current]); current++; break; } @@ -1999,11 +2014,9 @@ int DisassemblerIA32::InstructionDecode(v8::base::Vector<char> out_buffer, data += PrintOperands("xadd", OPER_REG_OP_ORDER, data); } else if (f0byte == 0xC2) { data += 2; - const char* const pseudo_op[] = {"eq", "lt", "le", "unord", - "neq", "nlt", "nle", "ord"}; AppendToBuffer("cmpps %s, ", NameOfXMMRegister(regop)); data += PrintRightXMMOperand(data); - AppendToBuffer(", (%s)", pseudo_op[*data]); + AppendToBuffer(", (%s)", cmp_pseudo_op[*data]); data++; } else if (f0byte == 0xC6) { // shufps xmm, xmm/m128, imm8 @@ -2485,10 +2498,9 @@ int DisassemblerIA32::InstructionDecode(v8::base::Vector<char> out_buffer, data++; int mod, regop, rm; get_modrm(*data, &mod, ®op, &rm); - const char* const pseudo_op[] = {"eq", "lt", "le", "unord", "neq"}; AppendToBuffer("cmppd %s, ", NameOfXMMRegister(regop)); data += PrintRightXMMOperand(data); - AppendToBuffer(", (%s)", pseudo_op[*data]); + AppendToBuffer(", (%s)", cmp_pseudo_op[*data]); data++; } else if (*data == 0xC4) { data++; @@ -2658,30 +2670,15 @@ int DisassemblerIA32::InstructionDecode(v8::base::Vector<char> out_buffer, case 0x2D: mnem = "cvtsd2si"; break; - case 0x51: - mnem = "sqrtsd"; - break; - case 0x58: - mnem = "addsd"; - break; - case 0x59: - mnem = "mulsd"; - break; - case 0x5C: - mnem = "subsd"; - break; - case 0x5D: - mnem = "minsd"; - break; - case 0x5E: - mnem = "divsd"; - break; - case 0x5F: - mnem = "maxsd"; - break; case 0x7C: mnem = "haddps"; break; +#define MNEM_FOR_SSE2_INSTRUCTION_LSIT_SD(instruction, _1, _2, opcode) \ + case 0x##opcode: \ + mnem = "" #instruction; \ + break; + SSE2_INSTRUCTION_LIST_SD(MNEM_FOR_SSE2_INSTRUCTION_LSIT_SD) +#undef MNEM_FOR_SSE2_INSTRUCTION_LSIT_SD } data += 3; int mod, regop, rm; @@ -2694,10 +2691,7 @@ int DisassemblerIA32::InstructionDecode(v8::base::Vector<char> out_buffer, data += PrintRightXMMOperand(data); } else if (b2 == 0xC2) { // Intel manual 2A, Table 3-18. - const char* const pseudo_op[] = { - "cmpeqsd", "cmpltsd", "cmplesd", "cmpunordsd", - "cmpneqsd", "cmpnltsd", "cmpnlesd", "cmpordsd"}; - AppendToBuffer("%s %s,%s", pseudo_op[data[1]], + AppendToBuffer("cmp%ssd %s,%s", cmp_pseudo_op[data[1]], NameOfXMMRegister(regop), NameOfXMMRegister(rm)); data += 2; } else { @@ -2835,10 +2829,7 @@ int DisassemblerIA32::InstructionDecode(v8::base::Vector<char> out_buffer, data += PrintRightXMMOperand(data); } else if (b2 == 0xC2) { // Intel manual 2A, Table 3-18. - const char* const pseudo_op[] = { - "cmpeqss", "cmpltss", "cmpless", "cmpunordss", - "cmpneqss", "cmpnltss", "cmpnless", "cmpordss"}; - AppendToBuffer("%s %s,%s", pseudo_op[data[1]], + AppendToBuffer("cmp%sss %s,%s", cmp_pseudo_op[data[1]], NameOfXMMRegister(regop), NameOfXMMRegister(rm)); data += 2; } else { diff --git a/chromium/v8/src/diagnostics/loong64/disasm-loong64.cc b/chromium/v8/src/diagnostics/loong64/disasm-loong64.cc new file mode 100644 index 00000000000..9d8aee96a3a --- /dev/null +++ b/chromium/v8/src/diagnostics/loong64/disasm-loong64.cc @@ -0,0 +1,1711 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <assert.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#if V8_TARGET_ARCH_LOONG64 + +#include "src/base/platform/platform.h" +#include "src/base/strings.h" +#include "src/base/vector.h" +#include "src/codegen/loong64/constants-loong64.h" +#include "src/codegen/macro-assembler.h" +#include "src/diagnostics/disasm.h" + +namespace v8 { +namespace internal { + +//------------------------------------------------------------------------------ + +// Decoder decodes and disassembles instructions into an output buffer. +// It uses the converter to convert register names and call destinations into +// more informative description. +class Decoder { + public: + Decoder(const disasm::NameConverter& converter, + v8::base::Vector<char> out_buffer) + : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) { + out_buffer_[out_buffer_pos_] = '\0'; + } + + ~Decoder() {} + + Decoder(const Decoder&) = delete; + Decoder& operator=(const Decoder&) = delete; + + // Writes one disassembled instruction into 'buffer' (0-terminated). + // Returns the length of the disassembled machine instruction in bytes. + int InstructionDecode(byte* instruction); + + private: + // Bottleneck functions to print into the out_buffer. + void PrintChar(const char ch); + void Print(const char* str); + + // Printing of common values. + void PrintRegister(int reg); + void PrintFPURegister(int freg); + void PrintFPUStatusRegister(int freg); + void PrintRj(Instruction* instr); + void PrintRk(Instruction* instr); + void PrintRd(Instruction* instr); + void PrintFj(Instruction* instr); + void PrintFk(Instruction* instr); + void PrintFd(Instruction* instr); + void PrintFa(Instruction* instr); + void PrintSa2(Instruction* instr); + void PrintSa3(Instruction* instr); + void PrintUi5(Instruction* instr); + void PrintUi6(Instruction* instr); + void PrintUi12(Instruction* instr); + void PrintMsbw(Instruction* instr); + void PrintLsbw(Instruction* instr); + void PrintMsbd(Instruction* instr); + void PrintLsbd(Instruction* instr); + // void PrintCond(Instruction* instr); + void PrintSi12(Instruction* instr); + void PrintSi14(Instruction* instr); + void PrintSi16(Instruction* instr); + void PrintSi20(Instruction* instr); + void PrintXi12(Instruction* instr); + void PrintXi20(Instruction* instr); + void PrintCj(Instruction* instr); + void PrintCd(Instruction* instr); + void PrintCa(Instruction* instr); + void PrintCode(Instruction* instr); + void PrintHint5(Instruction* instr); + void PrintHint15(Instruction* instr); + void PrintPCOffs16(Instruction* instr); + void PrintPCOffs21(Instruction* instr); + void PrintPCOffs26(Instruction* instr); + void PrintOffs16(Instruction* instr); + void PrintOffs21(Instruction* instr); + void PrintOffs26(Instruction* instr); + + // Handle formatting of instructions and their options. + int FormatRegister(Instruction* instr, const char* option); + int FormatFPURegister(Instruction* instr, const char* option); + int FormatOption(Instruction* instr, const char* option); + void Format(Instruction* instr, const char* format); + void Unknown(Instruction* instr); + int DecodeBreakInstr(Instruction* instr); + + // Each of these functions decodes one particular instruction type. + int InstructionDecode(Instruction* instr); + void DecodeTypekOp6(Instruction* instr); + void DecodeTypekOp7(Instruction* instr); + void DecodeTypekOp8(Instruction* instr); + void DecodeTypekOp10(Instruction* instr); + void DecodeTypekOp12(Instruction* instr); + void DecodeTypekOp14(Instruction* instr); + int DecodeTypekOp17(Instruction* instr); + void DecodeTypekOp22(Instruction* instr); + + const disasm::NameConverter& converter_; + v8::base::Vector<char> out_buffer_; + int out_buffer_pos_; +}; + +// Support for assertions in the Decoder formatting functions. +#define STRING_STARTS_WITH(string, compare_string) \ + (strncmp(string, compare_string, strlen(compare_string)) == 0) + +// Append the ch to the output buffer. +void Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; } + +// Append the str to the output buffer. +void Decoder::Print(const char* str) { + char cur = *str++; + while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) { + PrintChar(cur); + cur = *str++; + } + out_buffer_[out_buffer_pos_] = 0; +} + +// Print the register name according to the active name converter. +void Decoder::PrintRegister(int reg) { + Print(converter_.NameOfCPURegister(reg)); +} + +void Decoder::PrintRj(Instruction* instr) { + int reg = instr->RjValue(); + PrintRegister(reg); +} + +void Decoder::PrintRk(Instruction* instr) { + int reg = instr->RkValue(); + PrintRegister(reg); +} + +void Decoder::PrintRd(Instruction* instr) { + int reg = instr->RdValue(); + PrintRegister(reg); +} + +// Print the FPUregister name according to the active name converter. +void Decoder::PrintFPURegister(int freg) { + Print(converter_.NameOfXMMRegister(freg)); +} + +void Decoder::PrintFj(Instruction* instr) { + int freg = instr->FjValue(); + PrintFPURegister(freg); +} + +void Decoder::PrintFk(Instruction* instr) { + int freg = instr->FkValue(); + PrintFPURegister(freg); +} + +void Decoder::PrintFd(Instruction* instr) { + int freg = instr->FdValue(); + PrintFPURegister(freg); +} + +void Decoder::PrintFa(Instruction* instr) { + int freg = instr->FaValue(); + PrintFPURegister(freg); +} + +// Print the integer value of the sa field. +void Decoder::PrintSa2(Instruction* instr) { + int sa = instr->Sa2Value(); + uint32_t opcode = (instr->InstructionBits() >> 18) << 18; + if (opcode == ALSL || opcode == ALSL_D) { + sa += 1; + } + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa); +} + +void Decoder::PrintSa3(Instruction* instr) { + int sa = instr->Sa3Value(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa); +} + +void Decoder::PrintUi5(Instruction* instr) { + int ui = instr->Ui5Value(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", ui); +} + +void Decoder::PrintUi6(Instruction* instr) { + int ui = instr->Ui6Value(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", ui); +} + +void Decoder::PrintUi12(Instruction* instr) { + int ui = instr->Ui12Value(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", ui); +} + +void Decoder::PrintXi12(Instruction* instr) { + int xi = instr->Ui12Value(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", xi); +} + +void Decoder::PrintXi20(Instruction* instr) { + int xi = instr->Si20Value(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", xi); +} + +void Decoder::PrintMsbd(Instruction* instr) { + int msbd = instr->MsbdValue(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", msbd); +} + +void Decoder::PrintLsbd(Instruction* instr) { + int lsbd = instr->LsbdValue(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", lsbd); +} + +void Decoder::PrintMsbw(Instruction* instr) { + int msbw = instr->MsbwValue(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", msbw); +} + +void Decoder::PrintLsbw(Instruction* instr) { + int lsbw = instr->LsbwValue(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", lsbw); +} + +void Decoder::PrintSi12(Instruction* instr) { + int si = ((instr->Si12Value()) << (32 - kSi12Bits)) >> (32 - kSi12Bits); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d(0x%x)", + si, instr->Si12Value()); +} + +void Decoder::PrintSi14(Instruction* instr) { + int si = ((instr->Si14Value()) << (32 - kSi14Bits)) >> (32 - kSi14Bits); + si <<= 2; + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d(0x%x)", + si, instr->Si14Value() << 2); +} + +void Decoder::PrintSi16(Instruction* instr) { + int si = ((instr->Si16Value()) << (32 - kSi16Bits)) >> (32 - kSi16Bits); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d(0x%x)", + si, instr->Si16Value()); +} + +void Decoder::PrintSi20(Instruction* instr) { + int si = ((instr->Si20Value()) << (32 - kSi20Bits)) >> (32 - kSi20Bits); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d(0x%x)", + si, instr->Si20Value()); +} + +void Decoder::PrintCj(Instruction* instr) { + int cj = instr->CjValue(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", cj); +} + +void Decoder::PrintCd(Instruction* instr) { + int cd = instr->CdValue(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", cd); +} + +void Decoder::PrintCa(Instruction* instr) { + int ca = instr->CaValue(); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", ca); +} + +void Decoder::PrintCode(Instruction* instr) { + int code = instr->CodeValue(); + out_buffer_pos_ += + base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x(%u)", code, code); +} + +void Decoder::PrintHint5(Instruction* instr) { + int hint = instr->Hint5Value(); + out_buffer_pos_ += + base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x(%u)", hint, hint); +} + +void Decoder::PrintHint15(Instruction* instr) { + int hint = instr->Hint15Value(); + out_buffer_pos_ += + base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x(%u)", hint, hint); +} + +void Decoder::PrintPCOffs16(Instruction* instr) { + int n_bits = 2; + int offs = instr->Offs16Value(); + int target = ((offs << n_bits) << (32 - kOffsLowBits - n_bits)) >> + (32 - kOffsLowBits - n_bits); + out_buffer_pos_ += base::SNPrintF( + out_buffer_ + out_buffer_pos_, "%s", + converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + target)); +} + +void Decoder::PrintPCOffs21(Instruction* instr) { + int n_bits = 2; + int offs = instr->Offs21Value(); + int target = + ((offs << n_bits) << (32 - kOffsLowBits - kOffs21HighBits - n_bits)) >> + (32 - kOffsLowBits - kOffs21HighBits - n_bits); + out_buffer_pos_ += base::SNPrintF( + out_buffer_ + out_buffer_pos_, "%s", + converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + target)); +} + +void Decoder::PrintPCOffs26(Instruction* instr) { + int n_bits = 2; + int offs = instr->Offs26Value(); + int target = + ((offs << n_bits) << (32 - kOffsLowBits - kOffs26HighBits - n_bits)) >> + (32 - kOffsLowBits - kOffs26HighBits - n_bits); + out_buffer_pos_ += base::SNPrintF( + out_buffer_ + out_buffer_pos_, "%s", + converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + target)); +} + +void Decoder::PrintOffs16(Instruction* instr) { + int offs = instr->Offs16Value(); + out_buffer_pos_ += + base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", offs << 2); +} + +void Decoder::PrintOffs21(Instruction* instr) { + int offs = instr->Offs21Value(); + out_buffer_pos_ += + base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", offs << 2); +} + +void Decoder::PrintOffs26(Instruction* instr) { + int offs = instr->Offs26Value(); + out_buffer_pos_ += + base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", offs << 2); +} + +// Handle all register based formatting in this function to reduce the +// complexity of FormatOption. +int Decoder::FormatRegister(Instruction* instr, const char* format) { + DCHECK_EQ(format[0], 'r'); + if (format[1] == 'j') { // 'rj: Rj register. + int reg = instr->RjValue(); + PrintRegister(reg); + return 2; + } else if (format[1] == 'k') { // 'rk: rk register. + int reg = instr->RkValue(); + PrintRegister(reg); + return 2; + } else if (format[1] == 'd') { // 'rd: rd register. + int reg = instr->RdValue(); + PrintRegister(reg); + return 2; + } + UNREACHABLE(); +} + +// Handle all FPUregister based formatting in this function to reduce the +// complexity of FormatOption. +int Decoder::FormatFPURegister(Instruction* instr, const char* format) { + DCHECK_EQ(format[0], 'f'); + if (format[1] == 'j') { // 'fj: fj register. + int reg = instr->FjValue(); + PrintFPURegister(reg); + return 2; + } else if (format[1] == 'k') { // 'fk: fk register. + int reg = instr->FkValue(); + PrintFPURegister(reg); + return 2; + } else if (format[1] == 'd') { // 'fd: fd register. + int reg = instr->FdValue(); + PrintFPURegister(reg); + return 2; + } else if (format[1] == 'a') { // 'fa: fa register. + int reg = instr->FaValue(); + PrintFPURegister(reg); + return 2; + } + UNREACHABLE(); +} + +// FormatOption takes a formatting string and interprets it based on +// the current instructions. The format string points to the first +// character of the option string (the option escape has already been +// consumed by the caller.) FormatOption returns the number of +// characters that were consumed from the formatting string. +int Decoder::FormatOption(Instruction* instr, const char* format) { + switch (format[0]) { + case 'c': { + switch (format[1]) { + case 'a': + DCHECK(STRING_STARTS_WITH(format, "ca")); + PrintCa(instr); + return 2; + case 'd': + DCHECK(STRING_STARTS_WITH(format, "cd")); + PrintCd(instr); + return 2; + case 'j': + DCHECK(STRING_STARTS_WITH(format, "cj")); + PrintCj(instr); + return 2; + case 'o': + DCHECK(STRING_STARTS_WITH(format, "code")); + PrintCode(instr); + return 4; + } + } + case 'f': { + return FormatFPURegister(instr, format); + } + case 'h': { + if (format[4] == '5') { + DCHECK(STRING_STARTS_WITH(format, "hint5")); + PrintHint5(instr); + return 5; + } else if (format[4] == '1') { + DCHECK(STRING_STARTS_WITH(format, "hint15")); + PrintHint15(instr); + return 6; + } + break; + } + case 'l': { + switch (format[3]) { + case 'w': + DCHECK(STRING_STARTS_WITH(format, "lsbw")); + PrintLsbw(instr); + return 4; + case 'd': + DCHECK(STRING_STARTS_WITH(format, "lsbd")); + PrintLsbd(instr); + return 4; + default: + return 0; + } + } + case 'm': { + if (format[3] == 'w') { + DCHECK(STRING_STARTS_WITH(format, "msbw")); + PrintMsbw(instr); + } else if (format[3] == 'd') { + DCHECK(STRING_STARTS_WITH(format, "msbd")); + PrintMsbd(instr); + } + return 4; + } + case 'o': { + if (format[1] == 'f') { + if (format[4] == '1') { + DCHECK(STRING_STARTS_WITH(format, "offs16")); + PrintOffs16(instr); + return 6; + } else if (format[4] == '2') { + if (format[5] == '1') { + DCHECK(STRING_STARTS_WITH(format, "offs21")); + PrintOffs21(instr); + return 6; + } else if (format[5] == '6') { + DCHECK(STRING_STARTS_WITH(format, "offs26")); + PrintOffs26(instr); + return 6; + } + } + } + break; + } + case 'p': { + if (format[6] == '1') { + DCHECK(STRING_STARTS_WITH(format, "pcoffs16")); + PrintPCOffs16(instr); + return 8; + } else if (format[6] == '2') { + if (format[7] == '1') { + DCHECK(STRING_STARTS_WITH(format, "pcoffs21")); + PrintPCOffs21(instr); + return 8; + } else if (format[7] == '6') { + DCHECK(STRING_STARTS_WITH(format, "pcoffs26")); + PrintPCOffs26(instr); + return 8; + } + } + break; + } + case 'r': { + return FormatRegister(instr, format); + } + case 's': { + switch (format[1]) { + case 'a': + if (format[2] == '2') { + DCHECK(STRING_STARTS_WITH(format, "sa2")); + PrintSa2(instr); + } else if (format[2] == '3') { + DCHECK(STRING_STARTS_WITH(format, "sa3")); + PrintSa3(instr); + } + return 3; + case 'i': + if (format[2] == '2') { + DCHECK(STRING_STARTS_WITH(format, "si20")); + PrintSi20(instr); + return 4; + } else if (format[2] == '1') { + switch (format[3]) { + case '2': + DCHECK(STRING_STARTS_WITH(format, "si12")); + PrintSi12(instr); + return 4; + case '4': + DCHECK(STRING_STARTS_WITH(format, "si14")); + PrintSi14(instr); + return 4; + case '6': + DCHECK(STRING_STARTS_WITH(format, "si16")); + PrintSi16(instr); + return 4; + default: + break; + } + } + break; + default: + break; + } + break; + } + case 'u': { + if (format[2] == '5') { + DCHECK(STRING_STARTS_WITH(format, "ui5")); + PrintUi5(instr); + return 3; + } else if (format[2] == '6') { + DCHECK(STRING_STARTS_WITH(format, "ui6")); + PrintUi6(instr); + return 3; + } else if (format[2] == '1') { + DCHECK(STRING_STARTS_WITH(format, "ui12")); + PrintUi12(instr); + return 4; + } + break; + } + case 'x': { + if (format[2] == '2') { + DCHECK(STRING_STARTS_WITH(format, "xi20")); + PrintXi20(instr); + return 4; + } else if (format[3] == '2') { + DCHECK(STRING_STARTS_WITH(format, "xi12")); + PrintXi12(instr); + return 4; + } + break; + } + default: + UNREACHABLE(); + } + return 0; +} + +// Format takes a formatting string for a whole instruction and prints it into +// the output buffer. All escaped options are handed to FormatOption to be +// parsed further. +void Decoder::Format(Instruction* instr, const char* format) { + char cur = *format++; + while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { + if (cur == '\'') { // Single quote is used as the formatting escape. + format += FormatOption(instr, format); + } else { + out_buffer_[out_buffer_pos_++] = cur; + } + cur = *format++; + } + out_buffer_[out_buffer_pos_] = '\0'; +} + +// For currently unimplemented decodings the disassembler calls Unknown(instr) +// which will just print "unknown" of the instruction bits. +void Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); } + +int Decoder::DecodeBreakInstr(Instruction* instr) { + // This is already known to be BREAK instr, just extract the code. + /*if (instr->Bits(14, 0) == static_cast<int>(kMaxStopCode)) { + // This is stop(msg). + Format(instr, "break, code: 'code"); + out_buffer_pos_ += SNPrintF( + out_buffer_ + out_buffer_pos_, "\n%p %08" PRIx64, + static_cast<void*>(reinterpret_cast<int32_t*>(instr + kInstrSize)), + reinterpret_cast<uint64_t>( + *reinterpret_cast<char**>(instr + kInstrSize))); + // Size 3: the break_ instr, plus embedded 64-bit char pointer. + return 3 * kInstrSize; + } else { + Format(instr, "break, code: 'code"); + return kInstrSize; + }*/ + Format(instr, "break code: 'code"); + return kInstrSize; +} //=================================================== + +void Decoder::DecodeTypekOp6(Instruction* instr) { + switch (instr->Bits(31, 26) << 26) { + case ADDU16I_D: + Format(instr, "addu16i.d 'rd, 'rj, 'si16"); + break; + case BEQZ: + Format(instr, "beqz 'rj, 'offs21 -> 'pcoffs21"); + break; + case BNEZ: + Format(instr, "bnez 'rj, 'offs21 -> 'pcoffs21"); + break; + case BCZ: + if (instr->Bit(8)) + Format(instr, "bcnez fcc'cj, 'offs21 -> 'pcoffs21"); + else + Format(instr, "bceqz fcc'cj, 'offs21 -> 'pcoffs21"); + break; + case JIRL: + Format(instr, "jirl 'rd, 'rj, 'offs16"); + break; + case B: + Format(instr, "b 'offs26 -> 'pcoffs26"); + break; + case BL: + Format(instr, "bl 'offs26 -> 'pcoffs26"); + break; + case BEQ: + Format(instr, "beq 'rj, 'rd, 'offs16 -> 'pcoffs16"); + break; + case BNE: + Format(instr, "bne 'rj, 'rd, 'offs16 -> 'pcoffs16"); + break; + case BLT: + Format(instr, "blt 'rj, 'rd, 'offs16 -> 'pcoffs16"); + break; + case BGE: + Format(instr, "bge 'rj, 'rd, 'offs16 -> 'pcoffs16"); + break; + case BLTU: + Format(instr, "bltu 'rj, 'rd, 'offs16 -> 'pcoffs16"); + break; + case BGEU: + Format(instr, "bgeu 'rj, 'rd, 'offs16 -> 'pcoffs16"); + break; + default: + UNREACHABLE(); + } +} + +void Decoder::DecodeTypekOp7(Instruction* instr) { + switch (instr->Bits(31, 25) << 25) { + case LU12I_W: + Format(instr, "lu12i.w 'rd, 'xi20"); + break; + case LU32I_D: + Format(instr, "lu32i.d 'rd, 'xi20"); + break; + case PCADDI: + Format(instr, "pcaddi 'rd, 'xi20"); + break; + case PCALAU12I: + Format(instr, "pcalau12i 'rd, 'xi20"); + break; + case PCADDU12I: + Format(instr, "pcaddu12i 'rd, 'xi20"); + break; + case PCADDU18I: + Format(instr, "pcaddu18i 'rd, 'xi20"); + break; + default: + UNREACHABLE(); + } +} + +void Decoder::DecodeTypekOp8(Instruction* instr) { + switch (instr->Bits(31, 24) << 24) { + case LDPTR_W: + Format(instr, "ldptr.w 'rd, 'rj, 'si14"); + break; + case STPTR_W: + Format(instr, "stptr.w 'rd, 'rj, 'si14"); + break; + case LDPTR_D: + Format(instr, "ldptr.d 'rd, 'rj, 'si14"); + break; + case STPTR_D: + Format(instr, "stptr.d 'rd, 'rj, 'si14"); + break; + case LL_W: + Format(instr, "ll.w 'rd, 'rj, 'si14"); + break; + case SC_W: + Format(instr, "sc.w 'rd, 'rj, 'si14"); + break; + case LL_D: + Format(instr, "ll.d 'rd, 'rj, 'si14"); + break; + case SC_D: + Format(instr, "sc.d 'rd, 'rj, 'si14"); + break; + default: + UNREACHABLE(); + } +} + +void Decoder::DecodeTypekOp10(Instruction* instr) { + switch (instr->Bits(31, 22) << 22) { + case BSTR_W: { + if (instr->Bit(21) != 0) { + if (instr->Bit(15) == 0) { + Format(instr, "bstrins.w 'rd, 'rj, 'msbw, 'lsbw"); + } else { + Format(instr, "bstrpick.w 'rd, 'rj, 'msbw, 'lsbw"); + } + } + break; + } + case BSTRINS_D: + Format(instr, "bstrins.d 'rd, 'rj, 'msbd, 'lsbd"); + break; + case BSTRPICK_D: + Format(instr, "bstrpick.d 'rd, 'rj, 'msbd, 'lsbd"); + break; + case SLTI: + Format(instr, "slti 'rd, 'rj, 'si12"); + break; + case SLTUI: + Format(instr, "sltui 'rd, 'rj, 'si12"); + break; + case ADDI_W: + Format(instr, "addi.w 'rd, 'rj, 'si12"); + break; + case ADDI_D: + Format(instr, "addi.d 'rd, 'rj, 'si12"); + break; + case LU52I_D: + Format(instr, "lu52i.d 'rd, 'rj, 'xi12"); + break; + case ANDI: + Format(instr, "andi 'rd, 'rj, 'xi12"); + break; + case ORI: + Format(instr, "ori 'rd, 'rj, 'xi12"); + break; + case XORI: + Format(instr, "xori 'rd, 'rj, 'xi12"); + break; + case LD_B: + Format(instr, "ld.b 'rd, 'rj, 'si12"); + break; + case LD_H: + Format(instr, "ld.h 'rd, 'rj, 'si12"); + break; + case LD_W: + Format(instr, "ld.w 'rd, 'rj, 'si12"); + break; + case LD_D: + Format(instr, "ld.d 'rd, 'rj, 'si12"); + break; + case ST_B: + Format(instr, "st.b 'rd, 'rj, 'si12"); + break; + case ST_H: + Format(instr, "st.h 'rd, 'rj, 'si12"); + break; + case ST_W: + Format(instr, "st.w 'rd, 'rj, 'si12"); + break; + case ST_D: + Format(instr, "st.d 'rd, 'rj, 'si12"); + break; + case LD_BU: + Format(instr, "ld.bu 'rd, 'rj, 'si12"); + break; + case LD_HU: + Format(instr, "ld.hu 'rd, 'rj, 'si12"); + break; + case LD_WU: + Format(instr, "ld.wu 'rd, 'rj, 'si12"); + break; + case FLD_S: + Format(instr, "fld.s 'fd, 'rj, 'si12"); + break; + case FST_S: + Format(instr, "fst.s 'fd, 'rj, 'si12"); + break; + case FLD_D: + Format(instr, "fld.d 'fd, 'rj, 'si12"); + break; + case FST_D: + Format(instr, "fst.d 'fd, 'rj, 'si12"); + break; + default: + UNREACHABLE(); + } +} + +void Decoder::DecodeTypekOp12(Instruction* instr) { + switch (instr->Bits(31, 20) << 20) { + case FMADD_S: + Format(instr, "fmadd.s 'fd, 'fj, 'fk, 'fa"); + break; + case FMADD_D: + Format(instr, "fmadd.d 'fd, 'fj, 'fk, 'fa"); + break; + case FMSUB_S: + Format(instr, "fmsub.s 'fd, 'fj, 'fk, 'fa"); + break; + case FMSUB_D: + Format(instr, "fmsub.d 'fd, 'fj, 'fk, 'fa"); + break; + case FNMADD_S: + Format(instr, "fnmadd.s 'fd, 'fj, 'fk, 'fa"); + break; + case FNMADD_D: + Format(instr, "fnmadd.d 'fd, 'fj, 'fk, 'fa"); + break; + case FNMSUB_S: + Format(instr, "fnmsub.s 'fd, 'fj, 'fk, 'fa"); + break; + case FNMSUB_D: + Format(instr, "fnmsub.d 'fd, 'fj, 'fk, 'fa"); + break; + case FCMP_COND_S: + switch (instr->Bits(19, 15)) { + case CAF: + Format(instr, "fcmp.caf.s fcc'cd, 'fj, 'fk"); + break; + case SAF: + Format(instr, "fcmp.saf.s fcc'cd, 'fj, 'fk"); + break; + case CLT: + Format(instr, "fcmp.clt.s fcc'cd, 'fj, 'fk"); + break; + case CEQ: + Format(instr, "fcmp.ceq.s fcc'cd, 'fj, 'fk"); + break; + case SEQ: + Format(instr, "fcmp.seq.s fcc'cd, 'fj, 'fk"); + break; + case CLE: + Format(instr, "fcmp.cle.s fcc'cd, 'fj, 'fk"); + break; + case SLE: + Format(instr, "fcmp.sle.s fcc'cd, 'fj, 'fk"); + break; + case CUN: + Format(instr, "fcmp.cun.s fcc'cd, 'fj, 'fk"); + break; + case SUN: + Format(instr, "fcmp.sun.s fcc'cd, 'fj, 'fk"); + break; + case CULT: + Format(instr, "fcmp.cult.s fcc'cd, 'fj, 'fk"); + break; + case SULT: + Format(instr, "fcmp.sult.s fcc'cd, 'fj, 'fk"); + break; + case CUEQ: + Format(instr, "fcmp.cueq.s fcc'cd, 'fj, 'fk"); + break; + case SUEQ: + Format(instr, "fcmp.sueq.s fcc'cd, 'fj, 'fk"); + break; + case CULE: + Format(instr, "fcmp.cule.s fcc'cd, 'fj, 'fk"); + break; + case SULE: + Format(instr, "fcmp.sule.s fcc'cd, 'fj, 'fk"); + break; + case CNE: + Format(instr, "fcmp.cne.s fcc'cd, 'fj, 'fk"); + break; + case SNE: + Format(instr, "fcmp.sne.s fcc'cd, 'fj, 'fk"); + break; + case COR: + Format(instr, "fcmp.cor.s fcc'cd, 'fj, 'fk"); + break; + case SOR: + Format(instr, "fcmp.sor.s fcc'cd, 'fj, 'fk"); + break; + case CUNE: + Format(instr, "fcmp.cune.s fcc'cd, 'fj, 'fk"); + break; + case SUNE: + Format(instr, "fcmp.sune.s fcc'cd, 'fj, 'fk"); + break; + default: + UNREACHABLE(); + } + break; + case FCMP_COND_D: + switch (instr->Bits(19, 15)) { + case CAF: + Format(instr, "fcmp.caf.d fcc'cd, 'fj, 'fk"); + break; + case SAF: + Format(instr, "fcmp.saf.d fcc'cd, 'fj, 'fk"); + break; + case CLT: + Format(instr, "fcmp.clt.d fcc'cd, 'fj, 'fk"); + break; + case CEQ: + Format(instr, "fcmp.ceq.d fcc'cd, 'fj, 'fk"); + break; + case SEQ: + Format(instr, "fcmp.seq.d fcc'cd, 'fj, 'fk"); + break; + case CLE: + Format(instr, "fcmp.cle.d fcc'cd, 'fj, 'fk"); + break; + case SLE: + Format(instr, "fcmp.sle.d fcc'cd, 'fj, 'fk"); + break; + case CUN: + Format(instr, "fcmp.cun.d fcc'cd, 'fj, 'fk"); + break; + case SUN: + Format(instr, "fcmp.sun.d fcc'cd, 'fj, 'fk"); + break; + case CULT: + Format(instr, "fcmp.cult.d fcc'cd, 'fj, 'fk"); + break; + case SULT: + Format(instr, "fcmp.sult.d fcc'cd, 'fj, 'fk"); + break; + case CUEQ: + Format(instr, "fcmp.cueq.d fcc'cd, 'fj, 'fk"); + break; + case SUEQ: + Format(instr, "fcmp.sueq.d fcc'cd, 'fj, 'fk"); + break; + case CULE: + Format(instr, "fcmp.cule.d fcc'cd, 'fj, 'fk"); + break; + case SULE: + Format(instr, "fcmp.sule.d fcc'cd, 'fj, 'fk"); + break; + case CNE: + Format(instr, "fcmp.cne.d fcc'cd, 'fj, 'fk"); + break; + case SNE: + Format(instr, "fcmp.sne.d fcc'cd, 'fj, 'fk"); + break; + case COR: + Format(instr, "fcmp.cor.d fcc'cd, 'fj, 'fk"); + break; + case SOR: + Format(instr, "fcmp.sor.d fcc'cd, 'fj, 'fk"); + break; + case CUNE: + Format(instr, "fcmp.cune.d fcc'cd, 'fj, 'fk"); + break; + case SUNE: + Format(instr, "fcmp.sune.d fcc'cd, 'fj, 'fk"); + break; + default: + UNREACHABLE(); + } + break; + case FSEL: + Format(instr, "fsel 'fd, 'fj, 'fk, fcc'ca"); + break; + default: + UNREACHABLE(); + } +} + +void Decoder::DecodeTypekOp14(Instruction* instr) { + switch (instr->Bits(31, 18) << 18) { + case ALSL: + if (instr->Bit(17)) + Format(instr, "alsl.wu 'rd, 'rj, 'rk, 'sa2"); + else + Format(instr, "alsl.w 'rd, 'rj, 'rk, 'sa2"); + break; + case BYTEPICK_W: + Format(instr, "bytepick.w 'rd, 'rj, 'rk, 'sa2"); + break; + case BYTEPICK_D: + Format(instr, "bytepick.d 'rd, 'rj, 'rk, 'sa3"); + break; + case ALSL_D: + Format(instr, "alsl.d 'rd, 'rj, 'rk, 'sa2"); + break; + case SLLI: + if (instr->Bit(16)) + Format(instr, "slli.d 'rd, 'rj, 'ui6"); + else + Format(instr, "slli.w 'rd, 'rj, 'ui5"); + break; + case SRLI: + if (instr->Bit(16)) + Format(instr, "srli.d 'rd, 'rj, 'ui6"); + else + Format(instr, "srli.w 'rd, 'rj, 'ui5"); + break; + case SRAI: + if (instr->Bit(16)) + Format(instr, "srai.d 'rd, 'rj, 'ui6"); + else + Format(instr, "srai.w 'rd, 'rj, 'ui5"); + break; + case ROTRI: + if (instr->Bit(16)) + Format(instr, "rotri.d 'rd, 'rj, 'ui6"); + else + Format(instr, "rotri.w 'rd, 'rj, 'ui5"); + break; + default: + UNREACHABLE(); + } +} + +int Decoder::DecodeTypekOp17(Instruction* instr) { + switch (instr->Bits(31, 15) << 15) { + case ADD_W: + Format(instr, "add.w 'rd, 'rj, 'rk"); + break; + case ADD_D: + Format(instr, "add.d 'rd, 'rj, 'rk"); + break; + case SUB_W: + Format(instr, "sub.w 'rd, 'rj, 'rk"); + break; + case SUB_D: + Format(instr, "sub.d 'rd, 'rj, 'rk"); + break; + case SLT: + Format(instr, "slt 'rd, 'rj, 'rk"); + break; + case SLTU: + Format(instr, "sltu 'rd, 'rj, 'rk"); + break; + case MASKEQZ: + Format(instr, "maskeqz 'rd, 'rj, 'rk"); + break; + case MASKNEZ: + Format(instr, "masknez 'rd, 'rj, 'rk"); + break; + case NOR: + Format(instr, "nor 'rd, 'rj, 'rk"); + break; + case AND: + Format(instr, "and 'rd, 'rj, 'rk"); + break; + case OR: + Format(instr, "or 'rd, 'rj, 'rk"); + break; + case XOR: + Format(instr, "xor 'rd, 'rj, 'rk"); + break; + case ORN: + Format(instr, "orn 'rd, 'rj, 'rk"); + break; + case ANDN: + Format(instr, "andn 'rd, 'rj, 'rk"); + break; + case SLL_W: + Format(instr, "sll.w 'rd, 'rj, 'rk"); + break; + case SRL_W: + Format(instr, "srl.w 'rd, 'rj, 'rk"); + break; + case SRA_W: + Format(instr, "sra.w 'rd, 'rj, 'rk"); + break; + case SLL_D: + Format(instr, "sll.d 'rd, 'rj, 'rk"); + break; + case SRL_D: + Format(instr, "srl.d 'rd, 'rj, 'rk"); + break; + case SRA_D: + Format(instr, "sra.d 'rd, 'rj, 'rk"); + break; + case ROTR_D: + Format(instr, "rotr.d 'rd, 'rj, 'rk"); + break; + case ROTR_W: + Format(instr, "rotr.w 'rd, 'rj, 'rk"); + break; + case MUL_W: + Format(instr, "mul.w 'rd, 'rj, 'rk"); + break; + case MULH_W: + Format(instr, "mulh.w 'rd, 'rj, 'rk"); + break; + case MULH_WU: + Format(instr, "mulh.wu 'rd, 'rj, 'rk"); + break; + case MUL_D: + Format(instr, "mul.d 'rd, 'rj, 'rk"); + break; + case MULH_D: + Format(instr, "mulh.d 'rd, 'rj, 'rk"); + break; + case MULH_DU: + Format(instr, "mulh.du 'rd, 'rj, 'rk"); + break; + case MULW_D_W: + Format(instr, "mulw.d.w 'rd, 'rj, 'rk"); + break; + case MULW_D_WU: + Format(instr, "mulw.d.wu 'rd, 'rj, 'rk"); + break; + case DIV_W: + Format(instr, "div.w 'rd, 'rj, 'rk"); + break; + case MOD_W: + Format(instr, "mod.w 'rd, 'rj, 'rk"); + break; + case DIV_WU: + Format(instr, "div.wu 'rd, 'rj, 'rk"); + break; + case MOD_WU: + Format(instr, "mod.wu 'rd, 'rj, 'rk"); + break; + case DIV_D: + Format(instr, "div.d 'rd, 'rj, 'rk"); + break; + case MOD_D: + Format(instr, "mod.d 'rd, 'rj, 'rk"); + break; + case DIV_DU: + Format(instr, "div.du 'rd, 'rj, 'rk"); + break; + case MOD_DU: + Format(instr, "mod.du 'rd, 'rj, 'rk"); + break; + case BREAK: + return DecodeBreakInstr(instr); + case FADD_S: + Format(instr, "fadd.s 'fd, 'fj, 'fk"); + break; + case FADD_D: + Format(instr, "fadd.d 'fd, 'fj, 'fk"); + break; + case FSUB_S: + Format(instr, "fsub.s 'fd, 'fj, 'fk"); + break; + case FSUB_D: + Format(instr, "fsub.d 'fd, 'fj, 'fk"); + break; + case FMUL_S: + Format(instr, "fmul.s 'fd, 'fj, 'fk"); + break; + case FMUL_D: + Format(instr, "fmul.d 'fd, 'fj, 'fk"); + break; + case FDIV_S: + Format(instr, "fdiv.s 'fd, 'fj, 'fk"); + break; + case FDIV_D: + Format(instr, "fdiv.d 'fd, 'fj, 'fk"); + break; + case FMAX_S: + Format(instr, "fmax.s 'fd, 'fj, 'fk"); + break; + case FMAX_D: + Format(instr, "fmax.d 'fd, 'fj, 'fk"); + break; + case FMIN_S: + Format(instr, "fmin.s 'fd, 'fj, 'fk"); + break; + case FMIN_D: + Format(instr, "fmin.d 'fd, 'fj, 'fk"); + break; + case FMAXA_S: + Format(instr, "fmaxa.s 'fd, 'fj, 'fk"); + break; + case FMAXA_D: + Format(instr, "fmaxa.d 'fd, 'fj, 'fk"); + break; + case FMINA_S: + Format(instr, "fmina.s 'fd, 'fj, 'fk"); + break; + case FMINA_D: + Format(instr, "fmina.d 'fd, 'fj, 'fk"); + break; + case LDX_B: + Format(instr, "ldx.b 'rd, 'rj, 'rk"); + break; + case LDX_H: + Format(instr, "ldx.h 'rd, 'rj, 'rk"); + break; + case LDX_W: + Format(instr, "ldx.w 'rd, 'rj, 'rk"); + break; + case LDX_D: + Format(instr, "ldx.d 'rd, 'rj, 'rk"); + break; + case STX_B: + Format(instr, "stx.b 'rd, 'rj, 'rk"); + break; + case STX_H: + Format(instr, "stx.h 'rd, 'rj, 'rk"); + break; + case STX_W: + Format(instr, "stx.w 'rd, 'rj, 'rk"); + break; + case STX_D: + Format(instr, "stx.d 'rd, 'rj, 'rk"); + break; + case LDX_BU: + Format(instr, "ldx.bu 'rd, 'rj, 'rk"); + break; + case LDX_HU: + Format(instr, "ldx.hu 'rd, 'rj, 'rk"); + break; + case LDX_WU: + Format(instr, "ldx.wu 'rd, 'rj, 'rk"); + break; + case FLDX_S: + Format(instr, "fldx.s 'fd, 'rj, 'rk"); + break; + case FLDX_D: + Format(instr, "fldx.d 'fd, 'rj, 'rk"); + break; + case FSTX_S: + Format(instr, "fstx.s 'fd, 'rj, 'rk"); + break; + case FSTX_D: + Format(instr, "fstx.d 'fd, 'rj, 'rk"); + break; + case AMSWAP_W: + Format(instr, "amswap.w 'rd, 'rk, 'rj"); + break; + case AMSWAP_D: + Format(instr, "amswap.d 'rd, 'rk, 'rj"); + break; + case AMADD_W: + Format(instr, "amadd.w 'rd, 'rk, 'rj"); + break; + case AMADD_D: + Format(instr, "amadd.d 'rd, 'rk, 'rj"); + break; + case AMAND_W: + Format(instr, "amand.w 'rd, 'rk, 'rj"); + break; + case AMAND_D: + Format(instr, "amand.d 'rd, 'rk, 'rj"); + break; + case AMOR_W: + Format(instr, "amor.w 'rd, 'rk, 'rj"); + break; + case AMOR_D: + Format(instr, "amor.d 'rd, 'rk, 'rj"); + break; + case AMXOR_W: + Format(instr, "amxor.w 'rd, 'rk, 'rj"); + break; + case AMXOR_D: + Format(instr, "amxor.d 'rd, 'rk, 'rj"); + break; + case AMMAX_W: + Format(instr, "ammax.w 'rd, 'rk, 'rj"); + break; + case AMMAX_D: + Format(instr, "ammax.d 'rd, 'rk, 'rj"); + break; + case AMMIN_W: + Format(instr, "ammin.w 'rd, 'rk, 'rj"); + break; + case AMMIN_D: + Format(instr, "ammin.d 'rd, 'rk, 'rj"); + break; + case AMMAX_WU: + Format(instr, "ammax.wu 'rd, 'rk, 'rj"); + break; + case AMMAX_DU: + Format(instr, "ammax.du 'rd, 'rk, 'rj"); + break; + case AMMIN_WU: + Format(instr, "ammin.wu 'rd, 'rk, 'rj"); + break; + case AMMIN_DU: + Format(instr, "ammin.du 'rd, 'rk, 'rj"); + break; + case AMSWAP_DB_W: + Format(instr, "amswap_db.w 'rd, 'rk, 'rj"); + break; + case AMSWAP_DB_D: + Format(instr, "amswap_db.d 'rd, 'rk, 'rj"); + break; + case AMADD_DB_W: + Format(instr, "amadd_db.w 'rd, 'rk, 'rj"); + break; + case AMADD_DB_D: + Format(instr, "amadd_db.d 'rd, 'rk, 'rj"); + break; + case AMAND_DB_W: + Format(instr, "amand_db.w 'rd, 'rk, 'rj"); + break; + case AMAND_DB_D: + Format(instr, "amand_db.d 'rd, 'rk, 'rj"); + break; + case AMOR_DB_W: + Format(instr, "amor_db.w 'rd, 'rk, 'rj"); + break; + case AMOR_DB_D: + Format(instr, "amor_db.d 'rd, 'rk, 'rj"); + break; + case AMXOR_DB_W: + Format(instr, "amxor_db.w 'rd, 'rk, 'rj"); + break; + case AMXOR_DB_D: + Format(instr, "amxor_db.d 'rd, 'rk, 'rj"); + break; + case AMMAX_DB_W: + Format(instr, "ammax_db.w 'rd, 'rk, 'rj"); + break; + case AMMAX_DB_D: + Format(instr, "ammax_db.d 'rd, 'rk, 'rj"); + break; + case AMMIN_DB_W: + Format(instr, "ammin_db.w 'rd, 'rk, 'rj"); + break; + case AMMIN_DB_D: + Format(instr, "ammin_db.d 'rd, 'rk, 'rj"); + break; + case AMMAX_DB_WU: + Format(instr, "ammax_db.wu 'rd, 'rk, 'rj"); + break; + case AMMAX_DB_DU: + Format(instr, "ammax_db.du 'rd, 'rk, 'rj"); + break; + case AMMIN_DB_WU: + Format(instr, "ammin_db.wu 'rd, 'rk, 'rj"); + break; + case AMMIN_DB_DU: + Format(instr, "ammin_db.du 'rd, 'rk, 'rj"); + break; + case DBAR: + Format(instr, "dbar 'hint15"); + break; + case IBAR: + Format(instr, "ibar 'hint15"); + break; + case FSCALEB_S: + Format(instr, "fscaleb.s 'fd, 'fj, 'fk"); + break; + case FSCALEB_D: + Format(instr, "fscaleb.d 'fd, 'fj, 'fk"); + break; + case FCOPYSIGN_S: + Format(instr, "fcopysign.s 'fd, 'fj, 'fk"); + break; + case FCOPYSIGN_D: + Format(instr, "fcopysign.d 'fd, 'fj, 'fk"); + break; + default: + UNREACHABLE(); + } + return kInstrSize; +} + +void Decoder::DecodeTypekOp22(Instruction* instr) { + switch (instr->Bits(31, 10) << 10) { + case CLZ_W: + Format(instr, "clz.w 'rd, 'rj"); + break; + case CTZ_W: + Format(instr, "ctz.w 'rd, 'rj"); + break; + case CLZ_D: + Format(instr, "clz.d 'rd, 'rj"); + break; + case CTZ_D: + Format(instr, "ctz.d 'rd, 'rj"); + break; + case REVB_2H: + Format(instr, "revb.2h 'rd, 'rj"); + break; + case REVB_4H: + Format(instr, "revb.4h 'rd, 'rj"); + break; + case REVB_2W: + Format(instr, "revb.2w 'rd, 'rj"); + break; + case REVB_D: + Format(instr, "revb.d 'rd, 'rj"); + break; + case REVH_2W: + Format(instr, "revh.2w 'rd, 'rj"); + break; + case REVH_D: + Format(instr, "revh.d 'rd, 'rj"); + break; + case BITREV_4B: + Format(instr, "bitrev.4b 'rd, 'rj"); + break; + case BITREV_8B: + Format(instr, "bitrev.8b 'rd, 'rj"); + break; + case BITREV_W: + Format(instr, "bitrev.w 'rd, 'rj"); + break; + case BITREV_D: + Format(instr, "bitrev.d 'rd, 'rj"); + break; + case EXT_W_B: + Format(instr, "ext.w.b 'rd, 'rj"); + break; + case EXT_W_H: + Format(instr, "ext.w.h 'rd, 'rj"); + break; + case FABS_S: + Format(instr, "fabs.s 'fd, 'fj"); + break; + case FABS_D: + Format(instr, "fabs.d 'fd, 'fj"); + break; + case FNEG_S: + Format(instr, "fneg.s 'fd, 'fj"); + break; + case FNEG_D: + Format(instr, "fneg.d 'fd, 'fj"); + break; + case FSQRT_S: + Format(instr, "fsqrt.s 'fd, 'fj"); + break; + case FSQRT_D: + Format(instr, "fsqrt.d 'fd, 'fj"); + break; + case FMOV_S: + Format(instr, "fmov.s 'fd, 'fj"); + break; + case FMOV_D: + Format(instr, "fmov.d 'fd, 'fj"); + break; + case MOVGR2FR_W: + Format(instr, "movgr2fr.w 'fd, 'rj"); + break; + case MOVGR2FR_D: + Format(instr, "movgr2fr.d 'fd, 'rj"); + break; + case MOVGR2FRH_W: + Format(instr, "movgr2frh.w 'fd, 'rj"); + break; + case MOVFR2GR_S: + Format(instr, "movfr2gr.s 'rd, 'fj"); + break; + case MOVFR2GR_D: + Format(instr, "movfr2gr.d 'rd, 'fj"); + break; + case MOVFRH2GR_S: + Format(instr, "movfrh2gr.s 'rd, 'fj"); + break; + case MOVGR2FCSR: + Format(instr, "movgr2fcsr fcsr, 'rj"); + break; + case MOVFCSR2GR: + Format(instr, "movfcsr2gr 'rd, fcsr"); + break; + case FCVT_S_D: + Format(instr, "fcvt.s.d 'fd, 'fj"); + break; + case FCVT_D_S: + Format(instr, "fcvt.d.s 'fd, 'fj"); + break; + case FTINTRM_W_S: + Format(instr, "ftintrm.w.s 'fd, 'fj"); + break; + case FTINTRM_W_D: + Format(instr, "ftintrm.w.d 'fd, 'fj"); + break; + case FTINTRM_L_S: + Format(instr, "ftintrm.l.s 'fd, 'fj"); + break; + case FTINTRM_L_D: + Format(instr, "ftintrm.l.d 'fd, 'fj"); + break; + case FTINTRP_W_S: + Format(instr, "ftintrp.w.s 'fd, 'fj"); + break; + case FTINTRP_W_D: + Format(instr, "ftintrp.w.d 'fd, 'fj"); + break; + case FTINTRP_L_S: + Format(instr, "ftintrp.l.s 'fd, 'fj"); + break; + case FTINTRP_L_D: + Format(instr, "ftintrp.l.d 'fd, 'fj"); + break; + case FTINTRZ_W_S: + Format(instr, "ftintrz.w.s 'fd, 'fj"); + break; + case FTINTRZ_W_D: + Format(instr, "ftintrz.w.d 'fd, 'fj"); + break; + case FTINTRZ_L_S: + Format(instr, "ftintrz.l.s 'fd, 'fj"); + break; + case FTINTRZ_L_D: + Format(instr, "ftintrz.l.d 'fd, 'fj"); + break; + case FTINTRNE_W_S: + Format(instr, "ftintrne.w.s 'fd, 'fj"); + break; + case FTINTRNE_W_D: + Format(instr, "ftintrne.w.d 'fd, 'fj"); + break; + case FTINTRNE_L_S: + Format(instr, "ftintrne.l.s 'fd, 'fj"); + break; + case FTINTRNE_L_D: + Format(instr, "ftintrne.l.d 'fd, 'fj"); + break; + case FTINT_W_S: + Format(instr, "ftint.w.s 'fd, 'fj"); + break; + case FTINT_W_D: + Format(instr, "ftint.w.d 'fd, 'fj"); + break; + case FTINT_L_S: + Format(instr, "ftint.l.s 'fd, 'fj"); + break; + case FTINT_L_D: + Format(instr, "ftint.l.d 'fd, 'fj"); + break; + case FFINT_S_W: + Format(instr, "ffint.s.w 'fd, 'fj"); + break; + case FFINT_S_L: + Format(instr, "ffint.s.l 'fd, 'fj"); + break; + case FFINT_D_W: + Format(instr, "ffint.d.w 'fd, 'fj"); + break; + case FFINT_D_L: + Format(instr, "ffint.d.l 'fd, 'fj"); + break; + case FRINT_S: + Format(instr, "frint.s 'fd, 'fj"); + break; + case FRINT_D: + Format(instr, "frint.d 'fd, 'fj"); + break; + case MOVFR2CF: + Format(instr, "movfr2cf fcc'cd, 'fj"); + break; + case MOVCF2FR: + Format(instr, "movcf2fr 'fd, fcc'cj"); + break; + case MOVGR2CF: + Format(instr, "movgr2cf fcc'cd, 'rj"); + break; + case MOVCF2GR: + Format(instr, "movcf2gr 'rd, fcc'cj"); + break; + case FRECIP_S: + Format(instr, "frecip.s 'fd, 'fj"); + break; + case FRECIP_D: + Format(instr, "frecip.d 'fd, 'fj"); + break; + case FRSQRT_S: + Format(instr, "frsqrt.s 'fd, 'fj"); + break; + case FRSQRT_D: + Format(instr, "frsqrt.d 'fd, 'fj"); + break; + case FCLASS_S: + Format(instr, "fclass.s 'fd, 'fj"); + break; + case FCLASS_D: + Format(instr, "fclass.d 'fd, 'fj"); + break; + case FLOGB_S: + Format(instr, "flogb.s 'fd, 'fj"); + break; + case FLOGB_D: + Format(instr, "flogb.d 'fd, 'fj"); + break; + case CLO_W: + Format(instr, "clo.w 'rd, 'rj"); + break; + case CTO_W: + Format(instr, "cto.w 'rd, 'rj"); + break; + case CLO_D: + Format(instr, "clo.d 'rd, 'rj"); + break; + case CTO_D: + Format(instr, "cto.d 'rd, 'rj"); + break; + default: + UNREACHABLE(); + } +} + +int Decoder::InstructionDecode(byte* instr_ptr) { + Instruction* instr = Instruction::At(instr_ptr); + out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, + "%08x ", instr->InstructionBits()); + switch (instr->InstructionType()) { + case Instruction::kOp6Type: { + DecodeTypekOp6(instr); + break; + } + case Instruction::kOp7Type: { + DecodeTypekOp7(instr); + break; + } + case Instruction::kOp8Type: { + DecodeTypekOp8(instr); + break; + } + case Instruction::kOp10Type: { + DecodeTypekOp10(instr); + break; + } + case Instruction::kOp12Type: { + DecodeTypekOp12(instr); + break; + } + case Instruction::kOp14Type: { + DecodeTypekOp14(instr); + break; + } + case Instruction::kOp17Type: { + return DecodeTypekOp17(instr); + } + case Instruction::kOp22Type: { + DecodeTypekOp22(instr); + break; + } + case Instruction::kUnsupported: { + Format(instr, "UNSUPPORTED"); + break; + } + default: { + Format(instr, "UNSUPPORTED"); + break; + } + } + return kInstrSize; +} + +} // namespace internal +} // namespace v8 + +//------------------------------------------------------------------------------ + +namespace disasm { + +const char* NameConverter::NameOfAddress(byte* addr) const { + v8::base::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr)); + return tmp_buffer_.begin(); +} + +const char* NameConverter::NameOfConstant(byte* addr) const { + return NameOfAddress(addr); +} + +const char* NameConverter::NameOfCPURegister(int reg) const { + return v8::internal::Registers::Name(reg); +} + +const char* NameConverter::NameOfXMMRegister(int reg) const { + return v8::internal::FPURegisters::Name(reg); +} + +const char* NameConverter::NameOfByteCPURegister(int reg) const { + UNREACHABLE(); +} + +const char* NameConverter::NameInCode(byte* addr) const { + // The default name converter is called for unknown code. So we will not try + // to access any memory. + return ""; +} + +//------------------------------------------------------------------------------ + +int Disassembler::InstructionDecode(v8::base::Vector<char> buffer, + byte* instruction) { + v8::internal::Decoder d(converter_, buffer); + return d.InstructionDecode(instruction); +} + +int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } + +void Disassembler::Disassemble(FILE* f, byte* begin, byte* end, + UnimplementedOpcodeAction unimplemented_action) { + NameConverter converter; + Disassembler d(converter, unimplemented_action); + for (byte* pc = begin; pc < end;) { + v8::base::EmbeddedVector<char, 128> buffer; + buffer[0] = '\0'; + byte* prev_pc = pc; + pc += d.InstructionDecode(buffer, pc); + v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc), + *reinterpret_cast<int32_t*>(prev_pc), buffer.begin()); + } +} + +#undef STRING_STARTS_WITH + +} // namespace disasm + +#endif // V8_TARGET_ARCH_LOONG64 diff --git a/chromium/v8/src/diagnostics/loong64/unwinder-loong64.cc b/chromium/v8/src/diagnostics/loong64/unwinder-loong64.cc new file mode 100644 index 00000000000..84d2e41cfc8 --- /dev/null +++ b/chromium/v8/src/diagnostics/loong64/unwinder-loong64.cc @@ -0,0 +1,14 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/diagnostics/unwinder.h" + +namespace v8 { + +struct RegisterState; + +void GetCalleeSavedRegistersFromEntryFrame(void* fp, + RegisterState* register_state) {} + +} // namespace v8 diff --git a/chromium/v8/src/diagnostics/mips/disasm-mips.cc b/chromium/v8/src/diagnostics/mips/disasm-mips.cc index c5aeb274573..32a0bdb0488 100644 --- a/chromium/v8/src/diagnostics/mips/disasm-mips.cc +++ b/chromium/v8/src/diagnostics/mips/disasm-mips.cc @@ -555,7 +555,6 @@ void Decoder::PrintMsaDataFormat(Instruction* instr) { break; default: UNREACHABLE(); - break; } } else { char DF[] = {'b', 'h', 'w', 'd'}; @@ -600,7 +599,6 @@ void Decoder::PrintMsaDataFormat(Instruction* instr) { break; default: UNREACHABLE(); - break; } } @@ -904,7 +902,6 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { PrintSa(instr); return 2; } - break; case 'd': { DCHECK(STRING_STARTS_WITH(format, "sd")); PrintSd(instr); @@ -1521,7 +1518,6 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { } default: UNREACHABLE(); - break; } } } @@ -1538,7 +1534,6 @@ void Decoder::DecodeTypeRegister(Instruction* instr) { switch (instr->RsFieldRaw()) { case BC1: // bc1 handled in DecodeTypeImmediate. UNREACHABLE(); - break; case MFC1: Format(instr, "mfc1 'rt, 'fs"); break; @@ -1966,7 +1961,6 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { break; default: UNREACHABLE(); - break; } } } @@ -1997,7 +1991,6 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { break; default: UNREACHABLE(); - break; } break; default: @@ -2703,7 +2696,6 @@ const char* NameConverter::NameOfXMMRegister(int reg) const { const char* NameConverter::NameOfByteCPURegister(int reg) const { UNREACHABLE(); // MIPS does not have the concept of a byte register. - return "nobytereg"; } const char* NameConverter::NameInCode(byte* addr) const { diff --git a/chromium/v8/src/diagnostics/mips64/disasm-mips64.cc b/chromium/v8/src/diagnostics/mips64/disasm-mips64.cc index d8ff14730d0..0712431fc3b 100644 --- a/chromium/v8/src/diagnostics/mips64/disasm-mips64.cc +++ b/chromium/v8/src/diagnostics/mips64/disasm-mips64.cc @@ -596,7 +596,6 @@ void Decoder::PrintMsaDataFormat(Instruction* instr) { break; default: UNREACHABLE(); - break; } } else { char DF[] = {'b', 'h', 'w', 'd'}; @@ -641,7 +640,6 @@ void Decoder::PrintMsaDataFormat(Instruction* instr) { break; default: UNREACHABLE(); - break; } } @@ -945,7 +943,6 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { PrintSa(instr); return 2; } - break; case 'd': { DCHECK(STRING_STARTS_WITH(format, "sd")); PrintSd(instr); @@ -1744,7 +1741,6 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { } default: UNREACHABLE(); - break; } break; } @@ -1761,7 +1757,6 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { break; default: UNREACHABLE(); - break; } break; } @@ -1782,7 +1777,6 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { } default: UNREACHABLE(); - break; } break; } @@ -2250,7 +2244,6 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { break; default: UNREACHABLE(); - break; } break; } @@ -2285,7 +2278,6 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { break; default: UNREACHABLE(); - break; } break; default: @@ -2993,7 +2985,6 @@ const char* NameConverter::NameOfXMMRegister(int reg) const { const char* NameConverter::NameOfByteCPURegister(int reg) const { UNREACHABLE(); // MIPS does not have the concept of a byte register. - return "nobytereg"; } const char* NameConverter::NameInCode(byte* addr) const { diff --git a/chromium/v8/src/diagnostics/objects-debug.cc b/chromium/v8/src/diagnostics/objects-debug.cc index e45d7580c8f..de003a4a549 100644 --- a/chromium/v8/src/diagnostics/objects-debug.cc +++ b/chromium/v8/src/diagnostics/objects-debug.cc @@ -166,7 +166,9 @@ void TaggedIndex::TaggedIndexVerify(Isolate* isolate) { } void HeapObject::HeapObjectVerify(Isolate* isolate) { - TorqueGeneratedClassVerifiers::HeapObjectVerify(*this, isolate); + CHECK(IsHeapObject()); + VerifyPointer(isolate, map(isolate)); + CHECK(map(isolate).IsMap()); switch (map().instance_type()) { #define STRING_TYPE_CASE(TYPE, size, name, CamelName) case TYPE: @@ -293,6 +295,7 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) { BigIntBase::cast(*this).BigIntBaseVerify(isolate); break; + case JS_CLASS_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE: @@ -343,8 +346,6 @@ void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) { } } -USE_TORQUE_VERIFIER(JSReceiver) - bool JSObject::ElementsAreSafeToExamine(PtrComprCageBase cage_base) const { // If a GC was caused while constructing this object, the elements // pointer may point to a one pointer filler map. @@ -419,7 +420,7 @@ void JSObject::JSObjectVerify(Isolate* isolate) { for (InternalIndex i : map().IterateOwnDescriptors()) { PropertyDetails details = descriptors.GetDetails(i); - if (details.location() == kField) { + if (details.location() == PropertyLocation::kField) { DCHECK_EQ(kData, details.kind()); Representation r = details.representation(); FieldIndex index = FieldIndex::ForDescriptor(map(), i); @@ -654,7 +655,7 @@ void DescriptorArray::DescriptorArrayVerify(Isolate* isolate) { } MaybeObject value = GetValue(descriptor); HeapObject heap_object; - if (details.location() == kField) { + if (details.location() == PropertyLocation::kField) { CHECK_EQ(details.field_index(), expected_field_index); CHECK( value == MaybeObject::FromObject(FieldType::None()) || @@ -785,8 +786,6 @@ void JSDate::JSDateVerify(Isolate* isolate) { } } -USE_TORQUE_VERIFIER(JSMessageObject) - void String::StringVerify(Isolate* isolate) { TorqueGeneratedClassVerifiers::StringVerify(*this, isolate); CHECK(length() >= 0 && length() <= Smi::kMaxValue); @@ -830,7 +829,24 @@ void JSBoundFunction::JSBoundFunctionVerify(Isolate* isolate) { } void JSFunction::JSFunctionVerify(Isolate* isolate) { - TorqueGeneratedClassVerifiers::JSFunctionVerify(*this, isolate); + // Don't call TorqueGeneratedClassVerifiers::JSFunctionVerify here because the + // Torque class definition contains the field `prototype_or_initial_map` which + // may not be allocated. + + // This assertion exists to encourage updating this verification function if + // new fields are added in the Torque class layout definition. + STATIC_ASSERT(JSFunction::TorqueGeneratedClass::kHeaderSize == + 8 * kTaggedSize); + + JSFunctionOrBoundFunctionVerify(isolate); + CHECK(IsJSFunction()); + VerifyPointer(isolate, shared(isolate)); + CHECK(shared(isolate).IsSharedFunctionInfo()); + VerifyPointer(isolate, context(isolate, kRelaxedLoad)); + CHECK(context(isolate, kRelaxedLoad).IsContext()); + VerifyPointer(isolate, raw_feedback_cell(isolate)); + CHECK(raw_feedback_cell(isolate).IsFeedbackCell()); + VerifyPointer(isolate, raw_code(isolate)); CHECK(raw_code(isolate).IsCodeT()); CHECK(map(isolate).is_callable()); Handle<JSFunction> function(*this, isolate); @@ -1005,8 +1021,11 @@ void Code::CodeVerify(Isolate* isolate) { CHECK_LE(constant_pool_offset(), code_comments_offset()); CHECK_LE(code_comments_offset(), unwinding_info_offset()); CHECK_LE(unwinding_info_offset(), MetadataSize()); +#if !defined(_MSC_VER) || defined(__clang__) + // See also: PlatformEmbeddedFileWriterWin::AlignToCodeAlignment. CHECK_IMPLIES(!ReadOnlyHeap::Contains(*this), IsAligned(InstructionStart(), kCodeAlignment)); +#endif // !defined(_MSC_VER) || defined(__clang__) CHECK_IMPLIES(!ReadOnlyHeap::Contains(*this), IsAligned(raw_instruction_start(), kCodeAlignment)); if (V8_EXTERNAL_CODE_SPACE_BOOL) { @@ -1139,19 +1158,13 @@ void JSWeakRef::JSWeakRefVerify(Isolate* isolate) { } void JSFinalizationRegistry::JSFinalizationRegistryVerify(Isolate* isolate) { - CHECK(IsJSFinalizationRegistry()); - JSObjectVerify(isolate); - VerifyHeapPointer(isolate, cleanup()); - CHECK(active_cells().IsUndefined(isolate) || active_cells().IsWeakCell()); + TorqueGeneratedClassVerifiers::JSFinalizationRegistryVerify(*this, isolate); if (active_cells().IsWeakCell()) { CHECK(WeakCell::cast(active_cells()).prev().IsUndefined(isolate)); } - CHECK(cleared_cells().IsUndefined(isolate) || cleared_cells().IsWeakCell()); if (cleared_cells().IsWeakCell()) { CHECK(WeakCell::cast(cleared_cells()).prev().IsUndefined(isolate)); } - CHECK(next_dirty().IsUndefined(isolate) || - next_dirty().IsJSFinalizationRegistry()); } void JSWeakMap::JSWeakMapVerify(Isolate* isolate) { @@ -1236,8 +1249,9 @@ void SmallOrderedHashTable<Derived>::SmallOrderedHashTableVerify( } } } + void SmallOrderedHashMap::SmallOrderedHashMapVerify(Isolate* isolate) { - TorqueGeneratedClassVerifiers::SmallOrderedHashMapVerify(*this, isolate); + CHECK(IsSmallOrderedHashMap()); SmallOrderedHashTable<SmallOrderedHashMap>::SmallOrderedHashTableVerify( isolate); for (int entry = NumberOfElements(); entry < NumberOfDeletedElements(); @@ -1250,7 +1264,7 @@ void SmallOrderedHashMap::SmallOrderedHashMapVerify(Isolate* isolate) { } void SmallOrderedHashSet::SmallOrderedHashSetVerify(Isolate* isolate) { - TorqueGeneratedClassVerifiers::SmallOrderedHashSetVerify(*this, isolate); + CHECK(IsSmallOrderedHashSet()); SmallOrderedHashTable<SmallOrderedHashSet>::SmallOrderedHashTableVerify( isolate); for (int entry = NumberOfElements(); entry < NumberOfDeletedElements(); @@ -1264,8 +1278,7 @@ void SmallOrderedHashSet::SmallOrderedHashSetVerify(Isolate* isolate) { void SmallOrderedNameDictionary::SmallOrderedNameDictionaryVerify( Isolate* isolate) { - TorqueGeneratedClassVerifiers::SmallOrderedNameDictionaryVerify(*this, - isolate); + CHECK(IsSmallOrderedNameDictionary()); SmallOrderedHashTable< SmallOrderedNameDictionary>::SmallOrderedHashTableVerify(isolate); for (int entry = NumberOfElements(); entry < NumberOfDeletedElements(); @@ -1355,7 +1368,7 @@ void SwissNameDictionary::SwissNameDictionaryVerify(Isolate* isolate, void JSRegExp::JSRegExpVerify(Isolate* isolate) { TorqueGeneratedClassVerifiers::JSRegExpVerify(*this, isolate); - switch (TypeTag()) { + switch (type_tag()) { case JSRegExp::ATOM: { FixedArray arr = FixedArray::cast(data()); CHECK(arr.get(JSRegExp::kAtomPatternIndex).IsString()); @@ -1433,7 +1446,7 @@ void JSRegExp::JSRegExpVerify(Isolate* isolate) { break; } default: - CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag()); + CHECK_EQ(JSRegExp::NOT_COMPILED, type_tag()); CHECK(data().IsUndefined(isolate)); break; } @@ -1661,9 +1674,20 @@ void WasmExportedFunctionData::WasmExportedFunctionDataVerify( #endif // V8_ENABLE_WEBASSEMBLY void DataHandler::DataHandlerVerify(Isolate* isolate) { - TorqueGeneratedClassVerifiers::DataHandlerVerify(*this, isolate); + // Don't call TorqueGeneratedClassVerifiers::DataHandlerVerify because the + // Torque definition of this class includes all of the optional fields. + + // This assertion exists to encourage updating this verification function if + // new fields are added in the Torque class layout definition. + STATIC_ASSERT(DataHandler::kHeaderSize == 6 * kTaggedSize); + + StructVerify(isolate); + CHECK(IsDataHandler()); + VerifyPointer(isolate, smi_handler(isolate)); CHECK_IMPLIES(!smi_handler().IsSmi(), IsStoreHandler() && smi_handler().IsCodeT()); + VerifyPointer(isolate, validity_cell(isolate)); + CHECK(validity_cell().IsSmi() || validity_cell().IsCell()); int data_count = data_field_count(); if (data_count >= 1) { VerifyMaybeObjectField(isolate, kData1Offset); diff --git a/chromium/v8/src/diagnostics/objects-printer.cc b/chromium/v8/src/diagnostics/objects-printer.cc index 46fccedde75..8a98a152db0 100644 --- a/chromium/v8/src/diagnostics/objects-printer.cc +++ b/chromium/v8/src/diagnostics/objects-printer.cc @@ -234,6 +234,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { case BIG_INT_BASE_TYPE: BigIntBase::cast(*this).BigIntBasePrint(os); break; + case JS_CLASS_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE: @@ -295,18 +296,18 @@ bool JSObject::PrintProperties(std::ostream& os) { os << ": "; PropertyDetails details = descs.GetDetails(i); switch (details.location()) { - case kField: { + case PropertyLocation::kField: { FieldIndex field_index = FieldIndex::ForDescriptor(map(), i); os << Brief(RawFastPropertyAt(field_index)); break; } - case kDescriptor: + case PropertyLocation::kDescriptor: os << Brief(descs.GetStrongValue(i)); break; } os << " "; details.PrintAsFastTo(os, PropertyDetails::kForProperties); - if (details.location() == kField) { + if (details.location() == PropertyLocation::kField) { int field_index = details.field_index(); if (field_index < nof_inobject_properties) { os << ", location: in-object"; @@ -821,10 +822,15 @@ namespace { void PrintContextWithHeader(std::ostream& os, Context context, const char* type) { context.PrintHeader(os, type); - os << "\n - length: " << context.length(); + os << "\n - type: " << context.map().instance_type(); os << "\n - scope_info: " << Brief(context.scope_info()); os << "\n - previous: " << Brief(context.unchecked_previous()); os << "\n - native_context: " << Brief(context.native_context()); + if (context.scope_info().HasContextExtensionSlot()) { + os << "\n - extension: " << context.extension(); + } + os << "\n - length: " << context.length(); + os << "\n - elements:"; PrintFixedArrayElements(os, context); os << "\n"; } @@ -1336,24 +1342,15 @@ void JSDate::JSDatePrint(std::ostream& os) { JSObjectPrintBody(os, *this); } -void JSProxy::JSProxyPrint(std::ostream& os) { - PrintHeader(os, "JSProxy"); - os << "\n - target: "; - target().ShortPrint(os); - os << "\n - handler: "; - handler().ShortPrint(os); - os << "\n"; -} - void JSSet::JSSetPrint(std::ostream& os) { JSObjectPrintHeader(os, *this, "JSSet"); - os << " - table: " << Brief(table()); + os << "\n - table: " << Brief(table()); JSObjectPrintBody(os, *this); } void JSMap::JSMapPrint(std::ostream& os) { JSObjectPrintHeader(os, *this, "JSMap"); - os << " - table: " << Brief(table()); + os << "\n - table: " << Brief(table()); JSObjectPrintBody(os, *this); } @@ -1373,18 +1370,6 @@ void JSMapIterator::JSMapIteratorPrint(std::ostream& os) { JSCollectionIteratorPrint(os, "JSMapIterator"); } -void WeakCell::WeakCellPrint(std::ostream& os) { - PrintHeader(os, "WeakCell"); - os << "\n - finalization_registry: " << Brief(finalization_registry()); - os << "\n - target: " << Brief(target()); - os << "\n - holdings: " << Brief(holdings()); - os << "\n - prev: " << Brief(prev()); - os << "\n - next: " << Brief(next()); - os << "\n - unregister_token: " << Brief(unregister_token()); - os << "\n - key_list_prev: " << Brief(key_list_prev()); - os << "\n - key_list_next: " << Brief(key_list_next()); -} - void JSWeakRef::JSWeakRefPrint(std::ostream& os) { JSObjectPrintHeader(os, *this, "JSWeakRef"); os << "\n - target: " << Brief(target()); @@ -1513,7 +1498,7 @@ void JSFunction::JSFunctionPrint(std::ostream& os) { } os << "\n - formal_parameter_count: " - << shared().internal_formal_parameter_count(); + << shared().internal_formal_parameter_count_without_receiver(); os << "\n - kind: " << shared().kind(); os << "\n - context: " << Brief(context()); os << "\n - code: " << Brief(raw_code()); @@ -1583,7 +1568,8 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) { os << "\n - kind: " << kind(); os << "\n - syntax kind: " << syntax_kind(); os << "\n - function_map_index: " << function_map_index(); - os << "\n - formal_parameter_count: " << internal_formal_parameter_count(); + os << "\n - formal_parameter_count: " + << internal_formal_parameter_count_without_receiver(); os << "\n - expected_nof_properties: " << expected_nof_properties(); os << "\n - language_mode: " << language_mode(); os << "\n - data: " << Brief(function_data(kAcquireLoad)); @@ -1658,7 +1644,7 @@ void Code::CodePrint(std::ostream& os) { void CodeDataContainer::CodeDataContainerPrint(std::ostream& os) { PrintHeader(os, "CodeDataContainer"); - os << "\n - kind_specific_flags: " << kind_specific_flags(); + os << "\n - kind_specific_flags: " << kind_specific_flags(kRelaxedLoad); if (V8_EXTERNAL_CODE_SPACE_BOOL) { os << "\n - code: " << Brief(code()); os << "\n - code_entry_point: " @@ -1673,67 +1659,6 @@ void Foreign::ForeignPrint(std::ostream& os) { os << "\n"; } -void CallbackTask::CallbackTaskPrint(std::ostream& os) { - PrintHeader(os, "CallbackTask"); - os << "\n - callback: " << Brief(callback()); - os << "\n - data: " << Brief(data()); - os << "\n"; -} - -void CallableTask::CallableTaskPrint(std::ostream& os) { - PrintHeader(os, "CallableTask"); - os << "\n - context: " << Brief(context()); - os << "\n - callable: " << Brief(callable()); - os << "\n"; -} - -void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskPrint( - std::ostream& os) { - PrintHeader(os, "PromiseFulfillReactionJobTask"); - os << "\n - argument: " << Brief(argument()); - os << "\n - context: " << Brief(context()); - os << "\n - handler: " << Brief(handler()); - os << "\n - promise_or_capability: " << Brief(promise_or_capability()); - os << "\n"; -} - -void PromiseRejectReactionJobTask::PromiseRejectReactionJobTaskPrint( - std::ostream& os) { - PrintHeader(os, "PromiseRejectReactionJobTask"); - os << "\n - argument: " << Brief(argument()); - os << "\n - context: " << Brief(context()); - os << "\n - handler: " << Brief(handler()); - os << "\n - promise_or_capability: " << Brief(promise_or_capability()); - os << "\n"; -} - -void PromiseResolveThenableJobTask::PromiseResolveThenableJobTaskPrint( - std::ostream& os) { - PrintHeader(os, "PromiseResolveThenableJobTask"); - os << "\n - context: " << Brief(context()); - os << "\n - promise_to_resolve: " << Brief(promise_to_resolve()); - os << "\n - then: " << Brief(then()); - os << "\n - thenable: " << Brief(thenable()); - os << "\n"; -} - -void PromiseCapability::PromiseCapabilityPrint(std::ostream& os) { - PrintHeader(os, "PromiseCapability"); - os << "\n - promise: " << Brief(promise()); - os << "\n - resolve: " << Brief(resolve()); - os << "\n - reject: " << Brief(reject()); - os << "\n"; -} - -void PromiseReaction::PromiseReactionPrint(std::ostream& os) { - PrintHeader(os, "PromiseReaction"); - os << "\n - next: " << Brief(next()); - os << "\n - reject_handler: " << Brief(reject_handler()); - os << "\n - fulfill_handler: " << Brief(fulfill_handler()); - os << "\n - promise_or_capability: " << Brief(promise_or_capability()); - os << "\n"; -} - void AsyncGeneratorRequest::AsyncGeneratorRequestPrint(std::ostream& os) { PrintHeader(os, "AsyncGeneratorRequest"); const char* mode = "Invalid!"; @@ -1754,19 +1679,6 @@ void AsyncGeneratorRequest::AsyncGeneratorRequestPrint(std::ostream& os) { os << "\n"; } -void SourceTextModuleInfoEntry::SourceTextModuleInfoEntryPrint( - std::ostream& os) { - PrintHeader(os, "SourceTextModuleInfoEntry"); - os << "\n - export_name: " << Brief(export_name()); - os << "\n - local_name: " << Brief(local_name()); - os << "\n - import_name: " << Brief(import_name()); - os << "\n - module_request: " << module_request(); - os << "\n - cell_index: " << cell_index(); - os << "\n - beg_pos: " << beg_pos(); - os << "\n - end_pos: " << end_pos(); - os << "\n"; -} - static void PrintModuleFields(Module module, std::ostream& os) { os << "\n - exports: " << Brief(module.exports()); os << "\n - status: " << module.status(); @@ -1797,14 +1709,6 @@ void SourceTextModule::SourceTextModulePrint(std::ostream& os) { os << "\n"; } -void SyntheticModule::SyntheticModulePrint(std::ostream& os) { - PrintHeader(os, "SyntheticModule"); - PrintModuleFields(*this, os); - os << "\n - export_names: " << Brief(export_names()); - os << "\n - name: " << Brief(name()); - os << "\n"; -} - void JSModuleNamespace::JSModuleNamespacePrint(std::ostream& os) { JSObjectPrintHeader(os, *this, "JSModuleNamespace"); os << "\n - module: " << Brief(module()); @@ -1821,13 +1725,6 @@ void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) { os << "\n"; } -void ClassPositions::ClassPositionsPrint(std::ostream& os) { - PrintHeader(os, "ClassPositions"); - os << "\n - start position: " << start(); - os << "\n - end position: " << end(); - os << "\n"; -} - void ArrayBoilerplateDescription::ArrayBoilerplateDescriptionPrint( std::ostream& os) { PrintHeader(os, "ArrayBoilerplateDescription"); @@ -1836,15 +1733,6 @@ void ArrayBoilerplateDescription::ArrayBoilerplateDescriptionPrint( os << "\n"; } -void RegExpBoilerplateDescription::RegExpBoilerplateDescriptionPrint( - std::ostream& os) { - PrintHeader(os, "RegExpBoilerplateDescription"); - os << "\n - data: " << Brief(data()); - os << "\n - source: " << Brief(source()); - os << "\n - flags: " << flags(); - os << "\n"; -} - #if V8_ENABLE_WEBASSEMBLY void AsmWasmData::AsmWasmDataPrint(std::ostream& os) { PrintHeader(os, "AsmWasmData"); @@ -1898,10 +1786,11 @@ void WasmStruct::WasmStructPrint(std::ostream& os) { os << Brief(base::ReadUnalignedValue<Object>(field_address)); break; case wasm::kS128: - case wasm::kBottom: - case wasm::kVoid: os << "UNIMPLEMENTED"; // TODO(7748): Implement. break; + case wasm::kBottom: + case wasm::kVoid: + UNREACHABLE(); } } os << "\n"; @@ -1947,12 +1836,6 @@ void WasmArray::WasmArrayPrint(std::ostream& os) { os << "\n"; } -void WasmExceptionTag::WasmExceptionTagPrint(std::ostream& os) { - PrintHeader(os, "WasmExceptionTag"); - os << "\n - index: " << index(); - os << "\n"; -} - void WasmInstanceObject::WasmInstanceObjectPrint(std::ostream& os) { JSObjectPrintHeader(os, *this, "WasmInstanceObject"); os << "\n - module_object: " << Brief(module_object()); @@ -1985,7 +1868,6 @@ void WasmInstanceObject::WasmInstanceObjectPrint(std::ostream& os) { } os << "\n - memory_start: " << static_cast<void*>(memory_start()); os << "\n - memory_size: " << memory_size(); - os << "\n - memory_mask: " << AsHex(memory_mask()); os << "\n - imported_function_targets: " << static_cast<void*>(imported_function_targets()); os << "\n - globals_start: " << static_cast<void*>(globals_start()); @@ -2045,15 +1927,6 @@ void WasmModuleObject::WasmModuleObjectPrint(std::ostream& os) { os << "\n"; } -void WasmTableObject::WasmTableObjectPrint(std::ostream& os) { - PrintHeader(os, "WasmTableObject"); - os << "\n - elements: " << Brief(elements()); - os << "\n - maximum_length: " << Brief(maximum_length()); - os << "\n - dispatch_tables: " << Brief(dispatch_tables()); - os << "\n - raw_type: " << raw_type(); - os << "\n"; -} - void WasmGlobalObject::WasmGlobalObjectPrint(std::ostream& os) { PrintHeader(os, "WasmGlobalObject"); if (type().is_reference()) { @@ -2069,21 +1942,6 @@ void WasmGlobalObject::WasmGlobalObjectPrint(std::ostream& os) { os << "\n"; } -void WasmMemoryObject::WasmMemoryObjectPrint(std::ostream& os) { - PrintHeader(os, "WasmMemoryObject"); - os << "\n - array_buffer: " << Brief(array_buffer()); - os << "\n - maximum_pages: " << maximum_pages(); - os << "\n - instances: " << Brief(instances()); - os << "\n"; -} - -void WasmTagObject::WasmTagObjectPrint(std::ostream& os) { - PrintHeader(os, "WasmTagObject"); - os << "\n - serialized_signature: " << Brief(serialized_signature()); - os << "\n - tag: " << Brief(tag()); - os << "\n"; -} - void WasmIndirectFunctionTable::WasmIndirectFunctionTablePrint( std::ostream& os) { PrintHeader(os, "WasmIndirectFunctionTable"); @@ -2141,13 +1999,6 @@ void StoreHandler::StoreHandlerPrint(std::ostream& os) { os << "\n"; } -void AccessorPair::AccessorPairPrint(std::ostream& os) { - PrintHeader(os, "AccessorPair"); - os << "\n - getter: " << Brief(getter()); - os << "\n - setter: " << Brief(setter()); - os << "\n"; -} - void CallHandlerInfo::CallHandlerInfoPrint(std::ostream& os) { PrintHeader(os, "CallHandlerInfo"); os << "\n - callback: " << Brief(callback()); @@ -2431,18 +2282,6 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { os << "\n"; } -void StackFrameInfo::StackFrameInfoPrint(std::ostream& os) { - PrintHeader(os, "StackFrameInfo"); - os << "\n - receiver_or_instance: " << Brief(receiver_or_instance()); - os << "\n - function: " << Brief(function()); - os << "\n - code_object: " << Brief(TorqueGeneratedClass::code_object()); - os << "\n - code_offset_or_source_position: " - << code_offset_or_source_position(); - os << "\n - flags: " << flags(); - os << "\n - parameters: " << Brief(parameters()); - os << "\n"; -} - void PreparseData::PreparseDataPrint(std::ostream& os) { PrintHeader(os, "PreparseData"); os << "\n - data_length: " << data_length(); @@ -2459,13 +2298,6 @@ void PreparseData::PreparseDataPrint(std::ostream& os) { os << "\n"; } -void InterpreterData::InterpreterDataPrint(std::ostream& os) { - PrintHeader(os, "InterpreterData"); - os << "\n - bytecode_array: " << Brief(bytecode_array()); - os << "\n - interpreter_trampoline: " << Brief(interpreter_trampoline()); - os << "\n"; -} - template <HeapObjectReferenceType kRefType, typename StorageType> void TaggedImpl<kRefType, StorageType>::Print() { StdoutStream os; @@ -2659,12 +2491,12 @@ void DescriptorArray::PrintDescriptorDetails(std::ostream& os, details.PrintAsFastTo(os, mode); os << " @ "; switch (details.location()) { - case kField: { + case PropertyLocation::kField: { FieldType field_type = GetFieldType(descriptor); field_type.PrintTo(os); break; } - case kDescriptor: + case PropertyLocation::kDescriptor: Object value = GetStrongValue(descriptor); os << Brief(value); if (value.IsAccessorPair()) { diff --git a/chromium/v8/src/diagnostics/perf-jit.h b/chromium/v8/src/diagnostics/perf-jit.h index 746f9f7c857..47a6002b087 100644 --- a/chromium/v8/src/diagnostics/perf-jit.h +++ b/chromium/v8/src/diagnostics/perf-jit.h @@ -87,6 +87,7 @@ class PerfJitLogger : public CodeEventLogger { static const uint32_t kElfMachARM = 40; static const uint32_t kElfMachMIPS = 8; static const uint32_t kElfMachMIPS64 = 8; + static const uint32_t kElfMachLOONG64 = 258; static const uint32_t kElfMachARM64 = 183; static const uint32_t kElfMachS390x = 22; static const uint32_t kElfMachPPC64 = 21; @@ -103,6 +104,8 @@ class PerfJitLogger : public CodeEventLogger { return kElfMachMIPS; #elif V8_TARGET_ARCH_MIPS64 return kElfMachMIPS64; +#elif V8_TARGET_ARCH_LOONG64 + return kElfMachLOONG64; #elif V8_TARGET_ARCH_ARM64 return kElfMachARM64; #elif V8_TARGET_ARCH_S390X diff --git a/chromium/v8/src/diagnostics/ppc/disasm-ppc.cc b/chromium/v8/src/diagnostics/ppc/disasm-ppc.cc index affbc0fc8e7..7d366a6ba12 100644 --- a/chromium/v8/src/diagnostics/ppc/disasm-ppc.cc +++ b/chromium/v8/src/diagnostics/ppc/disasm-ppc.cc @@ -917,6 +917,18 @@ void Decoder::DecodeExt2(Instruction* instr) { Format(instr, "cnttzd'. 'ra, 'rs"); return; } + case BRH: { + Format(instr, "brh 'ra, 'rs"); + return; + } + case BRW: { + Format(instr, "brw 'ra, 'rs"); + return; + } + case BRD: { + Format(instr, "brd 'ra, 'rs"); + return; + } case ANDX: { Format(instr, "and'. 'ra, 'rs, 'rb"); return; @@ -1393,13 +1405,20 @@ void Decoder::DecodeExt6(Instruction* instr) { #undef DECODE_XX2_B_INSTRUCTIONS } switch (EXT6 | (instr->BitField(10, 2))) { -#define DECODE_XX2_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ - case opcode_name: { \ - Format(instr, #name " 'Xt, 'Xb"); \ - return; \ +#define DECODE_XX2_VECTOR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ + case opcode_name: { \ + Format(instr, #name " 'Xt, 'Xb"); \ + return; \ + } + PPC_XX2_OPCODE_VECTOR_A_FORM_LIST(DECODE_XX2_VECTOR_A_INSTRUCTIONS) +#undef DECODE_XX2_VECTOR_A_INSTRUCTIONS +#define DECODE_XX2_SCALAR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ + case opcode_name: { \ + Format(instr, #name " 'Dt, 'Db"); \ + return; \ } - PPC_XX2_OPCODE_A_FORM_LIST(DECODE_XX2_A_INSTRUCTIONS) -#undef DECODE_XX2_A_INSTRUCTIONS + PPC_XX2_OPCODE_SCALAR_A_FORM_LIST(DECODE_XX2_SCALAR_A_INSTRUCTIONS) +#undef DECODE_XX2_SCALAR_A_INSTRUCTIONS } Unknown(instr); // not used by V8 } diff --git a/chromium/v8/src/diagnostics/ppc/eh-frame-ppc.cc b/chromium/v8/src/diagnostics/ppc/eh-frame-ppc.cc index 148d01116df..8f7198cd05e 100644 --- a/chromium/v8/src/diagnostics/ppc/eh-frame-ppc.cc +++ b/chromium/v8/src/diagnostics/ppc/eh-frame-ppc.cc @@ -32,7 +32,6 @@ int EhFrameWriter::RegisterToDwarfCode(Register name) { return kR0DwarfCode; default: UNIMPLEMENTED(); - return -1; } } @@ -47,7 +46,6 @@ const char* EhFrameDisassembler::DwarfRegisterCodeToString(int code) { return "sp"; default: UNIMPLEMENTED(); - return nullptr; } } diff --git a/chromium/v8/src/diagnostics/riscv64/disasm-riscv64.cc b/chromium/v8/src/diagnostics/riscv64/disasm-riscv64.cc index 2955612166e..ed899d9212f 100644 --- a/chromium/v8/src/diagnostics/riscv64/disasm-riscv64.cc +++ b/chromium/v8/src/diagnostics/riscv64/disasm-riscv64.cc @@ -68,11 +68,15 @@ class Decoder { // Printing of common values. void PrintRegister(int reg); void PrintFPURegister(int freg); + void PrintVRegister(int reg); void PrintFPUStatusRegister(int freg); void PrintRs1(Instruction* instr); void PrintRs2(Instruction* instr); void PrintRd(Instruction* instr); + void PrintUimm(Instruction* instr); void PrintVs1(Instruction* instr); + void PrintVs2(Instruction* instr); + void PrintVd(Instruction* instr); void PrintFRs1(Instruction* instr); void PrintFRs2(Instruction* instr); void PrintFRs3(Instruction* instr); @@ -96,10 +100,15 @@ class Decoder { void PrintRvcImm8Addi4spn(Instruction* instr); void PrintRvcImm11CJ(Instruction* instr); void PrintRvcImm8B(Instruction* instr); + void PrintRvvVm(Instruction* instr); void PrintAcquireRelease(Instruction* instr); void PrintBranchOffset(Instruction* instr); void PrintStoreOffset(Instruction* instr); void PrintCSRReg(Instruction* instr); + void PrintRvvSEW(Instruction* instr); + void PrintRvvLMUL(Instruction* instr); + void PrintRvvSimm5(Instruction* instr); + void PrintRvvUimm5(Instruction* instr); void PrintRoundingMode(Instruction* instr); void PrintMemoryOrder(Instruction* instr, bool is_pred); @@ -123,6 +132,16 @@ class Decoder { void DecodeCJType(Instruction* instr); void DecodeCBType(Instruction* instr); + void DecodeVType(Instruction* instr); + void DecodeRvvIVV(Instruction* instr); + void DecodeRvvFVV(Instruction* instr); + void DecodeRvvFVF(Instruction* instr); + void DecodeRvvIVI(Instruction* instr); + void DecodeRvvIVX(Instruction* instr); + void DecodeRvvVL(Instruction* instr); + void DecodeRvvVS(Instruction* instr); + void DecodeRvvMVV(Instruction* instr); + void DecodeRvvMVX(Instruction* instr); // Printing of instruction name. void PrintInstructionName(Instruction* instr); @@ -137,6 +156,8 @@ class Decoder { void Format(Instruction* instr, const char* format); void Unknown(Instruction* instr); + int switch_sew(Instruction* instr); + int switch_nf(Instruction* instr); const disasm::NameConverter& converter_; v8::base::Vector<char> out_buffer_; int out_buffer_pos_; @@ -164,6 +185,10 @@ void Decoder::PrintRegister(int reg) { Print(converter_.NameOfCPURegister(reg)); } +void Decoder::PrintVRegister(int reg) { + Print(v8::internal::VRegisters::Name(reg)); +} + void Decoder::PrintRs1(Instruction* instr) { int reg = instr->Rs1Value(); PrintRegister(reg); @@ -179,11 +204,26 @@ void Decoder::PrintRd(Instruction* instr) { PrintRegister(reg); } -void Decoder::PrintVs1(Instruction* instr) { +void Decoder::PrintUimm(Instruction* instr) { int val = instr->Rs1Value(); out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", val); } +void Decoder::PrintVs1(Instruction* instr) { + int reg = instr->Vs1Value(); + PrintVRegister(reg); +} + +void Decoder::PrintVs2(Instruction* instr) { + int reg = instr->Vs2Value(); + PrintVRegister(reg); +} + +void Decoder::PrintVd(Instruction* instr) { + int reg = instr->VdValue(); + PrintVRegister(reg); +} + // Print the FPUregister name according to the active name converter. void Decoder::PrintFPURegister(int freg) { Print(converter_.NameOfXMMRegister(freg)); @@ -247,6 +287,26 @@ void Decoder::PrintStoreOffset(Instruction* instr) { out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); } +void Decoder::PrintRvvSEW(Instruction* instr) { + const char* sew = instr->RvvSEW(); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s", sew); +} + +void Decoder::PrintRvvLMUL(Instruction* instr) { + const char* lmul = instr->RvvLMUL(); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s", lmul); +} + +void Decoder::PrintRvvSimm5(Instruction* instr) { + const int simm5 = instr->RvvSimm5(); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", simm5); +} + +void Decoder::PrintRvvUimm5(Instruction* instr) { + const uint32_t uimm5 = instr->RvvUimm5(); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", uimm5); +} + void Decoder::PrintImm20U(Instruction* instr) { int32_t imm = instr->Imm20UValue(); out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); @@ -335,6 +395,13 @@ void Decoder::PrintRvcImm8B(Instruction* instr) { out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); } +void Decoder::PrintRvvVm(Instruction* instr) { + uint8_t imm = instr->RvvVM(); + if (imm == 0) { + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, " vm"); + } +} + void Decoder::PrintAcquireRelease(Instruction* instr) { bool aq = instr->AqValue(); bool rl = instr->RlValue(); @@ -724,13 +791,50 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { DCHECK(STRING_STARTS_WITH(format, "suc")); PrintMemoryOrder(instr, false); return 3; + } else if (format[1] == 'e') { + DCHECK(STRING_STARTS_WITH(format, "sew")); + PrintRvvSEW(instr); + return 3; + } else if (format[1] == 'i') { + DCHECK(STRING_STARTS_WITH(format, "simm5")); + PrintRvvSimm5(instr); + return 5; } UNREACHABLE(); } - case 'v': { // 'vs1: Raw values from register fields - DCHECK(STRING_STARTS_WITH(format, "vs1")); - PrintVs1(instr); - return 3; + case 'v': { + if (format[1] == 'd') { + DCHECK(STRING_STARTS_WITH(format, "vd")); + PrintVd(instr); + return 2; + } else if (format[2] == '1') { + DCHECK(STRING_STARTS_WITH(format, "vs1")); + PrintVs1(instr); + return 3; + } else if (format[2] == '2') { + DCHECK(STRING_STARTS_WITH(format, "vs2")); + PrintVs2(instr); + return 3; + } else { + DCHECK(STRING_STARTS_WITH(format, "vm")); + PrintRvvVm(instr); + return 2; + } + } + case 'l': { + DCHECK(STRING_STARTS_WITH(format, "lmul")); + PrintRvvLMUL(instr); + return 4; + } + case 'u': { + if (STRING_STARTS_WITH(format, "uimm5")) { + PrintRvvUimm5(instr); + return 5; + } else { + DCHECK(STRING_STARTS_WITH(format, "uimm")); + PrintUimm(instr); + return 4; + } } case 't': { // 'target: target of branch instructions' DCHECK(STRING_STARTS_WITH(format, "target")); @@ -1308,256 +1412,265 @@ void Decoder::DecodeR4Type(Instruction* instr) { } void Decoder::DecodeIType(Instruction* instr) { - switch (instr->InstructionBits() & kITypeMask) { - case RO_JALR: - if (instr->RdValue() == zero_reg.code() && - instr->Rs1Value() == ra.code() && instr->Imm12Value() == 0) - Format(instr, "ret"); - else if (instr->RdValue() == zero_reg.code() && instr->Imm12Value() == 0) - Format(instr, "jr 'rs1"); - else if (instr->RdValue() == ra.code() && instr->Imm12Value() == 0) - Format(instr, "jalr 'rs1"); - else - Format(instr, "jalr 'rd, 'imm12('rs1)'target"); - break; - case RO_LB: - Format(instr, "lb 'rd, 'imm12('rs1)"); - break; - case RO_LH: - Format(instr, "lh 'rd, 'imm12('rs1)"); - break; - case RO_LW: - Format(instr, "lw 'rd, 'imm12('rs1)"); - break; - case RO_LBU: - Format(instr, "lbu 'rd, 'imm12('rs1)"); - break; - case RO_LHU: - Format(instr, "lhu 'rd, 'imm12('rs1)"); - break; + if (instr->vl_vs_width() != -1) { + DecodeRvvVL(instr); + } else { + switch (instr->InstructionBits() & kITypeMask) { + case RO_JALR: + if (instr->RdValue() == zero_reg.code() && + instr->Rs1Value() == ra.code() && instr->Imm12Value() == 0) + Format(instr, "ret"); + else if (instr->RdValue() == zero_reg.code() && + instr->Imm12Value() == 0) + Format(instr, "jr 'rs1"); + else if (instr->RdValue() == ra.code() && instr->Imm12Value() == 0) + Format(instr, "jalr 'rs1"); + else + Format(instr, "jalr 'rd, 'imm12('rs1)"); + break; + case RO_LB: + Format(instr, "lb 'rd, 'imm12('rs1)"); + break; + case RO_LH: + Format(instr, "lh 'rd, 'imm12('rs1)"); + break; + case RO_LW: + Format(instr, "lw 'rd, 'imm12('rs1)"); + break; + case RO_LBU: + Format(instr, "lbu 'rd, 'imm12('rs1)"); + break; + case RO_LHU: + Format(instr, "lhu 'rd, 'imm12('rs1)"); + break; #ifdef V8_TARGET_ARCH_64_BIT - case RO_LWU: - Format(instr, "lwu 'rd, 'imm12('rs1)"); - break; - case RO_LD: - Format(instr, "ld 'rd, 'imm12('rs1)"); - break; + case RO_LWU: + Format(instr, "lwu 'rd, 'imm12('rs1)"); + break; + case RO_LD: + Format(instr, "ld 'rd, 'imm12('rs1)"); + break; #endif /*V8_TARGET_ARCH_64_BIT*/ - case RO_ADDI: - if (instr->Imm12Value() == 0) { - if (instr->RdValue() == zero_reg.code() && - instr->Rs1Value() == zero_reg.code()) - Format(instr, "nop"); + case RO_ADDI: + if (instr->Imm12Value() == 0) { + if (instr->RdValue() == zero_reg.code() && + instr->Rs1Value() == zero_reg.code()) + Format(instr, "nop"); + else + Format(instr, "mv 'rd, 'rs1"); + } else if (instr->Rs1Value() == zero_reg.code()) { + Format(instr, "li 'rd, 'imm12"); + } else { + Format(instr, "addi 'rd, 'rs1, 'imm12"); + } + break; + case RO_SLTI: + Format(instr, "slti 'rd, 'rs1, 'imm12"); + break; + case RO_SLTIU: + if (instr->Imm12Value() == 1) + Format(instr, "seqz 'rd, 'rs1"); else - Format(instr, "mv 'rd, 'rs1"); - } else if (instr->Rs1Value() == zero_reg.code()) { - Format(instr, "li 'rd, 'imm12"); - } else { - Format(instr, "addi 'rd, 'rs1, 'imm12"); - } - break; - case RO_SLTI: - Format(instr, "slti 'rd, 'rs1, 'imm12"); - break; - case RO_SLTIU: - if (instr->Imm12Value() == 1) - Format(instr, "seqz 'rd, 'rs1"); - else - Format(instr, "sltiu 'rd, 'rs1, 'imm12"); - break; - case RO_XORI: - if (instr->Imm12Value() == -1) - Format(instr, "not 'rd, 'rs1"); - else - Format(instr, "xori 'rd, 'rs1, 'imm12x"); - break; - case RO_ORI: - Format(instr, "ori 'rd, 'rs1, 'imm12x"); - break; - case RO_ANDI: - Format(instr, "andi 'rd, 'rs1, 'imm12x"); - break; - case RO_SLLI: - Format(instr, "slli 'rd, 'rs1, 's64"); - break; - case RO_SRLI: { // RO_SRAI - if (!instr->IsArithShift()) { - Format(instr, "srli 'rd, 'rs1, 's64"); - } else { - Format(instr, "srai 'rd, 'rs1, 's64"); + Format(instr, "sltiu 'rd, 'rs1, 'imm12"); + break; + case RO_XORI: + if (instr->Imm12Value() == -1) + Format(instr, "not 'rd, 'rs1"); + else + Format(instr, "xori 'rd, 'rs1, 'imm12x"); + break; + case RO_ORI: + Format(instr, "ori 'rd, 'rs1, 'imm12x"); + break; + case RO_ANDI: + Format(instr, "andi 'rd, 'rs1, 'imm12x"); + break; + case RO_SLLI: + Format(instr, "slli 'rd, 'rs1, 's64"); + break; + case RO_SRLI: { // RO_SRAI + if (!instr->IsArithShift()) { + Format(instr, "srli 'rd, 'rs1, 's64"); + } else { + Format(instr, "srai 'rd, 'rs1, 's64"); + } + break; } - break; - } #ifdef V8_TARGET_ARCH_64_BIT - case RO_ADDIW: - if (instr->Imm12Value() == 0) - Format(instr, "sext.w 'rd, 'rs1"); - else - Format(instr, "addiw 'rd, 'rs1, 'imm12"); - break; - case RO_SLLIW: - Format(instr, "slliw 'rd, 'rs1, 's32"); - break; - case RO_SRLIW: { // RO_SRAIW - if (!instr->IsArithShift()) { - Format(instr, "srliw 'rd, 'rs1, 's32"); - } else { - Format(instr, "sraiw 'rd, 'rs1, 's32"); + case RO_ADDIW: + if (instr->Imm12Value() == 0) + Format(instr, "sext.w 'rd, 'rs1"); + else + Format(instr, "addiw 'rd, 'rs1, 'imm12"); + break; + case RO_SLLIW: + Format(instr, "slliw 'rd, 'rs1, 's32"); + break; + case RO_SRLIW: { // RO_SRAIW + if (!instr->IsArithShift()) { + Format(instr, "srliw 'rd, 'rs1, 's32"); + } else { + Format(instr, "sraiw 'rd, 'rs1, 's32"); + } + break; } - break; - } #endif /*V8_TARGET_ARCH_64_BIT*/ - case RO_FENCE: - if (instr->MemoryOrder(true) == PSIORW && - instr->MemoryOrder(false) == PSIORW) - Format(instr, "fence"); - else - Format(instr, "fence 'pre, 'suc"); - break; - case RO_ECALL: { // RO_EBREAK - if (instr->Imm12Value() == 0) { // ECALL - Format(instr, "ecall"); - } else if (instr->Imm12Value() == 1) { // EBREAK - Format(instr, "ebreak"); - } else { - UNSUPPORTED_RISCV(); + case RO_FENCE: + if (instr->MemoryOrder(true) == PSIORW && + instr->MemoryOrder(false) == PSIORW) + Format(instr, "fence"); + else + Format(instr, "fence 'pre, 'suc"); + break; + case RO_ECALL: { // RO_EBREAK + if (instr->Imm12Value() == 0) { // ECALL + Format(instr, "ecall"); + } else if (instr->Imm12Value() == 1) { // EBREAK + Format(instr, "ebreak"); + } else { + UNSUPPORTED_RISCV(); + } + break; } - break; - } - // TODO(riscv): use Zifencei Standard Extension macro block - case RO_FENCE_I: - Format(instr, "fence.i"); - break; - // TODO(riscv): use Zicsr Standard Extension macro block - case RO_CSRRW: - if (instr->CsrValue() == csr_fcsr) { + // TODO(riscv): use Zifencei Standard Extension macro block + case RO_FENCE_I: + Format(instr, "fence.i"); + break; + // TODO(riscv): use Zicsr Standard Extension macro block + // FIXME(RISC-V): Add special formatting for CSR registers + case RO_CSRRW: + if (instr->CsrValue() == csr_fcsr) { + if (instr->RdValue() == zero_reg.code()) + Format(instr, "fscsr 'rs1"); + else + Format(instr, "fscsr 'rd, 'rs1"); + } else if (instr->CsrValue() == csr_frm) { + if (instr->RdValue() == zero_reg.code()) + Format(instr, "fsrm 'rs1"); + else + Format(instr, "fsrm 'rd, 'rs1"); + } else if (instr->CsrValue() == csr_fflags) { + if (instr->RdValue() == zero_reg.code()) + Format(instr, "fsflags 'rs1"); + else + Format(instr, "fsflags 'rd, 'rs1"); + } else if (instr->RdValue() == zero_reg.code()) { + Format(instr, "csrw 'csr, 'rs1"); + } else { + Format(instr, "csrrw 'rd, 'csr, 'rs1"); + } + break; + case RO_CSRRS: + if (instr->Rs1Value() == zero_reg.code()) { + switch (instr->CsrValue()) { + case csr_instret: + Format(instr, "rdinstret 'rd"); + break; + case csr_instreth: + Format(instr, "rdinstreth 'rd"); + break; + case csr_time: + Format(instr, "rdtime 'rd"); + break; + case csr_timeh: + Format(instr, "rdtimeh 'rd"); + break; + case csr_cycle: + Format(instr, "rdcycle 'rd"); + break; + case csr_cycleh: + Format(instr, "rdcycleh 'rd"); + break; + case csr_fflags: + Format(instr, "frflags 'rd"); + break; + case csr_frm: + Format(instr, "frrm 'rd"); + break; + case csr_fcsr: + Format(instr, "frcsr 'rd"); + break; + default: + UNREACHABLE(); + } + } else if (instr->Rs1Value() == zero_reg.code()) { + Format(instr, "csrr 'rd, 'csr"); + } else if (instr->RdValue() == zero_reg.code()) { + Format(instr, "csrs 'csr, 'rs1"); + } else { + Format(instr, "csrrs 'rd, 'csr, 'rs1"); + } + break; + case RO_CSRRC: if (instr->RdValue() == zero_reg.code()) - Format(instr, "fscsr 'rs1"); + Format(instr, "csrc 'csr, 'rs1"); else - Format(instr, "fscsr 'rd, 'rs1"); - } else if (instr->CsrValue() == csr_frm) { + Format(instr, "csrrc 'rd, 'csr, 'rs1"); + break; + case RO_CSRRWI: if (instr->RdValue() == zero_reg.code()) - Format(instr, "fsrm 'rs1"); + Format(instr, "csrwi 'csr, 'uimm"); else - Format(instr, "fsrm 'rd, 'rs1"); - } else if (instr->CsrValue() == csr_fflags) { + Format(instr, "csrrwi 'rd, 'csr, 'uimm"); + break; + case RO_CSRRSI: if (instr->RdValue() == zero_reg.code()) - Format(instr, "fsflags 'rs1"); + Format(instr, "csrsi 'csr, 'uimm"); else - Format(instr, "fsflags 'rd, 'rs1"); - } else if (instr->RdValue() == zero_reg.code()) { - Format(instr, "csrw 'csr, 'rs1"); - } else { - Format(instr, "csrrw 'rd, 'csr, 'rs1"); - } - break; - case RO_CSRRS: - if (instr->Rs1Value() == zero_reg.code()) { - switch (instr->CsrValue()) { - case csr_instret: - Format(instr, "rdinstret 'rd"); - break; - case csr_instreth: - Format(instr, "rdinstreth 'rd"); - break; - case csr_time: - Format(instr, "rdtime 'rd"); - break; - case csr_timeh: - Format(instr, "rdtimeh 'rd"); - break; - case csr_cycle: - Format(instr, "rdcycle 'rd"); - break; - case csr_cycleh: - Format(instr, "rdcycleh 'rd"); - break; - case csr_fflags: - Format(instr, "frflags 'rd"); - break; - case csr_frm: - Format(instr, "frrm 'rd"); - break; - case csr_fcsr: - Format(instr, "frcsr 'rd"); - break; - default: - UNREACHABLE(); - } - } else if (instr->Rs1Value() == zero_reg.code()) { - Format(instr, "csrr 'rd, 'csr"); - } else if (instr->RdValue() == zero_reg.code()) { - Format(instr, "csrs 'csr, 'rs1"); - } else { - Format(instr, "csrrs 'rd, 'csr, 'rs1"); - } - break; - case RO_CSRRC: - if (instr->RdValue() == zero_reg.code()) - Format(instr, "csrc 'csr, 'rs1"); - else - Format(instr, "csrrc 'rd, 'csr, 'rs1"); - break; - case RO_CSRRWI: - if (instr->RdValue() == zero_reg.code()) - Format(instr, "csrwi 'csr, 'vs1"); - else - Format(instr, "csrrwi 'rd, 'csr, 'vs1"); - break; - case RO_CSRRSI: - if (instr->RdValue() == zero_reg.code()) - Format(instr, "csrsi 'csr, 'vs1"); - else - Format(instr, "csrrsi 'rd, 'csr, 'vs1"); - break; - case RO_CSRRCI: - if (instr->RdValue() == zero_reg.code()) - Format(instr, "csrci 'csr, 'vs1"); - else - Format(instr, "csrrci 'rd, 'csr, 'vs1"); - break; - // TODO(riscv): use F Extension macro block - case RO_FLW: - Format(instr, "flw 'fd, 'imm12('rs1)"); - break; - // TODO(riscv): use D Extension macro block - case RO_FLD: - Format(instr, "fld 'fd, 'imm12('rs1)"); - break; - default: - UNSUPPORTED_RISCV(); + Format(instr, "csrrsi 'rd, 'csr, 'uimm"); + break; + case RO_CSRRCI: + if (instr->RdValue() == zero_reg.code()) + Format(instr, "csrci 'csr, 'uimm"); + else + Format(instr, "csrrci 'rd, 'csr, 'uimm"); + break; + // TODO(riscv): use F Extension macro block + case RO_FLW: + Format(instr, "flw 'fd, 'imm12('rs1)"); + break; + // TODO(riscv): use D Extension macro block + case RO_FLD: + Format(instr, "fld 'fd, 'imm12('rs1)"); + break; + default: + UNSUPPORTED_RISCV(); + } } } void Decoder::DecodeSType(Instruction* instr) { - switch (instr->InstructionBits() & kSTypeMask) { - case RO_SB: - Format(instr, "sb 'rs2, 'offS('rs1)"); - break; - case RO_SH: - Format(instr, "sh 'rs2, 'offS('rs1)"); - break; - case RO_SW: - Format(instr, "sw 'rs2, 'offS('rs1)"); - break; + if (instr->vl_vs_width() != -1) { + DecodeRvvVS(instr); + } else { + switch (instr->InstructionBits() & kSTypeMask) { + case RO_SB: + Format(instr, "sb 'rs2, 'offS('rs1)"); + break; + case RO_SH: + Format(instr, "sh 'rs2, 'offS('rs1)"); + break; + case RO_SW: + Format(instr, "sw 'rs2, 'offS('rs1)"); + break; #ifdef V8_TARGET_ARCH_64_BIT - case RO_SD: - Format(instr, "sd 'rs2, 'offS('rs1)"); - break; + case RO_SD: + Format(instr, "sd 'rs2, 'offS('rs1)"); + break; #endif /*V8_TARGET_ARCH_64_BIT*/ - // TODO(riscv): use F Extension macro block - case RO_FSW: - Format(instr, "fsw 'fs2, 'offS('rs1)"); - break; - // TODO(riscv): use D Extension macro block - case RO_FSD: - Format(instr, "fsd 'fs2, 'offS('rs1)"); - break; - default: - UNSUPPORTED_RISCV(); + // TODO(riscv): use F Extension macro block + case RO_FSW: + Format(instr, "fsw 'fs2, 'offS('rs1)"); + break; + // TODO(riscv): use D Extension macro block + case RO_FSD: + Format(instr, "fsd 'fs2, 'offS('rs1)"); + break; + default: + UNSUPPORTED_RISCV(); + } } } - void Decoder::DecodeBType(Instruction* instr) { switch (instr->InstructionBits() & kBTypeMask) { case RO_BEQ: @@ -1595,6 +1708,7 @@ void Decoder::DecodeUType(Instruction* instr) { UNSUPPORTED_RISCV(); } } +// namespace internal void Decoder::DecodeJType(Instruction* instr) { // J Type doesn't have additional mask switch (instr->BaseOpcodeValue()) { @@ -1791,6 +1905,631 @@ void Decoder::DecodeCBType(Instruction* instr) { } } +void Decoder::DecodeRvvIVV(Instruction* instr) { + DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_IVV); + switch (instr->InstructionBits() & kVTypeMask) { + case RO_V_VADD_VV: + Format(instr, "vadd.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VSADD_VV: + Format(instr, "vsadd.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VSADDU_VV: + Format(instr, "vsaddu.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VSUB_VV: + Format(instr, "vsub.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VSSUB_VV: + Format(instr, "vssub.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMIN_VV: + Format(instr, "vmin.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMINU_VV: + Format(instr, "vminu.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMAX_VV: + Format(instr, "vmax.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMAXU_VV: + Format(instr, "vmaxu.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VAND_VV: + Format(instr, "vand.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VOR_VV: + Format(instr, "vor.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VXOR_VV: + Format(instr, "vxor.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VRGATHER_VV: + Format(instr, "vrgather.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMSEQ_VV: + Format(instr, "vmseq.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMSNE_VV: + Format(instr, "vmsne.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMSLT_VV: + Format(instr, "vmslt.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMSLTU_VV: + Format(instr, "vmsltu.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMSLE_VV: + Format(instr, "vmsle.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMSLEU_VV: + Format(instr, "vmsleu.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMV_VV: + if (instr->RvvVM()) { + Format(instr, "vmv.vv 'vd, 'vs1"); + } else { + Format(instr, "vmerge.vvm 'vd, 'vs2, 'vs1, v0"); + } + break; + case RO_V_VADC_VV: + if (!instr->RvvVM()) { + Format(instr, "vadc.vvm 'vd, 'vs2, 'vs1"); + } else { + UNREACHABLE(); + } + break; + case RO_V_VMADC_VV: + if (!instr->RvvVM()) { + Format(instr, "vmadc.vvm 'vd, 'vs2, 'vs1"); + } else { + UNREACHABLE(); + } + break; + default: + UNSUPPORTED_RISCV(); + break; + } +} + +void Decoder::DecodeRvvIVI(Instruction* instr) { + DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_IVI); + switch (instr->InstructionBits() & kVTypeMask) { + case RO_V_VADD_VI: + Format(instr, "vadd.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VSADD_VI: + Format(instr, "vsadd.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VSADDU_VI: + Format(instr, "vsaddu.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VRSUB_VI: + Format(instr, "vrsub.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VAND_VI: + Format(instr, "vand.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VOR_VI: + Format(instr, "vor.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VXOR_VI: + Format(instr, "vxor.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VRGATHER_VI: + Format(instr, "vrgather.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VMV_VI: + if (instr->RvvVM()) { + Format(instr, "vmv.vi 'vd, 'simm5"); + } else { + Format(instr, "vmerge.vim 'vd, 'vs2, 'simm5, v0"); + } + break; + case RO_V_VMSEQ_VI: + Format(instr, "vmseq.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VMSNE_VI: + Format(instr, "vmsne.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VMSLEU_VI: + Format(instr, "vmsleu.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VMSLE_VI: + Format(instr, "vmsle.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VMSGTU_VI: + Format(instr, "vmsgtu.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VMSGT_VI: + Format(instr, "vmsgt.vi 'vd, 'vs2, 'simm5'vm"); + break; + case RO_V_VSLIDEDOWN_VI: + Format(instr, "vslidedown.vi 'vd, 'vs2, 'uimm5'vm"); + break; + case RO_V_VSRL_VI: + Format(instr, "vsrl.vi 'vd, 'vs2, 'uimm5'vm"); + break; + case RO_V_VSLL_VI: + Format(instr, "vsll.vi 'vd, 'vs2, 'uimm5'vm"); + break; + case RO_V_VADC_VI: + if (!instr->RvvVM()) { + Format(instr, "vadc.vim 'vd, 'vs2, 'uimm5"); + } else { + UNREACHABLE(); + } + break; + case RO_V_VMADC_VI: + if (!instr->RvvVM()) { + Format(instr, "vmadc.vim 'vd, 'vs2, 'uimm5"); + } else { + UNREACHABLE(); + } + break; + default: + UNSUPPORTED_RISCV(); + break; + } +} + +void Decoder::DecodeRvvIVX(Instruction* instr) { + DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_IVX); + switch (instr->InstructionBits() & kVTypeMask) { + case RO_V_VADD_VX: + Format(instr, "vadd.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VSADD_VX: + Format(instr, "vsadd.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VSADDU_VX: + Format(instr, "vsaddu.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VSUB_VX: + Format(instr, "vsub.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VSSUB_VX: + Format(instr, "vssub.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VRSUB_VX: + Format(instr, "vrsub.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMIN_VX: + Format(instr, "vmin.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMINU_VX: + Format(instr, "vminu.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMAX_VX: + Format(instr, "vmax.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMAXU_VX: + Format(instr, "vmaxu.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VAND_VX: + Format(instr, "vand.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VOR_VX: + Format(instr, "vor.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VXOR_VX: + Format(instr, "vxor.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VRGATHER_VX: + Format(instr, "vrgather.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMV_VX: + if (instr->RvvVM()) { + Format(instr, "vmv.vx 'vd, 'rs1"); + } else { + Format(instr, "vmerge.vxm 'vd, 'vs2, 'rs1, v0"); + } + break; + case RO_V_VMSEQ_VX: + Format(instr, "vmseq.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMSNE_VX: + Format(instr, "vmsne.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMSLT_VX: + Format(instr, "vmslt.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMSLTU_VX: + Format(instr, "vmsltu.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMSLE_VX: + Format(instr, "vmsle.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMSLEU_VX: + Format(instr, "vmsleu.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMSGT_VX: + Format(instr, "vmsgt.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VMSGTU_VX: + Format(instr, "vmsgtu.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VSLIDEDOWN_VX: + Format(instr, "vslidedown.vx 'vd, 'vs2, 'rs1'vm"); + break; + case RO_V_VADC_VX: + if (!instr->RvvVM()) { + Format(instr, "vadc.vxm 'vd, 'vs2, 'rs1"); + } else { + UNREACHABLE(); + } + break; + case RO_V_VMADC_VX: + if (!instr->RvvVM()) { + Format(instr, "vmadc.vxm 'vd, 'vs2, 'rs1"); + } else { + UNREACHABLE(); + } + break; + case RO_V_VSLL_VX: + Format(instr, "vsll.vx 'vd, 'vs2, 'rs1"); + break; + case RO_V_VSRL_VX: + Format(instr, "vsrl.vx 'vd, 'vs2, 'rs1"); + break; + default: + UNSUPPORTED_RISCV(); + break; + } +} + +void Decoder::DecodeRvvMVV(Instruction* instr) { + DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_MVV); + switch (instr->InstructionBits() & kVTypeMask) { + case RO_V_VWXUNARY0: + if (instr->Vs1Value() == 0x0) { + Format(instr, "vmv.x.s 'rd, 'vs2"); + } else { + UNSUPPORTED_RISCV(); + } + break; + case RO_V_VREDMAXU: + Format(instr, "vredmaxu.vs 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VREDMAX: + Format(instr, "vredmax.vs 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VREDMIN: + Format(instr, "vredmin.vs 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VREDMINU: + Format(instr, "vredminu.vs 'vd, 'vs2, 'vs1'vm"); + break; + default: + UNSUPPORTED_RISCV(); + break; + } +} + +void Decoder::DecodeRvvMVX(Instruction* instr) { + DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_MVX); + switch (instr->InstructionBits() & kVTypeMask) { + case RO_V_VRXUNARY0: + if (instr->Vs2Value() == 0x0) { + Format(instr, "vmv.s.x 'vd, 'rs1"); + } else { + UNSUPPORTED_RISCV(); + } + break; + default: + UNSUPPORTED_RISCV(); + break; + } +} + +void Decoder::DecodeRvvFVV(Instruction* instr) { + DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_FVV); + switch (instr->InstructionBits() & kVTypeMask) { + case RO_V_VFUNARY0: + switch (instr->Vs1Value()) { + case VFCVT_XU_F_V: + Format(instr, "vfcvt.xu.f.v 'vd, 'vs2'vm"); + break; + case VFCVT_X_F_V: + Format(instr, "vfcvt.x.f.v 'vd, 'vs2'vm"); + break; + case VFNCVT_F_F_W: + Format(instr, "vfncvt.f.f.w 'vd, 'vs2'vm"); + break; + case VFCVT_F_X_V: + Format(instr, "vfcvt.f.x.v 'vd, 'vs2'vm"); + break; + case VFCVT_F_XU_V: + Format(instr, "vfcvt.f.xu.v 'vd, 'vs2'vm"); + break; + default: + UNSUPPORTED_RISCV(); + break; + } + break; + case RO_V_VFUNARY1: + switch (instr->Vs1Value()) { + case VFCLASS_V: + Format(instr, "vfclass.v 'vd, 'vs2'vm"); + break; + default: + break; + } + break; + case RO_V_VMFEQ_VV: + Format(instr, "vmfeq.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMFNE_VV: + Format(instr, "vmfne.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMFLT_VV: + Format(instr, "vmflt.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VMFLE_VV: + Format(instr, "vmfle.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VFMAX_VV: + Format(instr, "vfmax.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VFMIN_VV: + Format(instr, "vfmin.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VFSGNJ_VV: + Format(instr, "vfsgnj.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VFSGNJN_VV: + if (instr->Vs1Value() == instr->Vs2Value()) { + Format(instr, "vneg.vv 'vd, 'vs1'vm"); + } else { + Format(instr, "vfsgnjn.vv 'vd, 'vs2, 'vs1'vm"); + } + break; + case RO_V_VFSGNJX_VV: + if (instr->Vs1Value() == instr->Vs2Value()) { + Format(instr, "vabs.vv 'vd, 'vs1'vm"); + } else { + Format(instr, "vfsgnjn.vv 'vd, 'vs2, 'vs1'vm"); + } + break; + case RO_V_VFADD_VV: + Format(instr, "vfadd.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VFSUB_VV: + Format(instr, "vfsub.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VFDIV_VV: + Format(instr, "vfdiv.vv 'vd, 'vs2, 'vs1'vm"); + break; + case RO_V_VFMUL_VV: + Format(instr, "vfmul.vv 'vd, 'vs2, 'vs1'vm"); + break; + default: + UNSUPPORTED_RISCV(); + break; + } +} + +void Decoder::DecodeRvvFVF(Instruction* instr) { + DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_FVF); + switch (instr->InstructionBits() & kVTypeMask) { + case RO_V_VFSGNJ_VF: + Format(instr, "vfsgnj.vf 'vd, 'vs2, 'fs1'vm"); + break; + case RO_V_VFSGNJN_VF: + Format(instr, "vfsgnjn.vf 'vd, 'vs2, 'fs1'vm"); + break; + case RO_V_VFSGNJX_VF: + Format(instr, "vfsgnjn.vf 'vd, 'vs2, 'fs1'vm"); + break; + default: + UNSUPPORTED_RISCV(); + break; + } +} + +void Decoder::DecodeVType(Instruction* instr) { + switch (instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask)) { + case OP_IVV: + DecodeRvvIVV(instr); + return; + case OP_FVV: + DecodeRvvFVV(instr); + return; + case OP_MVV: + DecodeRvvMVV(instr); + return; + case OP_IVI: + DecodeRvvIVI(instr); + return; + case OP_IVX: + DecodeRvvIVX(instr); + return; + case OP_FVF: + UNSUPPORTED_RISCV(); + return; + case OP_MVX: + DecodeRvvMVX(instr); + return; + } + switch (instr->InstructionBits() & + (kBaseOpcodeMask | kFunct3Mask | 0x80000000)) { + case RO_V_VSETVLI: + Format(instr, "vsetvli 'rd, 'rs1, 'sew, 'lmul"); + break; + case RO_V_VSETVL: + if (!(instr->InstructionBits() & 0x40000000)) { + Format(instr, "vsetvl 'rd, 'rs1, 'rs2"); + } else { + Format(instr, "vsetivli 'rd, 'uimm, 'sew, 'lmul"); + } + break; + default: + UNSUPPORTED_RISCV(); + break; + } +} +int Decoder::switch_nf(Instruction* instr) { + int nf = 0; + switch (instr->InstructionBits() & kRvvNfMask) { + case 0x20000000: + nf = 2; + break; + case 0x40000000: + nf = 3; + break; + case 0x60000000: + nf = 4; + break; + case 0x80000000: + nf = 5; + break; + case 0xa0000000: + nf = 6; + break; + case 0xc0000000: + nf = 7; + break; + case 0xe0000000: + nf = 8; + break; + } + return nf; +} +void Decoder::DecodeRvvVL(Instruction* instr) { + char str[50]; + uint32_t instr_temp = + instr->InstructionBits() & (kRvvMopMask | kRvvNfMask | kBaseOpcodeMask); + // switch (instr->InstructionBits() & + // (kRvvMopMask | kRvvNfMask | kBaseOpcodeMask)) { + if (RO_V_VL == instr_temp) { + if (!(instr->InstructionBits() & (kRvvRs2Mask))) { + snprintf(str, sizeof(str), "vle%d.v 'vd, ('rs1)'vm", + instr->vl_vs_width()); + Format(instr, str); + } else { + snprintf(str, sizeof(str), "vle%dff.v 'vd, ('rs1)'vm", + instr->vl_vs_width()); + Format(instr, str); + } + } else if (RO_V_VLS == instr_temp) { + snprintf(str, sizeof(str), "vlse%d.v 'vd, ('rs1), 'rs2'vm", + instr->vl_vs_width()); + Format(instr, str); + + } else if (RO_V_VLX == instr_temp) { + snprintf(str, sizeof(str), "vlxei%d.v 'vd, ('rs1), 'vs2'vm", + instr->vl_vs_width()); + Format(instr, str); + } else if (RO_V_VLSEG2 == instr_temp || RO_V_VLSEG3 == instr_temp || + RO_V_VLSEG4 == instr_temp || RO_V_VLSEG5 == instr_temp || + RO_V_VLSEG6 == instr_temp || RO_V_VLSEG7 == instr_temp || + RO_V_VLSEG8 == instr_temp) { + if (!(instr->InstructionBits() & (kRvvRs2Mask))) { + snprintf(str, sizeof(str), "vlseg%de%d.v 'vd, ('rs1)'vm", + switch_nf(instr), instr->vl_vs_width()); + } else { + snprintf(str, sizeof(str), "vlseg%de%dff.v 'vd, ('rs1)'vm", + switch_nf(instr), instr->vl_vs_width()); + } + Format(instr, str); + } else if (RO_V_VLSSEG2 == instr_temp || RO_V_VLSSEG3 == instr_temp || + RO_V_VLSSEG4 == instr_temp || RO_V_VLSSEG5 == instr_temp || + RO_V_VLSSEG6 == instr_temp || RO_V_VLSSEG7 == instr_temp || + RO_V_VLSSEG8 == instr_temp) { + snprintf(str, sizeof(str), "vlsseg%de%d.v 'vd, ('rs1), 'rs2'vm", + switch_nf(instr), instr->vl_vs_width()); + Format(instr, str); + } else if (RO_V_VLXSEG2 == instr_temp || RO_V_VLXSEG3 == instr_temp || + RO_V_VLXSEG4 == instr_temp || RO_V_VLXSEG5 == instr_temp || + RO_V_VLXSEG6 == instr_temp || RO_V_VLXSEG7 == instr_temp || + RO_V_VLXSEG8 == instr_temp) { + snprintf(str, sizeof(str), "vlxseg%dei%d.v 'vd, ('rs1), 'vs2'vm", + switch_nf(instr), instr->vl_vs_width()); + Format(instr, str); + } +} + +int Decoder::switch_sew(Instruction* instr) { + int width = 0; + if ((instr->InstructionBits() & kBaseOpcodeMask) != LOAD_FP && + (instr->InstructionBits() & kBaseOpcodeMask) != STORE_FP) + return -1; + switch (instr->InstructionBits() & (kRvvWidthMask | kRvvMewMask)) { + case 0x0: + width = 8; + break; + case 0x00005000: + width = 16; + break; + case 0x00006000: + width = 32; + break; + case 0x00007000: + width = 64; + break; + case 0x10000000: + width = 128; + break; + case 0x10005000: + width = 256; + break; + case 0x10006000: + width = 512; + break; + case 0x10007000: + width = 1024; + break; + default: + width = -1; + break; + } + return width; +} + +void Decoder::DecodeRvvVS(Instruction* instr) { + char str[50]; + uint32_t instr_temp = + instr->InstructionBits() & (kRvvMopMask | kRvvNfMask | kBaseOpcodeMask); + if (RO_V_VS == instr_temp) { + snprintf(str, sizeof(str), "vse%d.v 'vd, ('rs1)'vm", + instr->vl_vs_width()); + Format(instr, str); + } else if (RO_V_VSS == instr_temp) { + snprintf(str, sizeof(str), "vsse%d.v 'vd, ('rs1), 'rs2'vm", + instr->vl_vs_width()); + Format(instr, str); + } else if (RO_V_VSX == instr_temp) { + snprintf(str, sizeof(str), "vsxei%d.v 'vd, ('rs1), 'vs2'vm", + instr->vl_vs_width()); + Format(instr, str); + } else if (RO_V_VSU == instr_temp) { + snprintf(str, sizeof(str), "vsuxei%d.v 'vd, ('rs1), 'vs2'vm", + instr->vl_vs_width()); + Format(instr, str); + } else if (RO_V_VSSEG2 == instr_temp || RO_V_VSSEG3 == instr_temp || + RO_V_VSSEG4 == instr_temp || RO_V_VSSEG5 == instr_temp || + RO_V_VSSEG6 == instr_temp || RO_V_VSSEG7 == instr_temp || + RO_V_VSSEG8 == instr_temp) { + snprintf(str, sizeof(str), "vsseg%de%d.v 'vd, ('rs1)'vm", + switch_nf(instr), instr->vl_vs_width()); + Format(instr, str); + } else if (RO_V_VSSSEG2 == instr_temp || RO_V_VSSSEG3 == instr_temp || + RO_V_VSSSEG4 == instr_temp || RO_V_VSSSEG5 == instr_temp || + RO_V_VSSSEG6 == instr_temp || RO_V_VSSSEG7 == instr_temp || + RO_V_VSSSEG8 == instr_temp) { + snprintf(str, sizeof(str), "vssseg%de%d.v 'vd, ('rs1), 'rs2'vm", + switch_nf(instr), instr->vl_vs_width()); + Format(instr, str); + } else if (RO_V_VSXSEG2 == instr_temp || RO_V_VSXSEG3 == instr_temp || + RO_V_VSXSEG4 == instr_temp || RO_V_VSXSEG5 == instr_temp || + RO_V_VSXSEG6 == instr_temp || RO_V_VSXSEG7 == instr_temp || + RO_V_VSXSEG8 == instr_temp) { + snprintf(str, sizeof(str), "vsxseg%dei%d.v 'vd, ('rs1), 'vs2'vm", + switch_nf(instr), instr->vl_vs_width()); + Format(instr, str); + } +} + // Disassemble the instruction at *instr_ptr into the output buffer. // All instructions are one word long, except for the simulator // pseudo-instruction stop(msg). For that one special case, we return @@ -1849,6 +2588,9 @@ int Decoder::InstructionDecode(byte* instr_ptr) { case Instruction::kCBType: DecodeCBType(instr); break; + case Instruction::kVType: + DecodeVType(instr); + break; default: Format(instr, "UNSUPPORTED"); UNSUPPORTED_RISCV(); @@ -1882,7 +2624,7 @@ const char* NameConverter::NameOfXMMRegister(int reg) const { const char* NameConverter::NameOfByteCPURegister(int reg) const { UNREACHABLE(); // RISC-V does not have the concept of a byte register. - return "nobytereg"; + // return "nobytereg"; } const char* NameConverter::NameInCode(byte* addr) const { diff --git a/chromium/v8/src/diagnostics/s390/eh-frame-s390.cc b/chromium/v8/src/diagnostics/s390/eh-frame-s390.cc index 4f5994c8dab..6da3095e866 100644 --- a/chromium/v8/src/diagnostics/s390/eh-frame-s390.cc +++ b/chromium/v8/src/diagnostics/s390/eh-frame-s390.cc @@ -38,7 +38,6 @@ int EhFrameWriter::RegisterToDwarfCode(Register name) { return kR0DwarfCode; default: UNIMPLEMENTED(); - return -1; } } @@ -55,7 +54,6 @@ const char* EhFrameDisassembler::DwarfRegisterCodeToString(int code) { return "sp"; default: UNIMPLEMENTED(); - return nullptr; } } diff --git a/chromium/v8/src/diagnostics/system-jit-win.cc b/chromium/v8/src/diagnostics/system-jit-win.cc index c77c2231836..5ca36e67e6b 100644 --- a/chromium/v8/src/diagnostics/system-jit-win.cc +++ b/chromium/v8/src/diagnostics/system-jit-win.cc @@ -4,7 +4,11 @@ #include "src/diagnostics/system-jit-win.h" -#include "include/v8.h" +#include "include/v8-callbacks.h" +#include "include/v8-isolate.h" +#include "include/v8-local-handle.h" +#include "include/v8-primitive.h" +#include "include/v8-script.h" #include "src/api/api-inl.h" #include "src/base/lazy-instance.h" #include "src/base/logging.h" diff --git a/chromium/v8/src/diagnostics/unwinder.cc b/chromium/v8/src/diagnostics/unwinder.cc index 68ff6795954..00a5e7dbe68 100644 --- a/chromium/v8/src/diagnostics/unwinder.cc +++ b/chromium/v8/src/diagnostics/unwinder.cc @@ -6,7 +6,7 @@ #include <algorithm> -#include "include/v8.h" +#include "include/v8-unwinder.h" #include "src/execution/frame-constants.h" #include "src/execution/pointer-authentication.h" diff --git a/chromium/v8/src/diagnostics/unwinding-info-win64.h b/chromium/v8/src/diagnostics/unwinding-info-win64.h index ca66437e00f..bb32f49e5d8 100644 --- a/chromium/v8/src/diagnostics/unwinding-info-win64.h +++ b/chromium/v8/src/diagnostics/unwinding-info-win64.h @@ -5,7 +5,9 @@ #ifndef V8_DIAGNOSTICS_UNWINDING_INFO_WIN64_H_ #define V8_DIAGNOSTICS_UNWINDING_INFO_WIN64_H_ -#include "include/v8.h" +#include <vector> + +#include "include/v8-callbacks.h" #include "include/v8config.h" #include "src/common/globals.h" diff --git a/chromium/v8/src/diagnostics/x64/disasm-x64.cc b/chromium/v8/src/diagnostics/x64/disasm-x64.cc index 3ddb29e064b..469a6538dc0 100644 --- a/chromium/v8/src/diagnostics/x64/disasm-x64.cc +++ b/chromium/v8/src/diagnostics/x64/disasm-x64.cc @@ -244,8 +244,9 @@ static const InstructionDesc cmov_instructions[16] = { {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}}; -static const char* const cmp_pseudo_op[8] = {"eq", "lt", "le", "unord", - "neq", "nlt", "nle", "ord"}; +static const char* const cmp_pseudo_op[16] = { + "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord", + "eq_uq", "nge", "ngt", "false", "neq_oq", "ge", "gt", "true"}; namespace { int8_t Imm8(const uint8_t* data) { @@ -279,6 +280,10 @@ int64_t Imm64(const uint8_t* data) { //------------------------------------------------------------------------------ // DisassemblerX64 implementation. +// Forward-declare NameOfYMMRegister to keep its implementation with the +// NameConverter methods and register name arrays at bottom. +const char* NameOfYMMRegister(int reg); + // A new DisassemblerX64 object is created to disassemble each instruction. // The object can only disassemble a single instruction. class DisassemblerX64 { @@ -356,6 +361,12 @@ class DisassemblerX64 { return (checked & 4) == 0; } + bool vex_256() const { + DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); + byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; + return (checked & 4) != 0; + } + bool vex_none() { DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; @@ -424,6 +435,14 @@ class DisassemblerX64 { return converter_.NameOfXMMRegister(reg); } + const char* NameOfAVXRegister(int reg) const { + if (vex_256()) { + return NameOfYMMRegister(reg); + } else { + return converter_.NameOfXMMRegister(reg); + } + } + const char* NameOfAddress(byte* addr) const { return converter_.NameOfAddress(addr); } @@ -448,6 +467,7 @@ class DisassemblerX64 { int PrintRightOperand(byte* modrmp); int PrintRightByteOperand(byte* modrmp); int PrintRightXMMOperand(byte* modrmp); + int PrintRightAVXOperand(byte* modrmp); int PrintOperands(const char* mnem, OperandType op_order, byte* data); int PrintImmediate(byte* data, OperandSize size); int PrintImmediateOp(byte* data); @@ -606,6 +626,10 @@ int DisassemblerX64::PrintRightXMMOperand(byte* modrmp) { return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfXMMRegister); } +int DisassemblerX64::PrintRightAVXOperand(byte* modrmp) { + return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfAVXRegister); +} + // Returns number of bytes used including the current *data. // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. int DisassemblerX64::PrintOperands(const char* mnem, OperandType op_order, @@ -866,78 +890,98 @@ int DisassemblerX64::AVXInstruction(byte* data) { get_modrm(*current, &mod, ®op, &rm); switch (opcode) { case 0x18: - AppendToBuffer("vbroadcastss %s,", NameOfXMMRegister(regop)); + AppendToBuffer("vbroadcastss %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); + break; + case 0x98: + AppendToBuffer("vfmadd132p%c %s,%s,", float_size_code(), + NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); break; case 0x99: AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(), + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); + break; + case 0xA8: + AppendToBuffer("vfmadd213p%c %s,%s,", float_size_code(), NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); break; case 0xA9: AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0xB8: AppendToBuffer("vfmadd231p%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0xB9: AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x9B: AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(), + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); + break; + case 0x9C: + AppendToBuffer("vfnmadd132p%c %s,%s,", float_size_code(), NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); break; case 0xAB: AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(), + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); + break; + case 0xAC: + AppendToBuffer("vfnmadd213p%c %s,%s,", float_size_code(), NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); break; case 0xBB: AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0xBC: AppendToBuffer("vfnmadd231p%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x9D: AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0xAD: AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0xBD: AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x9F: AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0xAF: AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0xBF: AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(), - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0xF7: AppendToBuffer("shlx%c %s,", operand_size_code(), @@ -948,9 +992,9 @@ int DisassemblerX64::AVXInstruction(byte* data) { #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, \ opcode) \ case 0x##opcode: { \ - AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \ - NameOfXMMRegister(vvvv)); \ - current += PrintRightXMMOperand(current); \ + AppendToBuffer("v" #instruction " %s,%s,", NameOfAVXRegister(regop), \ + NameOfAVXRegister(vvvv)); \ + current += PrintRightAVXOperand(current); \ break; \ } @@ -962,8 +1006,8 @@ int DisassemblerX64::AVXInstruction(byte* data) { #define DECLARE_SSE_UNOP_AVX_DIS_CASE(instruction, notUsed1, notUsed2, \ notUsed3, opcode) \ case 0x##opcode: { \ - AppendToBuffer("v" #instruction " %s,", NameOfXMMRegister(regop)); \ - current += PrintRightXMMOperand(current); \ + AppendToBuffer("v" #instruction " %s,", NameOfAVXRegister(regop)); \ + current += PrintRightAVXOperand(current); \ break; \ } SSSE3_UNOP_INSTRUCTION_LIST(DECLARE_SSE_UNOP_AVX_DIS_CASE) @@ -972,8 +1016,8 @@ int DisassemblerX64::AVXInstruction(byte* data) { #define DISASSEMBLE_AVX2_BROADCAST(instruction, _1, _2, _3, code) \ case 0x##code: \ - AppendToBuffer("" #instruction " %s,", NameOfXMMRegister(regop)); \ - current += PrintRightXMMOperand(current); \ + AppendToBuffer("" #instruction " %s,", NameOfAVXRegister(regop)); \ + current += PrintRightAVXOperand(current); \ break; AVX2_BROADCAST_LIST(DISASSEMBLE_AVX2_BROADCAST) #undef DISASSEMBLE_AVX2_BROADCAST @@ -986,96 +1030,96 @@ int DisassemblerX64::AVXInstruction(byte* data) { get_modrm(*current, &mod, ®op, &rm); switch (opcode) { case 0x08: - AppendToBuffer("vroundps %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vroundps %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x09: - AppendToBuffer("vroundpd %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vroundpd %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x0A: - AppendToBuffer("vroundss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vroundss %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x0B: - AppendToBuffer("vroundsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vroundsd %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x0E: - AppendToBuffer("vpblendw %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vpblendw %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x0F: - AppendToBuffer("vpalignr %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vpalignr %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x14: AppendToBuffer("vpextrb "); current += PrintRightByteOperand(current); - AppendToBuffer(",%s,0x%x,", NameOfXMMRegister(regop), *current++); + AppendToBuffer(",%s,0x%x,", NameOfAVXRegister(regop), *current++); break; case 0x15: AppendToBuffer("vpextrw "); current += PrintRightOperand(current); - AppendToBuffer(",%s,0x%x,", NameOfXMMRegister(regop), *current++); + AppendToBuffer(",%s,0x%x,", NameOfAVXRegister(regop), *current++); break; case 0x16: AppendToBuffer("vpextr%c ", rex_w() ? 'q' : 'd'); current += PrintRightOperand(current); - AppendToBuffer(",%s,0x%x,", NameOfXMMRegister(regop), *current++); + AppendToBuffer(",%s,0x%x,", NameOfAVXRegister(regop), *current++); break; case 0x17: AppendToBuffer("vextractps "); current += PrintRightOperand(current); - AppendToBuffer(",%s,0x%x,", NameOfXMMRegister(regop), *current++); + AppendToBuffer(",%s,0x%x,", NameOfAVXRegister(regop), *current++); break; case 0x20: - AppendToBuffer("vpinsrb %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); + AppendToBuffer("vpinsrb %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); current += PrintRightByteOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x21: - AppendToBuffer("vinsertps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vinsertps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x22: AppendToBuffer("vpinsr%c %s,%s,", rex_w() ? 'q' : 'd', - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); current += PrintRightOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x4A: { - AppendToBuffer("vblendvps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister((*current++) >> 4)); + AppendToBuffer("vblendvps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister((*current++) >> 4)); break; } case 0x4B: { - AppendToBuffer("vblendvpd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister((*current++) >> 4)); + AppendToBuffer("vblendvpd %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister((*current++) >> 4)); break; } case 0x4C: { - AppendToBuffer("vpblendvb %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister((*current++) >> 4)); + AppendToBuffer("vpblendvb %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister((*current++) >> 4)); break; } default: @@ -1086,95 +1130,95 @@ int DisassemblerX64::AVXInstruction(byte* data) { get_modrm(*current, &mod, ®op, &rm); switch (opcode) { case 0x10: - AppendToBuffer("vmovss %s,", NameOfXMMRegister(regop)); + AppendToBuffer("vmovss %s,", NameOfAVXRegister(regop)); if (mod == 3) { - AppendToBuffer("%s,", NameOfXMMRegister(vvvv)); + AppendToBuffer("%s,", NameOfAVXRegister(vvvv)); } - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); break; case 0x11: AppendToBuffer("vmovss "); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); if (mod == 3) { - AppendToBuffer(",%s", NameOfXMMRegister(vvvv)); + AppendToBuffer(",%s", NameOfAVXRegister(vvvv)); } - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0x16: - AppendToBuffer("vmovshdup %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovshdup %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x2A: AppendToBuffer("%s %s,%s,", vex_w() ? "vcvtqsi2ss" : "vcvtlsi2ss", - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); current += PrintRightOperand(current); break; case 0x2C: AppendToBuffer("vcvttss2si%s %s,", vex_w() ? "q" : "", NameOfCPURegister(regop)); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); break; case 0x51: - AppendToBuffer("vsqrtss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vsqrtss %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x58: - AppendToBuffer("vaddss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vaddss %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x59: - AppendToBuffer("vmulss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmulss %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x5A: - AppendToBuffer("vcvtss2sd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vcvtss2sd %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x5B: - AppendToBuffer("vcvttps2dq %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vcvttps2dq %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x5C: - AppendToBuffer("vsubss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vsubss %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x5D: - AppendToBuffer("vminss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vminss %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x5E: - AppendToBuffer("vdivss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vdivss %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x5F: - AppendToBuffer("vmaxss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmaxss %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); break; case 0x6F: - AppendToBuffer("vmovdqu %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovdqu %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x70: - AppendToBuffer("vpshufhw %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vpshufhw %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x7F: AppendToBuffer("vmovdqu "); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0xE6: - AppendToBuffer("vcvtdq2pd %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vcvtdq2pd %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; default: UnimplementedInstruction(); @@ -1184,93 +1228,61 @@ int DisassemblerX64::AVXInstruction(byte* data) { get_modrm(*current, &mod, ®op, &rm); switch (opcode) { case 0x10: - AppendToBuffer("vmovsd %s,", NameOfXMMRegister(regop)); + AppendToBuffer("vmovsd %s,", NameOfAVXRegister(regop)); if (mod == 3) { - AppendToBuffer("%s,", NameOfXMMRegister(vvvv)); + AppendToBuffer("%s,", NameOfAVXRegister(vvvv)); } - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); break; case 0x11: AppendToBuffer("vmovsd "); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); if (mod == 3) { - AppendToBuffer(",%s", NameOfXMMRegister(vvvv)); + AppendToBuffer(",%s", NameOfAVXRegister(vvvv)); } - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0x12: - AppendToBuffer("vmovddup %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovddup %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x2A: AppendToBuffer("%s %s,%s,", vex_w() ? "vcvtqsi2sd" : "vcvtlsi2sd", - NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); + NameOfAVXRegister(regop), NameOfAVXRegister(vvvv)); current += PrintRightOperand(current); break; case 0x2C: AppendToBuffer("vcvttsd2si%s %s,", vex_w() ? "q" : "", NameOfCPURegister(regop)); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); break; case 0x2D: AppendToBuffer("vcvtsd2si%s %s,", vex_w() ? "q" : "", NameOfCPURegister(regop)); - current += PrintRightXMMOperand(current); - break; - case 0x51: - AppendToBuffer("vsqrtsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x58: - AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x59: - AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5A: - AppendToBuffer("vcvtsd2ss %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5C: - AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5D: - AppendToBuffer("vminsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5E: - AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; - case 0x5F: - AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); break; case 0xF0: - AppendToBuffer("vlddqu %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vlddqu %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x70: - AppendToBuffer("vpshuflw %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vpshuflw %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x7C: - AppendToBuffer("vhaddps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); - break; + AppendToBuffer("vhaddps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); + break; +#define DISASM_SSE2_INSTRUCTION_LIST_SD(instruction, _1, _2, opcode) \ + case 0x##opcode: \ + AppendToBuffer("v" #instruction " %s,%s,", NameOfAVXRegister(regop), \ + NameOfAVXRegister(vvvv)); \ + current += PrintRightAVXOperand(current); \ + break; + SSE2_INSTRUCTION_LIST_SD(DISASM_SSE2_INSTRUCTION_LIST_SD) +#undef DISASM_SSE2_INSTRUCTION_LIST_SD default: UnimplementedInstruction(); } @@ -1387,90 +1399,90 @@ int DisassemblerX64::AVXInstruction(byte* data) { get_modrm(*current, &mod, ®op, &rm); switch (opcode) { case 0x10: - AppendToBuffer("vmovups %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovups %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x11: AppendToBuffer("vmovups "); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0x12: if (mod == 0b11) { - AppendToBuffer("vmovhlps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovhlps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); } else { - AppendToBuffer("vmovlps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovlps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); } break; case 0x13: AppendToBuffer("vmovlps "); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0x16: if (mod == 0b11) { - AppendToBuffer("vmovlhps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovlhps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); } else { - AppendToBuffer("vmovhps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovhps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); } break; case 0x17: AppendToBuffer("vmovhps "); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0x28: - AppendToBuffer("vmovaps %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovaps %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x29: AppendToBuffer("vmovaps "); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0x2E: - AppendToBuffer("vucomiss %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vucomiss %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x50: AppendToBuffer("vmovmskps %s,", NameOfCPURegister(regop)); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); break; case 0xC2: { - AppendToBuffer("vcmpps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vcmpps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(", (%s)", cmp_pseudo_op[*current]); current += 1; break; } case 0xC6: { - AppendToBuffer("vshufps %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vshufps %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; } #define SSE_UNOP_CASE(instruction, unused, code) \ case 0x##code: \ - AppendToBuffer("v" #instruction " %s,", NameOfXMMRegister(regop)); \ - current += PrintRightXMMOperand(current); \ + AppendToBuffer("v" #instruction " %s,", NameOfAVXRegister(regop)); \ + current += PrintRightAVXOperand(current); \ break; SSE_UNOP_INSTRUCTION_LIST(SSE_UNOP_CASE) #undef SSE_UNOP_CASE #define SSE_BINOP_CASE(instruction, unused, code) \ case 0x##code: \ - AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \ - NameOfXMMRegister(vvvv)); \ - current += PrintRightXMMOperand(current); \ + AppendToBuffer("v" #instruction " %s,%s,", NameOfAVXRegister(regop), \ + NameOfAVXRegister(vvvv)); \ + current += PrintRightAVXOperand(current); \ break; SSE_BINOP_INSTRUCTION_LIST(SSE_BINOP_CASE) #undef SSE_BINOP_CASE @@ -1482,92 +1494,92 @@ int DisassemblerX64::AVXInstruction(byte* data) { get_modrm(*current, &mod, ®op, &rm); switch (opcode) { case 0x10: - AppendToBuffer("vmovupd %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovupd %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x11: AppendToBuffer("vmovupd "); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0x28: - AppendToBuffer("vmovapd %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovapd %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x29: AppendToBuffer("vmovapd "); - current += PrintRightXMMOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + current += PrintRightAVXOperand(current); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0x50: AppendToBuffer("vmovmskpd %s,", NameOfCPURegister(regop)); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); break; case 0x6E: AppendToBuffer("vmov%c %s,", vex_w() ? 'q' : 'd', - NameOfXMMRegister(regop)); + NameOfAVXRegister(regop)); current += PrintRightOperand(current); break; case 0x6F: - AppendToBuffer("vmovdqa %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vmovdqa %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); break; case 0x70: - AppendToBuffer("vpshufd %s,", NameOfXMMRegister(regop)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vpshufd %s,", NameOfAVXRegister(regop)); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0x71: AppendToBuffer("vps%sw %s,", sf_str[regop / 2], - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",%u", *current++); break; case 0x72: AppendToBuffer("vps%sd %s,", sf_str[regop / 2], - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",%u", *current++); break; case 0x73: AppendToBuffer("vps%sq %s,", sf_str[regop / 2], - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(",%u", *current++); break; case 0x7E: AppendToBuffer("vmov%c ", vex_w() ? 'q' : 'd'); current += PrintRightOperand(current); - AppendToBuffer(",%s", NameOfXMMRegister(regop)); + AppendToBuffer(",%s", NameOfAVXRegister(regop)); break; case 0xC2: { - AppendToBuffer("vcmppd %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); - current += PrintRightXMMOperand(current); + AppendToBuffer("vcmppd %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); + current += PrintRightAVXOperand(current); AppendToBuffer(", (%s)", cmp_pseudo_op[*current]); current += 1; break; } case 0xC4: - AppendToBuffer("vpinsrw %s,%s,", NameOfXMMRegister(regop), - NameOfXMMRegister(vvvv)); + AppendToBuffer("vpinsrw %s,%s,", NameOfAVXRegister(regop), + NameOfAVXRegister(vvvv)); current += PrintRightOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0xC5: AppendToBuffer("vpextrw %s,", NameOfCPURegister(regop)); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); AppendToBuffer(",0x%x", *current++); break; case 0xD7: AppendToBuffer("vpmovmskb %s,", NameOfCPURegister(regop)); - current += PrintRightXMMOperand(current); + current += PrintRightAVXOperand(current); break; #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \ case 0x##opcode: { \ - AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \ - NameOfXMMRegister(vvvv)); \ - current += PrintRightXMMOperand(current); \ + AppendToBuffer("v" #instruction " %s,%s,", NameOfAVXRegister(regop), \ + NameOfAVXRegister(vvvv)); \ + current += PrintRightAVXOperand(current); \ break; \ } @@ -1575,8 +1587,8 @@ int DisassemblerX64::AVXInstruction(byte* data) { #undef DECLARE_SSE_AVX_DIS_CASE #define DECLARE_SSE_UNOP_AVX_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \ case 0x##opcode: { \ - AppendToBuffer("v" #instruction " %s,", NameOfXMMRegister(regop)); \ - current += PrintRightXMMOperand(current); \ + AppendToBuffer("v" #instruction " %s,", NameOfAVXRegister(regop)); \ + current += PrintRightAVXOperand(current); \ break; \ } @@ -2799,9 +2811,9 @@ int DisassemblerX64::InstructionDecode(v8::base::Vector<char> out_buffer, for (byte* bp = instr; bp < data; bp++) { outp += v8::base::SNPrintF(out_buffer + outp, "%02x", *bp); } - // Indent instruction, leaving space for 9 bytes, i.e. 18 characters in hex. - // 9-byte nop and rip-relative mov are (probably) the largest we emit. - while (outp < 18) { + // Indent instruction, leaving space for 10 bytes, i.e. 20 characters in hex. + // 10-byte mov is (probably) the largest we emit. + while (outp < 20) { outp += v8::base::SNPrintF(out_buffer + outp, " "); } @@ -2823,6 +2835,10 @@ static const char* const xmm_regs[16] = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"}; +static const char* const ymm_regs[16] = { + "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15"}; + const char* NameConverter::NameOfAddress(byte* addr) const { v8::base::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr)); return tmp_buffer_.begin(); @@ -2847,6 +2863,11 @@ const char* NameConverter::NameOfXMMRegister(int reg) const { return "noxmmreg"; } +const char* NameOfYMMRegister(int reg) { + if (0 <= reg && reg < 16) return ymm_regs[reg]; + return "noymmreg"; +} + const char* NameConverter::NameInCode(byte* addr) const { // X64 does not embed debug strings at the moment. UNREACHABLE(); |