diff options
| author | bunnei <bunneidev@gmail.com> | 2017-05-08 16:02:53 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-05-08 16:02:53 -0400 | 
| commit | 7325413cd8b4f02719ca0f87c8a70d4713333a98 (patch) | |
| tree | 2bed3e545cb8b660d695763ce27dc3069847d7b1 | |
| parent | e33558c6ce38dac56ec66d2d65e51d4dee0b9840 (diff) | |
| parent | d97b9775409e05ffba8a78632bd41863570e9830 (diff) | |
Merge pull request #2689 from yuriks/remove-disassembler
Remove built-in disassembler and related code
23 files changed, 11 insertions, 2389 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 3e6106f0a..4e837668e 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -11,8 +11,6 @@ set(SRCS              configuration/configure_graphics.cpp              configuration/configure_input.cpp              configuration/configure_system.cpp -            debugger/callstack.cpp -            debugger/disassembler.cpp              debugger/graphics/graphics.cpp              debugger/graphics/graphics_breakpoint_observer.cpp              debugger/graphics/graphics_breakpoints.cpp @@ -43,8 +41,6 @@ set(HEADERS              configuration/configure_graphics.h              configuration/configure_input.h              configuration/configure_system.h -            debugger/callstack.h -            debugger/disassembler.h              debugger/graphics/graphics.h              debugger/graphics/graphics_breakpoint_observer.h              debugger/graphics/graphics_breakpoints.h @@ -74,8 +70,6 @@ set(UIS              configuration/configure_graphics.ui              configuration/configure_input.ui              configuration/configure_system.ui -            debugger/callstack.ui -            debugger/disassembler.ui              debugger/registers.ui              hotkeys.ui              main.ui diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp deleted file mode 100644 index 08d2e7a22..000000000 --- a/src/citra_qt/debugger/callstack.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <QStandardItemModel> -#include "citra_qt/debugger/callstack.h" -#include "common/common_types.h" -#include "common/symbols.h" -#include "core/arm/arm_interface.h" -#include "core/arm/disassembler/arm_disasm.h" -#include "core/core.h" -#include "core/memory.h" - -CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) { -    ui.setupUi(this); - -    callstack_model = new QStandardItemModel(this); -    callstack_model->setColumnCount(4); -    callstack_model->setHeaderData(0, Qt::Horizontal, "Stack Pointer"); -    callstack_model->setHeaderData(2, Qt::Horizontal, "Return Address"); -    callstack_model->setHeaderData(1, Qt::Horizontal, "Call Address"); -    callstack_model->setHeaderData(3, Qt::Horizontal, "Function"); -    ui.treeView->setModel(callstack_model); -} - -void CallstackWidget::OnDebugModeEntered() { -    // Stack pointer -    const u32 sp = Core::CPU().GetReg(13); - -    Clear(); - -    int counter = 0; -    for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { -        if (!Memory::IsValidVirtualAddress(addr)) -            break; - -        const u32 ret_addr = Memory::Read32(addr); -        const u32 call_addr = ret_addr - 4; // get call address??? - -        if (!Memory::IsValidVirtualAddress(call_addr)) -            break; - -        /* TODO (mattvail) clean me, move to debugger interface */ -        u32 insn = Memory::Read32(call_addr); -        if (ARM_Disasm::Decode(insn) == OP_BL) { -            std::string name; -            // ripped from disasm -            u32 i_offset = insn & 0xffffff; -            // Sign-extend the 24-bit offset -            if ((i_offset >> 23) & 1) -                i_offset |= 0xff000000; - -            // Pre-compute the left-shift and the prefetch offset -            i_offset <<= 2; -            i_offset += 8; -            const u32 func_addr = call_addr + i_offset; - -            callstack_model->setItem( -                counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); -            callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg( -                                                     ret_addr, 8, 16, QLatin1Char('0')))); -            callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg( -                                                     call_addr, 8, 16, QLatin1Char('0')))); - -            name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown"; -            callstack_model->setItem( -                counter, 3, new QStandardItem( -                                QString("%1_%2") -                                    .arg(QString::fromStdString(name)) -                                    .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0'))))); - -            counter++; -        } -    } -} - -void CallstackWidget::OnDebugModeLeft() {} - -void CallstackWidget::Clear() { -    for (int row = 0; row < callstack_model->rowCount(); row++) { -        for (int column = 0; column < callstack_model->columnCount(); column++) { -            callstack_model->setItem(row, column, new QStandardItem()); -        } -    } -} diff --git a/src/citra_qt/debugger/callstack.h b/src/citra_qt/debugger/callstack.h deleted file mode 100644 index f04ab9c7e..000000000 --- a/src/citra_qt/debugger/callstack.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <QDockWidget> -#include "ui_callstack.h" - -class QStandardItemModel; - -class CallstackWidget : public QDockWidget { -    Q_OBJECT - -public: -    explicit CallstackWidget(QWidget* parent = nullptr); - -public slots: -    void OnDebugModeEntered(); -    void OnDebugModeLeft(); - -private: -    Ui::CallStack ui; -    QStandardItemModel* callstack_model; - -    /// Clears the callstack widget while keeping the column widths the same -    void Clear(); -}; diff --git a/src/citra_qt/debugger/callstack.ui b/src/citra_qt/debugger/callstack.ui deleted file mode 100644 index 248ea3dd7..000000000 --- a/src/citra_qt/debugger/callstack.ui +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>CallStack</class> - <widget class="QDockWidget" name="CallStack"> -  <property name="geometry"> -   <rect> -    <x>0</x> -    <y>0</y> -    <width>400</width> -    <height>300</height> -   </rect> -  </property> -  <property name="windowTitle"> -   <string>Call Stack</string> -  </property> -  <widget class="QWidget" name="dockWidgetContents"> -   <layout class="QVBoxLayout" name="verticalLayout"> -    <item> -     <widget class="QTreeView" name="treeView"> -      <property name="editTriggers"> -       <set>QAbstractItemView::NoEditTriggers</set> -      </property> -      <property name="alternatingRowColors"> -       <bool>true</bool> -      </property> -      <property name="rootIsDecorated"> -       <bool>false</bool> -      </property> -      <property name="itemsExpandable"> -       <bool>false</bool> -      </property> -     </widget> -    </item> -   </layout> -  </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp deleted file mode 100644 index e9c8ad858..000000000 --- a/src/citra_qt/debugger/disassembler.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <QShortcut> -#include "citra_qt/bootmanager.h" -#include "citra_qt/debugger/disassembler.h" -#include "citra_qt/hotkeys.h" -#include "citra_qt/util/util.h" -#include "common/break_points.h" -#include "common/symbols.h" -#include "core/arm/arm_interface.h" -#include "core/arm/disassembler/arm_disasm.h" -#include "core/core.h" -#include "core/memory.h" - -DisassemblerModel::DisassemblerModel(QObject* parent) -    : QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), -      selection(QModelIndex()) {} - -int DisassemblerModel::columnCount(const QModelIndex& parent) const { -    return 3; -} - -int DisassemblerModel::rowCount(const QModelIndex& parent) const { -    return code_size; -} - -QVariant DisassemblerModel::data(const QModelIndex& index, int role) const { -    switch (role) { -    case Qt::DisplayRole: { -        u32 address = base_address + index.row() * 4; -        u32 instr = Memory::Read32(address); -        std::string disassembly = ARM_Disasm::Disassemble(address, instr); - -        if (index.column() == 0) { -            return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0')); -        } else if (index.column() == 1) { -            return QString::fromStdString(disassembly); -        } else if (index.column() == 2) { -            if (Symbols::HasSymbol(address)) { -                TSymbol symbol = Symbols::GetSymbol(address); -                return QString("%1 - Size:%2") -                    .arg(QString::fromStdString(symbol.name)) -                    .arg(symbol.size / 4); // divide by 4 to get instruction count -            } else if (ARM_Disasm::Decode(instr) == OP_BL) { -                u32 offset = instr & 0xFFFFFF; - -                // Sign-extend the 24-bit offset -                if ((offset >> 23) & 1) -                    offset |= 0xFF000000; - -                // Pre-compute the left-shift and the prefetch offset -                offset <<= 2; -                offset += 8; - -                TSymbol symbol = Symbols::GetSymbol(address + offset); -                return QString("    --> %1").arg(QString::fromStdString(symbol.name)); -            } -        } - -        break; -    } - -    case Qt::BackgroundRole: { -        unsigned int address = base_address + 4 * index.row(); - -        if (breakpoints.IsAddressBreakPoint(address)) -            return QBrush(QColor(0xFF, 0xC0, 0xC0)); -        else if (address == program_counter) -            return QBrush(QColor(0xC0, 0xC0, 0xFF)); - -        break; -    } - -    case Qt::FontRole: { -        if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column -            return GetMonospaceFont(); -        } -        break; -    } - -    default: -        break; -    } - -    return QVariant(); -} - -QModelIndex DisassemblerModel::IndexFromAbsoluteAddress(unsigned int address) const { -    return index((address - base_address) / 4, 0); -} - -const BreakPoints& DisassemblerModel::GetBreakPoints() const { -    return breakpoints; -} - -void DisassemblerModel::ParseFromAddress(unsigned int address) { - -    // NOTE: A too large value causes lagging when scrolling the disassembly -    const unsigned int chunk_size = 1000 * 500; - -    // If we haven't loaded anything yet, initialize base address to the parameter address -    if (code_size == 0) -        base_address = address; - -    // If the new area is already loaded, just continue -    if (base_address + code_size > address + chunk_size && base_address <= address) -        return; - -    // Insert rows before currently loaded data -    if (base_address > address) { -        unsigned int num_rows = (address - base_address) / 4; - -        beginInsertRows(QModelIndex(), 0, num_rows); -        code_size += num_rows; -        base_address = address; - -        endInsertRows(); -    } - -    // Insert rows after currently loaded data -    if (base_address + code_size < address + chunk_size) { -        unsigned int num_rows = (base_address + chunk_size - code_size - address) / 4; - -        beginInsertRows(QModelIndex(), 0, num_rows); -        code_size += num_rows; -        endInsertRows(); -    } - -    SetNextInstruction(address); -} - -void DisassemblerModel::OnSelectionChanged(const QModelIndex& new_selection) { -    selection = new_selection; -} - -void DisassemblerModel::OnSetOrUnsetBreakpoint() { -    if (!selection.isValid()) -        return; - -    unsigned int address = base_address + selection.row() * 4; - -    if (breakpoints.IsAddressBreakPoint(address)) { -        breakpoints.Remove(address); -    } else { -        breakpoints.Add(address); -    } - -    emit dataChanged(selection, selection); -} - -void DisassemblerModel::SetNextInstruction(unsigned int address) { -    QModelIndex cur_index = IndexFromAbsoluteAddress(program_counter); -    QModelIndex prev_index = IndexFromAbsoluteAddress(address); - -    program_counter = address; - -    emit dataChanged(cur_index, cur_index); -    emit dataChanged(prev_index, prev_index); -} - -DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) -    : QDockWidget(parent), base_addr(0), emu_thread(emu_thread) { - -    disasm_ui.setupUi(this); - -    RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut); -    RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut); -    RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut); -    RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), -                   Qt::ApplicationShortcut); - -    connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep())); -    connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause())); -    connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue())); - -    connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, -            SLOT(OnToggleStartStop())); -    connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep())); -    connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, -            SLOT(OnStepInto())); - -    setEnabled(false); -} - -void DisassemblerWidget::Init() { -    model->ParseFromAddress(Core::CPU().GetPC()); - -    disasm_ui.treeView->resizeColumnToContents(0); -    disasm_ui.treeView->resizeColumnToContents(1); -    disasm_ui.treeView->resizeColumnToContents(2); - -    QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::CPU().GetPC()); -    disasm_ui.treeView->scrollTo(model_index); -    disasm_ui.treeView->selectionModel()->setCurrentIndex( -        model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); -} - -void DisassemblerWidget::OnContinue() { -    emu_thread->SetRunning(true); -} - -void DisassemblerWidget::OnStep() { -    OnStepInto(); // change later -} - -void DisassemblerWidget::OnStepInto() { -    emu_thread->SetRunning(false); -    emu_thread->ExecStep(); -} - -void DisassemblerWidget::OnPause() { -    emu_thread->SetRunning(false); - -    // TODO: By now, the CPU might not have actually stopped... -    if (Core::System::GetInstance().IsPoweredOn()) { -        model->SetNextInstruction(Core::CPU().GetPC()); -    } -} - -void DisassemblerWidget::OnToggleStartStop() { -    emu_thread->SetRunning(!emu_thread->IsRunning()); -} - -void DisassemblerWidget::OnDebugModeEntered() { -    u32 next_instr = Core::CPU().GetPC(); - -    if (model->GetBreakPoints().IsAddressBreakPoint(next_instr)) -        emu_thread->SetRunning(false); - -    model->SetNextInstruction(next_instr); - -    QModelIndex model_index = model->IndexFromAbsoluteAddress(next_instr); -    disasm_ui.treeView->scrollTo(model_index); -    disasm_ui.treeView->selectionModel()->setCurrentIndex( -        model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); -} - -void DisassemblerWidget::OnDebugModeLeft() {} - -int DisassemblerWidget::SelectedRow() { -    QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex(); -    if (!index.isValid()) -        return -1; - -    return disasm_ui.treeView->selectionModel()->currentIndex().row(); -} - -void DisassemblerWidget::OnEmulationStarting(EmuThread* emu_thread) { -    this->emu_thread = emu_thread; - -    model = new DisassemblerModel(this); -    disasm_ui.treeView->setModel(model); - -    connect(disasm_ui.treeView->selectionModel(), -            SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), model, -            SLOT(OnSelectionChanged(const QModelIndex&))); -    connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), model, SLOT(OnSetOrUnsetBreakpoint())); -    connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model, -            SLOT(OnSetOrUnsetBreakpoint())); - -    Init(); -    setEnabled(true); -} - -void DisassemblerWidget::OnEmulationStopping() { -    disasm_ui.treeView->setModel(nullptr); -    delete model; -    emu_thread = nullptr; -    setEnabled(false); -} diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h deleted file mode 100644 index a6e59515c..000000000 --- a/src/citra_qt/debugger/disassembler.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <QAbstractListModel> -#include <QDockWidget> -#include "common/break_points.h" -#include "common/common_types.h" -#include "ui_disassembler.h" - -class QAction; -class EmuThread; - -class DisassemblerModel : public QAbstractListModel { -    Q_OBJECT - -public: -    explicit DisassemblerModel(QObject* parent); - -    int columnCount(const QModelIndex& parent = QModelIndex()) const override; -    int rowCount(const QModelIndex& parent = QModelIndex()) const override; -    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - -    QModelIndex IndexFromAbsoluteAddress(unsigned int address) const; -    const BreakPoints& GetBreakPoints() const; - -public slots: -    void ParseFromAddress(unsigned int address); -    void OnSelectionChanged(const QModelIndex&); -    void OnSetOrUnsetBreakpoint(); -    void SetNextInstruction(unsigned int address); - -private: -    unsigned int base_address; -    unsigned int code_size; -    unsigned int program_counter; - -    QModelIndex selection; -    BreakPoints breakpoints; -}; - -class DisassemblerWidget : public QDockWidget { -    Q_OBJECT - -public: -    DisassemblerWidget(QWidget* parent, EmuThread* emu_thread); - -    void Init(); - -public slots: -    void OnContinue(); -    void OnStep(); -    void OnStepInto(); -    void OnPause(); -    void OnToggleStartStop(); - -    void OnDebugModeEntered(); -    void OnDebugModeLeft(); - -    void OnEmulationStarting(EmuThread* emu_thread); -    void OnEmulationStopping(); - -private: -    // returns -1 if no row is selected -    int SelectedRow(); - -    Ui::DockWidget disasm_ui; - -    DisassemblerModel* model; - -    u32 base_addr; - -    EmuThread* emu_thread; -}; diff --git a/src/citra_qt/debugger/disassembler.ui b/src/citra_qt/debugger/disassembler.ui deleted file mode 100644 index 5ca6dc5d2..000000000 --- a/src/citra_qt/debugger/disassembler.ui +++ /dev/null @@ -1,81 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>DockWidget</class> - <widget class="QDockWidget" name="DockWidget"> -  <property name="geometry"> -   <rect> -    <x>0</x> -    <y>0</y> -    <width>430</width> -    <height>401</height> -   </rect> -  </property> -  <property name="windowTitle"> -   <string>Disassembly</string> -  </property> -  <widget class="QWidget" name="dockWidgetContents"> -   <layout class="QVBoxLayout" name="verticalLayout"> -    <item> -     <layout class="QHBoxLayout" name="horizontalLayout"> -      <item> -       <widget class="QPushButton" name="button_step"> -        <property name="text"> -         <string>Step</string> -        </property> -       </widget> -      </item> -      <item> -       <widget class="QPushButton" name="button_pause"> -        <property name="text"> -         <string>Pause</string> -        </property> -       </widget> -      </item> -      <item> -       <widget class="QPushButton" name="button_continue"> -        <property name="text"> -         <string>Continue</string> -        </property> -       </widget> -      </item> -      <item> -       <widget class="QPushButton" name="pushButton"> -        <property name="text"> -         <string>Step Into</string> -        </property> -       </widget> -      </item> -      <item> -       <widget class="QPushButton" name="button_breakpoint"> -        <property name="text"> -         <string>Set Breakpoint</string> -        </property> -       </widget> -      </item> -     </layout> -    </item> -    <item> -     <widget class="QTreeView" name="treeView"> -      <property name="alternatingRowColors"> -       <bool>true</bool> -      </property> -      <property name="indentation"> -       <number>20</number> -      </property> -      <property name="rootIsDecorated"> -       <bool>false</bool> -      </property> -      <property name="uniformRowHeights"> -       <bool>true</bool> -      </property> -      <attribute name="headerVisible"> -       <bool>false</bool> -      </attribute> -     </widget> -    </item> -   </layout> -  </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index ea66cc425..d7fad555f 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -16,8 +16,6 @@  #include "citra_qt/bootmanager.h"  #include "citra_qt/configuration/config.h"  #include "citra_qt/configuration/configure_dialog.h" -#include "citra_qt/debugger/callstack.h" -#include "citra_qt/debugger/disassembler.h"  #include "citra_qt/debugger/graphics/graphics.h"  #include "citra_qt/debugger/graphics/graphics_breakpoints.h"  #include "citra_qt/debugger/graphics/graphics_cmdlists.h" @@ -40,7 +38,6 @@  #include "common/scm_rev.h"  #include "common/scope_exit.h"  #include "common/string_util.h" -#include "core/arm/disassembler/load_symbol_map.h"  #include "core/core.h"  #include "core/file_sys/archive_source_sd_savedata.h"  #include "core/gdbstub/gdbstub.h" @@ -130,15 +127,6 @@ void GMainWindow::InitializeDebugWidgets() {      debug_menu->addAction(microProfileDialog->toggleViewAction());  #endif -    disasmWidget = new DisassemblerWidget(this, emu_thread.get()); -    addDockWidget(Qt::BottomDockWidgetArea, disasmWidget); -    disasmWidget->hide(); -    debug_menu->addAction(disasmWidget->toggleViewAction()); -    connect(this, &GMainWindow::EmulationStarting, disasmWidget, -            &DisassemblerWidget::OnEmulationStarting); -    connect(this, &GMainWindow::EmulationStopping, disasmWidget, -            &DisassemblerWidget::OnEmulationStopping); -      registersWidget = new RegistersWidget(this);      addDockWidget(Qt::RightDockWidgetArea, registersWidget);      registersWidget->hide(); @@ -148,11 +136,6 @@ void GMainWindow::InitializeDebugWidgets() {      connect(this, &GMainWindow::EmulationStopping, registersWidget,              &RegistersWidget::OnEmulationStopping); -    callstackWidget = new CallstackWidget(this); -    addDockWidget(Qt::RightDockWidgetArea, callstackWidget); -    callstackWidget->hide(); -    debug_menu->addAction(callstackWidget->toggleViewAction()); -      graphicsWidget = new GPUCommandStreamWidget(this);      addDockWidget(Qt::RightDockWidgetArea, graphicsWidget);      graphicsWidget->hide(); @@ -269,8 +252,6 @@ void GMainWindow::ConnectWidgetEvents() {  void GMainWindow::ConnectMenuEvents() {      // File      connect(ui.action_Load_File, &QAction::triggered, this, &GMainWindow::OnMenuLoadFile); -    connect(ui.action_Load_Symbol_Map, &QAction::triggered, this, -            &GMainWindow::OnMenuLoadSymbolMap);      connect(ui.action_Select_Game_List_Root, &QAction::triggered, this,              &GMainWindow::OnMenuSelectGameListRoot);      connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close); @@ -391,26 +372,17 @@ void GMainWindow::BootGame(const QString& filename) {      connect(render_window, SIGNAL(Closed()), this, SLOT(OnStopGame()));      // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views      // before the CPU continues -    connect(emu_thread.get(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()), -            Qt::BlockingQueuedConnection);      connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget,              SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); -    connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget, -            SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);      connect(emu_thread.get(), SIGNAL(DebugModeEntered()), waitTreeWidget,              SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); -    connect(emu_thread.get(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()), -            Qt::BlockingQueuedConnection);      connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()),              Qt::BlockingQueuedConnection); -    connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), -            Qt::BlockingQueuedConnection);      connect(emu_thread.get(), SIGNAL(DebugModeLeft()), waitTreeWidget, SLOT(OnDebugModeLeft()),              Qt::BlockingQueuedConnection);      // Update the GUI      registersWidget->OnDebugModeEntered(); -    callstackWidget->OnDebugModeEntered();      if (ui.action_Single_Window_Mode->isChecked()) {          game_list->hide();      } @@ -531,16 +503,6 @@ void GMainWindow::OnMenuLoadFile() {      }  } -void GMainWindow::OnMenuLoadSymbolMap() { -    QString filename = QFileDialog::getOpenFileName( -        this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol Map (*.*)")); -    if (!filename.isEmpty()) { -        UISettings::values.symbols_path = QFileInfo(filename).path(); - -        LoadSymbolMap(filename.toStdString()); -    } -} -  void GMainWindow::OnMenuSelectGameListRoot() {      QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));      if (!dir_path.isEmpty()) { diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 2f398eb7b..cb2e87cbd 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -10,9 +10,7 @@  #include <QTimer>  #include "ui_main.h" -class CallstackWidget;  class Config; -class DisassemblerWidget;  class EmuThread;  class GameList;  class GImageInfo; @@ -118,7 +116,6 @@ private slots:      void OnGameListLoadFile(QString game_path);      void OnGameListOpenSaveFolder(u64 program_id);      void OnMenuLoadFile(); -    void OnMenuLoadSymbolMap();      /// Called whenever a user selects the "File->Select Game List Root" menu item      void OnMenuSelectGameListRoot();      void OnMenuRecentFile(); @@ -152,9 +149,7 @@ private:      // Debugger panes      ProfilerWidget* profilerWidget;      MicroProfileDialog* microProfileDialog; -    DisassemblerWidget* disasmWidget;      RegistersWidget* registersWidget; -    CallstackWidget* callstackWidget;      GPUCommandStreamWidget* graphicsWidget;      GPUCommandListWidget* graphicsCommandsWidget;      GraphicsBreakPointsWidget* graphicsBreakpointsWidget; diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui index f64b878f0..b13d578f5 100644 --- a/src/citra_qt/main.ui +++ b/src/citra_qt/main.ui @@ -58,7 +58,6 @@       </property>      </widget>      <addaction name="action_Load_File"/> -    <addaction name="action_Load_Symbol_Map"/>      <addaction name="separator"/>      <addaction name="action_Select_Game_List_Root"/>      <addaction name="menu_recent_files"/> diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 13277a5c2..4b30185f1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -38,7 +38,6 @@ set(SRCS              param_package.cpp              scm_rev.cpp              string_util.cpp -            symbols.cpp              thread.cpp              timer.cpp              ) @@ -74,7 +73,6 @@ set(HEADERS              scope_exit.h              string_util.h              swap.h -            symbols.h              synchronized_wrapper.h              thread.h              thread_queue_list.h diff --git a/src/common/symbols.cpp b/src/common/symbols.cpp deleted file mode 100644 index c4d16af85..000000000 --- a/src/common/symbols.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/symbols.h" - -TSymbolsMap g_symbols; - -namespace Symbols { -bool HasSymbol(u32 address) { -    return g_symbols.find(address) != g_symbols.end(); -} - -void Add(u32 address, const std::string& name, u32 size, u32 type) { -    if (!HasSymbol(address)) { -        TSymbol symbol; -        symbol.address = address; -        symbol.name = name; -        symbol.size = size; -        symbol.type = type; - -        g_symbols.emplace(address, symbol); -    } -} - -TSymbol GetSymbol(u32 address) { -    const auto iter = g_symbols.find(address); - -    if (iter != g_symbols.end()) -        return iter->second; - -    return {}; -} - -const std::string GetName(u32 address) { -    return GetSymbol(address).name; -} - -void Remove(u32 address) { -    g_symbols.erase(address); -} - -void Clear() { -    g_symbols.clear(); -} -} diff --git a/src/common/symbols.h b/src/common/symbols.h deleted file mode 100644 index f5a48e05a..000000000 --- a/src/common/symbols.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <map> -#include <string> -#include <utility> -#include "common/common_types.h" - -struct TSymbol { -    u32 address = 0; -    std::string name; -    u32 size = 0; -    u32 type = 0; -}; - -typedef std::map<u32, TSymbol> TSymbolsMap; -typedef std::pair<u32, TSymbol> TSymbolsPair; - -namespace Symbols { -bool HasSymbol(u32 address); - -void Add(u32 address, const std::string& name, u32 size, u32 type); -TSymbol GetSymbol(u32 address); -const std::string GetName(u32 address); -void Remove(u32 address); -void Clear(); -} diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a2866fdd8..e404063f0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,6 +1,4 @@  set(SRCS -            arm/disassembler/arm_disasm.cpp -            arm/disassembler/load_symbol_map.cpp              arm/dynarmic/arm_dynarmic.cpp              arm/dynarmic/arm_dynarmic_cp15.cpp              arm/dyncom/arm_dyncom.cpp @@ -179,8 +177,6 @@ set(SRCS  set(HEADERS              arm/arm_interface.h -            arm/disassembler/arm_disasm.h -            arm/disassembler/load_symbol_map.h              arm/dynarmic/arm_dynarmic.h              arm/dynarmic/arm_dynarmic_cp15.h              arm/dyncom/arm_dyncom.h diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp deleted file mode 100644 index 05d6ed1fb..000000000 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ /dev/null @@ -1,1344 +0,0 @@ -// Copyright 2006 The Android Open Source Project - -#include <string> -#include <unordered_set> -#include "common/common_types.h" -#include "common/string_util.h" -#include "core/arm/disassembler/arm_disasm.h" -#include "core/arm/skyeye_common/armsupp.h" - -static const char* cond_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", -                                   "hi", "ls", "ge", "lt", "gt", "le", "",   "RESERVED"}; - -static const char* opcode_names[] = { -    "invalid",   "undefined", "adc",    "add",     "and",    "b",      "bl",     "bic", -    "bkpt",      "blx",       "bx",     "cdp",     "clrex",  "clz",    "cmn",    "cmp", -    "eor",       "ldc",       "ldm",    "ldr",     "ldrb",   "ldrbt",  "ldrex",  "ldrexb", -    "ldrexd",    "ldrexh",    "ldrh",   "ldrsb",   "ldrsh",  "ldrt",   "mcr",    "mla", -    "mov",       "mrc",       "mrs",    "msr",     "mul",    "mvn",    "nop",    "orr", -    "pkh",       "pld",       "qadd16", "qadd8",   "qasx",   "qsax",   "qsub16", "qsub8", -    "rev",       "rev16",     "revsh",  "rsb",     "rsc",    "sadd16", "sadd8",  "sasx", -    "sbc",       "sel",       "sev",    "shadd16", "shadd8", "shasx",  "shsax",  "shsub16", -    "shsub8",    "smlad",     "smlal",  "smlald",  "smlsd",  "smlsld", "smmla",  "smmls", -    "smmul",     "smuad",     "smull",  "smusd",   "ssat",   "ssat16", "ssax",   "ssub16", -    "ssub8",     "stc",       "stm",    "str",     "strb",   "strbt",  "strex",  "strexb", -    "strexd",    "strexh",    "strh",   "strt",    "sub",    "swi",    "swp",    "swpb", -    "sxtab",     "sxtab16",   "sxtah",  "sxtb",    "sxtb16", "sxth",   "teq",    "tst", -    "uadd16",    "uadd8",     "uasx",   "uhadd16", "uhadd8", "uhasx",  "uhsax",  "uhsub16", -    "uhsub8",    "umlal",     "umull",  "uqadd16", "uqadd8", "uqasx",  "uqsax",  "uqsub16", -    "uqsub8",    "usad8",     "usada8", "usat",    "usat16", "usax",   "usub16", "usub8", -    "uxtab",     "uxtab16",   "uxtah",  "uxtb",    "uxtb16", "uxth",   "wfe",    "wfi", -    "yield", - -    "undefined", "adc",       "add",    "and",     "asr",    "b",      "bic",    "bkpt", -    "bl",        "blx",       "bx",     "cmn",     "cmp",    "eor",    "ldmia",  "ldr", -    "ldrb",      "ldrh",      "ldrsb",  "ldrsh",   "lsl",    "lsr",    "mov",    "mul", -    "mvn",       "neg",       "orr",    "pop",     "push",   "ror",    "sbc",    "stmia", -    "str",       "strb",      "strh",   "sub",     "swi",    "tst", - -    nullptr}; - -// Indexed by the shift type (bits 6-5) -static const char* shift_names[] = {"LSL", "LSR", "ASR", "ROR"}; - -static const char* cond_to_str(u32 cond) { -    return cond_names[cond]; -} - -std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) { -    Opcode opcode = Decode(insn); -    switch (opcode) { -    case OP_INVALID: -        return "Invalid"; -    case OP_UNDEFINED: -        return "Undefined"; -    case OP_ADC: -    case OP_ADD: -    case OP_AND: -    case OP_BIC: -    case OP_CMN: -    case OP_CMP: -    case OP_EOR: -    case OP_MOV: -    case OP_MVN: -    case OP_ORR: -    case OP_RSB: -    case OP_RSC: -    case OP_SBC: -    case OP_SUB: -    case OP_TEQ: -    case OP_TST: -        return DisassembleALU(opcode, insn); -    case OP_B: -    case OP_BL: -        return DisassembleBranch(addr, opcode, insn); -    case OP_BKPT: -        return DisassembleBKPT(insn); -    case OP_BLX: -        // not supported yet -        break; -    case OP_BX: -        return DisassembleBX(insn); -    case OP_CDP: -        return "cdp"; -    case OP_CLREX: -        return "clrex"; -    case OP_CLZ: -        return DisassembleCLZ(insn); -    case OP_LDC: -        return "ldc"; -    case OP_LDM: -    case OP_STM: -        return DisassembleMemblock(opcode, insn); -    case OP_LDR: -    case OP_LDRB: -    case OP_LDRBT: -    case OP_LDRT: -    case OP_STR: -    case OP_STRB: -    case OP_STRBT: -    case OP_STRT: -        return DisassembleMem(insn); -    case OP_LDREX: -    case OP_LDREXB: -    case OP_LDREXD: -    case OP_LDREXH: -    case OP_STREX: -    case OP_STREXB: -    case OP_STREXD: -    case OP_STREXH: -        return DisassembleREX(opcode, insn); -    case OP_LDRH: -    case OP_LDRSB: -    case OP_LDRSH: -    case OP_STRH: -        return DisassembleMemHalf(insn); -    case OP_MCR: -    case OP_MRC: -        return DisassembleMCR(opcode, insn); -    case OP_MLA: -        return DisassembleMLA(opcode, insn); -    case OP_MRS: -        return DisassembleMRS(insn); -    case OP_MSR: -        return DisassembleMSR(insn); -    case OP_MUL: -        return DisassembleMUL(opcode, insn); -    case OP_NOP: -    case OP_SEV: -    case OP_WFE: -    case OP_WFI: -    case OP_YIELD: -        return DisassembleNoOperands(opcode, insn); -    case OP_PKH: -        return DisassemblePKH(insn); -    case OP_PLD: -        return DisassemblePLD(insn); -    case OP_QADD16: -    case OP_QADD8: -    case OP_QASX: -    case OP_QSAX: -    case OP_QSUB16: -    case OP_QSUB8: -    case OP_SADD16: -    case OP_SADD8: -    case OP_SASX: -    case OP_SHADD16: -    case OP_SHADD8: -    case OP_SHASX: -    case OP_SHSAX: -    case OP_SHSUB16: -    case OP_SHSUB8: -    case OP_SSAX: -    case OP_SSUB16: -    case OP_SSUB8: -    case OP_UADD16: -    case OP_UADD8: -    case OP_UASX: -    case OP_UHADD16: -    case OP_UHADD8: -    case OP_UHASX: -    case OP_UHSAX: -    case OP_UHSUB16: -    case OP_UHSUB8: -    case OP_UQADD16: -    case OP_UQADD8: -    case OP_UQASX: -    case OP_UQSAX: -    case OP_UQSUB16: -    case OP_UQSUB8: -    case OP_USAX: -    case OP_USUB16: -    case OP_USUB8: -        return DisassembleParallelAddSub(opcode, insn); -    case OP_REV: -    case OP_REV16: -    case OP_REVSH: -        return DisassembleREV(opcode, insn); -    case OP_SEL: -        return DisassembleSEL(insn); -    case OP_SMLAD: -    case OP_SMLALD: -    case OP_SMLSD: -    case OP_SMLSLD: -    case OP_SMMLA: -    case OP_SMMLS: -    case OP_SMMUL: -    case OP_SMUAD: -    case OP_SMUSD: -    case OP_USAD8: -    case OP_USADA8: -        return DisassembleMediaMulDiv(opcode, insn); -    case OP_SSAT: -    case OP_SSAT16: -    case OP_USAT: -    case OP_USAT16: -        return DisassembleSAT(opcode, insn); -    case OP_STC: -        return "stc"; -    case OP_SWI: -        return DisassembleSWI(insn); -    case OP_SWP: -    case OP_SWPB: -        return DisassembleSWP(opcode, insn); -    case OP_SXTAB: -    case OP_SXTAB16: -    case OP_SXTAH: -    case OP_SXTB: -    case OP_SXTB16: -    case OP_SXTH: -    case OP_UXTAB: -    case OP_UXTAB16: -    case OP_UXTAH: -    case OP_UXTB: -    case OP_UXTB16: -    case OP_UXTH: -        return DisassembleXT(opcode, insn); -    case OP_UMLAL: -    case OP_UMULL: -    case OP_SMLAL: -    case OP_SMULL: -        return DisassembleUMLAL(opcode, insn); -    default: -        return "Error"; -    } -    return nullptr; -} - -std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) { -    static const u8 kNoOperand1 = 1; -    static const u8 kNoDest = 2; -    static const u8 kNoSbit = 4; - -    std::string rn_str; -    std::string rd_str; - -    u8 flags = 0; -    u8 cond = (insn >> 28) & 0xf; -    u8 is_immed = (insn >> 25) & 0x1; -    u8 bit_s = (insn >> 20) & 1; -    u8 rn = (insn >> 16) & 0xf; -    u8 rd = (insn >> 12) & 0xf; -    u8 immed = insn & 0xff; - -    const char* opname = opcode_names[opcode]; -    switch (opcode) { -    case OP_CMN: -    case OP_CMP: -    case OP_TEQ: -    case OP_TST: -        flags = kNoDest | kNoSbit; -        break; -    case OP_MOV: -    case OP_MVN: -        flags = kNoOperand1; -        break; -    default: -        break; -    } - -    // The "mov" instruction ignores the first operand (rn). -    rn_str[0] = 0; -    if ((flags & kNoOperand1) == 0) { -        rn_str = Common::StringFromFormat("r%d, ", rn); -    } - -    // The following instructions do not write the result register (rd): -    // tst, teq, cmp, cmn. -    rd_str[0] = 0; -    if ((flags & kNoDest) == 0) { -        rd_str = Common::StringFromFormat("r%d, ", rd); -    } - -    const char* sbit_str = ""; -    if (bit_s && !(flags & kNoSbit)) -        sbit_str = "s"; - -    if (is_immed) { -        return Common::StringFromFormat("%s%s%s\t%s%s#%u  ; 0x%x", opname, cond_to_str(cond), -                                        sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed); -    } - -    u8 shift_is_reg = (insn >> 4) & 1; -    u8 rotate = (insn >> 8) & 0xf; -    u8 rm = insn & 0xf; -    u8 shift_type = (insn >> 5) & 0x3; -    u8 rs = (insn >> 8) & 0xf; -    u8 shift_amount = (insn >> 7) & 0x1f; -    u32 rotated_val = immed; -    u8 rotate2 = rotate << 1; -    rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2)); - -    if (!shift_is_reg && shift_type == 0 && shift_amount == 0) { -        return Common::StringFromFormat("%s%s%s\t%s%sr%d", opname, cond_to_str(cond), sbit_str, -                                        rd_str.c_str(), rn_str.c_str(), rm); -    } - -    const char* shift_name = shift_names[shift_type]; -    if (shift_is_reg) { -        return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s r%d", opname, cond_to_str(cond), -                                        sbit_str, rd_str.c_str(), rn_str.c_str(), rm, shift_name, -                                        rs); -    } -    if (shift_amount == 0) { -        if (shift_type == 3) { -            return Common::StringFromFormat("%s%s%s\t%s%sr%d, RRX", opname, cond_to_str(cond), -                                            sbit_str, rd_str.c_str(), rn_str.c_str(), rm); -        } -        shift_amount = 32; -    } -    return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s #%u", opname, cond_to_str(cond), sbit_str, -                                    rd_str.c_str(), rn_str.c_str(), rm, shift_name, shift_amount); -} - -std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u32 offset = insn & 0xffffff; -    // Sign-extend the 24-bit offset -    if ((offset >> 23) & 1) -        offset |= 0xff000000; - -    // Pre-compute the left-shift and the prefetch offset -    offset <<= 2; -    offset += 8; -    addr += offset; -    const char* opname = opcode_names[opcode]; -    return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr); -} - -std::string ARM_Disasm::DisassembleBX(u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 rn = insn & 0xf; -    return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn); -} - -std::string ARM_Disasm::DisassembleBKPT(u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf); -    return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed); -} - -std::string ARM_Disasm::DisassembleCLZ(u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 rd = (insn >> 12) & 0xf; -    u8 rm = insn & 0xf; -    return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm); -} - -std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) { -    u32 cond = BITS(insn, 28, 31); -    u32 rd = BITS(insn, 16, 19); -    u32 ra = BITS(insn, 12, 15); -    u32 rm = BITS(insn, 8, 11); -    u32 m = BIT(insn, 5); -    u32 rn = BITS(insn, 0, 3); - -    std::string cross = ""; -    if (m) { -        if (opcode == OP_SMMLA || opcode == OP_SMMUL || opcode == OP_SMMLS) -            cross = "r"; -        else -            cross = "x"; -    } - -    std::string ext_reg = ""; -    std::unordered_set<Opcode, std::hash<int>> with_ext_reg = {OP_SMLAD, OP_SMLSD, OP_SMMLA, -                                                               OP_SMMLS, OP_USADA8}; -    if (with_ext_reg.find(opcode) != with_ext_reg.end()) -        ext_reg = Common::StringFromFormat(", r%u", ra); - -    std::string rd_low = ""; -    if (opcode == OP_SMLALD || opcode == OP_SMLSLD) -        rd_low = Common::StringFromFormat("r%u, ", ra); - -    return Common::StringFromFormat("%s%s%s\t%sr%u, r%u, r%u%s", opcode_names[opcode], -                                    cross.c_str(), cond_to_str(cond), rd_low.c_str(), rd, rn, rm, -                                    ext_reg.c_str()); -} - -std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) { -    std::string tmp_list; - -    u8 cond = (insn >> 28) & 0xf; -    u8 write_back = (insn >> 21) & 0x1; -    u8 bit_s = (insn >> 22) & 0x1; -    u8 is_up = (insn >> 23) & 0x1; -    u8 is_pre = (insn >> 24) & 0x1; -    u8 rn = (insn >> 16) & 0xf; -    u16 reg_list = insn & 0xffff; - -    const char* opname = opcode_names[opcode]; - -    const char* bang = ""; -    if (write_back) -        bang = "!"; - -    const char* carret = ""; -    if (bit_s) -        carret = "^"; - -    const char* comma = ""; -    tmp_list[0] = 0; -    for (int ii = 0; ii < 16; ++ii) { -        if (reg_list & (1 << ii)) { -            tmp_list += Common::StringFromFormat("%sr%d", comma, ii); -            comma = ","; -        } -    } - -    const char* addr_mode = ""; -    if (is_pre) { -        if (is_up) { -            addr_mode = "ib"; -        } else { -            addr_mode = "db"; -        } -    } else { -        if (is_up) { -            addr_mode = "ia"; -        } else { -            addr_mode = "da"; -        } -    } - -    return Common::StringFromFormat("%s%s%s\tr%d%s, {%s}%s", opname, cond_to_str(cond), addr_mode, -                                    rn, bang, tmp_list.c_str(), carret); -} - -std::string ARM_Disasm::DisassembleMem(u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 is_reg = (insn >> 25) & 0x1; -    u8 is_load = (insn >> 20) & 0x1; -    u8 write_back = (insn >> 21) & 0x1; -    u8 is_byte = (insn >> 22) & 0x1; -    u8 is_up = (insn >> 23) & 0x1; -    u8 is_pre = (insn >> 24) & 0x1; -    u8 rn = (insn >> 16) & 0xf; -    u8 rd = (insn >> 12) & 0xf; -    u16 offset = insn & 0xfff; - -    const char* opname = "ldr"; -    if (!is_load) -        opname = "str"; - -    const char* bang = ""; -    if (write_back) -        bang = "!"; - -    const char* minus = ""; -    if (is_up == 0) -        minus = "-"; - -    const char* byte = ""; -    if (is_byte) -        byte = "b"; - -    if (is_reg == 0) { -        if (is_pre) { -            if (offset == 0) { -                return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond), -                                                byte, rd, rn); -            } else { -                return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", opname, -                                                cond_to_str(cond), byte, rd, rn, minus, offset, -                                                bang); -            } -        } else { -            const char* transfer = ""; -            if (write_back) -                transfer = "t"; - -            return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], #%s%u", opname, -                                            cond_to_str(cond), byte, transfer, rd, rn, minus, -                                            offset); -        } -    } - -    u8 rm = insn & 0xf; -    u8 shift_type = (insn >> 5) & 0x3; -    u8 shift_amount = (insn >> 7) & 0x1f; - -    const char* shift_name = shift_names[shift_type]; - -    if (is_pre) { -        if (shift_amount == 0) { -            if (shift_type == 0) { -                return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", opname, -                                                cond_to_str(cond), byte, rd, rn, minus, rm, bang); -            } -            if (shift_type == 3) { -                return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, RRX]%s", opname, -                                                cond_to_str(cond), byte, rd, rn, minus, rm, bang); -            } -            shift_amount = 32; -        } -        return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s", opname, -                                        cond_to_str(cond), byte, rd, rn, minus, rm, shift_name, -                                        shift_amount, bang); -    } - -    const char* transfer = ""; -    if (write_back) -        transfer = "t"; - -    if (shift_amount == 0) { -        if (shift_type == 0) { -            return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d", opname, -                                            cond_to_str(cond), byte, transfer, rd, rn, minus, rm); -        } -        if (shift_type == 3) { -            return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, RRX", opname, -                                            cond_to_str(cond), byte, transfer, rd, rn, minus, rm); -        } -        shift_amount = 32; -    } - -    return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u", opname, -                                    cond_to_str(cond), byte, transfer, rd, rn, minus, rm, -                                    shift_name, shift_amount); -} - -std::string ARM_Disasm::DisassembleMemHalf(u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 is_load = (insn >> 20) & 0x1; -    u8 write_back = (insn >> 21) & 0x1; -    u8 is_immed = (insn >> 22) & 0x1; -    u8 is_up = (insn >> 23) & 0x1; -    u8 is_pre = (insn >> 24) & 0x1; -    u8 rn = (insn >> 16) & 0xf; -    u8 rd = (insn >> 12) & 0xf; -    u8 bits_65 = (insn >> 5) & 0x3; -    u8 rm = insn & 0xf; -    u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf); - -    const char* opname = "ldr"; -    if (is_load == 0) -        opname = "str"; - -    const char* width = ""; -    if (bits_65 == 1) -        width = "h"; -    else if (bits_65 == 2) -        width = "sb"; -    else -        width = "sh"; - -    const char* bang = ""; -    if (write_back) -        bang = "!"; -    const char* minus = ""; -    if (is_up == 0) -        minus = "-"; - -    if (is_immed) { -        if (is_pre) { -            if (offset == 0) { -                return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond), -                                                width, rd, rn); -            } else { -                return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", opname, -                                                cond_to_str(cond), width, rd, rn, minus, offset, -                                                bang); -            } -        } else { -            return Common::StringFromFormat("%s%s%s\tr%d, [r%d], #%s%u", opname, cond_to_str(cond), -                                            width, rd, rn, minus, offset); -        } -    } - -    if (is_pre) { -        return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", opname, cond_to_str(cond), -                                        width, rd, rn, minus, rm, bang); -    } else { -        return Common::StringFromFormat("%s%s%s\tr%d, [r%d], %sr%d", opname, cond_to_str(cond), -                                        width, rd, rn, minus, rm); -    } -} - -std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 crn = (insn >> 16) & 0xf; -    u8 crd = (insn >> 12) & 0xf; -    u8 cpnum = (insn >> 8) & 0xf; -    u8 opcode2 = (insn >> 5) & 0x7; -    u8 crm = insn & 0xf; - -    const char* opname = opcode_names[opcode]; -    return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}", opname, cond_to_str(cond), -                                    cpnum, crd, crn, crm, opcode2); -} - -std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 rd = (insn >> 16) & 0xf; -    u8 rn = (insn >> 12) & 0xf; -    u8 rs = (insn >> 8) & 0xf; -    u8 rm = insn & 0xf; -    u8 bit_s = (insn >> 20) & 1; - -    const char* opname = opcode_names[opcode]; -    return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", opname, cond_to_str(cond), -                                    bit_s ? "s" : "", rd, rm, rs, rn); -} - -std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 rdhi = (insn >> 16) & 0xf; -    u8 rdlo = (insn >> 12) & 0xf; -    u8 rs = (insn >> 8) & 0xf; -    u8 rm = insn & 0xf; -    u8 bit_s = (insn >> 20) & 1; - -    const char* opname = opcode_names[opcode]; -    return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", opname, cond_to_str(cond), -                                    bit_s ? "s" : "", rdlo, rdhi, rm, rs); -} - -std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 rd = (insn >> 16) & 0xf; -    u8 rs = (insn >> 8) & 0xf; -    u8 rm = insn & 0xf; -    u8 bit_s = (insn >> 20) & 1; - -    const char* opname = opcode_names[opcode]; -    return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d", opname, cond_to_str(cond), -                                    bit_s ? "s" : "", rd, rm, rs); -} - -std::string ARM_Disasm::DisassembleMRS(u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 rd = (insn >> 12) & 0xf; -    u8 ps = (insn >> 22) & 1; - -    return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr"); -} - -std::string ARM_Disasm::DisassembleMSR(u32 insn) { -    char flags[8]; -    int flag_index = 0; -    u8 cond = (insn >> 28) & 0xf; -    u8 is_immed = (insn >> 25) & 0x1; -    u8 pd = (insn >> 22) & 1; -    u8 mask = (insn >> 16) & 0xf; - -    if (mask & 1) -        flags[flag_index++] = 'c'; -    if (mask & 2) -        flags[flag_index++] = 'x'; -    if (mask & 4) -        flags[flag_index++] = 's'; -    if (mask & 8) -        flags[flag_index++] = 'f'; -    flags[flag_index] = 0; - -    if (is_immed) { -        u32 immed = insn & 0xff; -        u8 rotate = (insn >> 8) & 0xf; -        u8 rotate2 = rotate << 1; -        u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2)); -        return Common::StringFromFormat("msr%s\t%s_%s, #0x%x", cond_to_str(cond), -                                        pd ? "spsr" : "cpsr", flags, rotated_val); -    } - -    u8 rm = insn & 0xf; - -    return Common::StringFromFormat("msr%s\t%s_%s, r%d", cond_to_str(cond), pd ? "spsr" : "cpsr", -                                    flags, rm); -} - -std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn) { -    u32 cond = BITS(insn, 28, 31); -    return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); -} - -std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, u32 insn) { -    u32 cond = BITS(insn, 28, 31); -    u32 rn = BITS(insn, 16, 19); -    u32 rd = BITS(insn, 12, 15); -    u32 rm = BITS(insn, 0, 3); - -    return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[opcode], cond_to_str(cond), -                                    rd, rn, rm); -} - -std::string ARM_Disasm::DisassemblePKH(u32 insn) { -    u32 cond = BITS(insn, 28, 31); -    u32 rn = BITS(insn, 16, 19); -    u32 rd = BITS(insn, 12, 15); -    u32 imm5 = BITS(insn, 7, 11); -    u32 tb = BIT(insn, 6); -    u32 rm = BITS(insn, 0, 3); - -    std::string suffix = tb ? "tb" : "bt"; -    std::string shift = ""; - -    if (tb && imm5 == 0) -        imm5 = 32; - -    if (imm5 > 0) { -        shift = tb ? ", ASR" : ", LSL"; -        shift += " #" + std::to_string(imm5); -    } - -    return Common::StringFromFormat("pkh%s%s\tr%u, r%u, r%u%s", suffix.c_str(), cond_to_str(cond), -                                    rd, rn, rm, shift.c_str()); -} - -std::string ARM_Disasm::DisassemblePLD(u32 insn) { -    u8 is_reg = (insn >> 25) & 0x1; -    u8 is_up = (insn >> 23) & 0x1; -    u8 rn = (insn >> 16) & 0xf; - -    const char* minus = ""; -    if (is_up == 0) -        minus = "-"; - -    if (is_reg) { -        u8 rm = insn & 0xf; -        return Common::StringFromFormat("pld\t[r%d, %sr%d]", rn, minus, rm); -    } - -    u16 offset = insn & 0xfff; -    if (offset == 0) { -        return Common::StringFromFormat("pld\t[r%d]", rn); -    } else { -        return Common::StringFromFormat("pld\t[r%d, #%s%u]", rn, minus, offset); -    } -} - -std::string ARM_Disasm::DisassembleREV(Opcode opcode, u32 insn) { -    u32 cond = BITS(insn, 28, 31); -    u32 rd = BITS(insn, 12, 15); -    u32 rm = BITS(insn, 0, 3); - -    return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), rd, -                                    rm); -} - -std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) { -    u32 rn = BITS(insn, 16, 19); -    u32 rd = BITS(insn, 12, 15); -    u32 rt = BITS(insn, 0, 3); -    u32 cond = BITS(insn, 28, 31); - -    switch (opcode) { -    case OP_STREX: -    case OP_STREXB: -    case OP_STREXH: -        return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], -                                        cond_to_str(cond), rd, rt, rn); -    case OP_STREXD: -        return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode], -                                        cond_to_str(cond), rd, rt, rt + 1, rn); - -    // for LDREX instructions, rd corresponds to Rt from reference manual -    case OP_LDREX: -    case OP_LDREXB: -    case OP_LDREXH: -        return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], cond_to_str(cond), -                                        rd, rn); -    case OP_LDREXD: -        return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], -                                        cond_to_str(cond), rd, rd + 1, rn); -    default: -        return opcode_names[OP_UNDEFINED]; -    } -} - -std::string ARM_Disasm::DisassembleSAT(Opcode opcode, u32 insn) { -    u32 cond = BITS(insn, 28, 31); -    u32 sat_imm = BITS(insn, 16, 20); -    u32 rd = BITS(insn, 12, 15); -    u32 imm5 = BITS(insn, 7, 11); -    u32 sh = BIT(insn, 6); -    u32 rn = BITS(insn, 0, 3); - -    std::string shift_part = ""; -    bool opcode_has_shift = (opcode == OP_SSAT) || (opcode == OP_USAT); -    if (opcode_has_shift && !(sh == 0 && imm5 == 0)) { -        if (sh == 0) -            shift_part += ", LSL #"; -        else -            shift_part += ", ASR #"; - -        if (imm5 == 0) -            imm5 = 32; -        shift_part += std::to_string(imm5); -    } - -    if (opcode == OP_SSAT || opcode == OP_SSAT16) -        sat_imm++; - -    return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], -                                    cond_to_str(cond), rd, sat_imm, rn, shift_part.c_str()); -} - -std::string ARM_Disasm::DisassembleSEL(u32 insn) { -    u32 cond = BITS(insn, 28, 31); -    u32 rn = BITS(insn, 16, 19); -    u32 rd = BITS(insn, 12, 15); -    u32 rm = BITS(insn, 0, 3); - -    return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[OP_SEL], cond_to_str(cond), -                                    rd, rn, rm); -} - -std::string ARM_Disasm::DisassembleSWI(u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u32 sysnum = insn & 0x00ffffff; - -    return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum); -} - -std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn) { -    u8 cond = (insn >> 28) & 0xf; -    u8 rn = (insn >> 16) & 0xf; -    u8 rd = (insn >> 12) & 0xf; -    u8 rm = insn & 0xf; - -    const char* opname = opcode_names[opcode]; -    return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn); -} - -std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) { -    u32 cond = BITS(insn, 28, 31); -    u32 rn = BITS(insn, 16, 19); -    u32 rd = BITS(insn, 12, 15); -    u32 rotate = BITS(insn, 10, 11); -    u32 rm = BITS(insn, 0, 3); - -    std::string rn_part = ""; -    static std::unordered_set<Opcode, std::hash<int>> extend_with_add = { -        OP_SXTAB, OP_SXTAB16, OP_SXTAH, OP_UXTAB, OP_UXTAB16, OP_UXTAH}; -    if (extend_with_add.find(opcode) != extend_with_add.end()) -        rn_part = ", r" + std::to_string(rn); - -    std::string rotate_part = ""; -    if (rotate != 0) -        rotate_part = ", ROR #" + std::to_string(rotate << 3); - -    return Common::StringFromFormat("%s%s\tr%u%s, r%u%s", opcode_names[opcode], cond_to_str(cond), -                                    rd, rn_part.c_str(), rm, rotate_part.c_str()); -} - -Opcode ARM_Disasm::Decode(u32 insn) { -    u32 bits27_26 = (insn >> 26) & 0x3; -    switch (bits27_26) { -    case 0x0: -        return Decode00(insn); -    case 0x1: -        return Decode01(insn); -    case 0x2: -        return Decode10(insn); -    case 0x3: -        return Decode11(insn); -    } -    return OP_INVALID; -} - -Opcode ARM_Disasm::Decode00(u32 insn) { -    u8 bit25 = (insn >> 25) & 0x1; -    u8 bit4 = (insn >> 4) & 0x1; -    if (bit25 == 0 && bit4 == 1) { -        if ((insn & 0x0ffffff0) == 0x012fff10) { -            // Bx instruction -            return OP_BX; -        } -        if ((insn & 0x0ff000f0) == 0x01600010) { -            // Clz instruction -            return OP_CLZ; -        } -        if ((insn & 0xfff000f0) == 0xe1200070) { -            // Bkpt instruction -            return OP_BKPT; -        } -        u32 bits7_4 = (insn >> 4) & 0xf; -        if (bits7_4 == 0x9) { -            u32 bit24 = BIT(insn, 24); -            if (bit24) { -                return DecodeSyncPrimitive(insn); -            } -            // One of the multiply instructions -            return DecodeMUL(insn); -        } - -        u8 bit7 = (insn >> 7) & 0x1; -        if (bit7 == 1) { -            // One of the load/store halfword/byte instructions -            return DecodeLDRH(insn); -        } -    } - -    u32 op1 = BITS(insn, 20, 24); -    if (bit25 && (op1 == 0x12 || op1 == 0x16)) { -        // One of the MSR (immediate) and hints instructions -        return DecodeMSRImmAndHints(insn); -    } - -    // One of the data processing instructions -    return DecodeALU(insn); -} - -Opcode ARM_Disasm::Decode01(u32 insn) { -    u8 is_reg = (insn >> 25) & 0x1; -    u8 bit4 = (insn >> 4) & 0x1; -    if (is_reg == 1 && bit4 == 1) -        return DecodeMedia(insn); -    u8 is_load = (insn >> 20) & 0x1; -    u8 is_byte = (insn >> 22) & 0x1; -    if ((insn & 0xfd70f000) == 0xf550f000) { -        // Pre-load -        return OP_PLD; -    } -    if (insn == 0xf57ff01f) { -        // Clear-Exclusive -        return OP_CLREX; -    } -    if (is_load) { -        if (is_byte) { -            // Load byte -            return OP_LDRB; -        } -        // Load word -        return OP_LDR; -    } -    if (is_byte) { -        // Store byte -        return OP_STRB; -    } -    // Store word -    return OP_STR; -} - -Opcode ARM_Disasm::Decode10(u32 insn) { -    u8 bit25 = (insn >> 25) & 0x1; -    if (bit25 == 0) { -        // LDM/STM -        u8 is_load = (insn >> 20) & 0x1; -        if (is_load) -            return OP_LDM; -        return OP_STM; -    } - -    // Branch with link -    if ((insn >> 24) & 1) -        return OP_BL; - -    return OP_B; -} - -Opcode ARM_Disasm::Decode11(u32 insn) { -    u8 bit25 = (insn >> 25) & 0x1; -    if (bit25 == 0) { -        // LDC, SDC -        u8 is_load = (insn >> 20) & 0x1; -        if (is_load) { -            // LDC -            return OP_LDC; -        } -        // STC -        return OP_STC; -    } - -    u8 bit24 = (insn >> 24) & 0x1; -    if (bit24 == 0x1) { -        // SWI -        return OP_SWI; -    } - -    u8 bit4 = (insn >> 4) & 0x1; -    u8 cpnum = (insn >> 8) & 0xf; - -    if (cpnum == 15) { -        // Special case for coprocessor 15 -        u8 opcode = (insn >> 21) & 0x7; -        if (bit4 == 0 || opcode != 0) { -            // This is an unexpected bit pattern.  Create an undefined -            // instruction in case this is ever executed. -            return OP_UNDEFINED; -        } - -        // MRC, MCR -        u8 is_mrc = (insn >> 20) & 0x1; -        if (is_mrc) -            return OP_MRC; -        return OP_MCR; -    } - -    if (bit4 == 0) { -        // CDP -        return OP_CDP; -    } -    // MRC, MCR -    u8 is_mrc = (insn >> 20) & 0x1; -    if (is_mrc) -        return OP_MRC; -    return OP_MCR; -} - -Opcode ARM_Disasm::DecodeSyncPrimitive(u32 insn) { -    u32 op = BITS(insn, 20, 23); -    u32 bit22 = BIT(insn, 22); -    switch (op) { -    case 0x0: -        if (bit22) -            return OP_SWPB; -        return OP_SWP; -    case 0x8: -        return OP_STREX; -    case 0x9: -        return OP_LDREX; -    case 0xA: -        return OP_STREXD; -    case 0xB: -        return OP_LDREXD; -    case 0xC: -        return OP_STREXB; -    case 0xD: -        return OP_LDREXB; -    case 0xE: -        return OP_STREXH; -    case 0xF: -        return OP_LDREXH; -    default: -        return OP_UNDEFINED; -    } -} - -Opcode ARM_Disasm::DecodeParallelAddSub(u32 insn) { -    u32 op1 = BITS(insn, 20, 21); -    u32 op2 = BITS(insn, 5, 7); -    u32 is_unsigned = BIT(insn, 22); - -    if (op1 == 0x0 || op2 == 0x5 || op2 == 0x6) -        return OP_UNDEFINED; - -    // change op1 range from [1, 3] to range [0, 2] -    op1--; - -    // change op2 range from [0, 4] U {7} to range [0, 5] -    if (op2 == 0x7) -        op2 = 0x5; - -    static std::vector<Opcode> opcodes = { -        // op1 = 0 -        OP_SADD16, OP_UADD16, OP_SASX, OP_UASX, OP_SSAX, OP_USAX, OP_SSUB16, OP_USUB16, OP_SADD8, -        OP_UADD8, OP_SSUB8, OP_USUB8, -        // op1 = 1 -        OP_QADD16, OP_UQADD16, OP_QASX, OP_UQASX, OP_QSAX, OP_UQSAX, OP_QSUB16, OP_UQSUB16, -        OP_QADD8, OP_UQADD8, OP_QSUB8, OP_UQSUB8, -        // op1 = 2 -        OP_SHADD16, OP_UHADD16, OP_SHASX, OP_UHASX, OP_SHSAX, OP_UHSAX, OP_SHSUB16, OP_UHSUB16, -        OP_SHADD8, OP_UHADD8, OP_SHSUB8, OP_UHSUB8}; - -    u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned; -    return opcodes[opcode_index]; -} - -Opcode ARM_Disasm::DecodePackingSaturationReversal(u32 insn) { -    u32 op1 = BITS(insn, 20, 22); -    u32 a = BITS(insn, 16, 19); -    u32 op2 = BITS(insn, 5, 7); - -    switch (op1) { -    case 0x0: -        if (BIT(op2, 0) == 0) -            return OP_PKH; -        if (op2 == 0x3 && a != 0xf) -            return OP_SXTAB16; -        if (op2 == 0x3 && a == 0xf) -            return OP_SXTB16; -        if (op2 == 0x5) -            return OP_SEL; -        break; -    case 0x2: -        if (BIT(op2, 0) == 0) -            return OP_SSAT; -        if (op2 == 0x1) -            return OP_SSAT16; -        if (op2 == 0x3 && a != 0xf) -            return OP_SXTAB; -        if (op2 == 0x3 && a == 0xf) -            return OP_SXTB; -        break; -    case 0x3: -        if (op2 == 0x1) -            return OP_REV; -        if (BIT(op2, 0) == 0) -            return OP_SSAT; -        if (op2 == 0x3 && a != 0xf) -            return OP_SXTAH; -        if (op2 == 0x3 && a == 0xf) -            return OP_SXTH; -        if (op2 == 0x5) -            return OP_REV16; -        break; -    case 0x4: -        if (op2 == 0x3 && a != 0xf) -            return OP_UXTAB16; -        if (op2 == 0x3 && a == 0xf) -            return OP_UXTB16; -        break; -    case 0x6: -        if (BIT(op2, 0) == 0) -            return OP_USAT; -        if (op2 == 0x1) -            return OP_USAT16; -        if (op2 == 0x3 && a != 0xf) -            return OP_UXTAB; -        if (op2 == 0x3 && a == 0xf) -            return OP_UXTB; -        break; -    case 0x7: -        if (BIT(op2, 0) == 0) -            return OP_USAT; -        if (op2 == 0x3 && a != 0xf) -            return OP_UXTAH; -        if (op2 == 0x3 && a == 0xf) -            return OP_UXTH; -        if (op2 == 0x5) -            return OP_REVSH; -        break; -    default: -        break; -    } - -    return OP_UNDEFINED; -} - -Opcode ARM_Disasm::DecodeMUL(u32 insn) { -    u8 bit24 = (insn >> 24) & 0x1; -    if (bit24 != 0) { -        // This is an unexpected bit pattern.  Create an undefined -        // instruction in case this is ever executed. -        return OP_UNDEFINED; -    } -    u8 bit23 = (insn >> 23) & 0x1; -    u8 bit22_U = (insn >> 22) & 0x1; -    u8 bit21_A = (insn >> 21) & 0x1; -    if (bit23 == 0) { -        // 32-bit multiply -        if (bit22_U != 0) { -            // This is an unexpected bit pattern.  Create an undefined -            // instruction in case this is ever executed. -            return OP_UNDEFINED; -        } -        if (bit21_A == 0) -            return OP_MUL; -        return OP_MLA; -    } -    // 64-bit multiply -    if (bit22_U == 0) { -        // Unsigned multiply long -        if (bit21_A == 0) -            return OP_UMULL; -        return OP_UMLAL; -    } -    // Signed multiply long -    if (bit21_A == 0) -        return OP_SMULL; -    return OP_SMLAL; -} - -Opcode ARM_Disasm::DecodeMSRImmAndHints(u32 insn) { -    u32 op = BIT(insn, 22); -    u32 op1 = BITS(insn, 16, 19); -    u32 op2 = BITS(insn, 0, 7); - -    if (op == 0 && op1 == 0) { -        switch (op2) { -        case 0x0: -            return OP_NOP; -        case 0x1: -            return OP_YIELD; -        case 0x2: -            return OP_WFE; -        case 0x3: -            return OP_WFI; -        case 0x4: -            return OP_SEV; -        default: -            return OP_UNDEFINED; -        } -    } - -    return OP_MSR; -} - -Opcode ARM_Disasm::DecodeMediaMulDiv(u32 insn) { -    u32 op1 = BITS(insn, 20, 22); -    u32 op2_h = BITS(insn, 6, 7); -    u32 a = BITS(insn, 12, 15); - -    switch (op1) { -    case 0x0: -        if (op2_h == 0x0) { -            if (a != 0xf) -                return OP_SMLAD; -            else -                return OP_SMUAD; -        } else if (op2_h == 0x1) { -            if (a != 0xf) -                return OP_SMLSD; -            else -                return OP_SMUSD; -        } -        break; -    case 0x4: -        if (op2_h == 0x0) -            return OP_SMLALD; -        else if (op2_h == 0x1) -            return OP_SMLSLD; -        break; -    case 0x5: -        if (op2_h == 0x0) { -            if (a != 0xf) -                return OP_SMMLA; -            else -                return OP_SMMUL; -        } else if (op2_h == 0x3) { -            return OP_SMMLS; -        } -        break; -    default: -        break; -    } - -    return OP_UNDEFINED; -} - -Opcode ARM_Disasm::DecodeMedia(u32 insn) { -    u32 op1 = BITS(insn, 20, 24); -    u32 rd = BITS(insn, 12, 15); -    u32 op2 = BITS(insn, 5, 7); - -    switch (BITS(op1, 3, 4)) { -    case 0x0: -        // unsigned and signed parallel addition and subtraction -        return DecodeParallelAddSub(insn); -    case 0x1: -        // Packing, unpacking, saturation, and reversal -        return DecodePackingSaturationReversal(insn); -    case 0x2: -        // Signed multiply, signed and unsigned divide -        return DecodeMediaMulDiv(insn); -    case 0x3: -        if (op2 == 0 && rd == 0xf) -            return OP_USAD8; -        if (op2 == 0 && rd != 0xf) -            return OP_USADA8; -        break; -    default: -        break; -    } - -    return OP_UNDEFINED; -} - -Opcode ARM_Disasm::DecodeLDRH(u32 insn) { -    u8 is_load = (insn >> 20) & 0x1; -    u8 bits_65 = (insn >> 5) & 0x3; -    if (is_load) { -        if (bits_65 == 0x1) { -            // Load unsigned halfword -            return OP_LDRH; -        } else if (bits_65 == 0x2) { -            // Load signed byte -            return OP_LDRSB; -        } -        // Signed halfword -        if (bits_65 != 0x3) { -            // This is an unexpected bit pattern.  Create an undefined -            // instruction in case this is ever executed. -            return OP_UNDEFINED; -        } -        // Load signed halfword -        return OP_LDRSH; -    } -    // Store halfword -    if (bits_65 != 0x1) { -        // This is an unexpected bit pattern.  Create an undefined -        // instruction in case this is ever executed. -        return OP_UNDEFINED; -    } -    // Store halfword -    return OP_STRH; -} - -Opcode ARM_Disasm::DecodeALU(u32 insn) { -    u8 is_immed = (insn >> 25) & 0x1; -    u8 opcode = (insn >> 21) & 0xf; -    u8 bit_s = (insn >> 20) & 1; -    u8 shift_is_reg = (insn >> 4) & 1; -    u8 bit7 = (insn >> 7) & 1; -    if (!is_immed && shift_is_reg && (bit7 != 0)) { -        // This is an unexpected bit pattern.  Create an undefined -        // instruction in case this is ever executed. -        return OP_UNDEFINED; -    } -    switch (opcode) { -    case 0x0: -        return OP_AND; -    case 0x1: -        return OP_EOR; -    case 0x2: -        return OP_SUB; -    case 0x3: -        return OP_RSB; -    case 0x4: -        return OP_ADD; -    case 0x5: -        return OP_ADC; -    case 0x6: -        return OP_SBC; -    case 0x7: -        return OP_RSC; -    case 0x8: -        if (bit_s) -            return OP_TST; -        return OP_MRS; -    case 0x9: -        if (bit_s) -            return OP_TEQ; -        return OP_MSR; -    case 0xa: -        if (bit_s) -            return OP_CMP; -        return OP_MRS; -    case 0xb: -        if (bit_s) -            return OP_CMN; -        return OP_MSR; -    case 0xc: -        return OP_ORR; -    case 0xd: -        return OP_MOV; -    case 0xe: -        return OP_BIC; -    case 0xf: -        return OP_MVN; -    } -    // Unreachable -    return OP_INVALID; -} diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h deleted file mode 100644 index 300e228ed..000000000 --- a/src/core/arm/disassembler/arm_disasm.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2006 The Android Open Source Project - -#pragma once - -#include <string> -#include "common/common_types.h" - -// Note: this list of opcodes must match the list used to initialize -// the opflags[] array in opcode.cpp. -enum Opcode { -    OP_INVALID, -    OP_UNDEFINED, -    OP_ADC, -    OP_ADD, -    OP_AND, -    OP_B, -    OP_BL, -    OP_BIC, -    OP_BKPT, -    OP_BLX, -    OP_BX, -    OP_CDP, -    OP_CLREX, -    OP_CLZ, -    OP_CMN, -    OP_CMP, -    OP_EOR, -    OP_LDC, -    OP_LDM, -    OP_LDR, -    OP_LDRB, -    OP_LDRBT, -    OP_LDREX, -    OP_LDREXB, -    OP_LDREXD, -    OP_LDREXH, -    OP_LDRH, -    OP_LDRSB, -    OP_LDRSH, -    OP_LDRT, -    OP_MCR, -    OP_MLA, -    OP_MOV, -    OP_MRC, -    OP_MRS, -    OP_MSR, -    OP_MUL, -    OP_MVN, -    OP_NOP, -    OP_ORR, -    OP_PKH, -    OP_PLD, -    OP_QADD16, -    OP_QADD8, -    OP_QASX, -    OP_QSAX, -    OP_QSUB16, -    OP_QSUB8, -    OP_REV, -    OP_REV16, -    OP_REVSH, -    OP_RSB, -    OP_RSC, -    OP_SADD16, -    OP_SADD8, -    OP_SASX, -    OP_SBC, -    OP_SEL, -    OP_SEV, -    OP_SHADD16, -    OP_SHADD8, -    OP_SHASX, -    OP_SHSAX, -    OP_SHSUB16, -    OP_SHSUB8, -    OP_SMLAD, -    OP_SMLAL, -    OP_SMLALD, -    OP_SMLSD, -    OP_SMLSLD, -    OP_SMMLA, -    OP_SMMLS, -    OP_SMMUL, -    OP_SMUAD, -    OP_SMULL, -    OP_SMUSD, -    OP_SSAT, -    OP_SSAT16, -    OP_SSAX, -    OP_SSUB16, -    OP_SSUB8, -    OP_STC, -    OP_STM, -    OP_STR, -    OP_STRB, -    OP_STRBT, -    OP_STREX, -    OP_STREXB, -    OP_STREXD, -    OP_STREXH, -    OP_STRH, -    OP_STRT, -    OP_SUB, -    OP_SWI, -    OP_SWP, -    OP_SWPB, -    OP_SXTAB, -    OP_SXTAB16, -    OP_SXTAH, -    OP_SXTB, -    OP_SXTB16, -    OP_SXTH, -    OP_TEQ, -    OP_TST, -    OP_UADD16, -    OP_UADD8, -    OP_UASX, -    OP_UHADD16, -    OP_UHADD8, -    OP_UHASX, -    OP_UHSAX, -    OP_UHSUB16, -    OP_UHSUB8, -    OP_UMLAL, -    OP_UMULL, -    OP_UQADD16, -    OP_UQADD8, -    OP_UQASX, -    OP_UQSAX, -    OP_UQSUB16, -    OP_UQSUB8, -    OP_USAD8, -    OP_USADA8, -    OP_USAT, -    OP_USAT16, -    OP_USAX, -    OP_USUB16, -    OP_USUB8, -    OP_UXTAB, -    OP_UXTAB16, -    OP_UXTAH, -    OP_UXTB, -    OP_UXTB16, -    OP_UXTH, -    OP_WFE, -    OP_WFI, -    OP_YIELD, - -    // Define thumb opcodes -    OP_THUMB_UNDEFINED, -    OP_THUMB_ADC, -    OP_THUMB_ADD, -    OP_THUMB_AND, -    OP_THUMB_ASR, -    OP_THUMB_B, -    OP_THUMB_BIC, -    OP_THUMB_BKPT, -    OP_THUMB_BL, -    OP_THUMB_BLX, -    OP_THUMB_BX, -    OP_THUMB_CMN, -    OP_THUMB_CMP, -    OP_THUMB_EOR, -    OP_THUMB_LDMIA, -    OP_THUMB_LDR, -    OP_THUMB_LDRB, -    OP_THUMB_LDRH, -    OP_THUMB_LDRSB, -    OP_THUMB_LDRSH, -    OP_THUMB_LSL, -    OP_THUMB_LSR, -    OP_THUMB_MOV, -    OP_THUMB_MUL, -    OP_THUMB_MVN, -    OP_THUMB_NEG, -    OP_THUMB_ORR, -    OP_THUMB_POP, -    OP_THUMB_PUSH, -    OP_THUMB_ROR, -    OP_THUMB_SBC, -    OP_THUMB_STMIA, -    OP_THUMB_STR, -    OP_THUMB_STRB, -    OP_THUMB_STRH, -    OP_THUMB_SUB, -    OP_THUMB_SWI, -    OP_THUMB_TST, - -    OP_END // must be last -}; - -class ARM_Disasm { -public: -    static std::string Disassemble(u32 addr, u32 insn); -    static Opcode Decode(u32 insn); - -private: -    static Opcode Decode00(u32 insn); -    static Opcode Decode01(u32 insn); -    static Opcode Decode10(u32 insn); -    static Opcode Decode11(u32 insn); -    static Opcode DecodeSyncPrimitive(u32 insn); -    static Opcode DecodeParallelAddSub(u32 insn); -    static Opcode DecodePackingSaturationReversal(u32 insn); -    static Opcode DecodeMUL(u32 insn); -    static Opcode DecodeMSRImmAndHints(u32 insn); -    static Opcode DecodeMediaMulDiv(u32 insn); -    static Opcode DecodeMedia(u32 insn); -    static Opcode DecodeLDRH(u32 insn); -    static Opcode DecodeALU(u32 insn); - -    static std::string DisassembleALU(Opcode opcode, u32 insn); -    static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn); -    static std::string DisassembleBX(u32 insn); -    static std::string DisassembleBKPT(u32 insn); -    static std::string DisassembleCLZ(u32 insn); -    static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn); -    static std::string DisassembleMemblock(Opcode opcode, u32 insn); -    static std::string DisassembleMem(u32 insn); -    static std::string DisassembleMemHalf(u32 insn); -    static std::string DisassembleMCR(Opcode opcode, u32 insn); -    static std::string DisassembleMLA(Opcode opcode, u32 insn); -    static std::string DisassembleUMLAL(Opcode opcode, u32 insn); -    static std::string DisassembleMUL(Opcode opcode, u32 insn); -    static std::string DisassembleMRS(u32 insn); -    static std::string DisassembleMSR(u32 insn); -    static std::string DisassembleNoOperands(Opcode opcode, u32 insn); -    static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn); -    static std::string DisassemblePKH(u32 insn); -    static std::string DisassemblePLD(u32 insn); -    static std::string DisassembleREV(Opcode opcode, u32 insn); -    static std::string DisassembleREX(Opcode opcode, u32 insn); -    static std::string DisassembleSAT(Opcode opcode, u32 insn); -    static std::string DisassembleSEL(u32 insn); -    static std::string DisassembleSWI(u32 insn); -    static std::string DisassembleSWP(Opcode opcode, u32 insn); -    static std::string DisassembleXT(Opcode opcode, u32 insn); -}; diff --git a/src/core/arm/disassembler/load_symbol_map.cpp b/src/core/arm/disassembler/load_symbol_map.cpp deleted file mode 100644 index 6863c103a..000000000 --- a/src/core/arm/disassembler/load_symbol_map.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <sstream> -#include <string> -#include <vector> -#include "common/file_util.h" -#include "common/symbols.h" -#include "core/arm/disassembler/load_symbol_map.h" - -/* - * Loads a symbol map file for use with the disassembler - * @param filename String filename path of symbol map file - */ -void LoadSymbolMap(std::string filename) { -    std::ifstream infile(filename); - -    std::string address_str, function_name, line; -    u32 size; - -    while (std::getline(infile, line)) { -        std::istringstream iss(line); -        if (!(iss >> address_str >> size >> function_name)) { -            break; // Error parsing -        } -        u32 address = std::stoul(address_str, nullptr, 16); - -        Symbols::Add(address, function_name, size, 2); -    } -} diff --git a/src/core/arm/disassembler/load_symbol_map.h b/src/core/arm/disassembler/load_symbol_map.h deleted file mode 100644 index d28c551c3..000000000 --- a/src/core/arm/disassembler/load_symbol_map.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <string> - -/* - * Loads a symbol map file for use with the disassembler - * @param filename String filename path of symbol map file - */ -void LoadSymbolMap(std::string filename); diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 64dcaae08..dcfcd6561 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.cpp +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp @@ -415,7 +415,7 @@ const InstructionSetEncodingItem arm_exclusion_code[] = {  };  // clang-format on -ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { +ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx) {      int n = 0;      int base = 0;      int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem); diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h index 2fb7ac37c..1dcf7ecd1 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.h +++ b/src/core/arm/dyncom/arm_dyncom_dec.h @@ -8,7 +8,7 @@  enum class ARMDecodeStatus { SUCCESS, FAILURE }; -ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); +ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx);  struct InstructionSetEncodingItem {      const char* name; diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 273bc8167..f4fbb8d04 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -5,11 +5,11 @@  #define CITRA_IGNORE_EXIT(x)  #include <algorithm> +#include <cinttypes>  #include <cstdio>  #include "common/common_types.h"  #include "common/logging/log.h"  #include "common/microprofile.h" -#include "core/arm/disassembler/arm_disasm.h"  #include "core/arm/dyncom/arm_dyncom_dec.h"  #include "core/arm/dyncom/arm_dyncom_interpreter.h"  #include "core/arm/dyncom/arm_dyncom_run.h" @@ -808,8 +808,8 @@ MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));  static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr,                                                      ARM_INST_PTR& inst_base) { -    unsigned int inst_size = 4; -    unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC); +    u32 inst_size = 4; +    u32 inst = Memory::Read32(phys_addr & 0xFFFFFFFC);      // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM      // instruction @@ -827,11 +827,10 @@ static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, cons      int idx;      if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { -        std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); -        LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, -                  disasm.c_str(), inst); -        LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, -                  cpu->Reg[15]); +        LOG_ERROR(Core_ARM11, "Decode failure.\tPC: [0x%08" PRIX32 "]\tInstruction: %08" PRIX32, +                  phys_addr, inst); +        LOG_ERROR(Core_ARM11, "cpsr=0x%" PRIX32 ", cpu->TFlag=%d, r15=0x%08" PRIX32, cpu->Cpsr, +                  cpu->TFlag, cpu->Reg[15]);          CITRA_IGNORE_EXIT(-1);      }      inst_base = arm_instruction_trans[idx](inst, idx); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 2db823c61..8538cfc9d 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -2,12 +2,12 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <cinttypes>  #include <map>  #include "common/logging/log.h"  #include "common/microprofile.h"  #include "common/scope_exit.h"  #include "common/string_util.h" -#include "common/symbols.h"  #include "core/arm/arm_interface.h"  #include "core/core_timing.h"  #include "core/hle/function_wrappers.h" @@ -524,13 +524,7 @@ static ResultCode CreateThread(Kernel::Handle* out_handle, s32 priority, u32 ent                                 u32 stack_top, s32 processor_id) {      using Kernel::Thread; -    std::string name; -    if (Symbols::HasSymbol(entry_point)) { -        TSymbol symbol = Symbols::GetSymbol(entry_point); -        name = symbol.name; -    } else { -        name = Common::StringFromFormat("unknown-%08x", entry_point); -    } +    std::string name = Common::StringFromFormat("unknown-%08" PRIX32, entry_point);      if (priority > THREADPRIO_LOWEST) {          return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 8eb5200ab..cfcde9167 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -8,7 +8,6 @@  #include "common/common_types.h"  #include "common/file_util.h"  #include "common/logging/log.h" -#include "common/symbols.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/resource_limit.h"  #include "core/loader/elf.h" @@ -210,7 +209,6 @@ public:          return (u32)(header->e_flags);      }      SharedPtr<CodeSet> LoadInto(u32 vaddr); -    bool LoadSymbols();      int GetNumSegments() const {          return (int)(header->e_phnum); @@ -258,8 +256,6 @@ ElfReader::ElfReader(void* ptr) {      sections = (Elf32_Shdr*)(base + header->e_shoff);      entryPoint = header->e_entry; - -    LoadSymbols();  }  const char* ElfReader::GetSectionName(int section) const { @@ -362,34 +358,6 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const      return -1;  } -bool ElfReader::LoadSymbols() { -    bool hasSymbols = false; -    SectionID sec = GetSectionByName(".symtab"); -    if (sec != -1) { -        int stringSection = sections[sec].sh_link; -        const char* stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); - -        // We have a symbol table! -        const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); -        unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); -        for (unsigned sym = 0; sym < numSymbols; sym++) { -            int size = symtab[sym].st_size; -            if (size == 0) -                continue; - -            int type = symtab[sym].st_info & 0xF; - -            const char* name = stringBase + symtab[sym].st_name; - -            Symbols::Add(symtab[sym].st_value, name, size, type); - -            hasSymbols = true; -        } -    } - -    return hasSymbols; -} -  ////////////////////////////////////////////////////////////////////////////////////////////////////  // Loader namespace  | 
