diff options
73 files changed, 2071 insertions, 2301 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e945a66790..a02b85da31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,7 @@ else() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "" FORCE) set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG" CACHE STRING "" FORCE) - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG" CACHE STRING "" FORCE) + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE) endif() add_definitions(-DSINGLETHREADED) diff --git a/externals/nihstro b/externals/nihstro -Subproject 81f1804a43f625e3a1a20752c0db70a41341038 +Subproject 676254f71e0a7ef0aca8acce078d3c3dc80ccf7 diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 506cb7939c..2c1407a6f2 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -40,31 +40,21 @@ bool Config::LoadINI(INIReader* config, const char* location, const std::string& return true; } +static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = { + GLFW_KEY_A, GLFW_KEY_S, GLFW_KEY_Z, GLFW_KEY_X, + GLFW_KEY_Q, GLFW_KEY_W, GLFW_KEY_1, GLFW_KEY_2, + GLFW_KEY_M, GLFW_KEY_N, GLFW_KEY_B, + GLFW_KEY_T, GLFW_KEY_G, GLFW_KEY_F, GLFW_KEY_H, + GLFW_KEY_UP, GLFW_KEY_DOWN, GLFW_KEY_LEFT, GLFW_KEY_RIGHT, + GLFW_KEY_I, GLFW_KEY_K, GLFW_KEY_J, GLFW_KEY_L +}; + void Config::ReadValues() { // Controls - Settings::values.pad_a_key = glfw_config->GetInteger("Controls", "pad_a", GLFW_KEY_A); - Settings::values.pad_b_key = glfw_config->GetInteger("Controls", "pad_b", GLFW_KEY_S); - Settings::values.pad_x_key = glfw_config->GetInteger("Controls", "pad_x", GLFW_KEY_Z); - Settings::values.pad_y_key = glfw_config->GetInteger("Controls", "pad_y", GLFW_KEY_X); - Settings::values.pad_l_key = glfw_config->GetInteger("Controls", "pad_l", GLFW_KEY_Q); - Settings::values.pad_r_key = glfw_config->GetInteger("Controls", "pad_r", GLFW_KEY_W); - Settings::values.pad_zl_key = glfw_config->GetInteger("Controls", "pad_zl", GLFW_KEY_1); - Settings::values.pad_zr_key = glfw_config->GetInteger("Controls", "pad_zr", GLFW_KEY_2); - Settings::values.pad_start_key = glfw_config->GetInteger("Controls", "pad_start", GLFW_KEY_M); - Settings::values.pad_select_key = glfw_config->GetInteger("Controls", "pad_select", GLFW_KEY_N); - Settings::values.pad_home_key = glfw_config->GetInteger("Controls", "pad_home", GLFW_KEY_B); - Settings::values.pad_dup_key = glfw_config->GetInteger("Controls", "pad_dup", GLFW_KEY_T); - Settings::values.pad_ddown_key = glfw_config->GetInteger("Controls", "pad_ddown", GLFW_KEY_G); - Settings::values.pad_dleft_key = glfw_config->GetInteger("Controls", "pad_dleft", GLFW_KEY_F); - Settings::values.pad_dright_key = glfw_config->GetInteger("Controls", "pad_dright", GLFW_KEY_H); - Settings::values.pad_sup_key = glfw_config->GetInteger("Controls", "pad_sup", GLFW_KEY_UP); - Settings::values.pad_sdown_key = glfw_config->GetInteger("Controls", "pad_sdown", GLFW_KEY_DOWN); - Settings::values.pad_sleft_key = glfw_config->GetInteger("Controls", "pad_sleft", GLFW_KEY_LEFT); - Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); - Settings::values.pad_cup_key = glfw_config->GetInteger("Controls", "pad_cup", GLFW_KEY_I); - Settings::values.pad_cdown_key = glfw_config->GetInteger("Controls", "pad_cdown", GLFW_KEY_K); - Settings::values.pad_cleft_key = glfw_config->GetInteger("Controls", "pad_cleft", GLFW_KEY_J); - Settings::values.pad_cright_key = glfw_config->GetInteger("Controls", "pad_cright", GLFW_KEY_L); + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { + Settings::values.input_mappings[Settings::NativeInput::All[i]] = + glfw_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]); + } // Core Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index fd5a90d568..1925bece89 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -33,10 +33,6 @@ pad_cleft = pad_cright = [Core] -# The refresh rate for the GPU -# Defaults to 30 -gpu_refresh_rate = - # The applied frameskip amount. Must be a power of two. # 0 (default): No frameskip, 1: x2 frameskip, 2: x4 frameskip, 3: x8 frameskip, etc. frame_skip = diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp index 42fb683a94..6d6656b5a1 100644 --- a/src/citra/emu_window/emu_window_glfw.cpp +++ b/src/citra/emu_window/emu_window_glfw.cpp @@ -150,32 +150,9 @@ void EmuWindow_GLFW::DoneCurrent() { } void EmuWindow_GLFW::ReloadSetKeymaps() { - KeyMap::SetKeyMapping({Settings::values.pad_a_key, keyboard_id}, Service::HID::PAD_A); - KeyMap::SetKeyMapping({Settings::values.pad_b_key, keyboard_id}, Service::HID::PAD_B); - KeyMap::SetKeyMapping({Settings::values.pad_select_key, keyboard_id}, Service::HID::PAD_SELECT); - KeyMap::SetKeyMapping({Settings::values.pad_start_key, keyboard_id}, Service::HID::PAD_START); - KeyMap::SetKeyMapping({Settings::values.pad_dright_key, keyboard_id}, Service::HID::PAD_RIGHT); - KeyMap::SetKeyMapping({Settings::values.pad_dleft_key, keyboard_id}, Service::HID::PAD_LEFT); - KeyMap::SetKeyMapping({Settings::values.pad_dup_key, keyboard_id}, Service::HID::PAD_UP); - KeyMap::SetKeyMapping({Settings::values.pad_ddown_key, keyboard_id}, Service::HID::PAD_DOWN); - KeyMap::SetKeyMapping({Settings::values.pad_r_key, keyboard_id}, Service::HID::PAD_R); - KeyMap::SetKeyMapping({Settings::values.pad_l_key, keyboard_id}, Service::HID::PAD_L); - KeyMap::SetKeyMapping({Settings::values.pad_x_key, keyboard_id}, Service::HID::PAD_X); - KeyMap::SetKeyMapping({Settings::values.pad_y_key, keyboard_id}, Service::HID::PAD_Y); - - KeyMap::SetKeyMapping({Settings::values.pad_zl_key, keyboard_id}, Service::HID::PAD_ZL); - KeyMap::SetKeyMapping({Settings::values.pad_zr_key, keyboard_id}, Service::HID::PAD_ZR); - - // KeyMap::SetKeyMapping({Settings::values.pad_touch_key, keyboard_id}, Service::HID::PAD_TOUCH); - - KeyMap::SetKeyMapping({Settings::values.pad_cright_key, keyboard_id}, Service::HID::PAD_C_RIGHT); - KeyMap::SetKeyMapping({Settings::values.pad_cleft_key, keyboard_id}, Service::HID::PAD_C_LEFT); - KeyMap::SetKeyMapping({Settings::values.pad_cup_key, keyboard_id}, Service::HID::PAD_C_UP); - KeyMap::SetKeyMapping({Settings::values.pad_cdown_key, keyboard_id}, Service::HID::PAD_C_DOWN); - KeyMap::SetKeyMapping({Settings::values.pad_sright_key, keyboard_id}, Service::HID::PAD_CIRCLE_RIGHT); - KeyMap::SetKeyMapping({Settings::values.pad_sleft_key, keyboard_id}, Service::HID::PAD_CIRCLE_LEFT); - KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, Service::HID::PAD_CIRCLE_UP); - KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, Service::HID::PAD_CIRCLE_DOWN); + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { + KeyMap::SetKeyMapping({Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, Service::HID::pad_mapping[i]); + } } void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index fa7bce4660..b12bd858bd 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -248,32 +248,9 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent *event) void GRenderWindow::ReloadSetKeymaps() { - KeyMap::SetKeyMapping({Settings::values.pad_a_key, keyboard_id}, Service::HID::PAD_A); - KeyMap::SetKeyMapping({Settings::values.pad_b_key, keyboard_id}, Service::HID::PAD_B); - KeyMap::SetKeyMapping({Settings::values.pad_select_key, keyboard_id}, Service::HID::PAD_SELECT); - KeyMap::SetKeyMapping({Settings::values.pad_start_key, keyboard_id}, Service::HID::PAD_START); - KeyMap::SetKeyMapping({Settings::values.pad_dright_key, keyboard_id}, Service::HID::PAD_RIGHT); - KeyMap::SetKeyMapping({Settings::values.pad_dleft_key, keyboard_id}, Service::HID::PAD_LEFT); - KeyMap::SetKeyMapping({Settings::values.pad_dup_key, keyboard_id}, Service::HID::PAD_UP); - KeyMap::SetKeyMapping({Settings::values.pad_ddown_key, keyboard_id}, Service::HID::PAD_DOWN); - KeyMap::SetKeyMapping({Settings::values.pad_r_key, keyboard_id}, Service::HID::PAD_R); - KeyMap::SetKeyMapping({Settings::values.pad_l_key, keyboard_id}, Service::HID::PAD_L); - KeyMap::SetKeyMapping({Settings::values.pad_x_key, keyboard_id}, Service::HID::PAD_X); - KeyMap::SetKeyMapping({Settings::values.pad_y_key, keyboard_id}, Service::HID::PAD_Y); - - KeyMap::SetKeyMapping({Settings::values.pad_zl_key, keyboard_id}, Service::HID::PAD_ZL); - KeyMap::SetKeyMapping({Settings::values.pad_zr_key, keyboard_id}, Service::HID::PAD_ZR); - - // KeyMap::SetKeyMapping({Settings::values.pad_touch_key, keyboard_id}, Service::HID::PAD_TOUCH); - - KeyMap::SetKeyMapping({Settings::values.pad_cright_key, keyboard_id}, Service::HID::PAD_C_RIGHT); - KeyMap::SetKeyMapping({Settings::values.pad_cleft_key, keyboard_id}, Service::HID::PAD_C_LEFT); - KeyMap::SetKeyMapping({Settings::values.pad_cup_key, keyboard_id}, Service::HID::PAD_C_UP); - KeyMap::SetKeyMapping({Settings::values.pad_cdown_key, keyboard_id}, Service::HID::PAD_C_DOWN); - KeyMap::SetKeyMapping({Settings::values.pad_sright_key, keyboard_id}, Service::HID::PAD_CIRCLE_RIGHT); - KeyMap::SetKeyMapping({Settings::values.pad_sleft_key, keyboard_id}, Service::HID::PAD_CIRCLE_LEFT); - KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, Service::HID::PAD_CIRCLE_UP); - KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, Service::HID::PAD_CIRCLE_DOWN); + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { + KeyMap::SetKeyMapping({Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, Service::HID::pad_mapping[i]); + } } void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index 5c056446e4..5716634ee3 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -21,31 +21,21 @@ Config::Config() { Reload(); } +static const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> defaults = { + Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, + Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2, + Qt::Key_M, Qt::Key_N, Qt::Key_B, + Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, + Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, + Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L +}; + void Config::ReadValues() { qt_config->beginGroup("Controls"); - Settings::values.pad_a_key = qt_config->value("pad_a", Qt::Key_A).toInt(); - Settings::values.pad_b_key = qt_config->value("pad_b", Qt::Key_S).toInt(); - Settings::values.pad_x_key = qt_config->value("pad_x", Qt::Key_Z).toInt(); - Settings::values.pad_y_key = qt_config->value("pad_y", Qt::Key_X).toInt(); - Settings::values.pad_l_key = qt_config->value("pad_l", Qt::Key_Q).toInt(); - Settings::values.pad_r_key = qt_config->value("pad_r", Qt::Key_W).toInt(); - Settings::values.pad_zl_key = qt_config->value("pad_zl", Qt::Key_1).toInt(); - Settings::values.pad_zr_key = qt_config->value("pad_zr", Qt::Key_2).toInt(); - Settings::values.pad_start_key = qt_config->value("pad_start", Qt::Key_M).toInt(); - Settings::values.pad_select_key = qt_config->value("pad_select", Qt::Key_N).toInt(); - Settings::values.pad_home_key = qt_config->value("pad_home", Qt::Key_B).toInt(); - Settings::values.pad_dup_key = qt_config->value("pad_dup", Qt::Key_T).toInt(); - Settings::values.pad_ddown_key = qt_config->value("pad_ddown", Qt::Key_G).toInt(); - Settings::values.pad_dleft_key = qt_config->value("pad_dleft", Qt::Key_F).toInt(); - Settings::values.pad_dright_key = qt_config->value("pad_dright", Qt::Key_H).toInt(); - Settings::values.pad_sup_key = qt_config->value("pad_sup", Qt::Key_Up).toInt(); - Settings::values.pad_sdown_key = qt_config->value("pad_sdown", Qt::Key_Down).toInt(); - Settings::values.pad_sleft_key = qt_config->value("pad_sleft", Qt::Key_Left).toInt(); - Settings::values.pad_sright_key = qt_config->value("pad_sright", Qt::Key_Right).toInt(); - Settings::values.pad_cup_key = qt_config->value("pad_cup", Qt::Key_I).toInt(); - Settings::values.pad_cdown_key = qt_config->value("pad_cdown", Qt::Key_K).toInt(); - Settings::values.pad_cleft_key = qt_config->value("pad_cleft", Qt::Key_J).toInt(); - Settings::values.pad_cright_key = qt_config->value("pad_cright", Qt::Key_L).toInt(); + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { + Settings::values.input_mappings[Settings::NativeInput::All[i]] = + qt_config->value(QString::fromStdString(Settings::NativeInput::Mapping[i]), defaults[i]).toInt(); + } qt_config->endGroup(); qt_config->beginGroup("Core"); @@ -75,29 +65,10 @@ void Config::ReadValues() { void Config::SaveValues() { qt_config->beginGroup("Controls"); - qt_config->setValue("pad_a", Settings::values.pad_a_key); - qt_config->setValue("pad_b", Settings::values.pad_b_key); - qt_config->setValue("pad_x", Settings::values.pad_x_key); - qt_config->setValue("pad_y", Settings::values.pad_y_key); - qt_config->setValue("pad_l", Settings::values.pad_l_key); - qt_config->setValue("pad_r", Settings::values.pad_r_key); - qt_config->setValue("pad_zl", Settings::values.pad_zl_key); - qt_config->setValue("pad_zr", Settings::values.pad_zr_key); - qt_config->setValue("pad_start", Settings::values.pad_start_key); - qt_config->setValue("pad_select", Settings::values.pad_select_key); - qt_config->setValue("pad_home", Settings::values.pad_home_key); - qt_config->setValue("pad_dup", Settings::values.pad_dup_key); - qt_config->setValue("pad_ddown", Settings::values.pad_ddown_key); - qt_config->setValue("pad_dleft", Settings::values.pad_dleft_key); - qt_config->setValue("pad_dright", Settings::values.pad_dright_key); - qt_config->setValue("pad_sup", Settings::values.pad_sup_key); - qt_config->setValue("pad_sdown", Settings::values.pad_sdown_key); - qt_config->setValue("pad_sleft", Settings::values.pad_sleft_key); - qt_config->setValue("pad_sright", Settings::values.pad_sright_key); - qt_config->setValue("pad_cup", Settings::values.pad_cup_key); - qt_config->setValue("pad_cdown", Settings::values.pad_cdown_key); - qt_config->setValue("pad_cleft", Settings::values.pad_cleft_key); - qt_config->setValue("pad_cright", Settings::values.pad_cright_key); + for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { + qt_config->setValue(QString::fromStdString(Settings::NativeInput::Mapping[i]), + Settings::values.input_mappings[Settings::NativeInput::All[i]]); + } qt_config->endGroup(); qt_config->beginGroup("Core"); diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index b41c40a0e2..1e5ef52996 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp @@ -15,7 +15,6 @@ #include "common/break_points.h" #include "common/symbols.h" #include "core/arm/arm_interface.h" -#include "core/arm/skyeye_common/armdefs.h" #include "core/arm/disassembler/arm_disasm.h" @@ -219,7 +218,7 @@ void DisassemblerWidget::OnToggleStartStop() { } void DisassemblerWidget::OnDebugModeEntered() { - ARMword next_instr = Core::g_app_core->GetPC(); + u32 next_instr = Core::g_app_core->GetPC(); if (model->GetBreakPoints().IsAddressBreakPoint(next_instr)) emu_thread->SetRunning(false); diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 1da64f6166..5202c168ce 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -4,7 +4,7 @@ #include <QMetaType> #include <QPushButton> -#include <QTreeWidget> +#include <QTreeView> #include <QVBoxLayout> #include <QLabel> @@ -23,7 +23,7 @@ BreakPointModel::BreakPointModel(std::shared_ptr<Pica::DebugContext> debug_conte int BreakPointModel::columnCount(const QModelIndex& parent) const { - return 2; + return 1; } int BreakPointModel::rowCount(const QModelIndex& parent) const @@ -38,29 +38,29 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const switch (role) { case Qt::DisplayRole: { - switch (index.column()) { - case 0: - { + if (index.column() == 0) { static const std::map<Pica::DebugContext::Event, QString> map = { - { Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded") }, - { Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed") }, + { Pica::DebugContext::Event::PicaCommandLoaded, tr("Pica command loaded") }, + { Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed") }, { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") }, { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") }, - { Pica::DebugContext::Event::VertexLoaded, tr("Vertex loaded") } + { Pica::DebugContext::Event::VertexLoaded, tr("Vertex loaded") }, + { Pica::DebugContext::Event::IncomingDisplayTransfer, tr("Incoming display transfer") }, + { Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed") }, + { Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped") } }; DEBUG_ASSERT(map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); - return (map.find(event) != map.end()) ? map.at(event) : QString(); } - case 1: - return data(index, Role_IsEnabled).toBool() ? tr("Enabled") : tr("Disabled"); - - default: - break; - } + break; + } + case Qt::CheckStateRole: + { + if (index.column() == 0) + return data(index, Role_IsEnabled).toBool() ? Qt::Checked : Qt::Unchecked; break; } @@ -84,37 +84,34 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const return QVariant(); } -QVariant BreakPointModel::headerData(int section, Qt::Orientation orientation, int role) const +Qt::ItemFlags BreakPointModel::flags(const QModelIndex &index) const { - switch(role) { - case Qt::DisplayRole: - { - if (section == 0) { - return tr("Event"); - } else if (section == 1) { - return tr("Status"); - } - - break; - } - } + if (!index.isValid()) + return 0; - return QVariant(); + Qt::ItemFlags flags = Qt::ItemIsEnabled; + if (index.column() == 0) + flags |= Qt::ItemIsUserCheckable; + return flags; } + bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) { const auto event = static_cast<Pica::DebugContext::Event>(index.row()); switch (role) { - case Role_IsEnabled: + case Qt::CheckStateRole: { + if (index.column() != 0) + return false; + auto context = context_weak.lock(); if (!context) return false; - context->breakpoints[event].enabled = value.toBool(); - QModelIndex changed_index = createIndex(index.row(), 1); + context->breakpoints[event].enabled = value == Qt::Checked; + QModelIndex changed_index = createIndex(index.row(), 0); emit dataChanged(changed_index, changed_index); return true; } @@ -133,7 +130,7 @@ void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) active_breakpoint = context->active_breakpoint; at_breakpoint = context->at_breakpoint; emit dataChanged(createIndex(static_cast<int>(event), 0), - createIndex(static_cast<int>(event), 1)); + createIndex(static_cast<int>(event), 0)); } void BreakPointModel::OnResumed() @@ -144,7 +141,7 @@ void BreakPointModel::OnResumed() at_breakpoint = context->at_breakpoint; emit dataChanged(createIndex(static_cast<int>(active_breakpoint), 0), - createIndex(static_cast<int>(active_breakpoint), 1)); + createIndex(static_cast<int>(active_breakpoint), 0)); active_breakpoint = context->active_breakpoint; } @@ -162,13 +159,15 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug breakpoint_model = new BreakPointModel(debug_context, this); breakpoint_list = new QTreeView; + breakpoint_list->setRootIsDecorated(false); + breakpoint_list->setHeaderHidden(true); breakpoint_list->setModel(breakpoint_model); - toggle_breakpoint_button = new QPushButton(tr("Enable")); - toggle_breakpoint_button->setEnabled(false); - qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); + connect(breakpoint_list, SIGNAL(doubleClicked(const QModelIndex&)), + this, SLOT(OnItemDoubleClicked(const QModelIndex&))); + connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested())); connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), @@ -184,11 +183,6 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&,const QModelIndex&)), breakpoint_model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))); - connect(breakpoint_list->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(OnBreakpointSelectionChanged(QModelIndex))); - - connect(toggle_breakpoint_button, SIGNAL(clicked()), this, SLOT(OnToggleBreakpointEnabled())); - QWidget* main_widget = new QWidget; auto main_layout = new QVBoxLayout; { @@ -198,7 +192,6 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug main_layout->addLayout(sub_layout); } main_layout->addWidget(breakpoint_list); - main_layout->addWidget(toggle_breakpoint_button); main_widget->setLayout(main_layout); setWidget(main_widget); @@ -234,32 +227,15 @@ void GraphicsBreakPointsWidget::OnResumeRequested() context->Resume(); } -void GraphicsBreakPointsWidget::OnBreakpointSelectionChanged(const QModelIndex& index) +void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index) { - if (!index.isValid()) { - toggle_breakpoint_button->setEnabled(false); + if (!index.isValid()) return; - } - toggle_breakpoint_button->setEnabled(true); - UpdateToggleBreakpointButton(index); -} - -void GraphicsBreakPointsWidget::OnToggleBreakpointEnabled() -{ - QModelIndex index = breakpoint_list->selectionModel()->currentIndex(); - bool new_state = !(breakpoint_model->data(index, BreakPointModel::Role_IsEnabled).toBool()); - - breakpoint_model->setData(index, new_state, - BreakPointModel::Role_IsEnabled); - UpdateToggleBreakpointButton(index); -} - -void GraphicsBreakPointsWidget::UpdateToggleBreakpointButton(const QModelIndex& index) -{ - if (true == breakpoint_model->data(index, BreakPointModel::Role_IsEnabled).toBool()) { - toggle_breakpoint_button->setText(tr("Disable")); - } else { - toggle_breakpoint_button->setText(tr("Enable")); - } + QModelIndex check_index = breakpoint_list->model()->index(index.row(), 0); + QVariant enabled = breakpoint_list->model()->data(check_index, Qt::CheckStateRole); + QVariant new_state = Qt::Unchecked; + if (enabled == Qt::Unchecked) + new_state = Qt::Checked; + breakpoint_list->model()->setData(check_index, new_state, Qt::CheckStateRole); } diff --git a/src/citra_qt/debugger/graphics_breakpoints.h b/src/citra_qt/debugger/graphics_breakpoints.h index 5b9ba324e3..d900729da6 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.h +++ b/src/citra_qt/debugger/graphics_breakpoints.h @@ -31,10 +31,9 @@ public: public slots: void OnBreakPointHit(Pica::DebugContext::Event event, void* data); + void OnItemDoubleClicked(const QModelIndex&); void OnResumeRequested(); void OnResumed(); - void OnBreakpointSelectionChanged(const QModelIndex&); - void OnToggleBreakpointEnabled(); signals: void Resumed(); @@ -42,11 +41,8 @@ signals: void BreakPointsChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); private: - void UpdateToggleBreakpointButton(const QModelIndex& index); - QLabel* status_text; QPushButton* resume_button; - QPushButton* toggle_breakpoint_button; BreakPointModel* breakpoint_model; QTreeView* breakpoint_list; diff --git a/src/citra_qt/debugger/graphics_breakpoints_p.h b/src/citra_qt/debugger/graphics_breakpoints_p.h index 34e72e8591..00d8d51013 100644 --- a/src/citra_qt/debugger/graphics_breakpoints_p.h +++ b/src/citra_qt/debugger/graphics_breakpoints_p.h @@ -23,7 +23,7 @@ public: 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; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp index 392ff570be..7ac3ea542d 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics_cmdlists.cpp @@ -10,6 +10,7 @@ #include <QPushButton> #include <QVBoxLayout> #include <QTreeView> +#include <QHeaderView> #include <QSpinBox> #include <QComboBox> @@ -170,11 +171,11 @@ GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(p } int GPUCommandListModel::rowCount(const QModelIndex& parent) const { - return pica_trace.writes.size(); + return static_cast<int>(pica_trace.writes.size()); } int GPUCommandListModel::columnCount(const QModelIndex& parent) const { - return 2; + return 3; } QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { @@ -187,14 +188,13 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) { QString content; - if (index.column() == 0) { - QString content = QString::fromLatin1(Pica::Regs::GetCommandName(cmd.cmd_id).c_str()); - content.append(" "); - return content; - } else if (index.column() == 1) { - QString content = QString("%1 ").arg(cmd.hex, 8, 16, QLatin1Char('0')); - content.append(QString("%1 ").arg(val, 8, 16, QLatin1Char('0'))); - return content; + switch ( index.column() ) { + case 0: + return QString::fromLatin1(Pica::Regs::GetCommandName(cmd.cmd_id).c_str()); + case 1: + return QString("%1").arg(cmd.cmd_id, 3, 16, QLatin1Char('0')); + case 2: + return QString("%1").arg(val, 8, 16, QLatin1Char('0')); } } else if (role == CommandIdRole) { return QVariant::fromValue<int>(cmd.cmd_id.Value()); @@ -207,10 +207,13 @@ QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientatio switch(role) { case Qt::DisplayRole: { - if (section == 0) { + switch (section) { + case 0: return tr("Command Name"); - } else if (section == 1) { - return tr("Data"); + case 1: + return tr("Register"); + case 2: + return tr("New Value"); } break; @@ -299,6 +302,13 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi list_widget->setModel(model); list_widget->setFont(QFont("monospace")); list_widget->setRootIsDecorated(false); + list_widget->setUniformRowHeights(true); + +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + list_widget->header()->setSectionResizeMode(QHeaderView::ResizeToContents); +#else + list_widget->header()->setResizeMode(QHeaderView::ResizeToContents); +#endif connect(list_widget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)), this, SLOT(SetCommandInfo(const QModelIndex&))); diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp index db622d8467..f42a2f4ce6 100644 --- a/src/citra_qt/debugger/graphics_vertex_shader.cpp +++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp @@ -34,7 +34,7 @@ int GraphicsVertexShaderModel::columnCount(const QModelIndex& parent) const { } int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const { - return info.code.size(); + return static_cast<int>(info.code.size()); } QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, int role) const { diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp index 2ac1748b76..89b28c2f4c 100644 --- a/src/citra_qt/debugger/profiler.cpp +++ b/src/citra_qt/debugger/profiler.cpp @@ -74,7 +74,7 @@ int ProfilerModel::rowCount(const QModelIndex& parent) const if (parent.isValid()) { return 0; } else { - return results.time_per_category.size() + 2; + return static_cast<int>(results.time_per_category.size() + 2); } } diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 2746de779b..e93e8ebb88 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -207,7 +207,7 @@ void GMainWindow::OnDisplayTitleBars(bool show) } } -void GMainWindow::BootGame(std::string filename) { +void GMainWindow::BootGame(const std::string& filename) { LOG_INFO(Frontend, "Citra starting...\n"); // Initialize the core emulation @@ -263,6 +263,7 @@ void GMainWindow::ShutdownGame() { // Update the GUI ui.action_Start->setEnabled(false); + ui.action_Start->setText(tr("Start")); ui.action_Pause->setEnabled(false); ui.action_Stop->setEnabled(false); render_window->hide(); @@ -291,6 +292,8 @@ void GMainWindow::OnStartGame() emu_thread->SetRunning(true); ui.action_Start->setEnabled(false); + ui.action_Start->setText(tr("Continue")); + ui.action_Pause->setEnabled(true); ui.action_Stop->setEnabled(true); } diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 242b08c395..9fe9e0c9c5 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -55,7 +55,7 @@ signals: void EmulationStopping(); private: - void BootGame(std::string filename); + void BootGame(const std::string& filename); void ShutdownGame(); void closeEvent(QCloseEvent* event) override; diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 2e80809abe..b2f7f7b1d0 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -313,7 +313,7 @@ static std::string UTF16ToUTF8(const std::wstring& input) std::string output; output.resize(size); - if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr)) + if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), &output[0], static_cast<int>(output.size()), nullptr, nullptr)) output.clear(); return output; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8267ee5861..6cc60fd582 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -4,10 +4,9 @@ set(SRCS arm/dyncom/arm_dyncom.cpp arm/dyncom/arm_dyncom_dec.cpp arm/dyncom/arm_dyncom_interpreter.cpp - arm/dyncom/arm_dyncom_run.cpp arm/dyncom/arm_dyncom_thumb.cpp - arm/interpreter/arminit.cpp - arm/interpreter/armsupp.cpp + arm/skyeye_common/armstate.cpp + arm/skyeye_common/armsupp.cpp arm/skyeye_common/vfp/vfp.cpp arm/skyeye_common/vfp/vfpdouble.cpp arm/skyeye_common/vfp/vfpinstr.cpp @@ -132,8 +131,8 @@ set(HEADERS arm/dyncom/arm_dyncom_run.h arm/dyncom/arm_dyncom_thumb.h arm/skyeye_common/arm_regformat.h - arm/skyeye_common/armdefs.h - arm/skyeye_common/armmmu.h + arm/skyeye_common/armstate.h + arm/skyeye_common/armsupp.h arm/skyeye_common/vfp/asm_vfp.h arm/skyeye_common/vfp/vfp.h arm/skyeye_common/vfp/vfp_helper.h diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 529c4ac708..c665f706f3 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -6,7 +6,8 @@ #include "common/make_unique.h" -#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/armstate.h" +#include "core/arm/skyeye_common/armsupp.h" #include "core/arm/skyeye_common/vfp/vfp.h" #include "core/arm/dyncom/arm_dyncom.h" @@ -17,26 +18,7 @@ #include "core/core_timing.h" ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { - state = Common::make_unique<ARMul_State>(); - - ARMul_NewState(state.get()); - ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); - - state->abort_model = ABORT_BASE_RESTORED; - - state->bigendSig = LOW; - state->lateabtSig = LOW; - state->NirqSig = HIGH; - - // Reset the core to initial state - ARMul_Reset(state.get()); - state->Emulate = RUN; - - // Switch to the desired privilege mode. - switch_mode(state.get(), initial_mode); - - state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack - state->Reg[15] = 0x00000000; + state = Common::make_unique<ARMul_State>(initial_mode); } ARM_DynCom::~ARM_DynCom() { @@ -100,8 +82,8 @@ void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 e } void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { - memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); - memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); + memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers)); + memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers)); ctx.sp = state->Reg[13]; ctx.lr = state->Reg[14]; @@ -113,8 +95,8 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { } void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { - memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); - memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); + memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers)); + memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers)); state->Reg[13] = ctx.sp; state->Reg[14] = ctx.lr; diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index cc93557222..87ab6908ab 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -9,8 +9,8 @@ #include "common/common_types.h" #include "core/arm/arm_interface.h" -#include "core/arm/skyeye_common/armdefs.h" #include "core/arm/skyeye_common/arm_regformat.h" +#include "core/arm/skyeye_common/armstate.h" namespace Core { struct ThreadContext; diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 697be9556a..ee4288314f 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.cpp +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp @@ -2,10 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/arm/skyeye_common/armdefs.h" #include "core/arm/dyncom/arm_dyncom_dec.h" +#include "core/arm/skyeye_common/armsupp.h" -const ISEITEM arm_instruction[] = { +const InstructionSetEncodingItem arm_instruction[] = { { "vmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }}, { "vmls", 7, ARMVFP2, { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }}, { "vnmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }}, @@ -207,7 +207,7 @@ const ISEITEM arm_instruction[] = { { "bbl", 1, 0, { 25, 27, 0x00000005 }}, }; -const ISEITEM arm_exclusion_code[] = { +const InstructionSetEncodingItem arm_exclusion_code[] = { { "vmla", 0, ARMVFP2, { 0 }}, { "vmls", 0, ARMVFP2, { 0 }}, { "vnmla", 0, ARMVFP2, { 0 }}, @@ -414,14 +414,13 @@ const ISEITEM arm_exclusion_code[] = { { "invalid", 0, INVALID, { 0 }} }; -int decode_arm_instr(uint32_t instr, int32_t *idx) { +ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { int n = 0; int base = 0; - int ret = DECODE_FAILURE; - int i = 0; - int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM); + int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem); + ARMDecodeStatus ret = ARMDecodeStatus::FAILURE; - for (i = 0; i < instr_slots; i++) { + for (int i = 0; i < instr_slots; i++) { n = arm_instruction[i].attribute_value; base = 0; @@ -438,11 +437,11 @@ int decode_arm_instr(uint32_t instr, int32_t *idx) { n--; } - // All conditions is satisfied. + // All conditions are satisfied. if (n == 0) - ret = DECODE_SUCCESS; + ret = ARMDecodeStatus::SUCCESS; - if (ret == DECODE_SUCCESS) { + if (ret == ARMDecodeStatus::SUCCESS) { n = arm_exclusion_code[i].attribute_value; if (n != 0) { base = 0; @@ -454,13 +453,13 @@ int decode_arm_instr(uint32_t instr, int32_t *idx) { n--; } - // All conditions is satisfied. + // All conditions are satisfied. if (n == 0) - ret = DECODE_FAILURE; + ret = ARMDecodeStatus::FAILURE; } } - if (ret == DECODE_SUCCESS) { + if (ret == ARMDecodeStatus::SUCCESS) { *idx = i; return ret; } diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h index 4b5f5ad7e2..d7170e0fcc 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.h +++ b/src/core/arm/dyncom/arm_dyncom_dec.h @@ -4,22 +4,22 @@ #pragma once -int decode_arm_instr(uint32_t instr, int32_t *idx); +#include "common/common_types.h" -enum DECODE_STATUS { - DECODE_SUCCESS, - DECODE_FAILURE +enum class ARMDecodeStatus { + SUCCESS, + FAILURE }; -struct instruction_set_encoding_item { +ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); + +struct InstructionSetEncodingItem { const char *name; int attribute_value; int version; u32 content[21]; }; -typedef struct instruction_set_encoding_item ISEITEM; - // ARM versions enum { INVALID = 0, @@ -36,4 +36,4 @@ enum { ARMV6K, }; -extern const ISEITEM arm_instruction[]; +extern const InstructionSetEncodingItem arm_instruction[]; diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 785f395666..bb0cbb4dcd 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -17,8 +17,8 @@ #include "core/arm/dyncom/arm_dyncom_interpreter.h" #include "core/arm/dyncom/arm_dyncom_thumb.h" #include "core/arm/dyncom/arm_dyncom_run.h" -#include "core/arm/skyeye_common/armdefs.h" -#include "core/arm/skyeye_common/armmmu.h" +#include "core/arm/skyeye_common/armstate.h" +#include "core/arm/skyeye_common/armsupp.h" #include "core/arm/skyeye_common/vfp/vfp.h" Common::Profiling::TimingCategory profile_execute("DynCom::Execute"); @@ -47,28 +47,6 @@ enum { typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); -// Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. -// This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to -// support LDR/STREXD. -static const ARMword RESERVATION_GRANULE_MASK = 0xFFFFFFF8; - -// Exclusive memory access -static int exclusive_detect(ARMul_State* state, ARMword addr) { - if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK)) - return 0; - else - return -1; -} - -static void add_exclusive_addr(ARMul_State* state, ARMword addr){ - state->exclusive_tag = addr & RESERVATION_GRANULE_MASK; - return; -} - -static void remove_exclusive(ARMul_State* state, ARMword addr){ - state->exclusive_tag = 0xFFFFFFFF; -} - static int CondPassed(ARMul_State* cpu, unsigned int cond) { const u32 NFLAG = cpu->NFlag; const u32 ZFLAG = cpu->ZFlag; @@ -3490,21 +3468,15 @@ enum { FETCH_FAILURE }; -static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { +static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { // Check if in Thumb mode - tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size); - if(ret == t_branch){ - // TODO: FIXME, endian should be judged - u32 tinstr; - if((addr & 0x3) != 0) - tinstr = inst >> 16; - else - tinstr = inst & 0xFFFF; - + ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); + if (ret == ThumbDecodeStatus::BRANCH) { int inst_index; int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); + u32 tinstr = GetThumbInstruction(inst, addr); - switch((tinstr & 0xF800) >> 11){ + switch ((tinstr & 0xF800) >> 11) { case 26: case 27: if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ @@ -3537,7 +3509,7 @@ static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_s *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); break; default: - ret = t_undefined; + ret = ThumbDecodeStatus::UNDEFINED; break; } } @@ -3549,10 +3521,6 @@ enum { FETCH_EXCEPTION }; -typedef struct instruction_set_encoding_item ISEITEM; - -extern const ISEITEM arm_instruction[]; - static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { Common::Profiling::ScopeTimer timer_decode(profile_decode); @@ -3574,20 +3542,19 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { inst = Memory::Read32(phys_addr & 0xFFFFFFFC); size++; - // If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction + // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction if (cpu->TFlag) { uint32_t arm_inst; - tdstate state = decode_thumb_instr(inst, phys_addr, &arm_inst, &inst_size, &inst_base); + ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); - // We have translated the branch instruction of thumb in thumb decoder - if(state == t_branch){ + // We have translated the Thumb branch instruction in the Thumb decoder + if (state == ThumbDecodeStatus::BRANCH) { goto translated; } inst = arm_inst; } - ret = decode_arm_instr(inst, &idx); - if (ret == DECODE_FAILURE) { + 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]); @@ -3919,7 +3886,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { #endif arm_inst* inst_base; unsigned int addr; - unsigned int phys_addr; unsigned int num_instrs = 0; int ptr; @@ -3938,8 +3904,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { else cpu->Reg[15] &= 0xfffffffc; - phys_addr = cpu->Reg[15]; - // Find the cached instruction cream, otherwise translate it... auto itr = cpu->instruction_cache.find(cpu->Reg[15]); if (itr != cpu->instruction_cache.end()) { @@ -3957,14 +3921,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { adc_inst* const inst_cream = (adc_inst*)inst_base->component; + u32 rn_val = RN; + if (inst_cream->Rn == 15) + rn_val += 2 * cpu->GetInstructionSize(); + bool carry; bool overflow; - RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); + RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -3978,7 +3946,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(adc_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -3990,7 +3958,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 rn_val = RN; if (inst_cream->Rn == 15) - rn_val += 2 * GET_INST_SIZE(cpu); + rn_val += 2 * cpu->GetInstructionSize(); bool carry; bool overflow; @@ -3999,7 +3967,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Cpsr & 0x1f); + cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -4013,22 +3981,28 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(add_inst)); FETCH_INST; GOTO_NEXT_INST; } AND_INST: { - and_inst *inst_cream = (and_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + and_inst* const inst_cream = (and_inst*)inst_base->component; + u32 lop = RN; u32 rop = SHIFTER_OPERAND; + + if (inst_cream->Rn == 15) + lop += 2 * cpu->GetInstructionSize(); + RD = lop & rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Cpsr & 0x1f); + cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -4041,7 +4015,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(and_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4057,7 +4031,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { INC_PC(sizeof(bbl_inst)); goto DISPATCH; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(bbl_inst)); goto DISPATCH; } @@ -4067,14 +4041,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { u32 lop = RN; if (inst_cream->Rn == 15) { - lop += 2 * GET_INST_SIZE(cpu); + lop += 2 * cpu->GetInstructionSize(); } u32 rop = SHIFTER_OPERAND; RD = lop & (~rop); if ((inst_cream->S) && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -4087,7 +4061,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(bic_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4098,7 +4072,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(bkpt_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4109,13 +4083,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { unsigned int inst = inst_cream->inst; if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { - cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu)); + cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); if(cpu->TFlag) cpu->Reg[14] |= 0x1; cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe; cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1; } else { - cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu)); + cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); cpu->TFlag = 0x1; int signed_int = inst_cream->val.signed_immed_24; signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int; @@ -4125,7 +4099,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { INC_PC(sizeof(blx_inst)); goto DISPATCH; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(blx_inst)); goto DISPATCH; } @@ -4147,7 +4121,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 address = RM; if (inst_cream->Rm == 15) - address += 2 * GET_INST_SIZE(cpu); + address += 2 * cpu->GetInstructionSize(); cpu->TFlag = address & 1; cpu->Reg[15] = address & 0xfffffffe; @@ -4155,7 +4129,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(bx_inst)); goto DISPATCH; } @@ -4167,7 +4141,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->NumInstrsToExecute = 0; return num_instrs; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(cdp_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4175,10 +4149,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { CLREX_INST: { - remove_exclusive(cpu, 0); - cpu->exclusive_state = 0; - - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->UnsetExclusiveMemoryAddress(); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(clrex_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4189,7 +4161,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { clz_inst* inst_cream = (clz_inst*)inst_base->component; RD = clz(RM); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(clz_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4199,16 +4171,20 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; + u32 rn_val = RN; + if (inst_cream->Rn == 15) + rn_val += 2 * cpu->GetInstructionSize(); + bool carry; bool overflow; - u32 result = AddWithCarry(RN, SHIFTER_OPERAND, 0, &carry, &overflow); + u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); UPDATE_NFLAG(result); UPDATE_ZFLAG(result); cpu->CFlag = carry; cpu->VFlag = overflow; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(cmn_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4220,7 +4196,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 rn_val = RN; if (inst_cream->Rn == 15) - rn_val += 2 * GET_INST_SIZE(cpu); + rn_val += 2 * cpu->GetInstructionSize(); bool carry; bool overflow; @@ -4231,7 +4207,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->CFlag = carry; cpu->VFlag = overflow; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(cmp_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4241,7 +4217,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cps_inst *inst_cream = (cps_inst *)inst_base->component; uint32_t aif_val = 0; uint32_t aif_mask = 0; - if (InAPrivilegedMode(cpu)) { + if (cpu->InAPrivilegedMode()) { if (inst_cream->imod1) { if (inst_cream->A) { aif_val |= (inst_cream->imod0 << 8); @@ -4260,10 +4236,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } if (inst_cream->mmod) { cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode; - switch_mode(cpu, inst_cream->mode); + cpu->ChangePrivilegeMode(inst_cream->mode); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(cps_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4279,7 +4255,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mov_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4291,14 +4267,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 lop = RN; if (inst_cream->Rn == 15) { - lop += 2 * GET_INST_SIZE(cpu); + lop += 2 * cpu->GetInstructionSize(); } u32 rop = SHIFTER_OPERAND; RD = lop ^ rop; if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -4311,7 +4287,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(eor_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4320,7 +4296,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { { // Instruction not implemented //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldc_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4335,30 +4311,30 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (BIT(inst, 22) && !BIT(inst, 15)) { for (int i = 0; i < 13; i++) { if(BIT(inst, i)) { - cpu->Reg[i] = ReadMemory32(cpu, addr); + cpu->Reg[i] = cpu->ReadMemory32(addr); addr += 4; } } if (BIT(inst, 13)) { if (cpu->Mode == USER32MODE) - cpu->Reg[13] = ReadMemory32(cpu, addr); + cpu->Reg[13] = cpu->ReadMemory32(addr); else - cpu->Reg_usr[0] = ReadMemory32(cpu, addr); + cpu->Reg_usr[0] = cpu->ReadMemory32(addr); addr += 4; } if (BIT(inst, 14)) { if (cpu->Mode == USER32MODE) - cpu->Reg[14] = ReadMemory32(cpu, addr); + cpu->Reg[14] = cpu->ReadMemory32(addr); else - cpu->Reg_usr[1] = ReadMemory32(cpu, addr); + cpu->Reg_usr[1] = cpu->ReadMemory32(addr); addr += 4; } } else if (!BIT(inst, 22)) { for(int i = 0; i < 16; i++ ){ if(BIT(inst, i)){ - unsigned int ret = ReadMemory32(cpu, addr); + unsigned int ret = cpu->ReadMemory32(addr); // For armv5t, should enter thumb when bits[0] is non-zero. if(i == 15){ @@ -4373,18 +4349,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } else if (BIT(inst, 22) && BIT(inst, 15)) { for(int i = 0; i < 15; i++ ){ if(BIT(inst, i)){ - cpu->Reg[i] = ReadMemory32(cpu, addr); + cpu->Reg[i] = cpu->ReadMemory32(addr); addr += 4; } } if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Cpsr & 0x1f); + cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); LOAD_NZCVT; } - cpu->Reg[15] = ReadMemory32(cpu, addr); + cpu->Reg[15] = cpu->ReadMemory32(addr); } if (BIT(inst, 15)) { @@ -4392,7 +4368,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4410,7 +4386,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } RD = operand2; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(sxth_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4420,7 +4396,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst *inst_cream = (ldst_inst *)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - unsigned int value = ReadMemory32(cpu, addr); + unsigned int value = cpu->ReadMemory32(addr); cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; if (BITS(inst_cream->inst, 12, 15) == 15) { @@ -4431,7 +4407,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4442,7 +4418,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst *inst_cream = (ldst_inst *)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - unsigned int value = ReadMemory32(cpu, addr); + unsigned int value = cpu->ReadMemory32(addr); cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; if (BITS(inst_cream->inst, 12, 15) == 15) { @@ -4453,7 +4429,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4464,7 +4440,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { uxth_inst* inst_cream = (uxth_inst*)inst_base->component; RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(uxth_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4477,7 +4453,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = RN + operand2; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(uxtah_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4495,7 +4471,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4513,7 +4489,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4527,8 +4503,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { // The 3DS doesn't have LPAE (Large Physical Access Extension), so it // wouldn't do this as a single read. - cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = ReadMemory32(cpu, addr); - cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = ReadMemory32(cpu, addr + 4); + cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr); + cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4); // No dispatch since this operation should not modify R15 } @@ -4544,16 +4520,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; unsigned int read_addr = RN; - add_exclusive_addr(cpu, read_addr); - cpu->exclusive_state = 1; + cpu->SetExclusiveMemoryAddress(read_addr); - RD = ReadMemory32(cpu, read_addr); + RD = cpu->ReadMemory32(read_addr); if (inst_cream->Rd == 15) { INC_PC(sizeof(generic_arm_inst)); goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4564,8 +4539,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; unsigned int read_addr = RN; - add_exclusive_addr(cpu, read_addr); - cpu->exclusive_state = 1; + cpu->SetExclusiveMemoryAddress(read_addr); RD = Memory::Read8(read_addr); if (inst_cream->Rd == 15) { @@ -4573,7 +4547,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4584,16 +4558,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; unsigned int read_addr = RN; - add_exclusive_addr(cpu, read_addr); - cpu->exclusive_state = 1; + cpu->SetExclusiveMemoryAddress(read_addr); - RD = ReadMemory16(cpu, read_addr); + RD = cpu->ReadMemory16(read_addr); if (inst_cream->Rd == 15) { INC_PC(sizeof(generic_arm_inst)); goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4604,18 +4577,17 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; unsigned int read_addr = RN; - add_exclusive_addr(cpu, read_addr); - cpu->exclusive_state = 1; + cpu->SetExclusiveMemoryAddress(read_addr); - RD = ReadMemory32(cpu, read_addr); - RD2 = ReadMemory32(cpu, read_addr + 4); + RD = cpu->ReadMemory32(read_addr); + RD2 = cpu->ReadMemory32(read_addr + 4); if (inst_cream->Rd == 15) { INC_PC(sizeof(generic_arm_inst)); goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4626,13 +4598,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ReadMemory16(cpu, addr); + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr); if (BITS(inst_cream->inst, 12, 15) == 15) { INC_PC(sizeof(ldst_inst)); goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4652,7 +4624,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4663,7 +4635,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - unsigned int value = ReadMemory16(cpu, addr); + unsigned int value = cpu->ReadMemory16(addr); if (BIT(value, 15)) { value |= 0xffff0000; } @@ -4673,7 +4645,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4684,7 +4656,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - unsigned int value = ReadMemory32(cpu, addr); + unsigned int value = cpu->ReadMemory32(addr); cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; if (BITS(inst_cream->inst, 12, 15) == 15) { @@ -4692,7 +4664,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4707,10 +4679,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { DEBUG_MSG; } else { if (inst_cream->cp_num == 15) - WriteCP15Register(cpu, RD, CRn, OPCODE_1, CRm, OPCODE_2); + cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mcr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4727,7 +4699,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mcrr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4752,7 +4724,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mla_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4766,7 +4738,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -4779,7 +4751,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mov_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4800,10 +4772,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto END; } else { if (inst_cream->cp_num == 15) - RD = ReadCP15Register(cpu, CRn, OPCODE_1, CRm, OPCODE_2); + RD = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mrc_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4820,7 +4792,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mcrr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4838,7 +4810,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = cpu->Cpsr; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mrs_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4861,7 +4833,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); uint32_t mask = 0; if (!inst_cream->R) { - if (InAPrivilegedMode(cpu)) { + if (cpu->InAPrivilegedMode()) { if ((operand & StateMask) != 0) { /// UNPREDICTABLE DEBUG_MSG; @@ -4873,7 +4845,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { SAVE_NZCVT; cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); - switch_mode(cpu, cpu->Cpsr & 0x1f); + cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); LOAD_NZCVT; } else { if (CurrentModeHasSPSR) { @@ -4882,7 +4854,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(msr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4904,7 +4876,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mul_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4919,7 +4891,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -4932,7 +4904,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mvn_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4944,12 +4916,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 lop = RN; u32 rop = SHIFTER_OPERAND; + + if (inst_cream->Rn == 15) + lop += 2 * cpu->GetInstructionSize(); + RD = lop | rop; if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -4962,7 +4938,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(orr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4970,7 +4946,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { NOP_INST: { - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC_STUB; FETCH_INST; GOTO_NEXT_INST; @@ -4982,7 +4958,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { pkh_inst *inst_cream = (pkh_inst *)inst_base->component; RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(pkh_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -4995,7 +4971,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { int shift_imm = inst_cream->imm ? inst_cream->imm : 31; RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(pkh_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5005,7 +4981,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { { // Not implemented. PLD is a hint instruction, so it's optional. - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(pld_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5078,7 +5054,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = result; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5140,7 +5116,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5173,7 +5149,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(rev_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5187,8 +5163,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 address = 0; inst_cream->get_addr(cpu, inst_cream->inst, address); - cpu->Cpsr = ReadMemory32(cpu, address); - cpu->Reg[15] = ReadMemory32(cpu, address + 4); + cpu->Cpsr = cpu->ReadMemory32(address); + cpu->Reg[15] = cpu->ReadMemory32(address + 4); INC_PC(sizeof(ldst_inst)); goto DISPATCH; @@ -5201,7 +5177,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 rn_val = RN; if (inst_cream->Rn == 15) - rn_val += 2 * GET_INST_SIZE(cpu); + rn_val += 2 * cpu->GetInstructionSize(); bool carry; bool overflow; @@ -5210,7 +5186,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -5224,7 +5200,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(rsb_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5234,14 +5210,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; + u32 rn_val = RN; + if (inst_cream->Rn == 15) + rn_val += 2 * cpu->GetInstructionSize(); + bool carry; bool overflow; - RD = AddWithCarry(~RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); + RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -5255,7 +5235,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(rsc_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5363,7 +5343,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5374,14 +5354,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; + u32 rn_val = RN; + if (inst_cream->Rn == 15) + rn_val += 2 * cpu->GetInstructionSize(); + bool carry; bool overflow; - RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); + RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -5395,7 +5379,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(sbc_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5434,7 +5418,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = result; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5453,7 +5437,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(setend_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5466,7 +5450,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { LOG_TRACE(Core_ARM11, "SEV executed."); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC_STUB; FETCH_INST; GOTO_NEXT_INST; @@ -5538,7 +5522,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5563,7 +5547,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (AddOverflow(operand1 * operand2, RN, RD)) cpu->Cpsr |= (1 << 27); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(smla_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5619,7 +5603,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(smlad_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5648,7 +5632,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->ZFlag = (RDHI == 0 && RDLO == 0); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(umlal_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5678,7 +5662,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RDHI = ((dest >> 32) & 0xFFFFFFFF); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(smlalxy_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5703,7 +5687,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->Cpsr |= (1 << 27); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(smlad_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5741,7 +5725,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RDHI = ((result >> 32) & 0xFFFFFFFF); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(smlald_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5777,7 +5761,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = ((result >> 32) & 0xFFFFFFFF); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(smlad_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5799,7 +5783,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); RD = operand1 * operand2; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(smul_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5825,7 +5809,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->ZFlag = (RDHI == 0 && RDLO == 0); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(umull_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5841,7 +5825,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { s64 result = (s64)rm * (s64)(s32)RN; RD = BITS(result, 16, 47); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(smlad_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5855,10 +5839,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 address = 0; inst_cream->get_addr(cpu, inst_cream->inst, address); - WriteMemory32(cpu, address + 0, cpu->Reg[14]); - WriteMemory32(cpu, address + 4, cpu->Spsr_copy); + cpu->WriteMemory32(address + 0, cpu->Reg[14]); + cpu->WriteMemory32(address + 4, cpu->Spsr_copy); - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5891,7 +5875,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = rn_val; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ssat_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5913,7 +5897,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->Cpsr |= (1 << 27); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ssat_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5923,7 +5907,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { { // Instruction not implemented //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(stc_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5941,36 +5925,36 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (BIT(inst_cream->inst, 22) == 1) { for (int i = 0; i < 13; i++) { if (BIT(inst_cream->inst, i)) { - WriteMemory32(cpu, addr, cpu->Reg[i]); + cpu->WriteMemory32(addr, cpu->Reg[i]); addr += 4; } } if (BIT(inst_cream->inst, 13)) { if (cpu->Mode == USER32MODE) - WriteMemory32(cpu, addr, cpu->Reg[13]); + cpu->WriteMemory32(addr, cpu->Reg[13]); else - WriteMemory32(cpu, addr, cpu->Reg_usr[0]); + cpu->WriteMemory32(addr, cpu->Reg_usr[0]); addr += 4; } if (BIT(inst_cream->inst, 14)) { if (cpu->Mode == USER32MODE) - WriteMemory32(cpu, addr, cpu->Reg[14]); + cpu->WriteMemory32(addr, cpu->Reg[14]); else - WriteMemory32(cpu, addr, cpu->Reg_usr[1]); + cpu->WriteMemory32(addr, cpu->Reg_usr[1]); addr += 4; } if (BIT(inst_cream->inst, 15)) { - WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8); + cpu->WriteMemory32(addr, cpu->Reg_usr[1] + 8); } } else { for (int i = 0; i < 15; i++) { if (BIT(inst_cream->inst, i)) { if (i == Rn) - WriteMemory32(cpu, addr, old_RN); + cpu->WriteMemory32(addr, old_RN); else - WriteMemory32(cpu, addr, cpu->Reg[i]); + cpu->WriteMemory32(addr, cpu->Reg[i]); addr += 4; } @@ -5978,10 +5962,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { // Check PC reg if (BIT(inst_cream->inst, 15)) - WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8); + cpu->WriteMemory32(addr, cpu->Reg_usr[1] + 8); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -5999,7 +5983,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } RD = operand2; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(sxtb_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6011,9 +5995,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { inst_cream->get_addr(cpu, inst_cream->inst, addr); unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; - WriteMemory32(cpu, addr, value); + cpu->WriteMemory32(addr, value); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6024,7 +6008,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component; RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(uxtb_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6037,7 +6021,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; RD = RN + operand2; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(uxtab_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6050,7 +6034,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; Memory::Write8(addr, value); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6063,7 +6047,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; Memory::Write8(addr, value); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6076,10 +6060,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { // The 3DS doesn't have the Large Physical Access Extension (LPAE) // so STRD wouldn't store these as a single write. - WriteMemory32(cpu, addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]); - WriteMemory32(cpu, addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]); + cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]); + cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6090,18 +6074,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; unsigned int write_addr = cpu->Reg[inst_cream->Rn]; - if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { - remove_exclusive(cpu, write_addr); - cpu->exclusive_state = 0; - - WriteMemory32(cpu, write_addr, RM); + if (cpu->IsExclusiveMemoryAccess(write_addr)) { + cpu->UnsetExclusiveMemoryAddress(); + cpu->WriteMemory32(write_addr, RM); RD = 0; } else { // Failed to write due to mutex access RD = 1; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6112,10 +6094,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; unsigned int write_addr = cpu->Reg[inst_cream->Rn]; - if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { - remove_exclusive(cpu, write_addr); - cpu->exclusive_state = 0; - + if (cpu->IsExclusiveMemoryAccess(write_addr)) { + cpu->UnsetExclusiveMemoryAddress(); Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); RD = 0; } else { @@ -6123,7 +6103,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = 1; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6134,20 +6114,19 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; unsigned int write_addr = cpu->Reg[inst_cream->Rn]; - if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { - remove_exclusive(cpu, write_addr); - cpu->exclusive_state = 0; + if (cpu->IsExclusiveMemoryAccess(write_addr)) { + cpu->UnsetExclusiveMemoryAddress(); const u32 rt = cpu->Reg[inst_cream->Rm + 0]; const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; u64 value; - if (InBigEndianMode(cpu)) + if (cpu->InBigEndianMode()) value = (((u64)rt << 32) | rt2); else value = (((u64)rt2 << 32) | rt); - WriteMemory64(cpu, write_addr, value); + cpu->WriteMemory64(write_addr, value); RD = 0; } else { @@ -6155,7 +6134,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = 1; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6166,18 +6145,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; unsigned int write_addr = cpu->Reg[inst_cream->Rn]; - if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { - remove_exclusive(cpu, write_addr); - cpu->exclusive_state = 0; - - WriteMemory16(cpu, write_addr, RM); + if (cpu->IsExclusiveMemoryAccess(write_addr)) { + cpu->UnsetExclusiveMemoryAddress(); + cpu->WriteMemory16(write_addr, RM); RD = 0; } else { // Failed to write due to mutex access RD = 1; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6189,9 +6166,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { inst_cream->get_addr(cpu, inst_cream->inst, addr); unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; - WriteMemory16(cpu, addr, value); + cpu->WriteMemory16(addr, value); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6203,9 +6180,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { inst_cream->get_addr(cpu, inst_cream->inst, addr); unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; - WriteMemory32(cpu, addr, value); + cpu->WriteMemory32(addr, value); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6217,7 +6194,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 rn_val = RN; if (inst_cream->Rn == 15) - rn_val += 8; + rn_val += 2 * cpu->GetInstructionSize(); bool carry; bool overflow; @@ -6226,7 +6203,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; - switch_mode(cpu, cpu->Spsr_copy & 0x1f); + cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); LOAD_NZCVT; } } else if (inst_cream->S) { @@ -6240,7 +6217,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto DISPATCH; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(sub_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6252,7 +6229,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { SVC::CallSVC(inst_cream->num & 0xFFFF); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(swi_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6263,12 +6240,12 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { swp_inst* inst_cream = (swp_inst*)inst_base->component; addr = RN; - unsigned int value = ReadMemory32(cpu, addr); - WriteMemory32(cpu, addr, RM); + unsigned int value = cpu->ReadMemory32(addr); + cpu->WriteMemory32(addr, RM); RD = value; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(swp_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6282,7 +6259,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { Memory::Write8(addr, (RM & 0xFF)); RD = value; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(swp_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6298,7 +6275,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2; RD = RN + operand2; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(uxtab_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6331,7 +6308,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(sxtab_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6347,7 +6324,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2; RD = RN + operand2; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(sxtah_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6362,7 +6339,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 rop = SHIFTER_OPERAND; if (inst_cream->Rn == 15) - lop += GET_INST_SIZE(cpu) * 2; + lop += cpu->GetInstructionSize() * 2; u32 result = lop ^ rop; @@ -6370,7 +6347,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { UPDATE_ZFLAG(result); UPDATE_CFLAG_WITH_SC; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(teq_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6384,7 +6361,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { u32 rop = SHIFTER_OPERAND; if (inst_cream->Rn == 15) - lop += GET_INST_SIZE(cpu) * 2; + lop += cpu->GetInstructionSize() * 2; u32 result = lop & rop; @@ -6392,7 +6369,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { UPDATE_ZFLAG(result); UPDATE_CFLAG_WITH_SC; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(tst_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6563,7 +6540,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6643,7 +6620,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6662,7 +6639,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RDLO = (result & 0xFFFFFFFF); RDHI = ((result >> 32) & 0xFFFFFFFF); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(umaal_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6685,7 +6662,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->ZFlag = (RDHI == 0 && RDLO == 0); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(umlal_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6705,7 +6682,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->ZFlag = (RDHI == 0 && RDLO == 0); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(umull_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6733,7 +6710,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { { bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component; cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm; - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(bl_1_thumb)); FETCH_INST; GOTO_NEXT_INST; @@ -6814,7 +6791,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = ((lo_val & 0xFFFF) | hi_val << 16); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6844,7 +6821,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = finalDif; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6877,7 +6854,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { RD = rn_val; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ssat_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6899,7 +6876,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->Cpsr |= (1 << 27); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ssat_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6930,7 +6907,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(uxtab_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -6943,7 +6920,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { LOG_TRACE(Core_ARM11, "WFE executed."); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC_STUB; FETCH_INST; GOTO_NEXT_INST; @@ -6956,7 +6933,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { LOG_TRACE(Core_ARM11, "WFI executed."); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC_STUB; FETCH_INST; GOTO_NEXT_INST; @@ -6969,7 +6946,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { LOG_TRACE(Core_ARM11, "YIELD executed."); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC_STUB; FETCH_INST; GOTO_NEXT_INST; diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h index 1c324d29cc..7a46dcc940 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.h +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h @@ -4,6 +4,6 @@ #pragma once -#include "core/arm/skyeye_common/armdefs.h" +struct ARMul_State; unsigned InterpreterMainLoop(ARMul_State* state); diff --git a/src/core/arm/dyncom/arm_dyncom_run.cpp b/src/core/arm/dyncom/arm_dyncom_run.cpp deleted file mode 100644 index 5a9a6a788d..0000000000 --- a/src/core/arm/dyncom/arm_dyncom_run.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2012 Michael Kang, 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/arm/dyncom/arm_dyncom_run.h" -#include "core/arm/skyeye_common/armdefs.h" - -void switch_mode(ARMul_State* core, uint32_t mode) { - if (core->Mode == mode) - return; - - if (mode != USERBANK) { - switch (core->Mode) { - case SYSTEM32MODE: // Shares registers with user mode - case USER32MODE: - core->Reg_usr[0] = core->Reg[13]; - core->Reg_usr[1] = core->Reg[14]; - break; - case IRQ32MODE: - core->Reg_irq[0] = core->Reg[13]; - core->Reg_irq[1] = core->Reg[14]; - core->Spsr[IRQBANK] = core->Spsr_copy; - break; - case SVC32MODE: - core->Reg_svc[0] = core->Reg[13]; - core->Reg_svc[1] = core->Reg[14]; - core->Spsr[SVCBANK] = core->Spsr_copy; - break; - case ABORT32MODE: - core->Reg_abort[0] = core->Reg[13]; - core->Reg_abort[1] = core->Reg[14]; - core->Spsr[ABORTBANK] = core->Spsr_copy; - break; - case UNDEF32MODE: - core->Reg_undef[0] = core->Reg[13]; - core->Reg_undef[1] = core->Reg[14]; - core->Spsr[UNDEFBANK] = core->Spsr_copy; - break; - case FIQ32MODE: - core->Reg_firq[0] = core->Reg[13]; - core->Reg_firq[1] = core->Reg[14]; - core->Spsr[FIQBANK] = core->Spsr_copy; - break; - } - - switch (mode) { - case USER32MODE: - core->Reg[13] = core->Reg_usr[0]; - core->Reg[14] = core->Reg_usr[1]; - core->Bank = USERBANK; - break; - case IRQ32MODE: - core->Reg[13] = core->Reg_irq[0]; - core->Reg[14] = core->Reg_irq[1]; - core->Spsr_copy = core->Spsr[IRQBANK]; - core->Bank = IRQBANK; - break; - case SVC32MODE: - core->Reg[13] = core->Reg_svc[0]; - core->Reg[14] = core->Reg_svc[1]; - core->Spsr_copy = core->Spsr[SVCBANK]; - core->Bank = SVCBANK; - break; - case ABORT32MODE: - core->Reg[13] = core->Reg_abort[0]; - core->Reg[14] = core->Reg_abort[1]; - core->Spsr_copy = core->Spsr[ABORTBANK]; - core->Bank = ABORTBANK; - break; - case UNDEF32MODE: - core->Reg[13] = core->Reg_undef[0]; - core->Reg[14] = core->Reg_undef[1]; - core->Spsr_copy = core->Spsr[UNDEFBANK]; - core->Bank = UNDEFBANK; - break; - case FIQ32MODE: - core->Reg[13] = core->Reg_firq[0]; - core->Reg[14] = core->Reg_firq[1]; - core->Spsr_copy = core->Spsr[FIQBANK]; - core->Bank = FIQBANK; - break; - case SYSTEM32MODE: // Shares registers with user mode. - core->Reg[13] = core->Reg_usr[0]; - core->Reg[14] = core->Reg_usr[1]; - core->Bank = SYSTEMBANK; - break; - } - - // Set the mode bits in the APSR - core->Cpsr = (core->Cpsr & ~core->Mode) | mode; - core->Mode = mode; - } -} diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h index 85774c565d..13bef17fc3 100644 --- a/src/core/arm/dyncom/arm_dyncom_run.h +++ b/src/core/arm/dyncom/arm_dyncom_run.h @@ -18,40 +18,31 @@ #pragma once -#include "core/arm/skyeye_common/armdefs.h" - -void switch_mode(ARMul_State* core, uint32_t mode); - -// Note that for the 3DS, a Thumb instruction will only ever be -// two bytes in size. Thus we don't need to worry about ThumbEE -// or Thumb-2 where instructions can be 4 bytes in length. -static inline u32 GET_INST_SIZE(ARMul_State* core) { - return core->TFlag? 2 : 4; -} +#include "core/arm/skyeye_common/armstate.h" /** * Checks if the PC is being read, and if so, word-aligns it. * Used with address calculations. * - * @param core The ARM CPU state instance. + * @param cpu The ARM CPU state instance. * @param Rn The register being read. * * @return If the PC is being read, then the word-aligned PC value is returned. * If the PC is not being read, then the value stored in the register is returned. */ -static inline u32 CHECK_READ_REG15_WA(ARMul_State* core, int Rn) { - return (Rn == 15) ? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; +static inline u32 CHECK_READ_REG15_WA(ARMul_State* cpu, int Rn) { + return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn]; } /** * Reads the PC. Used for data processing operations that use the PC. * - * @param core The ARM CPU state instance. + * @param cpu The ARM CPU state instance. * @param Rn The register being read. * * @return If the PC is being read, then the incremented PC value is returned. * If the PC is not being read, then the values stored in the register is returned. */ -static inline u32 CHECK_READ_REG15(ARMul_State* core, int Rn) { - return (Rn == 15) ? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; +static inline u32 CHECK_READ_REG15(ARMul_State* cpu, int Rn) { + return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn]; } diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp index f10a5b70f9..29272fd5d2 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp +++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp @@ -6,20 +6,15 @@ // ARM instruction, and using the existing ARM simulator. #include "core/arm/dyncom/arm_dyncom_thumb.h" +#include "core/arm/skyeye_common/armsupp.h" // Decode a 16bit Thumb instruction. The instruction is in the low 16-bits of the tinstr field, // with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions // allows easier simulation of the special dual BL instruction. -tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { - tdstate valid = t_uninitialized; - ARMword tinstr = instr; - - // The endian should be judge here - if((addr & 0x3) != 0) - tinstr = instr >> 16; - else - tinstr &= 0xFFFF; +ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { + ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED; + u32 tinstr = GetThumbInstruction(instr, addr); *ainstr = 0xDEADC0DE; // Debugging to catch non updates @@ -36,7 +31,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { case 3: // ADD/SUB { - static const ARMword subset[4] = { + static const u32 subset[4] = { 0xE0900000, // ADDS Rd,Rs,Rn 0xE0500000, // SUBS Rd,Rs,Rn 0xE2900000, // ADDS Rd,Rs,#imm3 @@ -55,7 +50,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { case 6: // ADD case 7: // SUB { - static const ARMword subset[4] = { + static const u32 subset[4] = { 0xE3B00000, // MOVS Rd,#imm8 0xE3500000, // CMP Rd,#imm8 0xE2900000, // ADDS Rd,Rd,#imm8 @@ -84,7 +79,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { }; static const struct { - ARMword opcode; + u32 opcode; otype type; } subset[16] = { { 0xE0100000, t_norm }, // ANDS Rd,Rd,Rs @@ -129,8 +124,8 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { break; } } else { - ARMword Rd = ((tinstr & 0x0007) >> 0); - ARMword Rs = ((tinstr & 0x0078) >> 3); + u32 Rd = ((tinstr & 0x0007) >> 0); + u32 Rs = ((tinstr & 0x0078) >> 3); if (tinstr & (1 << 7)) Rd += 8; @@ -184,7 +179,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { case 10: case 11: { - static const ARMword subset[8] = { + static const u32 subset[8] = { 0xE7800000, // STR Rd,[Rb,Ro] 0xE18000B0, // STRH Rd,[Rb,Ro] 0xE7C00000, // STRB Rd,[Rb,Ro] @@ -207,7 +202,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { case 14: // STRB Rd,[Rb,#imm5] case 15: // LDRB Rd,[Rb,#imm5] { - static const ARMword subset[4] = { + static const u32 subset[4] = { 0xE5800000, // STR Rd,[Rb,#imm5] 0xE5900000, // LDR Rd,[Rb,#imm5] 0xE5C00000, // STRB Rd,[Rb,#imm5] @@ -274,7 +269,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | BITS(tinstr, 0, 3) // imm4 field; | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12 } else if ((tinstr & 0x0F00) == 0x0200) { - static const ARMword subset[4] = { + static const u32 subset[4] = { 0xE6BF0070, // SXTH 0xE6AF0070, // SXTB 0xE6FF0070, // UXTH @@ -298,7 +293,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | (BIT(tinstr, 4) << 18); // enable bit } } else if ((tinstr & 0x0F00) == 0x0a00) { - static const ARMword subset[3] = { + static const u32 subset[3] = { 0xE6BF0F30, // REV 0xE6BF0FB0, // REV16 0xE6FF0FB0, // REVSH @@ -308,7 +303,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | (BITS(tinstr, 0, 2) << 12) // Rd | BITS(tinstr, 3, 5); // Rm } else { - static const ARMword subset[4] = { + static const u32 subset[4] = { 0xE92D0000, // STMDB sp!,{rlist} 0xE92D4000, // STMDB sp!,{rlist,lr} 0xE8BD0000, // LDMIA sp!,{rlist} @@ -356,21 +351,21 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { else *ainstr |= (tinstr & 0x00FF); } else if ((tinstr & 0x0F00) != 0x0E00) - valid = t_branch; + valid = ThumbDecodeStatus::BRANCH; else // UNDEFINED : cc=1110(AL) uses different format - valid = t_undefined; + valid = ThumbDecodeStatus::UNDEFINED; break; case 28: // B - valid = t_branch; + valid = ThumbDecodeStatus::BRANCH; break; case 29: - if(tinstr & 0x1) - valid = t_undefined; + if (tinstr & 0x1) + valid = ThumbDecodeStatus::UNDEFINED; else - valid = t_branch; + valid = ThumbDecodeStatus::BRANCH; break; case 30: // BL instruction 1 @@ -379,7 +374,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { // simulation simple (from the user perspective) we check if the following instruction is // the second half of this BL, and if it is we simulate it immediately - valid = t_branch; + valid = ThumbDecodeStatus::BRANCH; break; case 31: // BL instruction 2 @@ -388,7 +383,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the // simulation of it on its own, with undefined results if r14 is not suitably initialised. - valid = t_branch; + valid = ThumbDecodeStatus::BRANCH; break; } diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h index 8394ff156e..4479743639 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.h +++ b/src/core/arm/dyncom/arm_dyncom_thumb.h @@ -26,22 +26,24 @@ #pragma once -#include "core/arm/skyeye_common/armdefs.h" +#include "common/common_types.h" -enum tdstate { - t_undefined, // Undefined Thumb instruction - t_decoded, // Instruction decoded to ARM equivalent - t_branch, // Thumb branch (already processed) - t_uninitialized, +enum class ThumbDecodeStatus { + UNDEFINED, // Undefined Thumb instruction + DECODED, // Instruction decoded to ARM equivalent + BRANCH, // Thumb branch (already processed) + UNINITIALIZED, }; -tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size); +// Translates a Thumb mode instruction into its ARM equivalent. +ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size); -static inline u32 get_thumb_instr(u32 instr, u32 pc) { - u32 tinstr; - if ((pc & 0x3) != 0) - tinstr = instr >> 16; - else - tinstr = instr & 0xFFFF; - return tinstr; +static inline u32 GetThumbInstruction(u32 instr, u32 address) { + // Normally you would need to handle instruction endianness, + // however, it is fixed to little-endian on the MPCore, so + // there's no need to check for this beforehand. + if ((address & 0x3) != 0) + return instr >> 16; + + return instr & 0xFFFF; } diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp deleted file mode 100644 index 4f7a48fab8..0000000000 --- a/src/core/arm/interpreter/arminit.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* arminit.c -- ARMulator initialization: ARM6 Instruction Emulator. - Copyright (C) 1994 Advanced RISC Machines Ltd. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include <cstring> -#include "core/arm/skyeye_common/armdefs.h" -#include "core/arm/skyeye_common/vfp/vfp.h" - -/***************************************************************************\ -* Returns a new instantiation of the ARMulator's state * -\***************************************************************************/ -ARMul_State* ARMul_NewState(ARMul_State* state) -{ - state->Emulate = RUN; - state->Mode = USER32MODE; - - state->lateabtSig = HIGH; - state->bigendSig = LOW; - - return state; -} - -/***************************************************************************\ -* Call this routine to set ARMulator to model a certain processor * -\***************************************************************************/ - -void ARMul_SelectProcessor(ARMul_State* state, unsigned properties) -{ - state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0; - state->is_v5 = (properties & ARM_v5_Prop) != 0; - state->is_v5e = (properties & ARM_v5e_Prop) != 0; - state->is_v6 = (properties & ARM_v6_Prop) != 0; - state->is_v7 = (properties & ARM_v7_Prop) != 0; -} - -// Resets certain MPCore CP15 values to their ARM-defined reset values. -static void ResetMPCoreCP15Registers(ARMul_State* cpu) -{ - // c0 - cpu->CP15[CP15_MAIN_ID] = 0x410FB024; - cpu->CP15[CP15_TLB_TYPE] = 0x00000800; - cpu->CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111; - cpu->CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001; - cpu->CP15[CP15_DEBUG_FEATURE_0] = 0x00000002; - cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103; - cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302; - cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000; - cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000; - cpu->CP15[CP15_ISA_FEATURE_0] = 0x00100011; - cpu->CP15[CP15_ISA_FEATURE_1] = 0x12002111; - cpu->CP15[CP15_ISA_FEATURE_2] = 0x11221011; - cpu->CP15[CP15_ISA_FEATURE_3] = 0x01102131; - cpu->CP15[CP15_ISA_FEATURE_4] = 0x00000141; - - // c1 - cpu->CP15[CP15_CONTROL] = 0x00054078; - cpu->CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F; - cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000; - - // c2 - cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000; - cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000; - cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000; - - // c3 - cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000; - - // c7 - cpu->CP15[CP15_PHYS_ADDRESS] = 0x00000000; - - // c9 - cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0; - - // c10 - cpu->CP15[CP15_TLB_LOCKDOWN] = 0x00000000; - cpu->CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4; - cpu->CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0; - - // c13 - cpu->CP15[CP15_PID] = 0x00000000; - cpu->CP15[CP15_CONTEXT_ID] = 0x00000000; - cpu->CP15[CP15_THREAD_UPRW] = 0x00000000; - cpu->CP15[CP15_THREAD_URO] = 0x00000000; - cpu->CP15[CP15_THREAD_PRW] = 0x00000000; - - // c15 - cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000; - cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000; - cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000; - cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000; - cpu->CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; -} - -/***************************************************************************\ -* Call this routine to set up the initial machine state (or perform a RESET * -\***************************************************************************/ -void ARMul_Reset(ARMul_State* state) -{ - VFPInit(state); - - state->Reg[15] = 0; - state->Cpsr = INTBITS | SVC32MODE; - state->Mode = SVC32MODE; - state->Bank = SVCBANK; - - ResetMPCoreCP15Registers(state); - - state->NresetSig = HIGH; - state->NfiqSig = HIGH; - state->NirqSig = HIGH; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - state->abortSig = LOW; - - state->NumInstrs = 0; -} diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp deleted file mode 100644 index 83f7f3e2c4..0000000000 --- a/src/core/arm/interpreter/armsupp.cpp +++ /dev/null @@ -1,637 +0,0 @@ -/* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator. - Copyright (C) 1994 Advanced RISC Machines Ltd. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "common/logging/log.h" - -#include "core/mem_map.h" -#include "core/arm/skyeye_common/armdefs.h" -#include "core/arm/skyeye_common/arm_regformat.h" - -// Unsigned sum of absolute difference -u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) -{ - if (left > right) - return left - right; - - return right - left; -} - -// Add with carry, indicates if a carry-out or signed overflow occurred. -u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) -{ - u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; - s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; - u64 result = (unsigned_sum & 0xFFFFFFFF); - - if (carry_out_occurred) - *carry_out_occurred = (result != unsigned_sum); - - if (overflow_occurred) - *overflow_occurred = ((s64)(s32)result != signed_sum); - - return (u32)result; -} - -// Compute whether an addition of A and B, giving RESULT, overflowed. -bool AddOverflow(ARMword a, ARMword b, ARMword result) -{ - return ((NEG(a) && NEG(b) && POS(result)) || - (POS(a) && POS(b) && NEG(result))); -} - -// Compute whether a subtraction of A and B, giving RESULT, overflowed. -bool SubOverflow(ARMword a, ARMword b, ARMword result) -{ - return ((NEG(a) && POS(b) && POS(result)) || - (POS(a) && NEG(b) && NEG(result))); -} - -// Returns true if the Q flag should be set as a result of overflow. -bool ARMul_AddOverflowQ(ARMword a, ARMword b) -{ - u32 result = a + b; - if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) - return true; - - return false; -} - -// 8-bit signed saturated addition -u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) -{ - u8 result = left + right; - - if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { - if (left & 0x80) - result = 0x80; - else - result = 0x7F; - } - - return result; -} - -// 8-bit signed saturated subtraction -u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) -{ - u8 result = left - right; - - if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { - if (left & 0x80) - result = 0x80; - else - result = 0x7F; - } - - return result; -} - -// 16-bit signed saturated addition -u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) -{ - u16 result = left + right; - - if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { - if (left & 0x8000) - result = 0x8000; - else - result = 0x7FFF; - } - - return result; -} - -// 16-bit signed saturated subtraction -u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) -{ - u16 result = left - right; - - if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { - if (left & 0x8000) - result = 0x8000; - else - result = 0x7FFF; - } - - return result; -} - -// 8-bit unsigned saturated addition -u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) -{ - u8 result = left + right; - - if (result < left) - result = 0xFF; - - return result; -} - -// 16-bit unsigned saturated addition -u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) -{ - u16 result = left + right; - - if (result < left) - result = 0xFFFF; - - return result; -} - -// 8-bit unsigned saturated subtraction -u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) -{ - if (left <= right) - return 0; - - return left - right; -} - -// 16-bit unsigned saturated subtraction -u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) -{ - if (left <= right) - return 0; - - return left - right; -} - -// Signed saturation. -u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) -{ - const u32 max = (1 << shift) - 1; - const s32 top = (value >> shift); - - if (top > 0) { - *saturation_occurred = true; - return max; - } - else if (top < -1) { - *saturation_occurred = true; - return ~max; - } - - *saturation_occurred = false; - return (u32)value; -} - -// Unsigned saturation -u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) -{ - const u32 max = (1 << shift) - 1; - - if (value < 0) { - *saturation_occurred = true; - return 0; - } else if ((u32)value > max) { - *saturation_occurred = true; - return max; - } - - *saturation_occurred = false; - return (u32)value; -} - -// Whether or not the given CPU is in big endian mode (E bit is set) -bool InBigEndianMode(ARMul_State* cpu) -{ - return (cpu->Cpsr & (1 << 9)) != 0; -} - -// Whether or not the given CPU is in a mode other than user mode. -bool InAPrivilegedMode(ARMul_State* cpu) -{ - return (cpu->Mode != USER32MODE); -} - -// Reads from the CP15 registers. Used with implementation of the MRC instruction. -// Note that since the 3DS does not have the hypervisor extensions, these registers -// are not implemented. -u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) -{ - // Unprivileged registers - if (crn == 13 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 2) - return cpu->CP15[CP15_THREAD_UPRW]; - - if (opcode_2 == 3) - return cpu->CP15[CP15_THREAD_URO]; - } - - if (InAPrivilegedMode(cpu)) - { - if (crn == 0 && opcode_1 == 0) - { - if (crm == 0) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_MAIN_ID]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_CACHE_TYPE]; - - if (opcode_2 == 3) - return cpu->CP15[CP15_TLB_TYPE]; - - if (opcode_2 == 5) - return cpu->CP15[CP15_CPU_ID]; - } - else if (crm == 1) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_PROCESSOR_FEATURE_0]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_PROCESSOR_FEATURE_1]; - - if (opcode_2 == 2) - return cpu->CP15[CP15_DEBUG_FEATURE_0]; - - if (opcode_2 == 4) - return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0]; - - if (opcode_2 == 5) - return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1]; - - if (opcode_2 == 6) - return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2]; - - if (opcode_2 == 7) - return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3]; - } - else if (crm == 2) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_ISA_FEATURE_0]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_ISA_FEATURE_1]; - - if (opcode_2 == 2) - return cpu->CP15[CP15_ISA_FEATURE_2]; - - if (opcode_2 == 3) - return cpu->CP15[CP15_ISA_FEATURE_3]; - - if (opcode_2 == 4) - return cpu->CP15[CP15_ISA_FEATURE_4]; - } - } - - if (crn == 1 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_CONTROL]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_AUXILIARY_CONTROL]; - - if (opcode_2 == 2) - return cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; - } - - if (crn == 2 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1]; - - if (opcode_2 == 2) - return cpu->CP15[CP15_TRANSLATION_BASE_CONTROL]; - } - - if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) - return cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL]; - - if (crn == 5 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_FAULT_STATUS]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_INSTR_FAULT_STATUS]; - } - - if (crn == 6 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_FAULT_ADDRESS]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_WFAR]; - } - - if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0) - return cpu->CP15[CP15_PHYS_ADDRESS]; - - if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) - return cpu->CP15[CP15_DATA_CACHE_LOCKDOWN]; - - if (crn == 10 && opcode_1 == 0) - { - if (crm == 0 && opcode_2 == 0) - return cpu->CP15[CP15_TLB_LOCKDOWN]; - - if (crm == 2) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_PRIMARY_REGION_REMAP]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_NORMAL_REGION_REMAP]; - } - } - - if (crn == 13 && crm == 0) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_PID]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_CONTEXT_ID]; - - if (opcode_2 == 4) - return cpu->CP15[CP15_THREAD_PRW]; - } - - if (crn == 15) - { - if (opcode_1 == 0 && crm == 12) - { - if (opcode_2 == 0) - return cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; - - if (opcode_2 == 1) - return cpu->CP15[CP15_CYCLE_COUNTER]; - - if (opcode_2 == 2) - return cpu->CP15[CP15_COUNT_0]; - - if (opcode_2 == 3) - return cpu->CP15[CP15_COUNT_1]; - } - - if (opcode_1 == 5 && opcode_2 == 2) - { - if (crm == 5) - return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; - - if (crm == 6) - return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS]; - - if (crm == 7) - return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE]; - } - - if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) - return cpu->CP15[CP15_TLB_DEBUG_CONTROL]; - } - } - - LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); - return 0; -} - -// Write to the CP15 registers. Used with implementation of the MCR instruction. -// Note that since the 3DS does not have the hypervisor extensions, these registers -// are not implemented. -void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) -{ - if (InAPrivilegedMode(cpu)) - { - if (crn == 1 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - cpu->CP15[CP15_CONTROL] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_AUXILIARY_CONTROL] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; - } - else if (crn == 2 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = value; - } - else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) - { - cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; - } - else if (crn == 5 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - cpu->CP15[CP15_FAULT_STATUS] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_INSTR_FAULT_STATUS] = value; - } - else if (crn == 6 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - cpu->CP15[CP15_FAULT_ADDRESS] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_WFAR] = value; - } - else if (crn == 7 && opcode_1 == 0) - { - if (crm == 0 && opcode_2 == 4) - { - cpu->CP15[CP15_WAIT_FOR_INTERRUPT] = value; - } - else if (crm == 4 && opcode_2 == 0) - { - // NOTE: Not entirely accurate. This should do permission checks. - cpu->CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); - } - else if (crm == 5) - { - if (opcode_2 == 0) - cpu->CP15[CP15_INVALIDATE_INSTR_CACHE] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value; - else if (opcode_2 == 6) - cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; - else if (opcode_2 == 7) - cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; - } - else if (crm == 6) - { - if (opcode_2 == 0) - cpu->CP15[CP15_INVALIDATE_DATA_CACHE] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; - } - else if (crm == 7 && opcode_2 == 0) - { - cpu->CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; - } - else if (crm == 10) - { - if (opcode_2 == 0) - cpu->CP15[CP15_CLEAN_DATA_CACHE] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; - } - else if (crm == 14) - { - if (opcode_2 == 0) - cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; - } - } - else if (crn == 8 && opcode_1 == 0) - { - LOG_WARNING(Core_ARM11, "TLB operations not fully implemented."); - - if (crm == 5) - { - if (opcode_2 == 0) - cpu->CP15[CP15_INVALIDATE_ITLB] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; - else if (opcode_2 == 3) - cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; - } - else if (crm == 6) - { - if (opcode_2 == 0) - cpu->CP15[CP15_INVALIDATE_DTLB] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; - else if (opcode_2 == 3) - cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; - } - else if (crm == 7) - { - if (opcode_2 == 0) - cpu->CP15[CP15_INVALIDATE_UTLB] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value; - else if (opcode_2 == 3) - cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; - } - } - else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) - { - cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = value; - } - else if (crn == 10 && opcode_1 == 0) - { - if (crm == 0 && opcode_2 == 0) - { - cpu->CP15[CP15_TLB_LOCKDOWN] = value; - } - else if (crm == 2) - { - if (opcode_2 == 0) - cpu->CP15[CP15_PRIMARY_REGION_REMAP] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_NORMAL_REGION_REMAP] = value; - } - } - else if (crn == 13 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - cpu->CP15[CP15_PID] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_CONTEXT_ID] = value; - else if (opcode_2 == 3) - cpu->CP15[CP15_THREAD_URO] = value; - else if (opcode_2 == 4) - cpu->CP15[CP15_THREAD_PRW] = value; - } - else if (crn == 15) - { - if (opcode_1 == 0 && crm == 12) - { - if (opcode_2 == 0) - cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; - else if (opcode_2 == 1) - cpu->CP15[CP15_CYCLE_COUNTER] = value; - else if (opcode_2 == 2) - cpu->CP15[CP15_COUNT_0] = value; - else if (opcode_2 == 3) - cpu->CP15[CP15_COUNT_1] = value; - } - else if (opcode_1 == 5) - { - if (crm == 4) - { - if (opcode_2 == 2) - cpu->CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; - else if (opcode_2 == 4) - cpu->CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; - } - else if (crm == 5 && opcode_2 == 2) - { - cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; - } - else if (crm == 6 && opcode_2 == 2) - { - cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; - } - else if (crm == 7 && opcode_2 == 2) - { - cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; - } - } - else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) - { - cpu->CP15[CP15_TLB_DEBUG_CONTROL] = value; - } - } - } - - // Unprivileged registers - if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) - { - cpu->CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; - } - else if (crn == 7 && opcode_1 == 0 && crm == 10) - { - if (opcode_2 == 4) - cpu->CP15[CP15_DATA_SYNC_BARRIER] = value; - else if (opcode_2 == 5) - cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value; - - } - else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) - { - cpu->CP15[CP15_THREAD_UPRW] = value; - } -} diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h deleted file mode 100644 index d2c901100a..0000000000 --- a/src/core/arm/skyeye_common/armdefs.h +++ /dev/null @@ -1,318 +0,0 @@ -/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator. - Copyright (C) 1994 Advanced RISC Machines Ltd. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#pragma once - -#include <unordered_map> - -#include "common/common_types.h" -#include "core/arm/skyeye_common/arm_regformat.h" - -#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) -#define BIT(s, n) ((s >> (n)) & 1) - -// Signal levels -enum { - LOW = 0, - HIGH = 1, - LOWHIGH = 1, - HIGHLOW = 2 -}; - -// Cache types -enum { - NONCACHE = 0, - DATACACHE = 1, - INSTCACHE = 2, -}; - -// Abort models -enum { - ABORT_BASE_RESTORED = 0, - ABORT_EARLY = 1, - ABORT_BASE_UPDATED = 2 -}; - -#define POS(i) ( (~(i)) >> 31 ) -#define NEG(i) ( (i) >> 31 ) - -typedef u64 ARMdword; // must be 64 bits wide -typedef u32 ARMword; // must be 32 bits wide -typedef u16 ARMhword; // must be 16 bits wide -typedef u8 ARMbyte; // must be 8 bits wide - -#define VFP_REG_NUM 64 -struct ARMul_State -{ - ARMword Emulate; // To start and stop emulation - - // Order of the following register should not be modified - ARMword Reg[16]; // The current register file - ARMword Cpsr; // The current PSR - ARMword Spsr_copy; - ARMword phys_pc; - ARMword Reg_usr[2]; - ARMword Reg_svc[2]; // R13_SVC R14_SVC - ARMword Reg_abort[2]; // R13_ABORT R14_ABORT - ARMword Reg_undef[2]; // R13 UNDEF R14 UNDEF - ARMword Reg_irq[2]; // R13_IRQ R14_IRQ - ARMword Reg_firq[7]; // R8---R14 FIRQ - ARMword Spsr[7]; // The exception psr's - ARMword Mode; // The current mode - ARMword Bank; // The current register bank - ARMword exclusive_tag; // The address for which the local monitor is in exclusive access mode - ARMword exclusive_state; - ARMword exclusive_result; - ARMword CP15[CP15_REGISTER_COUNT]; - - // FPSID, FPSCR, and FPEXC - ARMword VFP[VFP_SYSTEM_REGISTER_COUNT]; - // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31). - // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31), - // and only 32 singleword registers are accessible (S0-S31). - ARMword ExtReg[VFP_REG_NUM]; - /* ---- End of the ordered registers ---- */ - - ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed - unsigned int shifter_carry_out; - - // Add armv6 flags dyf:2010-08-09 - ARMword GEFlag, EFlag, AFlag, QFlag; - - ARMword TFlag; // Thumb state - - unsigned long long NumInstrs; // The number of instructions executed - unsigned NumInstrsToExecute; - - unsigned NresetSig; // Reset the processor - unsigned NfiqSig; - unsigned NirqSig; - - unsigned abortSig; - unsigned NtransSig; - unsigned bigendSig; - unsigned syscallSig; - -/* 2004-05-09 chy ----------------------------------------------------------- -read ARM Architecture Reference Manual -2.6.5 Data Abort -There are three Abort Model in ARM arch. - -Early Abort Model: used in some ARMv3 and earlier implementations. In this -model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and -the base register was unchanged for all other instructions. (oldest) - -Base Restored Abort Model: If a Data Abort occurs in an instruction which -specifies base register writeback, the value in the base register is -unchanged. (strongarm, xscale) - -Base Updated Abort Model: If a Data Abort occurs in an instruction which -specifies base register writeback, the base register writeback still occurs. -(arm720T) - -read PART B -chap2 The System Control Coprocessor CP15 -2.4 Register1:control register -L(bit 6): in some ARMv3 and earlier implementations, the abort model of the -processor could be configured: -0=early Abort Model Selected(now obsolete) -1=Late Abort Model selceted(same as Base Updated Abort Model) - -on later processors, this bit reads as 1 and ignores writes. -------------------------------------------------------------- -So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model) - if lateabtSig=0, then it means Base Restored Abort Model -*/ - unsigned lateabtSig; - - // For differentiating ARM core emulaiton. - bool is_v4; // Are we emulating a v4 architecture (or higher)? - bool is_v5; // Are we emulating a v5 architecture? - bool is_v5e; // Are we emulating a v5e architecture? - bool is_v6; // Are we emulating a v6 architecture? - bool is_v7; // Are we emulating a v7 architecture? - - // ARM_ARM A2-18 - // 0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model - int abort_model; - - // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per - // process for our purposes), not per ARMul_State (which tracks CPU core state). - std::unordered_map<u32, int> instruction_cache; -}; - -/***************************************************************************\ -* Types of ARM we know about * -\***************************************************************************/ - -enum { - ARM_v4_Prop = 0x01, - ARM_v5_Prop = 0x02, - ARM_v5e_Prop = 0x04, - ARM_v6_Prop = 0x08, - ARM_v7_Prop = 0x10, -}; - -/***************************************************************************\ -* The hardware vector addresses * -\***************************************************************************/ - -enum { - ARMResetV = 0, - ARMUndefinedInstrV = 4, - ARMSWIV = 8, - ARMPrefetchAbortV = 12, - ARMDataAbortV = 16, - ARMAddrExceptnV = 20, - ARMIRQV = 24, - ARMFIQV = 28, - ARMErrorV = 32, // This is an offset, not an address! - - ARMul_ResetV = ARMResetV, - ARMul_UndefinedInstrV = ARMUndefinedInstrV, - ARMul_SWIV = ARMSWIV, - ARMul_PrefetchAbortV = ARMPrefetchAbortV, - ARMul_DataAbortV = ARMDataAbortV, - ARMul_AddrExceptnV = ARMAddrExceptnV, - ARMul_IRQV = ARMIRQV, - ARMul_FIQV = ARMFIQV -}; - -/***************************************************************************\ -* Mode and Bank Constants * -\***************************************************************************/ - -enum PrivilegeMode { - USER32MODE = 16, - FIQ32MODE = 17, - IRQ32MODE = 18, - SVC32MODE = 19, - ABORT32MODE = 23, - UNDEF32MODE = 27, - SYSTEM32MODE = 31 -}; - -enum { - USERBANK = 0, - FIQBANK = 1, - IRQBANK = 2, - SVCBANK = 3, - ABORTBANK = 4, - UNDEFBANK = 5, - DUMMYBANK = 6, - SYSTEMBANK = 7 -}; - -/***************************************************************************\ -* Definitons of things in the emulator * -\***************************************************************************/ -extern void ARMul_Reset(ARMul_State* state); -extern ARMul_State* ARMul_NewState(ARMul_State* state); - -/***************************************************************************\ -* Definitons of things in the co-processor interface * -\***************************************************************************/ - -enum { - ARMul_FIRST = 0, - ARMul_TRANSFER = 1, - ARMul_BUSY = 2, - ARMul_DATA = 3, - ARMul_INTERRUPT = 4, - ARMul_DONE = 0, - ARMul_CANT = 1, - ARMul_INC = 3 -}; - -/***************************************************************************\ -* Definitons of things in the host environment * -\***************************************************************************/ - -enum ConditionCode { - EQ = 0, - NE = 1, - CS = 2, - CC = 3, - MI = 4, - PL = 5, - VS = 6, - VC = 7, - HI = 8, - LS = 9, - GE = 10, - LT = 11, - GT = 12, - LE = 13, - AL = 14, - NV = 15, -}; - -// Flags for use with the APSR. -enum : u32 { - NBIT = (1U << 31U), - ZBIT = (1 << 30), - CBIT = (1 << 29), - VBIT = (1 << 28), - QBIT = (1 << 27), - JBIT = (1 << 24), - EBIT = (1 << 9), - ABIT = (1 << 8), - IBIT = (1 << 7), - FBIT = (1 << 6), - TBIT = (1 << 5), - - // Masks for groups of bits in the APSR. - MODEBITS = 0x1F, - INTBITS = 0x1C0, -}; - -// Values for Emulate. -enum { - STOP = 0, // Stop - CHANGEMODE = 1, // Change mode - ONCE = 2, // Execute just one iteration - RUN = 3 // Continuous execution -}; - - -extern bool AddOverflow(ARMword, ARMword, ARMword); -extern bool SubOverflow(ARMword, ARMword, ARMword); - -extern void ARMul_SelectProcessor(ARMul_State*, unsigned); - -extern u32 AddWithCarry(u32, u32, u32, bool*, bool*); -extern bool ARMul_AddOverflowQ(ARMword, ARMword); - -extern u8 ARMul_SignedSaturatedAdd8(u8, u8); -extern u8 ARMul_SignedSaturatedSub8(u8, u8); -extern u16 ARMul_SignedSaturatedAdd16(u16, u16); -extern u16 ARMul_SignedSaturatedSub16(u16, u16); - -extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8); -extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16); -extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); -extern u16 ARMul_UnsignedSaturatedSub16(u16, u16); -extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); -extern u32 ARMul_SignedSatQ(s32, u8, bool*); -extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); - -extern bool InBigEndianMode(ARMul_State*); -extern bool InAPrivilegedMode(ARMul_State*); - -extern u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); -extern void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h deleted file mode 100644 index c67d7209b7..0000000000 --- a/src/core/arm/skyeye_common/armmmu.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - armmmu.c - Memory Management Unit emulation. - ARMulator extensions for the ARM7100 family. - Copyright (C) 1999 Ben Williamson - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#pragma once - -#include "common/swap.h" - -#include "core/memory.h" -#include "core/arm/skyeye_common/armdefs.h" - -// Register numbers in the MMU -enum -{ - MMU_ID = 0, - MMU_CONTROL = 1, - MMU_TRANSLATION_TABLE_BASE = 2, - MMU_DOMAIN_ACCESS_CONTROL = 3, - MMU_FAULT_STATUS = 5, - MMU_FAULT_ADDRESS = 6, - MMU_CACHE_OPS = 7, - MMU_TLB_OPS = 8, - MMU_CACHE_LOCKDOWN = 9, - MMU_TLB_LOCKDOWN = 10, - MMU_PID = 13, - - // MMU_V4 - MMU_V4_CACHE_OPS = 7, - MMU_V4_TLB_OPS = 8, - - // MMU_V3 - MMU_V3_FLUSH_TLB = 5, - MMU_V3_FLUSH_TLB_ENTRY = 6, - MMU_V3_FLUSH_CACHE = 7, -}; - -// Reads data in big/little endian format based on the -// state of the E (endian) bit in the emulated CPU's APSR. -inline u16 ReadMemory16(ARMul_State* cpu, u32 address) { - u16 data = Memory::Read16(address); - - if (InBigEndianMode(cpu)) - data = Common::swap16(data); - - return data; -} - -inline u32 ReadMemory32(ARMul_State* cpu, u32 address) { - u32 data = Memory::Read32(address); - - if (InBigEndianMode(cpu)) - data = Common::swap32(data); - - return data; -} - -inline u64 ReadMemory64(ARMul_State* cpu, u32 address) { - u64 data = Memory::Read64(address); - - if (InBigEndianMode(cpu)) - data = Common::swap64(data); - - return data; -} - -// Writes data in big/little endian format based on the -// state of the E (endian) bit in the emulated CPU's APSR. -inline void WriteMemory16(ARMul_State* cpu, u32 address, u16 data) { - if (InBigEndianMode(cpu)) - data = Common::swap16(data); - - Memory::Write16(address, data); -} - -inline void WriteMemory32(ARMul_State* cpu, u32 address, u32 data) { - if (InBigEndianMode(cpu)) - data = Common::swap32(data); - - Memory::Write32(address, data); -} - -inline void WriteMemory64(ARMul_State* cpu, u32 address, u64 data) { - if (InBigEndianMode(cpu)) - data = Common::swap64(data); - - Memory::Write64(address, data); -} diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp new file mode 100644 index 0000000000..ccb2eb0ebe --- /dev/null +++ b/src/core/arm/skyeye_common/armstate.cpp @@ -0,0 +1,657 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/swap.h" +#include "common/logging/log.h" +#include "core/mem_map.h" +#include "core/memory.h" +#include "core/arm/skyeye_common/armstate.h" +#include "core/arm/skyeye_common/vfp/vfp.h" + +ARMul_State::ARMul_State(PrivilegeMode initial_mode) +{ + Reset(); + ChangePrivilegeMode(initial_mode); +} + +void ARMul_State::ChangePrivilegeMode(u32 new_mode) +{ + if (Mode == new_mode) + return; + + if (new_mode != USERBANK) { + switch (Mode) { + case SYSTEM32MODE: // Shares registers with user mode + case USER32MODE: + Reg_usr[0] = Reg[13]; + Reg_usr[1] = Reg[14]; + break; + case IRQ32MODE: + Reg_irq[0] = Reg[13]; + Reg_irq[1] = Reg[14]; + Spsr[IRQBANK] = Spsr_copy; + break; + case SVC32MODE: + Reg_svc[0] = Reg[13]; + Reg_svc[1] = Reg[14]; + Spsr[SVCBANK] = Spsr_copy; + break; + case ABORT32MODE: + Reg_abort[0] = Reg[13]; + Reg_abort[1] = Reg[14]; + Spsr[ABORTBANK] = Spsr_copy; + break; + case UNDEF32MODE: + Reg_undef[0] = Reg[13]; + Reg_undef[1] = Reg[14]; + Spsr[UNDEFBANK] = Spsr_copy; + break; + case FIQ32MODE: + Reg_firq[0] = Reg[13]; + Reg_firq[1] = Reg[14]; + Spsr[FIQBANK] = Spsr_copy; + break; + } + + switch (new_mode) { + case USER32MODE: + Reg[13] = Reg_usr[0]; + Reg[14] = Reg_usr[1]; + Bank = USERBANK; + break; + case IRQ32MODE: + Reg[13] = Reg_irq[0]; + Reg[14] = Reg_irq[1]; + Spsr_copy = Spsr[IRQBANK]; + Bank = IRQBANK; + break; + case SVC32MODE: + Reg[13] = Reg_svc[0]; + Reg[14] = Reg_svc[1]; + Spsr_copy = Spsr[SVCBANK]; + Bank = SVCBANK; + break; + case ABORT32MODE: + Reg[13] = Reg_abort[0]; + Reg[14] = Reg_abort[1]; + Spsr_copy = Spsr[ABORTBANK]; + Bank = ABORTBANK; + break; + case UNDEF32MODE: + Reg[13] = Reg_undef[0]; + Reg[14] = Reg_undef[1]; + Spsr_copy = Spsr[UNDEFBANK]; + Bank = UNDEFBANK; + break; + case FIQ32MODE: + Reg[13] = Reg_firq[0]; + Reg[14] = Reg_firq[1]; + Spsr_copy = Spsr[FIQBANK]; + Bank = FIQBANK; + break; + case SYSTEM32MODE: // Shares registers with user mode. + Reg[13] = Reg_usr[0]; + Reg[14] = Reg_usr[1]; + Bank = SYSTEMBANK; + break; + } + + // Set the mode bits in the APSR + Cpsr = (Cpsr & ~Mode) | new_mode; + Mode = new_mode; + } +} + +// Performs a reset +void ARMul_State::Reset() +{ + VFPInit(this); + + // Set stack pointer to the top of the stack + Reg[13] = 0x10000000; + Reg[15] = 0; + + Cpsr = INTBITS | SVC32MODE; + Mode = SVC32MODE; + Bank = SVCBANK; + + ResetMPCoreCP15Registers(); + + NresetSig = HIGH; + NfiqSig = HIGH; + NirqSig = HIGH; + NtransSig = (Mode & 3) ? HIGH : LOW; + abortSig = LOW; + + NumInstrs = 0; + Emulate = RUN; +} + +// Resets certain MPCore CP15 values to their ARM-defined reset values. +void ARMul_State::ResetMPCoreCP15Registers() +{ + // c0 + CP15[CP15_MAIN_ID] = 0x410FB024; + CP15[CP15_TLB_TYPE] = 0x00000800; + CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111; + CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001; + CP15[CP15_DEBUG_FEATURE_0] = 0x00000002; + CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103; + CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302; + CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000; + CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000; + CP15[CP15_ISA_FEATURE_0] = 0x00100011; + CP15[CP15_ISA_FEATURE_1] = 0x12002111; + CP15[CP15_ISA_FEATURE_2] = 0x11221011; + CP15[CP15_ISA_FEATURE_3] = 0x01102131; + CP15[CP15_ISA_FEATURE_4] = 0x00000141; + + // c1 + CP15[CP15_CONTROL] = 0x00054078; + CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F; + CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000; + + // c2 + CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000; + CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000; + CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000; + + // c3 + CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000; + + // c7 + CP15[CP15_PHYS_ADDRESS] = 0x00000000; + + // c9 + CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0; + + // c10 + CP15[CP15_TLB_LOCKDOWN] = 0x00000000; + CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4; + CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0; + + // c13 + CP15[CP15_PID] = 0x00000000; + CP15[CP15_CONTEXT_ID] = 0x00000000; + CP15[CP15_THREAD_UPRW] = 0x00000000; + CP15[CP15_THREAD_URO] = 0x00000000; + CP15[CP15_THREAD_PRW] = 0x00000000; + + // c15 + CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000; + CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000; + CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000; + CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000; + CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; +} + +u16 ARMul_State::ReadMemory16(u32 address) const +{ + u16 data = Memory::Read16(address); + + if (InBigEndianMode()) + data = Common::swap16(data); + + return data; +} + +u32 ARMul_State::ReadMemory32(u32 address) const +{ + u32 data = Memory::Read32(address); + + if (InBigEndianMode()) + data = Common::swap32(data); + + return data; +} + +u64 ARMul_State::ReadMemory64(u32 address) const +{ + u64 data = Memory::Read64(address); + + if (InBigEndianMode()) + data = Common::swap64(data); + + return data; +} + +void ARMul_State::WriteMemory16(u32 address, u16 data) +{ + if (InBigEndianMode()) + data = Common::swap16(data); + + Memory::Write16(address, data); +} + +void ARMul_State::WriteMemory32(u32 address, u32 data) +{ + if (InBigEndianMode()) + data = Common::swap32(data); + + Memory::Write32(address, data); +} + +void ARMul_State::WriteMemory64(u32 address, u64 data) +{ + if (InBigEndianMode()) + data = Common::swap64(data); + + Memory::Write64(address, data); +} + + +// Reads from the CP15 registers. Used with implementation of the MRC instruction. +// Note that since the 3DS does not have the hypervisor extensions, these registers +// are not implemented. +u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const +{ + // Unprivileged registers + if (crn == 13 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 2) + return CP15[CP15_THREAD_UPRW]; + + if (opcode_2 == 3) + return CP15[CP15_THREAD_URO]; + } + + if (InAPrivilegedMode()) + { + if (crn == 0 && opcode_1 == 0) + { + if (crm == 0) + { + if (opcode_2 == 0) + return CP15[CP15_MAIN_ID]; + + if (opcode_2 == 1) + return CP15[CP15_CACHE_TYPE]; + + if (opcode_2 == 3) + return CP15[CP15_TLB_TYPE]; + + if (opcode_2 == 5) + return CP15[CP15_CPU_ID]; + } + else if (crm == 1) + { + if (opcode_2 == 0) + return CP15[CP15_PROCESSOR_FEATURE_0]; + + if (opcode_2 == 1) + return CP15[CP15_PROCESSOR_FEATURE_1]; + + if (opcode_2 == 2) + return CP15[CP15_DEBUG_FEATURE_0]; + + if (opcode_2 == 4) + return CP15[CP15_MEMORY_MODEL_FEATURE_0]; + + if (opcode_2 == 5) + return CP15[CP15_MEMORY_MODEL_FEATURE_1]; + + if (opcode_2 == 6) + return CP15[CP15_MEMORY_MODEL_FEATURE_2]; + + if (opcode_2 == 7) + return CP15[CP15_MEMORY_MODEL_FEATURE_3]; + } + else if (crm == 2) + { + if (opcode_2 == 0) + return CP15[CP15_ISA_FEATURE_0]; + + if (opcode_2 == 1) + return CP15[CP15_ISA_FEATURE_1]; + + if (opcode_2 == 2) + return CP15[CP15_ISA_FEATURE_2]; + + if (opcode_2 == 3) + return CP15[CP15_ISA_FEATURE_3]; + + if (opcode_2 == 4) + return CP15[CP15_ISA_FEATURE_4]; + } + } + + if (crn == 1 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + return CP15[CP15_CONTROL]; + + if (opcode_2 == 1) + return CP15[CP15_AUXILIARY_CONTROL]; + + if (opcode_2 == 2) + return CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; + } + + if (crn == 2 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + return CP15[CP15_TRANSLATION_BASE_TABLE_0]; + + if (opcode_2 == 1) + return CP15[CP15_TRANSLATION_BASE_TABLE_1]; + + if (opcode_2 == 2) + return CP15[CP15_TRANSLATION_BASE_CONTROL]; + } + + if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) + return CP15[CP15_DOMAIN_ACCESS_CONTROL]; + + if (crn == 5 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + return CP15[CP15_FAULT_STATUS]; + + if (opcode_2 == 1) + return CP15[CP15_INSTR_FAULT_STATUS]; + } + + if (crn == 6 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + return CP15[CP15_FAULT_ADDRESS]; + + if (opcode_2 == 1) + return CP15[CP15_WFAR]; + } + + if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0) + return CP15[CP15_PHYS_ADDRESS]; + + if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) + return CP15[CP15_DATA_CACHE_LOCKDOWN]; + + if (crn == 10 && opcode_1 == 0) + { + if (crm == 0 && opcode_2 == 0) + return CP15[CP15_TLB_LOCKDOWN]; + + if (crm == 2) + { + if (opcode_2 == 0) + return CP15[CP15_PRIMARY_REGION_REMAP]; + + if (opcode_2 == 1) + return CP15[CP15_NORMAL_REGION_REMAP]; + } + } + + if (crn == 13 && crm == 0) + { + if (opcode_2 == 0) + return CP15[CP15_PID]; + + if (opcode_2 == 1) + return CP15[CP15_CONTEXT_ID]; + + if (opcode_2 == 4) + return CP15[CP15_THREAD_PRW]; + } + + if (crn == 15) + { + if (opcode_1 == 0 && crm == 12) + { + if (opcode_2 == 0) + return CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; + + if (opcode_2 == 1) + return CP15[CP15_CYCLE_COUNTER]; + + if (opcode_2 == 2) + return CP15[CP15_COUNT_0]; + + if (opcode_2 == 3) + return CP15[CP15_COUNT_1]; + } + + if (opcode_1 == 5 && opcode_2 == 2) + { + if (crm == 5) + return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; + + if (crm == 6) + return CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS]; + + if (crm == 7) + return CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE]; + } + + if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) + return CP15[CP15_TLB_DEBUG_CONTROL]; + } + } + + LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); + return 0; +} + +// Write to the CP15 registers. Used with implementation of the MCR instruction. +// Note that since the 3DS does not have the hypervisor extensions, these registers +// are not implemented. +void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) +{ + if (InAPrivilegedMode()) + { + if (crn == 1 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + CP15[CP15_CONTROL] = value; + else if (opcode_2 == 1) + CP15[CP15_AUXILIARY_CONTROL] = value; + else if (opcode_2 == 2) + CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; + } + else if (crn == 2 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; + else if (opcode_2 == 1) + CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; + else if (opcode_2 == 2) + CP15[CP15_TRANSLATION_BASE_CONTROL] = value; + } + else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) + { + CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; + } + else if (crn == 5 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + CP15[CP15_FAULT_STATUS] = value; + else if (opcode_2 == 1) + CP15[CP15_INSTR_FAULT_STATUS] = value; + } + else if (crn == 6 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + CP15[CP15_FAULT_ADDRESS] = value; + else if (opcode_2 == 1) + CP15[CP15_WFAR] = value; + } + else if (crn == 7 && opcode_1 == 0) + { + if (crm == 0 && opcode_2 == 4) + { + CP15[CP15_WAIT_FOR_INTERRUPT] = value; + } + else if (crm == 4 && opcode_2 == 0) + { + // NOTE: Not entirely accurate. This should do permission checks. + CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); + } + else if (crm == 5) + { + if (opcode_2 == 0) + CP15[CP15_INVALIDATE_INSTR_CACHE] = value; + else if (opcode_2 == 1) + CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value; + else if (opcode_2 == 2) + CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value; + else if (opcode_2 == 6) + CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; + else if (opcode_2 == 7) + CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; + } + else if (crm == 6) + { + if (opcode_2 == 0) + CP15[CP15_INVALIDATE_DATA_CACHE] = value; + else if (opcode_2 == 1) + CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; + else if (opcode_2 == 2) + CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; + } + else if (crm == 7 && opcode_2 == 0) + { + CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; + } + else if (crm == 10) + { + if (opcode_2 == 0) + CP15[CP15_CLEAN_DATA_CACHE] = value; + else if (opcode_2 == 1) + CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; + else if (opcode_2 == 2) + CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; + } + else if (crm == 14) + { + if (opcode_2 == 0) + CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; + else if (opcode_2 == 1) + CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; + else if (opcode_2 == 2) + CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; + } + } + else if (crn == 8 && opcode_1 == 0) + { + if (crm == 5) + { + if (opcode_2 == 0) + CP15[CP15_INVALIDATE_ITLB] = value; + else if (opcode_2 == 1) + CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value; + else if (opcode_2 == 2) + CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; + else if (opcode_2 == 3) + CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; + } + else if (crm == 6) + { + if (opcode_2 == 0) + CP15[CP15_INVALIDATE_DTLB] = value; + else if (opcode_2 == 1) + CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value; + else if (opcode_2 == 2) + CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; + else if (opcode_2 == 3) + CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; + } + else if (crm == 7) + { + if (opcode_2 == 0) + CP15[CP15_INVALIDATE_UTLB] = value; + else if (opcode_2 == 1) + CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value; + else if (opcode_2 == 2) + CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value; + else if (opcode_2 == 3) + CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; + } + } + else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) + { + CP15[CP15_DATA_CACHE_LOCKDOWN] = value; + } + else if (crn == 10 && opcode_1 == 0) + { + if (crm == 0 && opcode_2 == 0) + { + CP15[CP15_TLB_LOCKDOWN] = value; + } + else if (crm == 2) + { + if (opcode_2 == 0) + CP15[CP15_PRIMARY_REGION_REMAP] = value; + else if (opcode_2 == 1) + CP15[CP15_NORMAL_REGION_REMAP] = value; + } + } + else if (crn == 13 && opcode_1 == 0 && crm == 0) + { + if (opcode_2 == 0) + CP15[CP15_PID] = value; + else if (opcode_2 == 1) + CP15[CP15_CONTEXT_ID] = value; + else if (opcode_2 == 3) + CP15[CP15_THREAD_URO] = value; + else if (opcode_2 == 4) + CP15[CP15_THREAD_PRW] = value; + } + else if (crn == 15) + { + if (opcode_1 == 0 && crm == 12) + { + if (opcode_2 == 0) + CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; + else if (opcode_2 == 1) + CP15[CP15_CYCLE_COUNTER] = value; + else if (opcode_2 == 2) + CP15[CP15_COUNT_0] = value; + else if (opcode_2 == 3) + CP15[CP15_COUNT_1] = value; + } + else if (opcode_1 == 5) + { + if (crm == 4) + { + if (opcode_2 == 2) + CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; + else if (opcode_2 == 4) + CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; + } + else if (crm == 5 && opcode_2 == 2) + { + CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; + } + else if (crm == 6 && opcode_2 == 2) + { + CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; + } + else if (crm == 7 && opcode_2 == 2) + { + CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; + } + } + else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) + { + CP15[CP15_TLB_DEBUG_CONTROL] = value; + } + } + } + + // Unprivileged registers + if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) + { + CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; + } + else if (crn == 7 && opcode_1 == 0 && crm == 10) + { + if (opcode_2 == 4) + CP15[CP15_DATA_SYNC_BARRIER] = value; + else if (opcode_2 == 5) + CP15[CP15_DATA_MEMORY_BARRIER] = value; + } + else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) + { + CP15[CP15_THREAD_UPRW] = value; + } +} diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h new file mode 100644 index 0000000000..b364e26210 --- /dev/null +++ b/src/core/arm/skyeye_common/armstate.h @@ -0,0 +1,252 @@ +/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#pragma once + +#include <array> +#include <unordered_map> + +#include "common/common_types.h" +#include "core/arm/skyeye_common/arm_regformat.h" + +// Signal levels +enum { + LOW = 0, + HIGH = 1, + LOWHIGH = 1, + HIGHLOW = 2 +}; + +// Cache types +enum { + NONCACHE = 0, + DATACACHE = 1, + INSTCACHE = 2, +}; + +// ARM privilege modes +enum PrivilegeMode { + USER32MODE = 16, + FIQ32MODE = 17, + IRQ32MODE = 18, + SVC32MODE = 19, + ABORT32MODE = 23, + UNDEF32MODE = 27, + SYSTEM32MODE = 31 +}; + +// ARM privilege mode register banks +enum { + USERBANK = 0, + FIQBANK = 1, + IRQBANK = 2, + SVCBANK = 3, + ABORTBANK = 4, + UNDEFBANK = 5, + DUMMYBANK = 6, + SYSTEMBANK = 7 +}; + +// Hardware vector addresses +enum { + ARMResetV = 0, + ARMUndefinedInstrV = 4, + ARMSWIV = 8, + ARMPrefetchAbortV = 12, + ARMDataAbortV = 16, + ARMAddrExceptnV = 20, + ARMIRQV = 24, + ARMFIQV = 28, + ARMErrorV = 32, // This is an offset, not an address! + + ARMul_ResetV = ARMResetV, + ARMul_UndefinedInstrV = ARMUndefinedInstrV, + ARMul_SWIV = ARMSWIV, + ARMul_PrefetchAbortV = ARMPrefetchAbortV, + ARMul_DataAbortV = ARMDataAbortV, + ARMul_AddrExceptnV = ARMAddrExceptnV, + ARMul_IRQV = ARMIRQV, + ARMul_FIQV = ARMFIQV +}; + +// Coprocessor status values +enum { + ARMul_FIRST = 0, + ARMul_TRANSFER = 1, + ARMul_BUSY = 2, + ARMul_DATA = 3, + ARMul_INTERRUPT = 4, + ARMul_DONE = 0, + ARMul_CANT = 1, + ARMul_INC = 3 +}; + +// Instruction condition codes +enum ConditionCode { + EQ = 0, + NE = 1, + CS = 2, + CC = 3, + MI = 4, + PL = 5, + VS = 6, + VC = 7, + HI = 8, + LS = 9, + GE = 10, + LT = 11, + GT = 12, + LE = 13, + AL = 14, + NV = 15, +}; + +// Flags for use with the APSR. +enum : u32 { + NBIT = (1U << 31U), + ZBIT = (1 << 30), + CBIT = (1 << 29), + VBIT = (1 << 28), + QBIT = (1 << 27), + JBIT = (1 << 24), + EBIT = (1 << 9), + ABIT = (1 << 8), + IBIT = (1 << 7), + FBIT = (1 << 6), + TBIT = (1 << 5), + + // Masks for groups of bits in the APSR. + MODEBITS = 0x1F, + INTBITS = 0x1C0, +}; + +// Values for Emulate. +enum { + STOP = 0, // Stop + CHANGEMODE = 1, // Change mode + ONCE = 2, // Execute just one iteration + RUN = 3 // Continuous execution +}; + + +struct ARMul_State final +{ +public: + explicit ARMul_State(PrivilegeMode initial_mode); + + void ChangePrivilegeMode(u32 new_mode); + void Reset(); + + // Reads/writes data in big/little endian format based on the + // state of the E (endian) bit in the APSR. + u16 ReadMemory16(u32 address) const; + u32 ReadMemory32(u32 address) const; + u64 ReadMemory64(u32 address) const; + void WriteMemory16(u32 address, u16 data); + void WriteMemory32(u32 address, u32 data); + void WriteMemory64(u32 address, u64 data); + + u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; + void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); + + // Exclusive memory access functions + bool IsExclusiveMemoryAccess(u32 address) const { + return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK); + } + void SetExclusiveMemoryAddress(u32 address) { + exclusive_tag = address & RESERVATION_GRANULE_MASK; + exclusive_state = true; + } + void UnsetExclusiveMemoryAddress() { + exclusive_tag = 0xFFFFFFFF; + exclusive_state = false; + } + + // Whether or not the given CPU is in big endian mode (E bit is set) + bool InBigEndianMode() const { + return (Cpsr & (1 << 9)) != 0; + } + // Whether or not the given CPU is in a mode other than user mode. + bool InAPrivilegedMode() const { + return (Mode != USER32MODE); + } + // Note that for the 3DS, a Thumb instruction will only ever be + // two bytes in size. Thus we don't need to worry about ThumbEE + // or Thumb-2 where instructions can be 4 bytes in length. + u32 GetInstructionSize() const { + return TFlag ? 2 : 4; + } + + std::array<u32, 16> Reg; // The current register file + std::array<u32, 2> Reg_usr; + std::array<u32, 2> Reg_svc; // R13_SVC R14_SVC + std::array<u32, 2> Reg_abort; // R13_ABORT R14_ABORT + std::array<u32, 2> Reg_undef; // R13 UNDEF R14 UNDEF + std::array<u32, 2> Reg_irq; // R13_IRQ R14_IRQ + std::array<u32, 7> Reg_firq; // R8---R14 FIRQ + std::array<u32, 7> Spsr; // The exception psr's + std::array<u32, CP15_REGISTER_COUNT> CP15; + + // FPSID, FPSCR, and FPEXC + std::array<u32, VFP_SYSTEM_REGISTER_COUNT> VFP; + + // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31). + // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31), + // and only 32 singleword registers are accessible (S0-S31). + std::array<u32, 64> ExtReg; + + u32 Emulate; // To start and stop emulation + u32 Cpsr; // The current PSR + u32 Spsr_copy; + u32 phys_pc; + + u32 Mode; // The current mode + u32 Bank; // The current register bank + + u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed + unsigned int shifter_carry_out; + + u32 TFlag; // Thumb state + + unsigned long long NumInstrs; // The number of instructions executed + unsigned NumInstrsToExecute; + + unsigned NresetSig; // Reset the processor + unsigned NfiqSig; + unsigned NirqSig; + + unsigned abortSig; + unsigned NtransSig; + unsigned bigendSig; + unsigned syscallSig; + + // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per + // process for our purposes), not per ARMul_State (which tracks CPU core state). + std::unordered_map<u32, int> instruction_cache; + +private: + void ResetMPCoreCP15Registers(); + + // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. + // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to + // support LDR/STREXD. + static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; + + u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode + u32 exclusive_result; + bool exclusive_state; +}; diff --git a/src/core/arm/skyeye_common/armsupp.cpp b/src/core/arm/skyeye_common/armsupp.cpp new file mode 100644 index 0000000000..d31fb94490 --- /dev/null +++ b/src/core/arm/skyeye_common/armsupp.cpp @@ -0,0 +1,208 @@ +/* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "common/logging/log.h" + +#include "core/mem_map.h" +#include "core/arm/skyeye_common/arm_regformat.h" +#include "core/arm/skyeye_common/armstate.h" +#include "core/arm/skyeye_common/armsupp.h" + +// Unsigned sum of absolute difference +u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) +{ + if (left > right) + return left - right; + + return right - left; +} + +// Add with carry, indicates if a carry-out or signed overflow occurred. +u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) +{ + u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; + s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; + u64 result = (unsigned_sum & 0xFFFFFFFF); + + if (carry_out_occurred) + *carry_out_occurred = (result != unsigned_sum); + + if (overflow_occurred) + *overflow_occurred = ((s64)(s32)result != signed_sum); + + return (u32)result; +} + +// Compute whether an addition of A and B, giving RESULT, overflowed. +bool AddOverflow(u32 a, u32 b, u32 result) +{ + return ((NEG(a) && NEG(b) && POS(result)) || + (POS(a) && POS(b) && NEG(result))); +} + +// Compute whether a subtraction of A and B, giving RESULT, overflowed. +bool SubOverflow(u32 a, u32 b, u32 result) +{ + return ((NEG(a) && POS(b) && POS(result)) || + (POS(a) && NEG(b) && NEG(result))); +} + +// Returns true if the Q flag should be set as a result of overflow. +bool ARMul_AddOverflowQ(u32 a, u32 b) +{ + u32 result = a + b; + if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) + return true; + + return false; +} + +// 8-bit signed saturated addition +u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) +{ + u8 result = left + right; + + if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { + if (left & 0x80) + result = 0x80; + else + result = 0x7F; + } + + return result; +} + +// 8-bit signed saturated subtraction +u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) +{ + u8 result = left - right; + + if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { + if (left & 0x80) + result = 0x80; + else + result = 0x7F; + } + + return result; +} + +// 16-bit signed saturated addition +u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) +{ + u16 result = left + right; + + if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { + if (left & 0x8000) + result = 0x8000; + else + result = 0x7FFF; + } + + return result; +} + +// 16-bit signed saturated subtraction +u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) +{ + u16 result = left - right; + + if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { + if (left & 0x8000) + result = 0x8000; + else + result = 0x7FFF; + } + + return result; +} + +// 8-bit unsigned saturated addition +u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) +{ + u8 result = left + right; + + if (result < left) + result = 0xFF; + + return result; +} + +// 16-bit unsigned saturated addition +u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) +{ + u16 result = left + right; + + if (result < left) + result = 0xFFFF; + + return result; +} + +// 8-bit unsigned saturated subtraction +u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) +{ + if (left <= right) + return 0; + + return left - right; +} + +// 16-bit unsigned saturated subtraction +u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) +{ + if (left <= right) + return 0; + + return left - right; +} + +// Signed saturation. +u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) +{ + const u32 max = (1 << shift) - 1; + const s32 top = (value >> shift); + + if (top > 0) { + *saturation_occurred = true; + return max; + } + else if (top < -1) { + *saturation_occurred = true; + return ~max; + } + + *saturation_occurred = false; + return (u32)value; +} + +// Unsigned saturation +u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) +{ + const u32 max = (1 << shift) - 1; + + if (value < 0) { + *saturation_occurred = true; + return 0; + } else if ((u32)value > max) { + *saturation_occurred = true; + return max; + } + + *saturation_occurred = false; + return (u32)value; +} diff --git a/src/core/arm/skyeye_common/armsupp.h b/src/core/arm/skyeye_common/armsupp.h new file mode 100644 index 0000000000..391309fa81 --- /dev/null +++ b/src/core/arm/skyeye_common/armsupp.h @@ -0,0 +1,32 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) +#define BIT(s, n) ((s >> (n)) & 1) + +#define POS(i) ( (~(i)) >> 31 ) +#define NEG(i) ( (i) >> 31 ) + +bool AddOverflow(u32, u32, u32); +bool SubOverflow(u32, u32, u32); + +u32 AddWithCarry(u32, u32, u32, bool*, bool*); +bool ARMul_AddOverflowQ(u32, u32); + +u8 ARMul_SignedSaturatedAdd8(u8, u8); +u8 ARMul_SignedSaturatedSub8(u8, u8); +u16 ARMul_SignedSaturatedAdd16(u16, u16); +u16 ARMul_SignedSaturatedSub16(u16, u16); + +u8 ARMul_UnsignedSaturatedAdd8(u8, u8); +u16 ARMul_UnsignedSaturatedAdd16(u16, u16); +u8 ARMul_UnsignedSaturatedSub8(u8, u8); +u16 ARMul_UnsignedSaturatedSub16(u16, u16); +u8 ARMul_UnsignedAbsoluteDifference(u8, u8); +u32 ARMul_SignedSatQ(s32, u8, bool*); +u32 ARMul_UnsignedSatQ(s32, u8, bool*); diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp index 1ffc1f9af7..26f303de42 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.cpp +++ b/src/core/arm/skyeye_common/vfp/vfp.cpp @@ -23,7 +23,7 @@ #include "common/common_funcs.h" #include "common/logging/log.h" -#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/vfp/asm_vfp.h" #include "core/arm/skyeye_common/vfp/vfp.h" @@ -43,7 +43,7 @@ void VFPInit(ARMul_State* state) state->VFP[VFP_MVFR1] = 0; } -void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) +void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) { if (to_arm) { @@ -55,7 +55,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* } } -void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) +void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) { if (to_arm) { @@ -68,7 +68,7 @@ void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword state->ExtReg[n*2] = *value1; } } -void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) +void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) { if (to_arm) { @@ -82,7 +82,7 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor } } -void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) +void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) { if (single) { @@ -95,7 +95,7 @@ void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) state->ExtReg[d*2] = 0; } } -void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword m) +void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) { if (single) { diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h index 80ca93ccde..88908da9f3 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.h +++ b/src/core/arm/skyeye_common/vfp/vfp.h @@ -36,8 +36,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); -void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); -void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); -void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); -void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); -void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); +void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value); +void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2); +void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2); +void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm); +void VMOVR(ARMul_State* state, u32 single, u32 d, u32 imm); diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h index 2007d6dc4b..91a8d4d574 100644 --- a/src/core/arm/skyeye_common/vfp/vfp_helper.h +++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h @@ -34,7 +34,7 @@ #include <cstdio> #include "common/common_types.h" -#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/vfp/asm_vfp.h" #define do_div(n, base) {n/=base;} @@ -415,7 +415,7 @@ struct op { u32 flags; }; -static inline u32 fls(ARMword x) +static inline u32 fls(u32 x) { int r = 32; diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index f91049585c..1d844a66e8 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp @@ -70,9 +70,9 @@ static void vfp_double_dump(const char *str, struct vfp_double *d) static void vfp_double_normalise_denormal(struct vfp_double *vd) { - int bits = 31 - fls((ARMword)(vd->significand >> 32)); + int bits = 31 - fls((u32)(vd->significand >> 32)); if (bits == 31) - bits = 63 - fls((ARMword)vd->significand); + bits = 63 - fls((u32)vd->significand); vfp_double_dump("normalise_denormal: in", vd); @@ -109,9 +109,9 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, exponent = vd->exponent; significand = vd->significand; - shift = 32 - fls((ARMword)(significand >> 32)); + shift = 32 - fls((u32)(significand >> 32)); if (shift == 32) - shift = 64 - fls((ARMword)significand); + shift = 64 - fls((u32)significand); if (shift) { exponent -= shift; significand <<= shift; @@ -566,7 +566,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 /* * 2^0 <= m < 2^32-2^8 */ - d = (ARMword)((vdm.significand << 1) >> shift); + d = (u32)((vdm.significand << 1) >> shift); rem = vdm.significand << (65 - shift); if (rmode == FPSCR_ROUND_NEAREST) { @@ -647,7 +647,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 int shift = 1023 + 63 - vdm.exponent; /* 58 */ u64 rem, incr = 0; - d = (ARMword)((vdm.significand << 1) >> shift); + d = (u32)((vdm.significand << 1) >> shift); rem = vdm.significand << (65 - shift); if (rmode == FPSCR_ROUND_NEAREST) { diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index 8efcbab1cf..9b99fc5bc0 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp @@ -51,7 +51,7 @@ VMLA_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmla_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -100,7 +100,7 @@ VMLS_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmls_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -149,7 +149,7 @@ VNMLA_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vnmla_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -199,7 +199,7 @@ VNMLS_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vnmls_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -248,7 +248,7 @@ VNMUL_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vnmul_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -297,7 +297,7 @@ VMUL_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmul_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -346,7 +346,7 @@ VADD_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vadd_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -395,7 +395,7 @@ VSUB_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vsub_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -444,7 +444,7 @@ VDIV_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vdiv_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -492,7 +492,7 @@ VMOVI_INST: VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmovi_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -536,7 +536,7 @@ VMOVR_INST: VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmovr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -585,7 +585,7 @@ VABS_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vabs_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -635,7 +635,7 @@ VNEG_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vneg_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -684,7 +684,7 @@ VSQRT_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vsqrt_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -733,7 +733,7 @@ VCMP_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vcmp_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -782,7 +782,7 @@ VCMP2_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vcmp2_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -831,7 +831,7 @@ VCVTBDS_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vcvtbds_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -882,7 +882,7 @@ VCVTBFF_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vcvtbff_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -931,7 +931,7 @@ VCVTBFI_INST: CHECK_VFP_CDP_RET; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vcvtbfi_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -981,7 +981,7 @@ VMOVBRS_INST: VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmovbrs_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1032,7 +1032,7 @@ VMSR_INST: { cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; } - else if (InAPrivilegedMode(cpu)) + else if (cpu->InAPrivilegedMode()) { if (reg == 8) cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; @@ -1042,7 +1042,7 @@ VMSR_INST: cpu->VFP[VFP_FPINST2] = cpu->Reg[rt]; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmsr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1090,7 +1090,7 @@ VMOVBRC_INST: cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t]; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmovbrc_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1163,7 +1163,7 @@ VMRS_INST: { cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; } - else if (InAPrivilegedMode(cpu)) + else if (cpu->InAPrivilegedMode()) { if (reg == 8) cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; @@ -1173,7 +1173,7 @@ VMRS_INST: cpu->Reg[rt] = cpu->VFP[VFP_FPINST2]; } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmrs_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1221,7 +1221,7 @@ VMOVBCR_INST: cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmovbcr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1274,7 +1274,7 @@ VMOVBRRSS_INST: VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmovbrrss_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1322,7 +1322,7 @@ VMOVBRRD_INST: VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vmovbrrd_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1378,23 +1378,23 @@ VSTR_INST: if (inst_cream->single) { - WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]); + cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]); } else { const u32 word1 = cpu->ExtReg[inst_cream->d*2+0]; const u32 word2 = cpu->ExtReg[inst_cream->d*2+1]; - if (InBigEndianMode(cpu)) { - WriteMemory32(cpu, addr + 0, word2); - WriteMemory32(cpu, addr + 4, word1); + if (cpu->InBigEndianMode()) { + cpu->WriteMemory32(addr + 0, word2); + cpu->WriteMemory32(addr + 4, word1); } else { - WriteMemory32(cpu, addr + 0, word1); - WriteMemory32(cpu, addr + 4, word2); + cpu->WriteMemory32(addr + 0, word1); + cpu->WriteMemory32(addr + 4, word2); } } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vstr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1444,7 +1444,7 @@ VPUSH_INST: { if (inst_cream->single) { - WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); + cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); addr += 4; } else @@ -1452,12 +1452,12 @@ VPUSH_INST: const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; - if (InBigEndianMode(cpu)) { - WriteMemory32(cpu, addr + 0, word2); - WriteMemory32(cpu, addr + 4, word1); + if (cpu->InBigEndianMode()) { + cpu->WriteMemory32(addr + 0, word2); + cpu->WriteMemory32(addr + 4, word1); } else { - WriteMemory32(cpu, addr + 0, word1); - WriteMemory32(cpu, addr + 4, word2); + cpu->WriteMemory32(addr + 0, word1); + cpu->WriteMemory32(addr + 4, word2); } addr += 8; @@ -1466,7 +1466,7 @@ VPUSH_INST: cpu->Reg[R13] -= inst_cream->imm32; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vpush_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1522,7 +1522,7 @@ VSTM_INST: /* encoding 1 */ { if (inst_cream->single) { - WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); + cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); addr += 4; } else @@ -1530,12 +1530,12 @@ VSTM_INST: /* encoding 1 */ const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; - if (InBigEndianMode(cpu)) { - WriteMemory32(cpu, addr + 0, word2); - WriteMemory32(cpu, addr + 4, word1); + if (cpu->InBigEndianMode()) { + cpu->WriteMemory32(addr + 0, word2); + cpu->WriteMemory32(addr + 4, word1); } else { - WriteMemory32(cpu, addr + 0, word1); - WriteMemory32(cpu, addr + 4, word2); + cpu->WriteMemory32(addr + 0, word1); + cpu->WriteMemory32(addr + 4, word2); } addr += 8; @@ -1597,15 +1597,15 @@ VPOP_INST: { if (inst_cream->single) { - cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); + cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); addr += 4; } else { - const u32 word1 = ReadMemory32(cpu, addr + 0); - const u32 word2 = ReadMemory32(cpu, addr + 4); + const u32 word1 = cpu->ReadMemory32(addr + 0); + const u32 word2 = cpu->ReadMemory32(addr + 4); - if (InBigEndianMode(cpu)) { + if (cpu->InBigEndianMode()) { cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; } else { @@ -1618,7 +1618,7 @@ VPOP_INST: } cpu->Reg[R13] += inst_cream->imm32; } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vpop_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1670,14 +1670,14 @@ VLDR_INST: if (inst_cream->single) { - cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr); + cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr); } else { - const u32 word1 = ReadMemory32(cpu, addr + 0); - const u32 word2 = ReadMemory32(cpu, addr + 4); + const u32 word1 = cpu->ReadMemory32(addr + 0); + const u32 word2 = cpu->ReadMemory32(addr + 4); - if (InBigEndianMode(cpu)) { + if (cpu->InBigEndianMode()) { cpu->ExtReg[inst_cream->d*2+0] = word2; cpu->ExtReg[inst_cream->d*2+1] = word1; } else { @@ -1686,7 +1686,7 @@ VLDR_INST: } } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vldr_inst)); FETCH_INST; GOTO_NEXT_INST; @@ -1742,15 +1742,15 @@ VLDM_INST: { if (inst_cream->single) { - cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); + cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); addr += 4; } else { - const u32 word1 = ReadMemory32(cpu, addr + 0); - const u32 word2 = ReadMemory32(cpu, addr + 4); + const u32 word1 = cpu->ReadMemory32(addr + 0); + const u32 word2 = cpu->ReadMemory32(addr + 4); - if (InBigEndianMode(cpu)) { + if (cpu->InBigEndianMode()) { cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; } else { @@ -1766,7 +1766,7 @@ VLDM_INST: cpu->Reg[inst_cream->n] - inst_cream->imm32); } } - cpu->Reg[15] += GET_INST_SIZE(cpu); + cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(vldm_inst)); FETCH_INST; GOTO_NEXT_INST; diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 72006a53e9..20f2da0fe3 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -502,7 +502,7 @@ void Advance() { Core::g_app_core->down_count += diff; } if (advance_callback) - advance_callback(cycles_executed); + advance_callback(static_cast<int>(cycles_executed)); } void LogPendingEvents() { diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp index 826f6cbb6f..bc2a1829eb 100644 --- a/src/core/hle/applets/applet.cpp +++ b/src/core/hle/applets/applet.cpp @@ -89,12 +89,21 @@ ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter) return result; } +bool IsLibraryAppletRunning() { + // Check the applets map for instances of any applet + for (auto itr = applets.begin(); itr != applets.end(); ++itr) + if (itr->second != nullptr) + return true; + return false; +} + void Init() { // Register the applet update callback applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent); } void Shutdown() { + CoreTiming::RemoveEvent(applet_update_event); } } diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h index b235d0b8a4..af442f81d5 100644 --- a/src/core/hle/applets/applet.h +++ b/src/core/hle/applets/applet.h @@ -67,6 +67,9 @@ protected: Service::APT::AppletId id; ///< Id of this Applet }; +/// Returns whether a library applet is currently running +bool IsLibraryAppletRunning(); + /// Initializes the HLE applets void Init(); diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 9294789ec1..1a0518926d 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -133,7 +133,7 @@ template<ResultCode func(u32)> void Wrap() { FuncReturn(func(PARAM(0)).raw); } -template<ResultCode func(s64*, u32, u32*, s32)> void Wrap(){ +template<ResultCode func(s64*, u32, u32*, u32)> void Wrap(){ FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)), (s32)PARAM(3)).raw); } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 8b49fc7dfe..29ea6d5319 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -13,7 +13,7 @@ #include "common/thread_queue_list.h" #include "core/arm/arm_interface.h" -#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/armstate.h" #include "core/core.h" #include "core/core_timing.h" #include "core/hle/hle.h" diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 7332478fb1..64f3bc7e9b 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -5,6 +5,7 @@ #include "common/logging/log.h" #include "core/hle/service/service.h" +#include "core/hle/service/am/am.h" #include "core/hle/service/am/am_app.h" #include "core/hle/service/am/am_net.h" #include "core/hle/service/am/am_sys.h" diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp index b1af0e9d81..aa391f3b2b 100644 --- a/src/core/hle/service/am/am_net.cpp +++ b/src/core/hle/service/am/am_net.cpp @@ -28,7 +28,8 @@ const Interface::FunctionInfo FunctionTable[] = { {0x08130000, nullptr, "GetTotalContents"}, {0x08140042, nullptr, "GetContentIndexes"}, {0x08150044, nullptr, "GetContentsInfo"}, - {0x08190108, nullptr, "Unknown"}, + {0x08180042, nullptr, "GetCTCert"}, + {0x08190108, nullptr, "SetCertificates"}, {0x081B00C2, nullptr, "InstallTitlesFinish"}, }; diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 7b6ab4ce01..35402341b7 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -101,18 +101,19 @@ void NotifyToWait(Service::Interface* self) { void GetLockHandle(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field + // Bits [0:2] are the applet type (System, Library, etc) + // Bit 5 tells the application that there's a pending APT parameter, + // this will cause the app to wait until parameter_event is signaled. + u32 applet_attributes = cmd_buff[1]; cmd_buff[1] = RESULT_SUCCESS.raw; // No error - // Not sure what these parameters are used for, but retail apps check that they are 0 after - // GetLockHandle has been called. - cmd_buff[2] = 0; // Applet Attributes, this value is passed to Enable. - cmd_buff[3] = 0; - cmd_buff[4] = 0; - + cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable. + cmd_buff[3] = 0; // Least significant bit = power button state + cmd_buff[4] = IPC::CopyHandleDesc(); cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); - LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]); + + LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], applet_attributes); } void Enable(Service::Interface* self) { @@ -139,13 +140,16 @@ void IsRegistered(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; cmd_buff[1] = RESULT_SUCCESS.raw; // No error - /// TODO(Subv): It is currently unknown what this value (0x400) means, - /// but i believe it is used as a global "LibraryApplet" id, to verify if there's - /// any LibApplet currently running. This is not verified. - if (app_id != 0x400) + + // TODO(Subv): An application is considered "registered" if it has already called APT::Enable + // handle this properly once we implement multiprocess support. + cmd_buff[2] = 0; // Set to not registered by default + + if (app_id == static_cast<u32>(AppletId::AnyLibraryApplet)) { + cmd_buff[2] = HLE::Applets::IsLibraryAppletRunning() ? 1 : 0; + } else if (auto applet = HLE::Applets::Applet::Get(static_cast<AppletId>(app_id))) { cmd_buff[2] = 1; // Set to registered - else - cmd_buff[2] = 0; // Set to not registered + } LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); } @@ -330,7 +334,26 @@ void GetAppCpuTimeLimit(Service::Interface* self) { void PrepareToStartLibraryApplet(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); - cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; + auto applet = HLE::Applets::Applet::Get(applet_id); + if (applet) { + LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); + cmd_buff[1] = RESULT_SUCCESS.raw; + } else { + cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; + } + LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); +} + +void PreloadLibraryApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); + auto applet = HLE::Applets::Applet::Get(applet_id); + if (applet) { + LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); + cmd_buff[1] = RESULT_SUCCESS.raw; + } else { + cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; + } LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); } diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 72972d05bb..4a72b6b5c6 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -62,6 +62,7 @@ enum class AppletId : u32 { Extrapad = 0x208, Memolib = 0x209, Application = 0x300, + AnyLibraryApplet = 0x400, SoftwareKeyboard2 = 0x401, }; @@ -96,8 +97,26 @@ void GetSharedFont(Service::Interface* self); */ void NotifyToWait(Service::Interface* self); +/** + * APT::GetLockHandle service function + * Inputs: + * 1 : Applet attributes + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Applet attributes + * 3 : Power button state + * 4 : IPC handle descriptor + * 5 : APT mutex handle + */ void GetLockHandle(Service::Interface* self); +/** + * APT::Enable service function + * Inputs: + * 1 : Applet attributes + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ void Enable(Service::Interface* self); /** @@ -284,6 +303,17 @@ void GetAppCpuTimeLimit(Service::Interface* self); void PrepareToStartLibraryApplet(Service::Interface* self); /** + * APT::PreloadLibraryApplet service function + * Inputs: + * 0 : Command header [0x00160040] + * 1 : Id of the applet to start + * Outputs: + * 0 : Return header + * 1 : Result of function, 0 on success, otherwise error code + */ +void PreloadLibraryApplet(Service::Interface* self); + +/** * APT::StartLibraryApplet service function * Inputs: * 0 : Command header [0x001E0084] diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp index 88de339f97..22800c56f9 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp @@ -21,6 +21,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x000D0080, ReceiveParameter, "ReceiveParameter"}, {0x000E0080, GlanceParameter, "GlanceParameter"}, {0x000F0100, CancelParameter, "CancelParameter"}, + {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, {0x003B0040, nullptr, "CancelLibraryApplet?"}, diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index 396d1f04a4..3ac6ff94fa 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -32,9 +32,9 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00130000, nullptr, "GetPreparationState"}, {0x00140040, nullptr, "SetPreparationState"}, {0x00150140, nullptr, "PrepareToStartApplication"}, - {0x00160040, nullptr, "PreloadLibraryApplet"}, + {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, - {0x00180040, nullptr, "PrepareToStartLibraryApplet"}, + {0x00180040, PrepareToStartLibraryApplet,"PrepareToStartLibraryApplet"}, {0x00190040, nullptr, "PrepareToStartSystemApplet"}, {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, {0x001B00C4, nullptr, "StartApplication"}, diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index b724cd72bd..146bfd5959 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -33,7 +33,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00130000, nullptr, "GetPreparationState"}, {0x00140040, nullptr, "SetPreparationState"}, {0x00150140, nullptr, "PrepareToStartApplication"}, - {0x00160040, nullptr, "PreloadLibraryApplet"}, + {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, {0x00190040, nullptr, "PrepareToStartSystemApplet"}, diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 8b40ba3760..e93c1b4369 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -14,6 +14,7 @@ #include "core/hw/lcd.h" #include "video_core/gpu_debugger.h" +#include "video_core/debug_utils/debug_utils.h" #include "video_core/renderer_base.h" #include "video_core/video_core.h" @@ -226,6 +227,9 @@ void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { &info.format); WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4, &info.shown_fb); + + if (Pica::g_debug_context) + Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); } /** @@ -391,19 +395,24 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { case CommandId::SET_MEMORY_FILL: { auto& params = command.memory_fill; - WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), - Memory::VirtualToPhysicalAddress(params.start1) >> 3); - WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), - Memory::VirtualToPhysicalAddress(params.end1) >> 3); - WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1); - WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), params.control1); - - WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), - Memory::VirtualToPhysicalAddress(params.start2) >> 3); - WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), - Memory::VirtualToPhysicalAddress(params.end2) >> 3); - WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2); - WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), params.control2); + + if (params.start1 != 0) { + WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), + Memory::VirtualToPhysicalAddress(params.start1) >> 3); + WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), + Memory::VirtualToPhysicalAddress(params.end1) >> 3); + WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1); + WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), params.control1); + } + + if (params.start2 != 0) { + WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), + Memory::VirtualToPhysicalAddress(params.start2) >> 3); + WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), + Memory::VirtualToPhysicalAddress(params.end2) >> 3); + WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2); + WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), params.control2); + } break; } @@ -448,6 +457,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { default: LOG_ERROR(Service_GSP, "unknown command 0x%08X", (int)command.id.Value()); } + + if (Pica::g_debug_context) + Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed, (void*)&command); } /** diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 70caa7d802..c35b13b25f 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -35,6 +35,16 @@ static Kernel::SharedPtr<Kernel::Event> event_debug_pad; static u32 next_pad_index; static u32 next_touch_index; +const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = { + Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y, + Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR, + Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE, + Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT, + Service::HID::PAD_CIRCLE_UP, Service::HID::PAD_CIRCLE_DOWN, Service::HID::PAD_CIRCLE_LEFT, Service::HID::PAD_CIRCLE_RIGHT, + Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT +}; + + // TODO(peachum): // Add a method for setting analog input from joystick device for the circle Pad. // diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index d50d479f81..517f4f2ae6 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -9,7 +9,7 @@ #ifndef _MSC_VER #include <cstddef> #endif - +#include "core/settings.h" #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" @@ -157,6 +157,9 @@ const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; const PadState PAD_CIRCLE_UP = {{1u << 30}}; const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; + +extern const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping; + /** * HID::GetIPCHandles service function * Inputs: diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index d0e166fdf9..d768a3fc76 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp @@ -481,11 +481,17 @@ static void GetHostId(Service::Interface* self) { char name[128]; gethostname(name, sizeof(name)); - hostent* host = gethostbyname(name); - in_addr* addr = reinterpret_cast<in_addr*>(host->h_addr); + addrinfo hints = {}; + addrinfo* res; + + hints.ai_family = AF_INET; + getaddrinfo(name, NULL, &hints, &res); + sockaddr_in* sock_addr = reinterpret_cast<sockaddr_in*>(res->ai_addr); + in_addr* addr = &sock_addr->sin_addr; cmd_buffer[2] = addr->s_addr; cmd_buffer[1] = 0; + freeaddrinfo(res); } static void Close(Service::Interface* self) { diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index bdede964e2..bb64fdfb76 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -334,7 +334,7 @@ static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle /// Get resource limit current values static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, - s32 name_count) { + u32 name_count) { LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", resource_limit_handle, names, name_count); @@ -350,7 +350,7 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim /// Get resource limit max values static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, - s32 name_count) { + u32 name_count) { LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", resource_limit_handle, names, name_count); diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 2a338e8fc9..3ccbc03b26 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -151,6 +151,10 @@ inline void Write(u32 addr, const T data) { { const auto& config = g_regs.display_transfer_config; if (config.trigger & 1) { + + if (Pica::g_debug_context) + Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer, nullptr); + u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); u8* dst_pointer = Memory::GetPhysicalPointer(config.GetPhysicalOutputAddress()); diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp index f80e26ecdb..082a4db827 100644 --- a/src/core/hw/y2r.cpp +++ b/src/core/hw/y2r.cpp @@ -14,6 +14,7 @@ #include "common/vector_math.h" #include "core/hle/service/y2r_u.h" +#include "core/hw/y2r.h" #include "core/memory.h" namespace HW { diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index d043fa9bd2..530837d088 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -191,7 +191,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared *pos = (addr); break; case 1: - *pos = (addr - in_addr); + *pos = static_cast<u32>(addr - in_addr); break; default: break; //this should never happen diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 9ef2f8900d..f5b349a776 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -56,18 +56,18 @@ static FileType IdentifyFile(FileUtil::IOFile& file) { static FileType GuessFromExtension(const std::string& extension_) { std::string extension = Common::ToLower(extension_); - if (extension == ".elf") + if (extension == ".elf" || extension == ".axf") return FileType::ELF; - else if (extension == ".axf") - return FileType::ELF; - else if (extension == ".cxi") - return FileType::CXI; - else if (extension == ".cci") - return FileType::CCI; - else if (extension == ".3ds") + + if (extension == ".cci" || extension == ".3ds") return FileType::CCI; - else if (extension == ".3dsx") + + if (extension == ".cxi") + return FileType::CXI; + + if (extension == ".3dsx") return FileType::THREEDSX; + return FileType::Unknown; } diff --git a/src/core/settings.h b/src/core/settings.h index 5a70d157a6..2775ee257c 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -5,34 +5,42 @@ #pragma once #include <string> +#include <array> namespace Settings { +namespace NativeInput { +enum Values { + A, B, X, Y, + L, R, ZL, ZR, + START, SELECT, HOME, + DUP, DDOWN, DLEFT, DRIGHT, + SUP, SDOWN, SLEFT, SRIGHT, + CUP, CDOWN, CLEFT, CRIGHT, + NUM_INPUTS +}; +static const std::array<const char*, NUM_INPUTS> Mapping = { + "pad_a", "pad_b", "pad_x", "pad_y", + "pad_l", "pad_r", "pad_zl", "pad_zr", + "pad_start", "pad_select", "pad_home", + "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", + "pad_sup", "pad_sdown", "pad_sleft", "pad_sright", + "pad_cup", "pad_cdown", "pad_cleft", "pad_cright" +}; +static const std::array<Values, NUM_INPUTS> All = { + A, B, X, Y, + L, R, ZL, ZR, + START, SELECT, HOME, + DUP, DDOWN, DLEFT, DRIGHT, + SUP, SDOWN, SLEFT, SRIGHT, + CUP, CDOWN, CLEFT, CRIGHT +}; +} + + struct Values { // Controls - int pad_a_key; - int pad_b_key; - int pad_x_key; - int pad_y_key; - int pad_l_key; - int pad_r_key; - int pad_zl_key; - int pad_zr_key; - int pad_start_key; - int pad_select_key; - int pad_home_key; - int pad_dup_key; - int pad_ddown_key; - int pad_dleft_key; - int pad_dright_key; - int pad_sup_key; - int pad_sdown_key; - int pad_sleft_key; - int pad_sright_key; - int pad_cup_key; - int pad_cdown_key; - int pad_cleft_key; - int pad_cright_key; + std::array<int, NativeInput::NUM_INPUTS> input_mappings; // Core int frame_skip; diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 5c7f4ae181..162108301a 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -2,7 +2,6 @@ set(SRCS renderer_opengl/generated/gl_3_2_core.c renderer_opengl/gl_rasterizer.cpp renderer_opengl/gl_rasterizer_cache.cpp - renderer_opengl/gl_resource_manager.cpp renderer_opengl/gl_shader_util.cpp renderer_opengl/gl_state.cpp renderer_opengl/renderer_opengl.cpp diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index bbe7e63dc6..36c3b99478 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -50,7 +50,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { regs[id] = (old_value & ~mask) | (value & mask); if (g_debug_context) - g_debug_context->OnEvent(DebugContext::Event::CommandLoaded, reinterpret_cast<void*>(&id)); + g_debug_context->OnEvent(DebugContext::Event::PicaCommandLoaded, reinterpret_cast<void*>(&id)); DebugUtils::OnPicaRegWrite(id, regs[id]); @@ -103,7 +103,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c): case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d): { - unsigned index = id - PICA_REG_INDEX(command_buffer.trigger[0]); + unsigned index = static_cast<unsigned>(id - PICA_REG_INDEX(command_buffer.trigger[0])); u32* head_ptr = (u32*)Memory::GetPhysicalPointer(regs.command_buffer.GetPhysicalAddress(index)); g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; g_state.cmd_list.length = regs.command_buffer.GetSize(index) / sizeof(u32); @@ -116,7 +116,9 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { { Common::Profiling::ScopeTimer scope_timer(category_drawing); +#if PICA_LOG_TEV DebugUtils::DumpTevStageConfig(regs.GetTevStages()); +#endif if (g_debug_context) g_debug_context->OnEvent(DebugContext::Event::IncomingPrimitiveBatch, nullptr); @@ -159,9 +161,11 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { const u16* index_address_16 = (u16*)index_address_8; bool index_u16 = index_info.format != 0; +#if PICA_DUMP_GEOMETRY DebugUtils::GeometryDumper geometry_dumper; - PrimitiveAssembler<VertexShader::OutputVertex> primitive_assembler(regs.triangle_topology.Value()); PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value()); +#endif + PrimitiveAssembler<VertexShader::OutputVertex> primitive_assembler(regs.triangle_topology.Value()); if (g_debug_context) { for (int i = 0; i < 3; ++i) { @@ -267,6 +271,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { if (g_debug_context) g_debug_context->OnEvent(DebugContext::Event::VertexLoaded, (void*)&input); +#if PICA_DUMP_GEOMETRY // NOTE: When dumping geometry, we simply assume that the first input attribute // corresponds to the position for now. DebugUtils::GeometryDumper::Vertex dumped_vertex = { @@ -276,6 +281,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { dumping_primitive_assembler.SubmitVertex(dumped_vertex, std::bind(&DebugUtils::GeometryDumper::AddTriangle, &geometry_dumper, _1, _2, _3)); +#endif // Send to vertex shader VertexShader::OutputVertex output = VertexShader::RunShader(input, attribute_config.GetNumTotalAttributes(), g_state.regs.vs, g_state.vs); @@ -308,7 +314,9 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { VideoCore::g_renderer->hw_rasterizer->DrawTriangles(); } +#if PICA_DUMP_GEOMETRY geometry_dumper.Dump(); +#endif if (g_debug_context) { g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr); @@ -424,7 +432,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id); if (g_debug_context) - g_debug_context->OnEvent(DebugContext::Event::CommandProcessed, reinterpret_cast<void*>(&id)); + g_debug_context->OnEvent(DebugContext::Event::PicaCommandProcessed, reinterpret_cast<void*>(&id)); } void ProcessCommandList(const u32* list, u32 size) { diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index d24c0f11e2..e9a8584114 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp @@ -85,15 +85,11 @@ void GeometryDumper::AddTriangle(Vertex& v0, Vertex& v1, Vertex& v2) { vertices.push_back(v1); vertices.push_back(v2); - int num_vertices = vertices.size(); + int num_vertices = (int)vertices.size(); faces.push_back({ num_vertices-3, num_vertices-2, num_vertices-1 }); } void GeometryDumper::Dump() { - // NOTE: Permanently enabling this just trashes the hard disk for no reason. - // Hence, this is currently disabled. - return; - static int index = 0; std::string filename = std::string("geometry_dump") + std::to_string(++index) + ".obj"; @@ -116,10 +112,6 @@ void GeometryDumper::Dump() { void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, u32 main_offset, const Regs::VSOutputAttributes* output_attributes) { - // NOTE: Permanently enabling this just trashes hard disks for no reason. - // Hence, this is currently disabled. - return; - struct StuffToWrite { u8* pointer; u32 size; @@ -241,8 +233,8 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data dvle.main_offset_words = main_offset; dvle.output_register_table_offset = write_offset - dvlb.dvle_offset; - dvle.output_register_table_size = output_info_table.size(); - QueueForWriting((u8*)output_info_table.data(), output_info_table.size() * sizeof(OutputRegisterInfo)); + dvle.output_register_table_size = static_cast<uint32_t>(output_info_table.size()); + QueueForWriting((u8*)output_info_table.data(), static_cast<u32>(output_info_table.size() * sizeof(OutputRegisterInfo))); // TODO: Create a label table for "main" @@ -497,31 +489,31 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture // Lookup base value Math::Vec3<int> ret; if (differential_mode) { - ret.r() = differential.r; - ret.g() = differential.g; - ret.b() = differential.b; + ret.r() = static_cast<int>(differential.r); + ret.g() = static_cast<int>(differential.g); + ret.b() = static_cast<int>(differential.b); if (x >= 2) { - ret.r() += differential.dr; - ret.g() += differential.dg; - ret.b() += differential.db; + ret.r() += static_cast<int>(differential.dr); + ret.g() += static_cast<int>(differential.dg); + ret.b() += static_cast<int>(differential.db); } ret.r() = Color::Convert5To8(ret.r()); ret.g() = Color::Convert5To8(ret.g()); ret.b() = Color::Convert5To8(ret.b()); } else { if (x < 2) { - ret.r() = Color::Convert4To8(separate.r1); - ret.g() = Color::Convert4To8(separate.g1); - ret.b() = Color::Convert4To8(separate.b1); + ret.r() = Color::Convert4To8(static_cast<u8>(separate.r1)); + ret.g() = Color::Convert4To8(static_cast<u8>(separate.g1)); + ret.b() = Color::Convert4To8(static_cast<u8>(separate.b1)); } else { - ret.r() = Color::Convert4To8(separate.r2); - ret.g() = Color::Convert4To8(separate.g2); - ret.b() = Color::Convert4To8(separate.b2); + ret.r() = Color::Convert4To8(static_cast<u8>(separate.r2)); + ret.g() = Color::Convert4To8(static_cast<u8>(separate.g2)); + ret.b() = Color::Convert4To8(static_cast<u8>(separate.b2)); } } // Add modifier - unsigned table_index = (x < 2) ? table_index_1.Value() : table_index_2.Value(); + unsigned table_index = static_cast<int>((x < 2) ? table_index_1.Value() : table_index_2.Value()); static const std::array<std::array<u8, 2>, 8> etc1_modifier_table = {{ { 2, 8 }, { 5, 17 }, { 9, 29 }, { 13, 42 }, @@ -565,10 +557,6 @@ TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config, } void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { - // NOTE: Permanently enabling this just trashes hard disks for no reason. - // Hence, this is currently disabled. - return; - #ifndef HAVE_PNG return; #else diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h index 2573292e25..81eea30a95 100644 --- a/src/video_core/debug_utils/debug_utils.h +++ b/src/video_core/debug_utils/debug_utils.h @@ -25,11 +25,14 @@ public: enum class Event { FirstEvent = 0, - CommandLoaded = FirstEvent, - CommandProcessed, + PicaCommandLoaded = FirstEvent, + PicaCommandProcessed, IncomingPrimitiveBatch, FinishedPrimitiveBatch, VertexLoaded, + IncomingDisplayTransfer, + GSPCommandProcessed, + BufferSwapped, NumEvents }; @@ -154,6 +157,11 @@ extern std::shared_ptr<DebugContext> g_debug_context; // TODO: Get rid of this g namespace DebugUtils { +#define PICA_DUMP_GEOMETRY 0 +#define PICA_DUMP_SHADERS 0 +#define PICA_DUMP_TEXTURES 0 +#define PICA_LOG_TEV 0 + // Simple utility class for dumping geometry data to an OBJ file class GeometryDumper { public: diff --git a/src/video_core/pica.cpp b/src/video_core/pica.cpp index 543d9c443d..17cb667805 100644 --- a/src/video_core/pica.cpp +++ b/src/video_core/pica.cpp @@ -2,7 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <string.h> +#include <cstring> +#include <unordered_map> #include "pica.h" @@ -10,6 +11,75 @@ namespace Pica { State g_state; +std::string Regs::GetCommandName(int index) { + static std::unordered_map<u32, std::string> map; + + if (map.empty()) { + #define ADD_FIELD(name) \ + map.insert({static_cast<u32>(PICA_REG_INDEX(name)), #name}); \ + /* TODO: change to Regs::name when VS2015 and other compilers support it */ \ + for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \ + map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ + + ADD_FIELD(trigger_irq); + ADD_FIELD(cull_mode); + ADD_FIELD(viewport_size_x); + ADD_FIELD(viewport_size_y); + ADD_FIELD(viewport_depth_range); + ADD_FIELD(viewport_depth_far_plane); + ADD_FIELD(viewport_corner); + ADD_FIELD(texture0_enable); + ADD_FIELD(texture0); + ADD_FIELD(texture0_format); + ADD_FIELD(texture1); + ADD_FIELD(texture1_format); + ADD_FIELD(texture2); + ADD_FIELD(texture2_format); + ADD_FIELD(tev_stage0); + ADD_FIELD(tev_stage1); + ADD_FIELD(tev_stage2); + ADD_FIELD(tev_stage3); + ADD_FIELD(tev_combiner_buffer_input); + ADD_FIELD(tev_stage4); + ADD_FIELD(tev_stage5); + ADD_FIELD(tev_combiner_buffer_color); + ADD_FIELD(output_merger); + ADD_FIELD(framebuffer); + ADD_FIELD(vertex_attributes); + ADD_FIELD(index_array); + ADD_FIELD(num_vertices); + ADD_FIELD(trigger_draw); + ADD_FIELD(trigger_draw_indexed); + ADD_FIELD(vs_default_attributes_setup); + ADD_FIELD(command_buffer); + ADD_FIELD(triangle_topology); + ADD_FIELD(gs.bool_uniforms); + ADD_FIELD(gs.int_uniforms); + ADD_FIELD(gs.main_offset); + ADD_FIELD(gs.input_register_map); + ADD_FIELD(gs.uniform_setup); + ADD_FIELD(gs.program); + ADD_FIELD(gs.swizzle_patterns); + ADD_FIELD(vs.bool_uniforms); + ADD_FIELD(vs.int_uniforms); + ADD_FIELD(vs.main_offset); + ADD_FIELD(vs.input_register_map); + ADD_FIELD(vs.uniform_setup); + ADD_FIELD(vs.program); + ADD_FIELD(vs.swizzle_patterns); + +#undef ADD_FIELD + } + + // Return empty string if no match is found + auto it = map.find(index); + if (it != map.end()) { + return it->second; + } else { + return std::string(); + } +} + void Init() { } diff --git a/src/video_core/pica.h b/src/video_core/pica.h index aec6f06607..34b02b2f83 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -7,7 +7,6 @@ #include <array> #include <cmath> #include <cstddef> -#include <map> #include <string> #include "common/assert.h" @@ -908,69 +907,7 @@ struct Regs { // Map register indices to names readable by humans // Used for debugging purposes, so performance is not an issue here - static std::string GetCommandName(int index) { - std::map<u32, std::string> map; - - #define ADD_FIELD(name) \ - do { \ - map.insert({PICA_REG_INDEX(name), #name}); \ - /* TODO: change to Regs::name when VS2015 and other compilers support it */ \ - for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \ - map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ - } while(false) - - ADD_FIELD(trigger_irq); - ADD_FIELD(cull_mode); - ADD_FIELD(viewport_size_x); - ADD_FIELD(viewport_size_y); - ADD_FIELD(viewport_depth_range); - ADD_FIELD(viewport_depth_far_plane); - ADD_FIELD(viewport_corner); - ADD_FIELD(texture0_enable); - ADD_FIELD(texture0); - ADD_FIELD(texture0_format); - ADD_FIELD(texture1); - ADD_FIELD(texture1_format); - ADD_FIELD(texture2); - ADD_FIELD(texture2_format); - ADD_FIELD(tev_stage0); - ADD_FIELD(tev_stage1); - ADD_FIELD(tev_stage2); - ADD_FIELD(tev_stage3); - ADD_FIELD(tev_combiner_buffer_input); - ADD_FIELD(tev_stage4); - ADD_FIELD(tev_stage5); - ADD_FIELD(tev_combiner_buffer_color); - ADD_FIELD(output_merger); - ADD_FIELD(framebuffer); - ADD_FIELD(vertex_attributes); - ADD_FIELD(index_array); - ADD_FIELD(num_vertices); - ADD_FIELD(trigger_draw); - ADD_FIELD(trigger_draw_indexed); - ADD_FIELD(vs_default_attributes_setup); - ADD_FIELD(command_buffer); - ADD_FIELD(triangle_topology); - ADD_FIELD(gs.bool_uniforms); - ADD_FIELD(gs.int_uniforms); - ADD_FIELD(gs.main_offset); - ADD_FIELD(gs.input_register_map); - ADD_FIELD(gs.uniform_setup); - ADD_FIELD(gs.program); - ADD_FIELD(gs.swizzle_patterns); - ADD_FIELD(vs.bool_uniforms); - ADD_FIELD(vs.int_uniforms); - ADD_FIELD(vs.main_offset); - ADD_FIELD(vs.input_register_map); - ADD_FIELD(vs.uniform_setup); - ADD_FIELD(vs.program); - ADD_FIELD(vs.swizzle_patterns); - - #undef ADD_FIELD - - // Return empty string if no match is found - return map[index]; - } + static std::string GetCommandName(int index); static inline size_t NumIds() { return sizeof(Regs) / sizeof(u32); diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index e2b90ad1c0..68b7cc05db 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -462,7 +462,9 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, // TODO: Apply the min and mag filters to the texture texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info); +#if PICA_DUMP_TEXTURES DebugUtils::DumpTexture(texture.config, texture_data); +#endif } } diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp deleted file mode 100644 index 8f4ae28a4c..0000000000 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "video_core/renderer_opengl/gl_resource_manager.h" -#include "video_core/renderer_opengl/gl_shader_util.h" - -// Textures -OGLTexture::OGLTexture() : handle(0) { -} - -OGLTexture::~OGLTexture() { - Release(); -} - -void OGLTexture::Create() { - if (handle != 0) { - return; - } - - glGenTextures(1, &handle); -} - -void OGLTexture::Release() { - glDeleteTextures(1, &handle); - handle = 0; -} - -// Shaders -OGLShader::OGLShader() : handle(0) { -} - -OGLShader::~OGLShader() { - Release(); -} - -void OGLShader::Create(const char* vert_shader, const char* frag_shader) { - if (handle != 0) { - return; - } - - handle = ShaderUtil::LoadShaders(vert_shader, frag_shader); -} - -void OGLShader::Release() { - glDeleteProgram(handle); - handle = 0; -} - -// Buffer objects -OGLBuffer::OGLBuffer() : handle(0) { -} - -OGLBuffer::~OGLBuffer() { - Release(); -} - -void OGLBuffer::Create() { - if (handle != 0) { - return; - } - - glGenBuffers(1, &handle); -} - -void OGLBuffer::Release() { - glDeleteBuffers(1, &handle); - handle = 0; -} - -// Vertex array objects -OGLVertexArray::OGLVertexArray() : handle(0) { -} - -OGLVertexArray::~OGLVertexArray() { - Release(); -} - -void OGLVertexArray::Create() { - if (handle != 0) { - return; - } - - glGenVertexArrays(1, &handle); -} - -void OGLVertexArray::Release() { - glDeleteVertexArrays(1, &handle); - handle = 0; -} - -// Framebuffers -OGLFramebuffer::OGLFramebuffer() : handle(0) { -} - -OGLFramebuffer::~OGLFramebuffer() { - Release(); -} - -void OGLFramebuffer::Create() { - if (handle != 0) { - return; - } - - glGenFramebuffers(1, &handle); -} - -void OGLFramebuffer::Release() { - glDeleteFramebuffers(1, &handle); - handle = 0; -} diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 975720d0ab..6f9dc012d6 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h @@ -4,76 +4,124 @@ #pragma once +#include <utility> + #include "common/common_types.h" -#include "generated/gl_3_2_core.h" +#include "video_core/renderer_opengl/generated/gl_3_2_core.h" +#include "video_core/renderer_opengl/gl_shader_util.h" -class OGLTexture : public NonCopyable { +class OGLTexture : private NonCopyable { public: - OGLTexture(); - ~OGLTexture(); + OGLTexture() = default; + OGLTexture(OGLTexture&& o) { std::swap(handle, o.handle); } + ~OGLTexture() { Release(); } + OGLTexture& operator=(OGLTexture&& o) { std::swap(handle, o.handle); return *this; } /// Creates a new internal OpenGL resource and stores the handle - void Create(); + void Create() { + if (handle != 0) return; + glGenTextures(1, &handle); + } /// Deletes the internal OpenGL resource - void Release(); + void Release() { + if (handle == 0) return; + glDeleteTextures(1, &handle); + handle = 0; + } - GLuint handle; + GLuint handle = 0; }; -class OGLShader : public NonCopyable { +class OGLShader : private NonCopyable { public: - OGLShader(); - ~OGLShader(); + OGLShader() = default; + OGLShader(OGLShader&& o) { std::swap(handle, o.handle); } + ~OGLShader() { Release(); } + OGLShader& operator=(OGLShader&& o) { std::swap(handle, o.handle); return *this; } /// Creates a new internal OpenGL resource and stores the handle - void Create(const char* vert_shader, const char* frag_shader); + void Create(const char* vert_shader, const char* frag_shader) { + if (handle != 0) return; + handle = ShaderUtil::LoadShaders(vert_shader, frag_shader); + } /// Deletes the internal OpenGL resource - void Release(); + void Release() { + if (handle == 0) return; + glDeleteProgram(handle); + handle = 0; + } - GLuint handle; + GLuint handle = 0; }; -class OGLBuffer : public NonCopyable { +class OGLBuffer : private NonCopyable { public: - OGLBuffer(); - ~OGLBuffer(); + OGLBuffer() = default; + OGLBuffer(OGLBuffer&& o) { std::swap(handle, o.handle); } + ~OGLBuffer() { Release(); } + OGLBuffer& operator=(OGLBuffer&& o) { std::swap(handle, o.handle); return *this; } /// Creates a new internal OpenGL resource and stores the handle - void Create(); + void Create() { + if (handle != 0) return; + glGenBuffers(1, &handle); + } /// Deletes the internal OpenGL resource - void Release(); + void Release() { + if (handle == 0) return; + glDeleteBuffers(1, &handle); + handle = 0; + } - GLuint handle; + GLuint handle = 0; }; -class OGLVertexArray : public NonCopyable { +class OGLVertexArray : private NonCopyable { public: - OGLVertexArray(); - ~OGLVertexArray(); + OGLVertexArray() = default; + OGLVertexArray(OGLVertexArray&& o) { std::swap(handle, o.handle); } + ~OGLVertexArray() { Release(); } + OGLVertexArray& operator=(OGLVertexArray&& o) { std::swap(handle, o.handle); return *this; } /// Creates a new internal OpenGL resource and stores the handle - void Create(); + void Create() { + if (handle != 0) return; + glGenVertexArrays(1, &handle); + } /// Deletes the internal OpenGL resource - void Release(); + void Release() { + if (handle == 0) return; + glDeleteVertexArrays(1, &handle); + handle = 0; + } - GLuint handle; + GLuint handle = 0; }; -class OGLFramebuffer : public NonCopyable { +class OGLFramebuffer : private NonCopyable { public: - OGLFramebuffer(); - ~OGLFramebuffer(); + OGLFramebuffer() = default; + OGLFramebuffer(OGLFramebuffer&& o) { std::swap(handle, o.handle); } + ~OGLFramebuffer() { Release(); } + OGLFramebuffer& operator=(OGLFramebuffer&& o) { std::swap(handle, o.handle); return *this; } /// Creates a new internal OpenGL resource and stores the handle - void Create(); + void Create() { + if (handle != 0) return; + glGenFramebuffers(1, &handle); + } /// Deletes the internal OpenGL resource - void Release(); + void Release() { + if (handle == 0) return; + glDeleteFramebuffers(1, &handle); + handle = 0; + } - GLuint handle; + GLuint handle = 0; }; diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp index ff114fc3a1..5f66f3455f 100644 --- a/src/video_core/vertex_shader.cpp +++ b/src/video_core/vertex_shader.cpp @@ -2,8 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <stack> - +#include <boost/container/static_vector.hpp> #include <boost/range/algorithm.hpp> #include <common/file_util.h> @@ -27,7 +26,7 @@ namespace Pica { namespace VertexShader { struct VertexShaderState { - const u32* program_counter; + u32 program_counter; const float24* input_register_table[16]; Math::Vec4<float24> output_registers[16]; @@ -53,7 +52,7 @@ struct VertexShaderState { }; // TODO: Is there a maximal size for this? - std::stack<CallStackElement> call_stack; + boost::container::static_vector<CallStackElement, 16> call_stack; struct { u32 max_offset; // maximum program counter ever reached @@ -71,15 +70,15 @@ static void ProcessShaderCode(VertexShaderState& state) { while (true) { if (!state.call_stack.empty()) { - auto& top = state.call_stack.top(); - if (state.program_counter - program_code.data() == top.final_address) { + auto& top = state.call_stack.back(); + if (state.program_counter == top.final_address) { state.address_registers[2] += top.loop_increment; if (top.repeat_counter-- == 0) { - state.program_counter = &program_code[top.return_address]; - state.call_stack.pop(); + state.program_counter = top.return_address; + state.call_stack.pop_back(); } else { - state.program_counter = &program_code[top.loop_address]; + state.program_counter = top.loop_address; } // TODO: Is "trying again" accurate to hardware? @@ -88,17 +87,16 @@ static void ProcessShaderCode(VertexShaderState& state) { } bool exit_loop = false; - const Instruction& instr = *(const Instruction*)state.program_counter; - const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id]; + const Instruction instr = { program_code[state.program_counter] }; + const SwizzlePattern swizzle = { swizzle_data[instr.common.operand_desc_id] }; - static auto call = [&program_code](VertexShaderState& state, u32 offset, u32 num_instructions, + static auto call = [](VertexShaderState& state, u32 offset, u32 num_instructions, u32 return_offset, u8 repeat_count, u8 loop_increment) { - state.program_counter = &program_code[offset] - 1; // -1 to make sure when incrementing the PC we end up at the correct offset - state.call_stack.push({ offset + num_instructions, return_offset, repeat_count, loop_increment, offset }); + state.program_counter = offset - 1; // -1 to make sure when incrementing the PC we end up at the correct offset + ASSERT(state.call_stack.size() < state.call_stack.capacity()); + state.call_stack.push_back({ offset + num_instructions, return_offset, repeat_count, loop_increment, offset }); }; - u32 binary_offset = state.program_counter - program_code.data(); - - state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + binary_offset); + state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + state.program_counter); auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* { switch (source_reg.GetRegisterType()) { @@ -442,13 +440,13 @@ static void ProcessShaderCode(VertexShaderState& state) { case OpCode::Id::JMPC: if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { - state.program_counter = &program_code[instr.flow_control.dest_offset] - 1; + state.program_counter = instr.flow_control.dest_offset - 1; } break; case OpCode::Id::JMPU: if (uniforms.b[instr.flow_control.bool_uniform_id]) { - state.program_counter = &program_code[instr.flow_control.dest_offset] - 1; + state.program_counter = instr.flow_control.dest_offset - 1; } break; @@ -456,7 +454,7 @@ static void ProcessShaderCode(VertexShaderState& state) { call(state, instr.flow_control.dest_offset, instr.flow_control.num_instructions, - binary_offset + 1, 0, 0); + state.program_counter + 1, 0, 0); break; case OpCode::Id::CALLU: @@ -464,7 +462,7 @@ static void ProcessShaderCode(VertexShaderState& state) { call(state, instr.flow_control.dest_offset, instr.flow_control.num_instructions, - binary_offset + 1, 0, 0); + state.program_counter + 1, 0, 0); } break; @@ -473,7 +471,7 @@ static void ProcessShaderCode(VertexShaderState& state) { call(state, instr.flow_control.dest_offset, instr.flow_control.num_instructions, - binary_offset + 1, 0, 0); + state.program_counter + 1, 0, 0); } break; @@ -483,8 +481,8 @@ static void ProcessShaderCode(VertexShaderState& state) { case OpCode::Id::IFU: if (uniforms.b[instr.flow_control.bool_uniform_id]) { call(state, - binary_offset + 1, - instr.flow_control.dest_offset - binary_offset - 1, + state.program_counter + 1, + instr.flow_control.dest_offset - state.program_counter - 1, instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); } else { call(state, @@ -501,8 +499,8 @@ static void ProcessShaderCode(VertexShaderState& state) { if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { call(state, - binary_offset + 1, - instr.flow_control.dest_offset - binary_offset - 1, + state.program_counter + 1, + instr.flow_control.dest_offset - state.program_counter - 1, instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); } else { call(state, @@ -519,8 +517,8 @@ static void ProcessShaderCode(VertexShaderState& state) { state.address_registers[2] = uniforms.i[instr.flow_control.int_uniform_id].y; call(state, - binary_offset + 1, - instr.flow_control.dest_offset - binary_offset + 1, + state.program_counter + 1, + instr.flow_control.dest_offset - state.program_counter + 1, instr.flow_control.dest_offset + 1, uniforms.i[instr.flow_control.int_uniform_id].x, uniforms.i[instr.flow_control.int_uniform_id].z); @@ -551,8 +549,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes, const Regs: VertexShaderState state; - const u32* main = &setup.program_code[config.main_offset]; - state.program_counter = (u32*)main; + state.program_counter = config.main_offset; state.debug.max_offset = 0; state.debug.max_opdesc_id = 0; @@ -582,9 +579,11 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes, const Regs: state.conditional_code[1] = false; ProcessShaderCode(state); +#if PICA_DUMP_SHADERS DebugUtils::DumpShader(setup.program_code.data(), state.debug.max_offset, setup.swizzle_data.data(), state.debug.max_opdesc_id, config.main_offset, g_state.regs.vs_output_attributes); // TODO: Don't hardcode VS here +#endif // Setup output data OutputVertex ret; |