diff options
Diffstat (limited to 'chromium/v8/src/diagnostics')
-rw-r--r-- | chromium/v8/src/diagnostics/arm/disasm-arm.cc | 65 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/arm64/disasm-arm64.cc | 12 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/basic-block-profiler.cc | 142 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/basic-block-profiler.h | 85 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/code-tracer.h | 24 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/ia32/disasm-ia32.cc | 39 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/objects-debug.cc | 78 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/objects-printer.cc | 134 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/ppc/disasm-ppc.cc | 81 | ||||
-rw-r--r-- | chromium/v8/src/diagnostics/x64/disasm-x64.cc | 24 |
10 files changed, 450 insertions, 234 deletions
diff --git a/chromium/v8/src/diagnostics/arm/disasm-arm.cc b/chromium/v8/src/diagnostics/arm/disasm-arm.cc index e17936d8d2d..e7f006f0e90 100644 --- a/chromium/v8/src/diagnostics/arm/disasm-arm.cc +++ b/chromium/v8/src/diagnostics/arm/disasm-arm.cc @@ -34,6 +34,7 @@ #include "src/base/platform/platform.h" #include "src/codegen/arm/assembler-arm.h" #include "src/codegen/arm/constants-arm.h" +#include "src/codegen/arm/register-arm.h" #include "src/diagnostics/disasm.h" #include "src/utils/vector.h" @@ -70,7 +71,9 @@ class Decoder { void PrintRegister(int reg); void PrintSRegister(int reg); void PrintDRegister(int reg); - int FormatVFPRegister(Instruction* instr, const char* format); + void PrintQRegister(int reg); + int FormatVFPRegister(Instruction* instr, const char* format, + VFPRegPrecision precision); void PrintMovwMovt(Instruction* instr); int FormatVFPinstruction(Instruction* instr, const char* format); void PrintCondition(Instruction* instr); @@ -160,6 +163,11 @@ void Decoder::PrintSRegister(int reg) { Print(VFPRegisters::Name(reg, false)); } // Print the VFP D register name according to the active name converter. void Decoder::PrintDRegister(int reg) { Print(VFPRegisters::Name(reg, true)); } +// Print the VFP Q register name according to the active name converter. +void Decoder::PrintQRegister(int reg) { + Print(RegisterName(QwNeonRegister::from_code(reg))); +} + // These shift names are defined in a way to match the native disassembler // formatting. See for example the command "objdump -d <binary file>". static const char* const shift_names[kNumberOfShifts] = {"lsl", "lsr", "asr", @@ -312,12 +320,8 @@ int Decoder::FormatRegister(Instruction* instr, const char* format) { // Handle all VFP register based formatting in this function to reduce the // complexity of FormatOption. -int Decoder::FormatVFPRegister(Instruction* instr, const char* format) { - DCHECK((format[0] == 'S') || (format[0] == 'D')); - - VFPRegPrecision precision = - format[0] == 'D' ? kDoublePrecision : kSinglePrecision; - +int Decoder::FormatVFPRegister(Instruction* instr, const char* format, + VFPRegPrecision precision) { int retval = 2; int reg = -1; if (format[1] == 'n') { @@ -334,9 +338,10 @@ int Decoder::FormatVFPRegister(Instruction* instr, const char* format) { } if (format[2] == '+') { + DCHECK_NE(kSimd128Precision, precision); // Simd128 unimplemented. int immed8 = instr->Immed8Value(); - if (format[0] == 'S') reg += immed8 - 1; - if (format[0] == 'D') reg += (immed8 / 2 - 1); + if (precision == kSinglePrecision) reg += immed8 - 1; + if (precision == kDoublePrecision) reg += (immed8 / 2 - 1); } if (format[2] == '+') retval = 3; } else { @@ -345,8 +350,11 @@ int Decoder::FormatVFPRegister(Instruction* instr, const char* format) { if (precision == kSinglePrecision) { PrintSRegister(reg); - } else { + } else if (precision == kDoublePrecision) { PrintDRegister(reg); + } else { + DCHECK_EQ(kSimd128Precision, precision); + PrintQRegister(reg); } return retval; @@ -644,9 +652,11 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { return 1; } case 'S': - case 'D': { - return FormatVFPRegister(instr, format); - } + return FormatVFPRegister(instr, format, kSinglePrecision); + case 'D': + return FormatVFPRegister(instr, format, kDoublePrecision); + case 'Q': + return FormatVFPRegister(instr, format, kSimd128Precision); case 'w': { // 'w: W field of load and store instructions if (instr->HasW()) { Print("!"); @@ -2264,6 +2274,35 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s.%c%i d%d, q%d", name, type, size, Vd, Vm); + } else if (instr->Bits(17, 16) == 0x2 && instr->Bit(10) == 1) { + // NEON vrintm, vrintp, vrintz + bool dp_op = instr->Bit(6) == 0; + int rounding_mode = instr->Bits(9, 7); + switch (rounding_mode) { + case 3: + if (dp_op) { + Format(instr, "vrintz.f32 'Dd, 'Dm"); + } else { + Format(instr, "vrintz.f32 'Qd, 'Qm"); + } + break; + case 5: + if (dp_op) { + Format(instr, "vrintm.f32 'Dd, 'Dm"); + } else { + Format(instr, "vrintm.f32 'Qd, 'Qm"); + } + break; + case 7: + if (dp_op) { + Format(instr, "vrintp.f32 'Dd, 'Dm"); + } else { + Format(instr, "vrintp.f32 'Qd, 'Qm"); + } + break; + default: + UNIMPLEMENTED(); + } } else { int Vd, Vm; if (instr->Bit(6) == 0) { diff --git a/chromium/v8/src/diagnostics/arm64/disasm-arm64.cc b/chromium/v8/src/diagnostics/arm64/disasm-arm64.cc index 3f8f40a244d..7ee499c183f 100644 --- a/chromium/v8/src/diagnostics/arm64/disasm-arm64.cc +++ b/chromium/v8/src/diagnostics/arm64/disasm-arm64.cc @@ -1377,6 +1377,10 @@ void DisassemblingDecoder::VisitFPIntegerConvert(Instruction* instr) { mnemonic = "ucvtf"; form = form_fr; break; + case FJCVTZS: + mnemonic = "fjcvtzs"; + form = form_rf; + break; } Format(instr, mnemonic, form); } @@ -1419,10 +1423,10 @@ void DisassemblingDecoder::VisitFPFixedPointConvert(Instruction* instr) { // clang-format off #define PAUTH_SYSTEM_MNEMONICS(V) \ - V(PACIA1716, "pacia1716") \ - V(AUTIA1716, "autia1716") \ - V(PACIASP, "paciasp") \ - V(AUTIASP, "autiasp") + V(PACIB1716, "pacib1716") \ + V(AUTIB1716, "autib1716") \ + V(PACIBSP, "pacibsp") \ + V(AUTIBSP, "autibsp") // clang-format on void DisassemblingDecoder::VisitSystem(Instruction* instr) { diff --git a/chromium/v8/src/diagnostics/basic-block-profiler.cc b/chromium/v8/src/diagnostics/basic-block-profiler.cc index 262a5364b5e..f61292c3cdd 100644 --- a/chromium/v8/src/diagnostics/basic-block-profiler.cc +++ b/chromium/v8/src/diagnostics/basic-block-profiler.cc @@ -9,84 +9,138 @@ #include <sstream> #include "src/base/lazy-instance.h" +#include "src/heap/heap-inl.h" +#include "torque-generated/exported-class-definitions-tq-inl.h" namespace v8 { namespace internal { DEFINE_LAZY_LEAKY_OBJECT_GETTER(BasicBlockProfiler, BasicBlockProfiler::Get) -BasicBlockProfiler::Data::Data(size_t n_blocks) - : n_blocks_(n_blocks), - block_rpo_numbers_(n_blocks_), - counts_(n_blocks_, 0) {} +BasicBlockProfilerData::BasicBlockProfilerData(size_t n_blocks) + : block_rpo_numbers_(n_blocks), counts_(n_blocks, 0) {} -static void InsertIntoString(std::ostringstream* os, std::string* string) { - string->insert(0, os->str()); +void BasicBlockProfilerData::SetCode(const std::ostringstream& os) { + code_ = os.str(); } -static void InsertIntoString(const char* data, std::string* string) { - string->insert(0, data); +void BasicBlockProfilerData::SetFunctionName(std::unique_ptr<char[]> name) { + function_name_ = name.get(); } -void BasicBlockProfiler::Data::SetCode(std::ostringstream* os) { - InsertIntoString(os, &code_); +void BasicBlockProfilerData::SetSchedule(const std::ostringstream& os) { + schedule_ = os.str(); } -void BasicBlockProfiler::Data::SetFunctionName(std::unique_ptr<char[]> name) { - InsertIntoString(name.get(), &function_name_); +void BasicBlockProfilerData::SetBlockRpoNumber(size_t offset, + int32_t block_rpo) { + DCHECK(offset < n_blocks()); + block_rpo_numbers_[offset] = block_rpo; } -void BasicBlockProfiler::Data::SetSchedule(std::ostringstream* os) { - InsertIntoString(os, &schedule_); +void BasicBlockProfilerData::ResetCounts() { + for (size_t i = 0; i < n_blocks(); ++i) { + counts_[i] = 0; + } } -void BasicBlockProfiler::Data::SetBlockRpoNumber(size_t offset, - int32_t block_rpo) { - DCHECK(offset < n_blocks_); - block_rpo_numbers_[offset] = block_rpo; +BasicBlockProfilerData* BasicBlockProfiler::NewData(size_t n_blocks) { + base::MutexGuard lock(&data_list_mutex_); + auto data = std::make_unique<BasicBlockProfilerData>(n_blocks); + BasicBlockProfilerData* data_ptr = data.get(); + data_list_.push_back(std::move(data)); + return data_ptr; } -intptr_t BasicBlockProfiler::Data::GetCounterAddress(size_t offset) { - DCHECK(offset < n_blocks_); - return reinterpret_cast<intptr_t>(&(counts_[offset])); +namespace { +Handle<String> CopyStringToJSHeap(const std::string& source, Isolate* isolate) { + return isolate->factory()->NewStringFromAsciiChecked(source.c_str(), + AllocationType::kOld); } -void BasicBlockProfiler::Data::ResetCounts() { - for (size_t i = 0; i < n_blocks_; ++i) { - counts_[i] = 0; +// Size of entries in both block_rpo_numbers and counts. +constexpr int kBasicBlockSlotSize = kInt32Size; +} // namespace + +BasicBlockProfilerData::BasicBlockProfilerData( + Handle<OnHeapBasicBlockProfilerData> js_heap_data, Isolate* isolate) { + function_name_ = js_heap_data->name().ToCString().get(); + schedule_ = js_heap_data->schedule().ToCString().get(); + code_ = js_heap_data->code().ToCString().get(); + Handle<ByteArray> counts(js_heap_data->counts(), isolate); + for (int i = 0; i < counts->length() / kBasicBlockSlotSize; ++i) { + counts_.push_back(counts->get_uint32(i)); } + Handle<ByteArray> rpo_numbers(js_heap_data->block_rpo_numbers(), isolate); + for (int i = 0; i < rpo_numbers->length() / kBasicBlockSlotSize; ++i) { + block_rpo_numbers_.push_back(rpo_numbers->get_int(i)); + } + CHECK_EQ(block_rpo_numbers_.size(), counts_.size()); } -BasicBlockProfiler::Data* BasicBlockProfiler::NewData(size_t n_blocks) { - base::MutexGuard lock(&data_list_mutex_); - Data* data = new Data(n_blocks); - data_list_.push_back(data); - return data; +Handle<OnHeapBasicBlockProfilerData> BasicBlockProfilerData::CopyToJSHeap( + Isolate* isolate) { + int array_size_in_bytes = static_cast<int>(n_blocks() * kBasicBlockSlotSize); + CHECK(array_size_in_bytes >= 0 && + static_cast<size_t>(array_size_in_bytes) / kBasicBlockSlotSize == + n_blocks()); // Overflow + Handle<ByteArray> block_rpo_numbers = isolate->factory()->NewByteArray( + array_size_in_bytes, AllocationType::kOld); + for (int i = 0; i < static_cast<int>(n_blocks()); ++i) { + block_rpo_numbers->set_int(i, block_rpo_numbers_[i]); + } + Handle<ByteArray> counts = isolate->factory()->NewByteArray( + array_size_in_bytes, AllocationType::kOld); + for (int i = 0; i < static_cast<int>(n_blocks()); ++i) { + counts->set_uint32(i, counts_[i]); + } + Handle<String> name = CopyStringToJSHeap(function_name_, isolate); + Handle<String> schedule = CopyStringToJSHeap(schedule_, isolate); + Handle<String> code = CopyStringToJSHeap(code_, isolate); + + return isolate->factory()->NewOnHeapBasicBlockProfilerData( + block_rpo_numbers, counts, name, schedule, code, AllocationType::kOld); } -BasicBlockProfiler::~BasicBlockProfiler() { - for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) { - delete (*i); +void BasicBlockProfiler::ResetCounts(Isolate* isolate) { + for (const auto& data : data_list_) { + data->ResetCounts(); + } + HandleScope scope(isolate); + Handle<ArrayList> list(isolate->heap()->basic_block_profiling_data(), + isolate); + for (int i = 0; i < list->Length(); ++i) { + Handle<ByteArray> counts( + OnHeapBasicBlockProfilerData::cast(list->Get(i)).counts(), isolate); + for (int j = 0; j < counts->length() / kBasicBlockSlotSize; ++j) { + counts->set_uint32(j, 0); + } } } -void BasicBlockProfiler::ResetCounts() { - for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) { - (*i)->ResetCounts(); - } +bool BasicBlockProfiler::HasData(Isolate* isolate) { + return data_list_.size() > 0 || + isolate->heap()->basic_block_profiling_data().Length() > 0; } -std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler& p) { +void BasicBlockProfiler::Print(std::ostream& os, Isolate* isolate) { os << "---- Start Profiling Data ----" << std::endl; - using iterator = BasicBlockProfiler::DataList::const_iterator; - for (iterator i = p.data_list_.begin(); i != p.data_list_.end(); ++i) { - os << **i; + for (const auto& data : data_list_) { + os << *data; + } + HandleScope scope(isolate); + Handle<ArrayList> list(isolate->heap()->basic_block_profiling_data(), + isolate); + for (int i = 0; i < list->Length(); ++i) { + BasicBlockProfilerData data( + handle(OnHeapBasicBlockProfilerData::cast(list->Get(i)), isolate), + isolate); + os << data; } os << "---- End Profiling Data ----" << std::endl; - return os; } -std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler::Data& d) { +std::ostream& operator<<(std::ostream& os, const BasicBlockProfilerData& d) { int block_count_sum = std::accumulate(d.counts_.begin(), d.counts_.end(), 0); if (block_count_sum == 0) return os; const char* name = "unknown function"; @@ -100,8 +154,8 @@ std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler::Data& d) { } os << "block counts for " << name << ":" << std::endl; std::vector<std::pair<int32_t, uint32_t>> pairs; - pairs.reserve(d.n_blocks_); - for (size_t i = 0; i < d.n_blocks_; ++i) { + pairs.reserve(d.n_blocks()); + for (size_t i = 0; i < d.n_blocks(); ++i) { pairs.push_back(std::make_pair(d.block_rpo_numbers_[i], d.counts_[i])); } std::sort(pairs.begin(), pairs.end(), diff --git a/chromium/v8/src/diagnostics/basic-block-profiler.h b/chromium/v8/src/diagnostics/basic-block-profiler.h index 9639e0b6615..0eb82e8a1bc 100644 --- a/chromium/v8/src/diagnostics/basic-block-profiler.h +++ b/chromium/v8/src/diagnostics/basic-block-profiler.h @@ -14,66 +14,71 @@ #include "src/base/macros.h" #include "src/base/platform/mutex.h" #include "src/common/globals.h" +#include "torque-generated/exported-class-definitions-tq.h" namespace v8 { namespace internal { +class BasicBlockProfilerData { + public: + explicit BasicBlockProfilerData(size_t n_blocks); + V8_EXPORT_PRIVATE BasicBlockProfilerData( + Handle<OnHeapBasicBlockProfilerData> js_heap_data, Isolate* isolate); + + size_t n_blocks() const { + DCHECK_EQ(block_rpo_numbers_.size(), counts_.size()); + return block_rpo_numbers_.size(); + } + const uint32_t* counts() const { return &counts_[0]; } + + void SetCode(const std::ostringstream& os); + void SetFunctionName(std::unique_ptr<char[]> name); + void SetSchedule(const std::ostringstream& os); + void SetBlockRpoNumber(size_t offset, int32_t block_rpo); + + // Copy the data from this object into an equivalent object stored on the JS + // heap, so that it can survive snapshotting and relocation. This must + // happen on the main thread during finalization of the compilation. + Handle<OnHeapBasicBlockProfilerData> CopyToJSHeap(Isolate* isolate); + + private: + friend class BasicBlockProfiler; + friend std::ostream& operator<<(std::ostream& os, + const BasicBlockProfilerData& s); + + V8_EXPORT_PRIVATE void ResetCounts(); + + std::vector<int32_t> block_rpo_numbers_; + std::vector<uint32_t> counts_; + std::string function_name_; + std::string schedule_; + std::string code_; + DISALLOW_COPY_AND_ASSIGN(BasicBlockProfilerData); +}; + class BasicBlockProfiler { public: - class Data { - public: - size_t n_blocks() const { return n_blocks_; } - const uint32_t* counts() const { return &counts_[0]; } - - void SetCode(std::ostringstream* os); - void SetFunctionName(std::unique_ptr<char[]> name); - void SetSchedule(std::ostringstream* os); - void SetBlockRpoNumber(size_t offset, int32_t block_rpo); - intptr_t GetCounterAddress(size_t offset); - - private: - friend class BasicBlockProfiler; - friend std::ostream& operator<<(std::ostream& os, - const BasicBlockProfiler::Data& s); - - explicit Data(size_t n_blocks); - ~Data() = default; - - V8_EXPORT_PRIVATE void ResetCounts(); - - const size_t n_blocks_; - std::vector<int32_t> block_rpo_numbers_; - std::vector<uint32_t> counts_; - std::string function_name_; - std::string schedule_; - std::string code_; - DISALLOW_COPY_AND_ASSIGN(Data); - }; - - using DataList = std::list<Data*>; + using DataList = std::list<std::unique_ptr<BasicBlockProfilerData>>; BasicBlockProfiler() = default; - ~BasicBlockProfiler(); + ~BasicBlockProfiler() = default; V8_EXPORT_PRIVATE static BasicBlockProfiler* Get(); - Data* NewData(size_t n_blocks); - V8_EXPORT_PRIVATE void ResetCounts(); + BasicBlockProfilerData* NewData(size_t n_blocks); + V8_EXPORT_PRIVATE void ResetCounts(Isolate* isolate); + V8_EXPORT_PRIVATE bool HasData(Isolate* isolate); + V8_EXPORT_PRIVATE void Print(std::ostream& os, Isolate* isolate); const DataList* data_list() { return &data_list_; } private: - friend V8_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, const BasicBlockProfiler& s); - DataList data_list_; base::Mutex data_list_mutex_; DISALLOW_COPY_AND_ASSIGN(BasicBlockProfiler); }; -V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, - const BasicBlockProfiler& s); -std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler::Data& s); +std::ostream& operator<<(std::ostream& os, const BasicBlockProfilerData& s); } // namespace internal } // namespace v8 diff --git a/chromium/v8/src/diagnostics/code-tracer.h b/chromium/v8/src/diagnostics/code-tracer.h index a9f276bf448..194d3cbe667 100644 --- a/chromium/v8/src/diagnostics/code-tracer.h +++ b/chromium/v8/src/diagnostics/code-tracer.h @@ -5,9 +5,11 @@ #ifndef V8_DIAGNOSTICS_CODE_TRACER_H_ #define V8_DIAGNOSTICS_CODE_TRACER_H_ +#include "src/base/optional.h" #include "src/common/globals.h" #include "src/flags/flags.h" #include "src/utils/allocation.h" +#include "src/utils/ostreams.h" #include "src/utils/utils.h" #include "src/utils/vector.h" @@ -45,6 +47,28 @@ class CodeTracer final : public Malloced { CodeTracer* tracer_; }; + class StreamScope : public Scope { + public: + explicit StreamScope(CodeTracer* tracer) : Scope(tracer) { + FILE* file = this->file(); + if (file == stdout) { + stdout_stream_.emplace(); + } else { + file_stream_.emplace(file); + } + } + + std::ostream& stream() { + if (stdout_stream_.has_value()) return stdout_stream_.value(); + return file_stream_.value(); + } + + private: + // Exactly one of these two will be initialized. + base::Optional<StdoutStream> stdout_stream_; + base::Optional<OFStream> file_stream_; + }; + void OpenFile() { if (!ShouldRedirect()) { return; diff --git a/chromium/v8/src/diagnostics/ia32/disasm-ia32.cc b/chromium/v8/src/diagnostics/ia32/disasm-ia32.cc index 5e0c5c65e23..6db09c3c97a 100644 --- a/chromium/v8/src/diagnostics/ia32/disasm-ia32.cc +++ b/chromium/v8/src/diagnostics/ia32/disasm-ia32.cc @@ -791,6 +791,18 @@ int DisassemblerIA32::AVXInstruction(byte* data) { int mod, regop, rm, vvvv = vex_vreg(); get_modrm(*current, &mod, ®op, &rm); switch (opcode) { + case 0x08: + AppendToBuffer("vroundps %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + AppendToBuffer(",%d", Imm8_U(current)); + current++; + break; + case 0x09: + AppendToBuffer("vroundpd %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + AppendToBuffer(",%d", Imm8_U(current)); + current++; + break; case 0x0E: AppendToBuffer("vpblendw %s,%s,", NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); @@ -1847,6 +1859,12 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, AppendToBuffer("movmskps %s,%s", NameOfCPURegister(regop), NameOfXMMRegister(rm)); data++; + } else if (f0byte == 0xC0) { + data += 2; + data += PrintOperands("xadd_b", OPER_REG_OP_ORDER, data); + } else if (f0byte == 0xC1) { + data += 2; + data += PrintOperands("xadd", OPER_REG_OP_ORDER, data); } else if (f0byte == 0xC2) { data += 2; int mod, regop, rm; @@ -2120,7 +2138,23 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, } } else if (*data == 0x3A) { data++; - if (*data == 0x0A) { + if (*data == 0x08) { + data++; + int mod, regop, rm; + get_modrm(*data, &mod, ®op, &rm); + int8_t imm8 = static_cast<int8_t>(data[1]); + AppendToBuffer("roundps %s,%s,%d", NameOfXMMRegister(regop), + NameOfXMMRegister(rm), static_cast<int>(imm8)); + data += 2; + } else if (*data == 0x09) { + data++; + int mod, regop, rm; + get_modrm(*data, &mod, ®op, &rm); + int8_t imm8 = static_cast<int8_t>(data[1]); + AppendToBuffer("roundpd %s,%s,%d", NameOfXMMRegister(regop), + NameOfXMMRegister(rm), static_cast<int>(imm8)); + data += 2; + } else if (*data == 0x0A) { data++; int mod, regop, rm; get_modrm(*data, &mod, ®op, &rm); @@ -2318,6 +2352,9 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, AppendToBuffer("movd "); data += PrintRightOperand(data); AppendToBuffer(",%s", NameOfXMMRegister(regop)); + } else if (*data == 0xC1) { + data += 2; + data += PrintOperands("xadd_w", OPER_REG_OP_ORDER, data); } else if (*data == 0xC2) { data++; int mod, regop, rm; diff --git a/chromium/v8/src/diagnostics/objects-debug.cc b/chromium/v8/src/diagnostics/objects-debug.cc index 32caba2da84..f94dd8a3c6a 100644 --- a/chromium/v8/src/diagnostics/objects-debug.cc +++ b/chromium/v8/src/diagnostics/objects-debug.cc @@ -29,7 +29,6 @@ #include "src/objects/free-space-inl.h" #include "src/objects/function-kind.h" #include "src/objects/hash-table-inl.h" -#include "src/objects/js-aggregate-error-inl.h" #include "src/objects/js-array-inl.h" #include "src/objects/layout-descriptor.h" #include "src/objects/objects-inl.h" @@ -326,6 +325,11 @@ void VerifyJSObjectElements(Isolate* isolate, JSObject object) { return; } + if (object.HasSloppyArgumentsElements()) { + CHECK(object.elements().IsSloppyArgumentsElements()); + return; + } + FixedArray elements = FixedArray::cast(object.elements()); if (object.HasSmiElements()) { // We might have a partially initialized backing store, in which case we @@ -626,39 +630,15 @@ void TransitionArray::TransitionArrayVerify(Isolate* isolate) { CHECK_LE(LengthFor(number_of_transitions()), length()); } -void JSArgumentsObject::JSArgumentsObjectVerify(Isolate* isolate) { - TorqueGeneratedClassVerifiers::JSArgumentsObjectVerify(*this, isolate); - if (IsSloppyArgumentsElementsKind(GetElementsKind())) { - SloppyArgumentsElements::cast(elements()) - .SloppyArgumentsElementsVerify(isolate, *this); - } - if (isolate->IsInAnyContext(map(), Context::SLOPPY_ARGUMENTS_MAP_INDEX) || - isolate->IsInAnyContext(map(), - Context::SLOW_ALIASED_ARGUMENTS_MAP_INDEX) || - isolate->IsInAnyContext(map(), - Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX)) { - VerifyObjectField(isolate, JSSloppyArgumentsObject::kLengthOffset); - VerifyObjectField(isolate, JSSloppyArgumentsObject::kCalleeOffset); - } else if (isolate->IsInAnyContext(map(), - Context::STRICT_ARGUMENTS_MAP_INDEX)) { - VerifyObjectField(isolate, JSStrictArgumentsObject::kLengthOffset); - } -} - -void SloppyArgumentsElements::SloppyArgumentsElementsVerify(Isolate* isolate, - JSObject holder) { - FixedArrayVerify(isolate); - // Abort verification if only partially initialized (can't use arguments() - // getter because it does FixedArray::cast()). - if (get(kArgumentsIndex).IsUndefined(isolate)) return; - +namespace { +void SloppyArgumentsElementsVerify(Isolate* isolate, + SloppyArgumentsElements elements, + JSObject holder) { + elements.SloppyArgumentsElementsVerify(isolate); ElementsKind kind = holder.GetElementsKind(); bool is_fast = kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS; - CHECK(IsFixedArray()); - CHECK_GE(length(), 2); - CHECK_EQ(map(), ReadOnlyRoots(isolate).sloppy_arguments_elements_map()); - Context context_object = context(); - FixedArray arg_elements = FixedArray::cast(arguments()); + Context context_object = elements.context(); + FixedArray arg_elements = elements.arguments(); if (arg_elements.length() == 0) { CHECK(arg_elements == ReadOnlyRoots(isolate).empty_fixed_array()); return; @@ -674,7 +654,7 @@ void SloppyArgumentsElements::SloppyArgumentsElementsVerify(Isolate* isolate, for (int i = 0; i < nofMappedParameters; i++) { // Verify that each context-mapped argument is either the hole or a valid // Smi within context length range. - Object mapped = get_mapped_entry(i); + Object mapped = elements.mapped_entries(i); if (mapped.IsTheHole(isolate)) { // Slow sloppy arguments can be holey. if (!is_fast) continue; @@ -698,6 +678,26 @@ void SloppyArgumentsElements::SloppyArgumentsElementsVerify(Isolate* isolate, CHECK_LE(maxMappedIndex, context_object.length()); CHECK_LE(maxMappedIndex, arg_elements.length()); } +} // namespace + +void JSArgumentsObject::JSArgumentsObjectVerify(Isolate* isolate) { + TorqueGeneratedClassVerifiers::JSArgumentsObjectVerify(*this, isolate); + if (IsSloppyArgumentsElementsKind(GetElementsKind())) { + SloppyArgumentsElementsVerify( + isolate, SloppyArgumentsElements::cast(elements()), *this); + } + if (isolate->IsInAnyContext(map(), Context::SLOPPY_ARGUMENTS_MAP_INDEX) || + isolate->IsInAnyContext(map(), + Context::SLOW_ALIASED_ARGUMENTS_MAP_INDEX) || + isolate->IsInAnyContext(map(), + Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX)) { + VerifyObjectField(isolate, JSSloppyArgumentsObject::kLengthOffset); + VerifyObjectField(isolate, JSSloppyArgumentsObject::kCalleeOffset); + } else if (isolate->IsInAnyContext(map(), + Context::STRICT_ARGUMENTS_MAP_INDEX)) { + VerifyObjectField(isolate, JSStrictArgumentsObject::kLengthOffset); + } +} void JSAsyncFunctionObject::JSAsyncFunctionObjectVerify(Isolate* isolate) { TorqueGeneratedClassVerifiers::JSAsyncFunctionObjectVerify(*this, isolate); @@ -926,6 +926,8 @@ void Oddball::OddballVerify(Isolate* isolate) { } else if (map() == roots.self_reference_marker_map()) { // Multiple instances of this oddball may exist at once. CHECK_EQ(kind(), Oddball::kSelfReferenceMarker); + } else if (map() == roots.basic_block_counters_marker_map()) { + CHECK(*this == roots.basic_block_counters_marker()); } else { UNREACHABLE(); } @@ -1424,8 +1426,6 @@ void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionVerify( USE_TORQUE_VERIFIER(AsmWasmData) -USE_TORQUE_VERIFIER(WasmDebugInfo) - void WasmInstanceObject::WasmInstanceObjectVerify(Isolate* isolate) { JSObjectVerify(isolate); CHECK(IsWasmInstanceObject()); @@ -1532,8 +1532,6 @@ void NormalizedMapCache::NormalizedMapCacheVerify(Isolate* isolate) { } } -USE_TORQUE_VERIFIER(StackFrameInfo) - void PreparseData::PreparseDataVerify(Isolate* isolate) { TorqueGeneratedClassVerifiers::PreparseDataVerify(*this, isolate); CHECK_LE(0, data_length()); @@ -1659,8 +1657,7 @@ void JSObject::SpillInformation::Print() { PrintF("\n"); } -bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) { - if (valid_entries == -1) valid_entries = number_of_descriptors(); +bool DescriptorArray::IsSortedNoDuplicates() { Name current_key; uint32_t current = 0; for (int i = 0; i < number_of_descriptors(); i++) { @@ -1680,8 +1677,7 @@ bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) { return true; } -bool TransitionArray::IsSortedNoDuplicates(int valid_entries) { - DCHECK_EQ(valid_entries, -1); +bool TransitionArray::IsSortedNoDuplicates() { Name prev_key; PropertyKind prev_kind = kData; PropertyAttributes prev_attributes = NONE; diff --git a/chromium/v8/src/diagnostics/objects-printer.cc b/chromium/v8/src/diagnostics/objects-printer.cc index 00ef81f56a6..9e554978a24 100644 --- a/chromium/v8/src/diagnostics/objects-printer.cc +++ b/chromium/v8/src/diagnostics/objects-printer.cc @@ -24,7 +24,6 @@ #include "src/objects/free-space-inl.h" #include "src/objects/hash-table-inl.h" #include "src/objects/heap-number-inl.h" -#include "src/objects/js-aggregate-error-inl.h" #include "src/objects/js-array-buffer-inl.h" #include "src/objects/js-array-inl.h" #include "src/objects/objects-inl.h" @@ -98,19 +97,28 @@ void Object::Print(std::ostream& os) const { // NOLINT } } -void HeapObject::PrintHeader(std::ostream& os, const char* id) { // NOLINT - os << reinterpret_cast<void*>(ptr()) << ": ["; +namespace { + +void PrintHeapObjectHeaderWithoutMap(HeapObject object, std::ostream& os, + const char* id) { // NOLINT + os << reinterpret_cast<void*>(object.ptr()) << ": ["; if (id != nullptr) { os << id; } else { - os << map().instance_type(); + os << object.map().instance_type(); } os << "]"; - if (ReadOnlyHeap::Contains(*this)) { + if (ReadOnlyHeap::Contains(object)) { os << " in ReadOnlySpace"; - } else if (GetHeapFromWritableObject(*this)->InOldSpace(*this)) { + } else if (GetHeapFromWritableObject(object)->InOldSpace(object)) { os << " in OldSpace"; } +} + +} // namespace + +void HeapObject::PrintHeader(std::ostream& os, const char* id) { // NOLINT + PrintHeapObjectHeaderWithoutMap(*this, os, id); if (!IsMap()) os << "\n - map: " << Brief(map()); } @@ -436,11 +444,9 @@ void PrintSloppyArgumentElements(std::ostream& os, ElementsKind kind, os << "\n 0: context: " << Brief(elements.context()) << "\n 1: arguments_store: " << Brief(arguments_store) << "\n parameter to context slot map:"; - for (uint32_t i = 0; i < elements.parameter_map_length(); i++) { - uint32_t raw_index = i + SloppyArgumentsElements::kParameterMapStart; - Object mapped_entry = elements.get_mapped_entry(i); - os << "\n " << raw_index << ": param(" << i - << "): " << Brief(mapped_entry); + for (int i = 0; i < elements.length(); i++) { + Object mapped_entry = elements.mapped_entries(i); + os << "\n " << i << ": param(" << i << "): " << Brief(mapped_entry); if (mapped_entry.IsTheHole()) { os << " in the arguments_store[" << i << "]"; } else { @@ -643,12 +649,6 @@ void JSGeneratorObject::JSGeneratorObjectPrint(std::ostream& os) { // NOLINT JSObjectPrintBody(os, *this); } -void JSAggregateError::JSAggregateErrorPrint(std::ostream& os) { - JSObjectPrintHeader(os, *this, "JSAggregateError"); - os << "\n - errors: " << Brief(errors()); - JSObjectPrintBody(os, *this); -} - void JSArray::JSArrayPrint(std::ostream& os) { // NOLINT JSObjectPrintHeader(os, *this, "JSArray"); os << "\n - length: " << Brief(this->length()); @@ -1005,7 +1005,13 @@ void FeedbackNexus::Print(std::ostream& os) { // NOLINT } void Oddball::OddballPrint(std::ostream& os) { // NOLINT - to_string().Print(os); + PrintHeapObjectHeaderWithoutMap(*this, os, "Oddball"); + os << ": "; + String s = to_string(); + os << s.PrefixForDebugPrint(); + s.PrintUC16(os); + os << s.SuffixForDebugPrint(); + os << std::endl; } void JSAsyncFunctionObject::JSAsyncFunctionObjectPrint( @@ -1055,34 +1061,11 @@ void JSMessageObject::JSMessageObjectPrint(std::ostream& os) { // NOLINT } void String::StringPrint(std::ostream& os) { // NOLINT - if (!IsOneByteRepresentation()) { - os << "u"; - } - if (StringShape(*this).IsInternalized()) { - os << "#"; - } else if (StringShape(*this).IsCons()) { - os << "c\""; - } else if (StringShape(*this).IsThin()) { - os << ">\""; - } else { - os << "\""; - } - - const char truncated_epilogue[] = "...<truncated>"; - int len = length(); - if (!FLAG_use_verbose_printer) { - if (len > 100) { - len = 100 - sizeof(truncated_epilogue); - } - } - for (int i = 0; i < len; i++) { - os << AsUC16(Get(i)); - } - if (len != length()) { - os << truncated_epilogue; - } - - if (!StringShape(*this).IsInternalized()) os << "\""; + PrintHeapObjectHeaderWithoutMap(*this, os, "String"); + os << ": "; + os << PrefixForDebugPrint(); + PrintUC16(os, 0, length()); + os << SuffixForDebugPrint(); } void Name::NamePrint(std::ostream& os) { // NOLINT @@ -1484,9 +1467,7 @@ void Code::CodePrint(std::ostream& os) { // NOLINT PrintHeader(os, "Code"); os << "\n"; #ifdef ENABLE_DISASSEMBLER - if (FLAG_use_verbose_printer) { - Disassemble(nullptr, os, GetIsolate()); - } + Disassemble(nullptr, os, GetIsolate()); #endif } @@ -1692,14 +1673,12 @@ void WasmStruct::WasmStructPrint(std::ostream& os) { // NOLINT case wasm::ValueType::kF64: os << base::ReadUnalignedValue<double>(field_address); break; + case wasm::ValueType::kI8: + case wasm::ValueType::kI16: case wasm::ValueType::kS128: - case wasm::ValueType::kAnyRef: - case wasm::ValueType::kFuncRef: - case wasm::ValueType::kNullRef: - case wasm::ValueType::kExnRef: case wasm::ValueType::kRef: case wasm::ValueType::kOptRef: - case wasm::ValueType::kEqRef: + case wasm::ValueType::kRtt: case wasm::ValueType::kBottom: case wasm::ValueType::kStmt: UNIMPLEMENTED(); // TODO(7748): Implement. @@ -1733,14 +1712,12 @@ void WasmArray::WasmArrayPrint(std::ostream& os) { // NOLINT PrintTypedArrayElements(os, reinterpret_cast<double*>(data_ptr), len, true); break; + case wasm::ValueType::kI8: + case wasm::ValueType::kI16: case wasm::ValueType::kS128: - case wasm::ValueType::kAnyRef: - case wasm::ValueType::kFuncRef: - case wasm::ValueType::kNullRef: - case wasm::ValueType::kExnRef: case wasm::ValueType::kRef: case wasm::ValueType::kOptRef: - case wasm::ValueType::kEqRef: + case wasm::ValueType::kRtt: case wasm::ValueType::kBottom: case wasm::ValueType::kStmt: UNIMPLEMENTED(); // TODO(7748): Implement. @@ -1749,12 +1726,6 @@ void WasmArray::WasmArrayPrint(std::ostream& os) { // NOLINT os << "\n"; } -void WasmDebugInfo::WasmDebugInfoPrint(std::ostream& os) { // NOLINT - PrintHeader(os, "WasmDebugInfo"); - os << "\n - wasm_instance: " << Brief(wasm_instance()); - os << "\n"; -} - void WasmExceptionTag::WasmExceptionTagPrint(std::ostream& os) { // NOLINT PrintHeader(os, "WasmExceptionTag"); os << "\n - index: " << index(); @@ -1779,9 +1750,6 @@ void WasmInstanceObject::WasmInstanceObjectPrint(std::ostream& os) { // NOLINT os << "\n - imported_mutable_globals_buffers: " << Brief(imported_mutable_globals_buffers()); } - if (has_debug_info()) { - os << "\n - debug_info: " << Brief(debug_info()); - } for (int i = 0; i < tables().length(); i++) { os << "\n - table " << i << ": " << Brief(tables().get(i)); } @@ -1850,7 +1818,8 @@ void WasmGlobalObject::WasmGlobalObjectPrint(std::ostream& os) { // NOLINT os << "\n - untagged_buffer: " << Brief(untagged_buffer()); os << "\n - tagged_buffer: " << Brief(tagged_buffer()); os << "\n - offset: " << offset(); - os << "\n - flags: " << flags(); + os << "\n - raw_type: " << raw_type(); + os << "\n - is_mutable: " << is_mutable(); os << "\n - type: " << type().kind(); os << "\n - is_mutable: " << is_mutable(); os << "\n"; @@ -1929,8 +1898,8 @@ void FunctionTemplateInfo::FunctionTemplateInfoPrint( std::ostream& os) { // NOLINT PrintHeader(os, "FunctionTemplateInfo"); os << "\n - class name: " << Brief(class_name()); - os << "\n - tag: " << Brief(tag()); - os << "\n - serial_number: " << Brief(serial_number()); + os << "\n - tag: " << tag(); + os << "\n - serial_number: " << serial_number(); os << "\n - property_list: " << Brief(property_list()); os << "\n - call_code: " << Brief(call_code()); os << "\n - property_accessors: " << Brief(property_accessors()); @@ -1943,21 +1912,6 @@ void FunctionTemplateInfo::FunctionTemplateInfoPrint( os << "\n"; } -void FunctionTemplateRareData::FunctionTemplateRareDataPrint( - std::ostream& os) { // NOLINT - PrintHeader(os, "FunctionTemplateRareData"); - os << "\n - prototype_template: " << Brief(prototype_template()); - os << "\n - prototype_provider_template: " - << Brief(prototype_provider_template()); - os << "\n - parent_template: " << Brief(parent_template()); - os << "\n - named_property_handler: " << Brief(named_property_handler()); - os << "\n - indexed_property_handler: " << Brief(indexed_property_handler()); - os << "\n - instance_template: " << Brief(instance_template()); - os << "\n - instance_call_handler: " << Brief(instance_call_handler()); - os << "\n - access_check_info: " << Brief(access_check_info()); - os << "\n"; -} - void WasmCapiFunctionData::WasmCapiFunctionDataPrint( std::ostream& os) { // NOLINT PrintHeader(os, "WasmCapiFunctionData"); @@ -1984,8 +1938,8 @@ void WasmIndirectFunctionTable::WasmIndirectFunctionTablePrint( void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) { // NOLINT PrintHeader(os, "ObjectTemplateInfo"); - os << "\n - tag: " << Brief(tag()); - os << "\n - serial_number: " << Brief(serial_number()); + os << "\n - tag: " << tag(); + os << "\n - serial_number: " << serial_number(); os << "\n - property_list: " << Brief(property_list()); os << "\n - property_accessors: " << Brief(property_accessors()); os << "\n - constructor: " << Brief(constructor()); @@ -2205,8 +2159,8 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { // NOLINT if (HasOuterScopeInfo()) { os << "\n - outer scope info: " << Brief(OuterScopeInfo()); } - if (HasLocalsBlackList()) { - os << "\n - locals blacklist: " << Brief(LocalsBlackList()); + if (HasLocalsBlockList()) { + os << "\n - locals blocklist: " << Brief(LocalsBlockList()); } if (HasFunctionName()) { os << "\n - function name: " << Brief(FunctionName()); diff --git a/chromium/v8/src/diagnostics/ppc/disasm-ppc.cc b/chromium/v8/src/diagnostics/ppc/disasm-ppc.cc index b682bb8c5ac..8394a05f89b 100644 --- a/chromium/v8/src/diagnostics/ppc/disasm-ppc.cc +++ b/chromium/v8/src/diagnostics/ppc/disasm-ppc.cc @@ -358,6 +358,17 @@ void Decoder::UnknownFormat(Instruction* instr, const char* name) { } void Decoder::DecodeExt0(Instruction* instr) { + // Some encodings are 5-0 bits, handle those first + switch (EXT0 | (instr->BitField(5, 0))) { + case VPERM: { + Format(instr, "vperm 'Dt, 'Da, 'Db, 'Dc"); + return; + } + case VMLADDUHM: { + Format(instr, "vmladduhm 'Dt, 'Da, 'Db, 'Dc"); + return; + } + } switch (EXT0 | (instr->BitField(10, 0))) { case VSPLTB: { Format(instr, "vspltb 'Dt, 'Db, 'UIM"); @@ -379,6 +390,74 @@ void Decoder::DecodeExt0(Instruction* instr) { Format(instr, "vor 'Dt, 'Da, 'Db"); break; } + case VXOR: { + Format(instr, "vxor 'Dt, 'Da, 'Db"); + break; + } + case VNOR: { + Format(instr, "vnor 'Dt, 'Da, 'Db"); + break; + } + case VSLO: { + Format(instr, "vslo 'Dt, 'Da, 'Db"); + break; + } + case VADDUDM: { + Format(instr, "vaddudm 'Dt, 'Da, 'Db"); + break; + } + case VADDUWM: { + Format(instr, "vadduwm 'Dt, 'Da, 'Db"); + break; + } + case VADDUHM: { + Format(instr, "vadduhm 'Dt, 'Da, 'Db"); + break; + } + case VADDUBM: { + Format(instr, "vaddubm 'Dt, 'Da, 'Db"); + break; + } + case VADDFP: { + Format(instr, "vaddfp 'Dt, 'Da, 'Db"); + break; + } + case VSUBFP: { + Format(instr, "vsubfp 'Dt, 'Da, 'Db"); + break; + } + case VSUBUDM: { + Format(instr, "vsubudm 'Dt, 'Da, 'Db"); + break; + } + case VSUBUWM: { + Format(instr, "vsubuwm 'Dt, 'Da, 'Db"); + break; + } + case VSUBUHM: { + Format(instr, "vsubuhm 'Dt, 'Da, 'Db"); + break; + } + case VSUBUBM: { + Format(instr, "vsububm 'Dt, 'Da, 'Db"); + break; + } + case VMULUWM: { + Format(instr, "vmuluwm 'Dt, 'Da, 'Db"); + break; + } + case VPKUHUM: { + Format(instr, "vpkuhum 'Dt, 'Da, 'Db"); + break; + } + case VMULEUB: { + Format(instr, "vmuleub 'Dt, 'Da, 'Db"); + break; + } + case VMULOUB: { + Format(instr, "vmuloub 'Dt, 'Da, 'Db"); + break; + } } } @@ -912,7 +991,7 @@ void Decoder::DecodeExt2(Instruction* instr) { return; } case LVX: { - Format(instr, "lvx 'Dt, 'ra, 'rb"); + Format(instr, "lvx 'Dt, 'ra, 'rb"); return; } #if V8_TARGET_ARCH_PPC64 diff --git a/chromium/v8/src/diagnostics/x64/disasm-x64.cc b/chromium/v8/src/diagnostics/x64/disasm-x64.cc index 4d0760b17c0..1ca13c1a3ed 100644 --- a/chromium/v8/src/diagnostics/x64/disasm-x64.cc +++ b/chromium/v8/src/diagnostics/x64/disasm-x64.cc @@ -947,6 +947,16 @@ int DisassemblerX64::AVXInstruction(byte* data) { int mod, regop, rm, vvvv = vex_vreg(); get_modrm(*current, &mod, ®op, &rm); switch (opcode) { + case 0x08: + AppendToBuffer("vroundps %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + AppendToBuffer(",0x%x", *current++); + break; + case 0x09: + AppendToBuffer("vroundpd %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + AppendToBuffer(",0x%x", *current++); + break; case 0x0A: AppendToBuffer("vroundss %s,%s,", NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); @@ -1840,6 +1850,18 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { current += PrintRightOperand(current); AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3); current += 1; + } else if (third_byte == 0x08) { + get_modrm(*current, &mod, ®op, &rm); + AppendToBuffer("roundps %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + AppendToBuffer(",0x%x", (*current) & 3); + current += 1; + } else if (third_byte == 0x09) { + get_modrm(*current, &mod, ®op, &rm); + AppendToBuffer("roundpd %s,", NameOfXMMRegister(regop)); + current += PrintRightXMMOperand(current); + AppendToBuffer(",0x%x", (*current) & 3); + current += 1; } else if (third_byte == 0x0A) { get_modrm(*current, &mod, ®op, &rm); AppendToBuffer("roundss %s,", NameOfXMMRegister(regop)); @@ -2111,6 +2133,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { mnemonic = "psllq"; } else if (opcode == 0xF4) { mnemonic = "pmuludq"; + } else if (opcode == 0xF5) { + mnemonic = "pmaddwd"; } else if (opcode == 0xF8) { mnemonic = "psubb"; } else if (opcode == 0xF9) { |