diff --git a/Common/UI/View.h b/Common/UI/View.h index c75b96fcfe..5648b064ce 100644 --- a/Common/UI/View.h +++ b/Common/UI/View.h @@ -462,7 +462,7 @@ public: Visibility GetVisibility() const { return visibility_; } const std::string &Tag() const { return tag_; } - void SetTag(const std::string &str) { tag_ = str; } + void SetTag(std::string_view str) { tag_ = str; } // Fake RTTI virtual bool IsViewGroup() const { return false; } diff --git a/Common/UI/ViewGroup.cpp b/Common/UI/ViewGroup.cpp index fd7881ea39..9b7c82beec 100644 --- a/Common/UI/ViewGroup.cpp +++ b/Common/UI/ViewGroup.cpp @@ -67,6 +67,16 @@ bool ViewGroup::ContainsSubview(const View *view) const { return false; } +int ViewGroup::IndexOfSubview(const View *view) const { + int index = 0; + for (const View *subview : views_) { + if (subview == view) + return index; + index++; + } + return -1; +} + void ViewGroup::Clear() { for (View *view : views_) { delete view; diff --git a/Common/UI/ViewGroup.h b/Common/UI/ViewGroup.h index 9ccde20aec..da2e4e5fd0 100644 --- a/Common/UI/ViewGroup.h +++ b/Common/UI/ViewGroup.h @@ -65,6 +65,7 @@ public: bool CanBeFocused() const override { return false; } bool IsViewGroup() const override { return true; } bool ContainsSubview(const View *view) const override; + int IndexOfSubview(const View *view) const; virtual void SetBG(const Drawable &bg) { bg_ = bg; } diff --git a/Core/MIPS/IR/IRJit.h b/Core/MIPS/IR/IRJit.h index 1c32d0b08a..deeffe8ff7 100644 --- a/Core/MIPS/IR/IRJit.h +++ b/Core/MIPS/IR/IRJit.h @@ -155,6 +155,14 @@ public: void RestoreSavedEmuHackOps(const std::vector &saved); JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const override; + JitBlockMeta GetBlockMeta(int blockNum) const override { + JitBlockMeta meta{}; + if (IsValidBlock(blockNum)) { + meta.valid = true; + blocks_[blockNum].GetRange(meta.addr, meta.sizeInBytes); + } + return meta; + } void ComputeStats(BlockCacheStats &bcStats) const override; int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const override; diff --git a/Core/MIPS/IR/IRNativeCommon.cpp b/Core/MIPS/IR/IRNativeCommon.cpp index 754435e8c6..cf9d597823 100644 --- a/Core/MIPS/IR/IRNativeCommon.cpp +++ b/Core/MIPS/IR/IRNativeCommon.cpp @@ -718,6 +718,10 @@ bool IRNativeBlockCacheDebugInterface::IsValidBlock(int blockNum) const { return irBlocks_.IsValidBlock(blockNum); } +JitBlockMeta IRNativeBlockCacheDebugInterface::GetBlockMeta(int blockNum) const { + return irBlocks_.GetBlockMeta(blockNum); +} + int IRNativeBlockCacheDebugInterface::GetNumBlocks() const { return irBlocks_.GetNumBlocks(); } diff --git a/Core/MIPS/IR/IRNativeCommon.h b/Core/MIPS/IR/IRNativeCommon.h index eae86ada35..dd2f3878a4 100644 --- a/Core/MIPS/IR/IRNativeCommon.h +++ b/Core/MIPS/IR/IRNativeCommon.h @@ -165,6 +165,7 @@ public: int GetNumBlocks() const override; int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const override; JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const override; + JitBlockMeta GetBlockMeta(int blockNum) const override; void ComputeStats(BlockCacheStats &bcStats) const override; bool IsValidBlock(int blockNum) const override; diff --git a/Core/MIPS/JitCommon/JitBlockCache.h b/Core/MIPS/JitCommon/JitBlockCache.h index ab3ea74e04..793650af29 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -103,6 +103,12 @@ struct JitBlockDebugInfo { std::vector targetDisasm; }; +struct JitBlockMeta { + bool valid; + uint32_t addr; + uint32_t sizeInBytes; +}; + struct JitBlockProfileStats { int64_t executions; int64_t totalNanos; @@ -113,6 +119,7 @@ public: virtual int GetNumBlocks() const = 0; virtual int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const = 0; virtual JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const = 0; // Expensive + virtual JitBlockMeta GetBlockMeta(int blockNum) const = 0; virtual JitBlockProfileStats GetBlockProfileStats(int blockNum) const { // Cheap return JitBlockProfileStats{}; } @@ -174,7 +181,16 @@ public: void RestoreSavedEmuHackOps(const std::vector &saved); int GetNumBlocks() const override { return num_blocks_; } - bool IsValidBlock(int blockNum) const override { return blockNum < num_blocks_ && !blocks_[blockNum].invalid; } + bool IsValidBlock(int blockNum) const override { return blockNum >= 0 && blockNum < num_blocks_ && !blocks_[blockNum].invalid; } + JitBlockMeta GetBlockMeta(int blockNum) const override { + JitBlockMeta meta{}; + if (IsValidBlock(blockNum)) { + meta.valid = true; + meta.addr = blocks_[blockNum].originalAddress; + meta.sizeInBytes = blocks_[blockNum].originalSize; + } + return meta; + } static int GetBlockExitSize(); diff --git a/UI/JitCompareScreen.cpp b/UI/JitCompareScreen.cpp index 3d94797ad6..be447fc604 100644 --- a/UI/JitCompareScreen.cpp +++ b/UI/JitCompareScreen.cpp @@ -1,3 +1,5 @@ +#include + #include "UI/JitCompareScreen.h" #include "Core/MemMap.h" @@ -6,6 +8,24 @@ #include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/MIPS/JitCommon/JitState.h" +JitCompareScreen::JitCompareScreen() : UIDialogScreenWithBackground() { + FillBlockList(); +} + +void JitCompareScreen::Flip() { + using namespace UI; + switch (viewMode_) { + case ViewMode::DISASM: + comparisonView_->SetVisibility(V_VISIBLE); + blockListView_->SetVisibility(V_GONE); + break; + case ViewMode::BLOCK_LIST: + comparisonView_->SetVisibility(V_GONE); + blockListView_->SetVisibility(V_VISIBLE); + break; + } +} + // Three panes: Block chooser, MIPS view, ARM/x86 view void JitCompareScreen::CreateViews() { auto di = GetI18NCategory(I18NCat::DIALOG); @@ -18,39 +38,130 @@ void JitCompareScreen::CreateViews() { ScrollView *leftColumnScroll = root_->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(200, FILL_PARENT))); LinearLayout *leftColumn = leftColumnScroll->Add(new LinearLayout(ORIENT_VERTICAL)); - LinearLayout *mainView = root_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); - LinearLayout *topBar = mainView->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - topBar->Add(new Button(dev->T("Prev")))->OnClick.Handle(this, &JitCompareScreen::OnPrevBlock); - topBar->Add(new Button(dev->T("Next")))->OnClick.Handle(this, &JitCompareScreen::OnNextBlock); - blockAddr_ = topBar->Add(new TextEdit("", dev->T("Block address"), "")); + comparisonView_ = root_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); + LinearLayout *blockTopBar = comparisonView_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + blockTopBar->Add(new Button(dev->T("Back to list")))->OnClick.Add([this](UI::EventParams &e) { + viewMode_ = ViewMode::BLOCK_LIST; + Flip(); + return UI::EVENT_DONE; + }); + blockTopBar->Add(new Button(dev->T("Prev")))->OnClick.Add([=](UI::EventParams &e) { + currentBlock_--; + UpdateDisasm(); + return UI::EVENT_DONE; + }); + blockTopBar->Add(new Button(dev->T("Next")))->OnClick.Add([=](UI::EventParams &e) { + currentBlock_++; + UpdateDisasm(); + return UI::EVENT_DONE; + }); + blockTopBar->Add(new Button(dev->T("Random")))->OnClick.Add([=](UI::EventParams &e) { + if (blockList_.empty()) { + return UI::EVENT_DONE; + } + currentBlock_ = rand() % blockList_.size(); + UpdateDisasm(); + return UI::EVENT_DONE; + }); + + blockAddr_ = blockTopBar->Add(new TextEdit("", dev->T("Block address"), "")); blockAddr_->OnEnter.Handle(this, &JitCompareScreen::OnAddressChange); - blockName_ = topBar->Add(new TextView(dev->T("No block"))); - blockStats_ = topBar->Add(new TextView("")); + blockName_ = blockTopBar->Add(new TextView(dev->T("No block"))); + blockStats_ = blockTopBar->Add(new TextView("")); - LinearLayout *comparisonView = mainView->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(1.0f))); + LinearLayout *columns = comparisonView_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(1.0f))); - ScrollView *midColumnScroll = comparisonView->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); + ScrollView *midColumnScroll = columns->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); LinearLayout *midColumn = midColumnScroll->Add(new LinearLayout(ORIENT_VERTICAL)); midColumn->SetTag("JitCompareLeftDisasm"); leftDisasm_ = midColumn->Add(new LinearLayout(ORIENT_VERTICAL)); leftDisasm_->SetSpacing(0.0f); - ScrollView *rightColumnScroll = comparisonView->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); + ScrollView *rightColumnScroll = columns->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); rightColumnScroll->SetTag("JitCompareRightDisasm"); LinearLayout *rightColumn = rightColumnScroll->Add(new LinearLayout(ORIENT_VERTICAL)); rightDisasm_ = rightColumn->Add(new LinearLayout(ORIENT_VERTICAL)); rightDisasm_->SetSpacing(0.0f); - leftColumn->Add(new Choice(dev->T("Current")))->OnClick.Handle(this, &JitCompareScreen::OnCurrentBlock); - leftColumn->Add(new Choice(dev->T("By Address")))->OnClick.Handle(this, &JitCompareScreen::OnSelectBlock); - leftColumn->Add(new Choice(dev->T("Random")))->OnClick.Handle(this, &JitCompareScreen::OnRandomBlock); - leftColumn->Add(new Choice(dev->T("FPU")))->OnClick.Handle(this, &JitCompareScreen::OnRandomFPUBlock); - leftColumn->Add(new Choice(dev->T("VFPU")))->OnClick.Handle(this, &JitCompareScreen::OnRandomVFPUBlock); + blockListView_ = root_->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); + blockListView_->SetVisibility(V_GONE); + blockListContainer_ = blockListView_->Add(new LinearLayout(ORIENT_VERTICAL)); + + // leftColumn->Add(new Choice(dev->T("By Address")))->OnClick.Handle(this, &JitCompareScreen::OnSelectBlock); + leftColumn->Add(new Choice(dev->T("All")))->OnClick.Add([=](UI::EventParams &e) { + listType_ = ListType::ALL_BLOCKS; + viewMode_ = ViewMode::BLOCK_LIST; + UpdateDisasm(); + return UI::EVENT_DONE; + }); + leftColumn->Add(new Choice(dev->T("FPU")))->OnClick.Add([=](UI::EventParams &e) { + listType_ = ListType::FPU_BLOCKS; + viewMode_ = ViewMode::BLOCK_LIST; + UpdateDisasm(); + return UI::EVENT_DONE; + }); + leftColumn->Add(new Choice(dev->T("VFPU")))->OnClick.Add([=](UI::EventParams &e) { + listType_ = ListType::VFPU_BLOCKS; + viewMode_ = ViewMode::BLOCK_LIST; + UpdateDisasm(); + return UI::EVENT_DONE; + }); leftColumn->Add(new Choice(dev->T("Stats")))->OnClick.Handle(this, &JitCompareScreen::OnShowStats); leftColumn->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); + UpdateDisasm(); +} - EventParams ignore{}; - OnCurrentBlock(ignore); +void JitCompareScreen::FillBlockList() { + JitBlockCacheDebugInterface *blockCacheDebug = MIPSComp::jit->GetBlockCacheDebugInterface(); + blockList_.clear(); + for (int i = 0; i < blockCacheDebug->GetNumBlocks(); i++) { + if (!blockCacheDebug->IsValidBlock(i)) { + continue; + } + + switch (listType_) { + case ListType::ALL_BLOCKS: + blockList_.push_back(i); + break; + case ListType::FPU_BLOCKS: + case ListType::VFPU_BLOCKS: + { + const int flags = listType_ == ListType::FPU_BLOCKS ? IS_FPU : IS_VFPU; + JitBlockMeta meta = blockCacheDebug->GetBlockMeta(i); + if (meta.valid) { + for (u32 addr = meta.addr; addr < meta.addr + meta.sizeInBytes; addr += 4) { + MIPSOpcode opcode = Memory::Read_Instruction(addr); + if (MIPSGetInfo(opcode) & flags) { + blockList_.push_back(i); + break; + } + } + } + } + default: + break; + } + } + + if (listSort_ == ListSort::BLOCK_NUM) { + // Already sorted, effectively. + return; + } + if (listSort_ != ListSort::BLOCK_LENGTH_DESC) { + return; + } + + std::sort(blockList_.begin(), blockList_.end(), [=](const int &a_index, const int &b_index) { + JitBlockMeta a_meta = blockCacheDebug->GetBlockMeta(a_index); + JitBlockMeta b_meta = blockCacheDebug->GetBlockMeta(b_index); + + switch (listSort_) { + case ListSort::BLOCK_LENGTH_DESC: + return a_meta.sizeInBytes > b_meta.sizeInBytes; // reverse for descending + default: + return false; + } + }); } void JitCompareScreen::UpdateDisasm() { @@ -64,50 +175,76 @@ void JitCompareScreen::UpdateDisasm() { } JitBlockCacheDebugInterface *blockCacheDebug = MIPSComp::jit->GetBlockCacheDebugInterface(); - if (!blockCacheDebug->IsValidBlock(currentBlock_)) { - return; + if (viewMode_ == ViewMode::DISASM && (currentBlock_ < 0 || currentBlock_ >= (int)blockList_.size())) { + viewMode_ = ViewMode::BLOCK_LIST; } - char temp[256]; - snprintf(temp, sizeof(temp), "%d/%d", currentBlock_, blockCacheDebug->GetNumBlocks()); - blockName_->SetText(temp); + FillBlockList(); + Flip(); - if (currentBlock_ < 0 || !blockCacheDebug || currentBlock_ >= blockCacheDebug->GetNumBlocks()) { - auto dev = GetI18NCategory(I18NCat::DEVELOPER); - leftDisasm_->Add(new TextView(dev->T("No block"))); - rightDisasm_->Add(new TextView(dev->T("No block"))); - blockStats_->SetText(""); - return; - } + if (viewMode_ == ViewMode::DISASM) { + char temp[256]; + snprintf(temp, sizeof(temp), "%d/%d", currentBlock_, (int)blockList_.size()); + blockName_->SetText(temp); - JitBlockDebugInfo debugInfo = blockCacheDebug->GetBlockDebugInfo(currentBlock_); + int blockNum = blockList_[currentBlock_]; - snprintf(temp, sizeof(temp), "%08x", debugInfo.originalAddress); - blockAddr_->SetText(temp); - - // Alright. First generate the MIPS disassembly. - - // TODO: Need a way to communicate branch continuing. - for (const auto &line : debugInfo.origDisasm) { - leftDisasm_->Add(new TextView(line))->SetFocusable(true); - } - - // TODO : When we have both target and IR, need a third column. - if (debugInfo.targetDisasm.size()) { - for (const auto &line : debugInfo.targetDisasm) { - rightDisasm_->Add(new TextView(line))->SetFocusable(true); + if (!blockCacheDebug->IsValidBlock(blockNum)) { + auto dev = GetI18NCategory(I18NCat::DEVELOPER); + leftDisasm_->Add(new TextView(dev->T("No block"))); + rightDisasm_->Add(new TextView(dev->T("No block"))); + blockStats_->SetText(""); + return; } + + JitBlockDebugInfo debugInfo = blockCacheDebug->GetBlockDebugInfo(blockNum); + snprintf(temp, sizeof(temp), "%08x", debugInfo.originalAddress); + blockAddr_->SetText(temp); + + // Alright. First generate the MIPS disassembly. + + // TODO: Need a way to communicate branch continuing. + for (const auto &line : debugInfo.origDisasm) { + leftDisasm_->Add(new TextView(line, FLAG_DYNAMIC_ASCII, false))->SetFocusable(true); + } + + // TODO : When we have both target and IR, need a third column. + if (debugInfo.targetDisasm.size()) { + for (const auto &line : debugInfo.targetDisasm) { + rightDisasm_->Add(new TextView(line, FLAG_DYNAMIC_ASCII, false))->SetFocusable(true); + } + } else { + for (const auto &line : debugInfo.irDisasm) { + rightDisasm_->Add(new TextView(line, FLAG_DYNAMIC_ASCII, false))->SetFocusable(true); + } + } + + int numMips = leftDisasm_->GetNumSubviews(); + int numHost = rightDisasm_->GetNumSubviews(); + snprintf(temp, sizeof(temp), "%d to %d : %d%%", numMips, numHost, 100 * numHost / numMips); + blockStats_->SetText(temp); } else { - for (const auto &line : debugInfo.irDisasm) { - rightDisasm_->Add(new TextView(line))->SetFocusable(true); + blockListContainer_->Clear(); + for (int i = 0; i < std::min(100, (int)blockList_.size()); i++) { + JitBlockMeta meta = blockCacheDebug->GetBlockMeta(blockList_[i]); + + char temp[512], small[512]; + snprintf(temp, sizeof(temp), "%08x: %d instrs", meta.addr, meta.sizeInBytes / 4); + snprintf(small, sizeof(small), "Small text"); + Choice *blockChoice = blockListContainer_->Add(new Choice(temp, small)); + blockChoice->OnClick.Handle(this, &JitCompareScreen::OnBlockClick); } } +} - int numMips = leftDisasm_->GetNumSubviews(); - int numHost = rightDisasm_->GetNumSubviews(); - - snprintf(temp, sizeof(temp), "%d to %d : %d%%", numMips, numHost, 100 * numHost / numMips); - blockStats_->SetText(temp); +UI::EventReturn JitCompareScreen::OnBlockClick(UI::EventParams &e) { + int blockIndex = blockListContainer_->IndexOfSubview(e.v); + if (blockIndex >= 0) { + viewMode_ = ViewMode::DISASM; + currentBlock_ = blockIndex; + UpdateDisasm(); + } + return UI::EVENT_DONE; } UI::EventReturn JitCompareScreen::OnAddressChange(UI::EventParams &e) { @@ -169,18 +306,6 @@ UI::EventReturn JitCompareScreen::OnSelectBlock(UI::EventParams &e) { return UI::EVENT_DONE; } -UI::EventReturn JitCompareScreen::OnPrevBlock(UI::EventParams &e) { - currentBlock_--; - UpdateDisasm(); - return UI::EVENT_DONE; -} - -UI::EventReturn JitCompareScreen::OnNextBlock(UI::EventParams &e) { - currentBlock_++; - UpdateDisasm(); - return UI::EVENT_DONE; -} - UI::EventReturn JitCompareScreen::OnBlockAddress(UI::EventParams &e) { std::lock_guard guard(MIPSComp::jitLock); if (!MIPSComp::jit) { @@ -200,40 +325,7 @@ UI::EventReturn JitCompareScreen::OnBlockAddress(UI::EventParams &e) { return UI::EVENT_DONE; } -UI::EventReturn JitCompareScreen::OnRandomBlock(UI::EventParams &e) { - std::lock_guard guard(MIPSComp::jitLock); - if (!MIPSComp::jit) { - return UI::EVENT_DONE; - } - - JitBlockCacheDebugInterface *blockCache = MIPSComp::jit->GetBlockCacheDebugInterface(); - if (!blockCache) - return UI::EVENT_DONE; - - int numBlocks = blockCache->GetNumBlocks(); - if (numBlocks > 0) { - int tries = 100; - while (tries-- > 0) { - currentBlock_ = rand() % numBlocks; - if (blockCache->IsValidBlock(currentBlock_)) { - break; - } - } - } - UpdateDisasm(); - return UI::EVENT_DONE; -} - -UI::EventReturn JitCompareScreen::OnRandomVFPUBlock(UI::EventParams &e) { - OnRandomBlock(IS_VFPU); - return UI::EVENT_DONE; -} - -UI::EventReturn JitCompareScreen::OnRandomFPUBlock(UI::EventParams &e) { - OnRandomBlock(IS_FPU); - return UI::EVENT_DONE; -} - +/* void JitCompareScreen::OnRandomBlock(int flag) { std::lock_guard guard(MIPSComp::jitLock); if (!MIPSComp::jit) { @@ -270,21 +362,7 @@ void JitCompareScreen::OnRandomBlock(int flag) { currentBlock_ = -1; } UpdateDisasm(); -} - -UI::EventReturn JitCompareScreen::OnCurrentBlock(UI::EventParams &e) { - std::lock_guard guard(MIPSComp::jitLock); - if (!MIPSComp::jit) { - return UI::EVENT_DONE; - } - JitBlockCache *blockCache = MIPSComp::jit->GetBlockCache(); - if (!blockCache) - return UI::EVENT_DONE; - currentBlock_ = blockCache->GetBlockNumberFromAddress(currentMIPS->pc); - UpdateDisasm(); - return UI::EVENT_DONE; -} - +}*/ void AddressPromptScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; diff --git a/UI/JitCompareScreen.h b/UI/JitCompareScreen.h index ab92ef7c33..14b07f60de 100644 --- a/UI/JitCompareScreen.h +++ b/UI/JitCompareScreen.h @@ -4,31 +4,48 @@ class JitCompareScreen : public UIDialogScreenWithBackground { public: + JitCompareScreen(); void CreateViews() override; const char *tag() const override { return "JitCompare"; } private: + void Flip(); void UpdateDisasm(); - UI::EventReturn OnRandomBlock(UI::EventParams &e); - UI::EventReturn OnRandomFPUBlock(UI::EventParams &e); - UI::EventReturn OnRandomVFPUBlock(UI::EventParams &e); - void OnRandomBlock(int flag); - UI::EventReturn OnCurrentBlock(UI::EventParams &e); + // Uses the current ListType + void FillBlockList(); + + UI::LinearLayout *comparisonView_; + UI::ScrollView *blockListView_; + UI::LinearLayout *blockListContainer_; + UI::EventReturn OnSelectBlock(UI::EventParams &e); - UI::EventReturn OnPrevBlock(UI::EventParams &e); - UI::EventReturn OnNextBlock(UI::EventParams &e); UI::EventReturn OnBlockAddress(UI::EventParams &e); UI::EventReturn OnAddressChange(UI::EventParams &e); UI::EventReturn OnShowStats(UI::EventParams &e); + UI::EventReturn OnBlockClick(UI::EventParams &e); // To switch, change the below things and call RecreateViews(); - enum ViewMode { + enum class ViewMode { BLOCK_LIST, DISASM, }; - ViewMode viewMode_ = DISASM; + enum class ListType { + ALL_BLOCKS, + FPU_BLOCKS, + VFPU_BLOCKS, + }; + enum class ListSort { + BLOCK_NUM, + BLOCK_LENGTH_DESC, + TIME_SPENT, + EXECUTIONS, + }; + ViewMode viewMode_ = ViewMode::BLOCK_LIST; + ListType listType_ = ListType::ALL_BLOCKS; + ListSort listSort_ = ListSort::BLOCK_LENGTH_DESC; + int currentBlock_ = -1; // For DISASM mode std::vector blockList_; // for BLOCK_LIST mode