diff options
73 files changed, 2071 insertions, 2301 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e945a6679..a02b85da3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -48,7 +48,7 @@ else() | |||
| 48 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "" FORCE) | 48 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "" FORCE) |
| 49 | 49 | ||
| 50 | set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG" CACHE STRING "" FORCE) | 50 | set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG" CACHE STRING "" FORCE) |
| 51 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG" CACHE STRING "" FORCE) | 51 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE) |
| 52 | endif() | 52 | endif() |
| 53 | 53 | ||
| 54 | add_definitions(-DSINGLETHREADED) | 54 | 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 506cb7939..2c1407a6f 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& | |||
| 40 | return true; | 40 | return true; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = { | ||
| 44 | GLFW_KEY_A, GLFW_KEY_S, GLFW_KEY_Z, GLFW_KEY_X, | ||
| 45 | GLFW_KEY_Q, GLFW_KEY_W, GLFW_KEY_1, GLFW_KEY_2, | ||
| 46 | GLFW_KEY_M, GLFW_KEY_N, GLFW_KEY_B, | ||
| 47 | GLFW_KEY_T, GLFW_KEY_G, GLFW_KEY_F, GLFW_KEY_H, | ||
| 48 | GLFW_KEY_UP, GLFW_KEY_DOWN, GLFW_KEY_LEFT, GLFW_KEY_RIGHT, | ||
| 49 | GLFW_KEY_I, GLFW_KEY_K, GLFW_KEY_J, GLFW_KEY_L | ||
| 50 | }; | ||
| 51 | |||
| 43 | void Config::ReadValues() { | 52 | void Config::ReadValues() { |
| 44 | // Controls | 53 | // Controls |
| 45 | Settings::values.pad_a_key = glfw_config->GetInteger("Controls", "pad_a", GLFW_KEY_A); | 54 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { |
| 46 | Settings::values.pad_b_key = glfw_config->GetInteger("Controls", "pad_b", GLFW_KEY_S); | 55 | Settings::values.input_mappings[Settings::NativeInput::All[i]] = |
| 47 | Settings::values.pad_x_key = glfw_config->GetInteger("Controls", "pad_x", GLFW_KEY_Z); | 56 | glfw_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]); |
| 48 | Settings::values.pad_y_key = glfw_config->GetInteger("Controls", "pad_y", GLFW_KEY_X); | 57 | } |
| 49 | Settings::values.pad_l_key = glfw_config->GetInteger("Controls", "pad_l", GLFW_KEY_Q); | ||
| 50 | Settings::values.pad_r_key = glfw_config->GetInteger("Controls", "pad_r", GLFW_KEY_W); | ||
| 51 | Settings::values.pad_zl_key = glfw_config->GetInteger("Controls", "pad_zl", GLFW_KEY_1); | ||
| 52 | Settings::values.pad_zr_key = glfw_config->GetInteger("Controls", "pad_zr", GLFW_KEY_2); | ||
| 53 | Settings::values.pad_start_key = glfw_config->GetInteger("Controls", "pad_start", GLFW_KEY_M); | ||
| 54 | Settings::values.pad_select_key = glfw_config->GetInteger("Controls", "pad_select", GLFW_KEY_N); | ||
| 55 | Settings::values.pad_home_key = glfw_config->GetInteger("Controls", "pad_home", GLFW_KEY_B); | ||
| 56 | Settings::values.pad_dup_key = glfw_config->GetInteger("Controls", "pad_dup", GLFW_KEY_T); | ||
| 57 | Settings::values.pad_ddown_key = glfw_config->GetInteger("Controls", "pad_ddown", GLFW_KEY_G); | ||
| 58 | Settings::values.pad_dleft_key = glfw_config->GetInteger("Controls", "pad_dleft", GLFW_KEY_F); | ||
| 59 | Settings::values.pad_dright_key = glfw_config->GetInteger("Controls", "pad_dright", GLFW_KEY_H); | ||
| 60 | Settings::values.pad_sup_key = glfw_config->GetInteger("Controls", "pad_sup", GLFW_KEY_UP); | ||
| 61 | Settings::values.pad_sdown_key = glfw_config->GetInteger("Controls", "pad_sdown", GLFW_KEY_DOWN); | ||
| 62 | Settings::values.pad_sleft_key = glfw_config->GetInteger("Controls", "pad_sleft", GLFW_KEY_LEFT); | ||
| 63 | Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); | ||
| 64 | Settings::values.pad_cup_key = glfw_config->GetInteger("Controls", "pad_cup", GLFW_KEY_I); | ||
| 65 | Settings::values.pad_cdown_key = glfw_config->GetInteger("Controls", "pad_cdown", GLFW_KEY_K); | ||
| 66 | Settings::values.pad_cleft_key = glfw_config->GetInteger("Controls", "pad_cleft", GLFW_KEY_J); | ||
| 67 | Settings::values.pad_cright_key = glfw_config->GetInteger("Controls", "pad_cright", GLFW_KEY_L); | ||
| 68 | 58 | ||
| 69 | // Core | 59 | // Core |
| 70 | Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0); | 60 | 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 fd5a90d56..1925bece8 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h | |||
| @@ -33,10 +33,6 @@ pad_cleft = | |||
| 33 | pad_cright = | 33 | pad_cright = |
| 34 | 34 | ||
| 35 | [Core] | 35 | [Core] |
| 36 | # The refresh rate for the GPU | ||
| 37 | # Defaults to 30 | ||
| 38 | gpu_refresh_rate = | ||
| 39 | |||
| 40 | # The applied frameskip amount. Must be a power of two. | 36 | # The applied frameskip amount. Must be a power of two. |
| 41 | # 0 (default): No frameskip, 1: x2 frameskip, 2: x4 frameskip, 3: x8 frameskip, etc. | 37 | # 0 (default): No frameskip, 1: x2 frameskip, 2: x4 frameskip, 3: x8 frameskip, etc. |
| 42 | frame_skip = | 38 | frame_skip = |
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp index 42fb683a9..6d6656b5a 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() { | |||
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | void EmuWindow_GLFW::ReloadSetKeymaps() { | 152 | void EmuWindow_GLFW::ReloadSetKeymaps() { |
| 153 | KeyMap::SetKeyMapping({Settings::values.pad_a_key, keyboard_id}, Service::HID::PAD_A); | 153 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { |
| 154 | KeyMap::SetKeyMapping({Settings::values.pad_b_key, keyboard_id}, Service::HID::PAD_B); | 154 | KeyMap::SetKeyMapping({Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, Service::HID::pad_mapping[i]); |
| 155 | KeyMap::SetKeyMapping({Settings::values.pad_select_key, keyboard_id}, Service::HID::PAD_SELECT); | 155 | } |
| 156 | KeyMap::SetKeyMapping({Settings::values.pad_start_key, keyboard_id}, Service::HID::PAD_START); | ||
| 157 | KeyMap::SetKeyMapping({Settings::values.pad_dright_key, keyboard_id}, Service::HID::PAD_RIGHT); | ||
| 158 | KeyMap::SetKeyMapping({Settings::values.pad_dleft_key, keyboard_id}, Service::HID::PAD_LEFT); | ||
| 159 | KeyMap::SetKeyMapping({Settings::values.pad_dup_key, keyboard_id}, Service::HID::PAD_UP); | ||
| 160 | KeyMap::SetKeyMapping({Settings::values.pad_ddown_key, keyboard_id}, Service::HID::PAD_DOWN); | ||
| 161 | KeyMap::SetKeyMapping({Settings::values.pad_r_key, keyboard_id}, Service::HID::PAD_R); | ||
| 162 | KeyMap::SetKeyMapping({Settings::values.pad_l_key, keyboard_id}, Service::HID::PAD_L); | ||
| 163 | KeyMap::SetKeyMapping({Settings::values.pad_x_key, keyboard_id}, Service::HID::PAD_X); | ||
| 164 | KeyMap::SetKeyMapping({Settings::values.pad_y_key, keyboard_id}, Service::HID::PAD_Y); | ||
| 165 | |||
| 166 | KeyMap::SetKeyMapping({Settings::values.pad_zl_key, keyboard_id}, Service::HID::PAD_ZL); | ||
| 167 | KeyMap::SetKeyMapping({Settings::values.pad_zr_key, keyboard_id}, Service::HID::PAD_ZR); | ||
| 168 | |||
| 169 | // KeyMap::SetKeyMapping({Settings::values.pad_touch_key, keyboard_id}, Service::HID::PAD_TOUCH); | ||
| 170 | |||
| 171 | KeyMap::SetKeyMapping({Settings::values.pad_cright_key, keyboard_id}, Service::HID::PAD_C_RIGHT); | ||
| 172 | KeyMap::SetKeyMapping({Settings::values.pad_cleft_key, keyboard_id}, Service::HID::PAD_C_LEFT); | ||
| 173 | KeyMap::SetKeyMapping({Settings::values.pad_cup_key, keyboard_id}, Service::HID::PAD_C_UP); | ||
| 174 | KeyMap::SetKeyMapping({Settings::values.pad_cdown_key, keyboard_id}, Service::HID::PAD_C_DOWN); | ||
| 175 | KeyMap::SetKeyMapping({Settings::values.pad_sright_key, keyboard_id}, Service::HID::PAD_CIRCLE_RIGHT); | ||
| 176 | KeyMap::SetKeyMapping({Settings::values.pad_sleft_key, keyboard_id}, Service::HID::PAD_CIRCLE_LEFT); | ||
| 177 | KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, Service::HID::PAD_CIRCLE_UP); | ||
| 178 | KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, Service::HID::PAD_CIRCLE_DOWN); | ||
| 179 | } | 156 | } |
| 180 | 157 | ||
| 181 | void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { | 158 | 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 fa7bce466..b12bd858b 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp | |||
| @@ -248,32 +248,9 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent *event) | |||
| 248 | 248 | ||
| 249 | void GRenderWindow::ReloadSetKeymaps() | 249 | void GRenderWindow::ReloadSetKeymaps() |
| 250 | { | 250 | { |
| 251 | KeyMap::SetKeyMapping({Settings::values.pad_a_key, keyboard_id}, Service::HID::PAD_A); | 251 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { |
| 252 | KeyMap::SetKeyMapping({Settings::values.pad_b_key, keyboard_id}, Service::HID::PAD_B); | 252 | KeyMap::SetKeyMapping({Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, Service::HID::pad_mapping[i]); |
| 253 | KeyMap::SetKeyMapping({Settings::values.pad_select_key, keyboard_id}, Service::HID::PAD_SELECT); | 253 | } |
| 254 | KeyMap::SetKeyMapping({Settings::values.pad_start_key, keyboard_id}, Service::HID::PAD_START); | ||
| 255 | KeyMap::SetKeyMapping({Settings::values.pad_dright_key, keyboard_id}, Service::HID::PAD_RIGHT); | ||
| 256 | KeyMap::SetKeyMapping({Settings::values.pad_dleft_key, keyboard_id}, Service::HID::PAD_LEFT); | ||
| 257 | KeyMap::SetKeyMapping({Settings::values.pad_dup_key, keyboard_id}, Service::HID::PAD_UP); | ||
| 258 | KeyMap::SetKeyMapping({Settings::values.pad_ddown_key, keyboard_id}, Service::HID::PAD_DOWN); | ||
| 259 | KeyMap::SetKeyMapping({Settings::values.pad_r_key, keyboard_id}, Service::HID::PAD_R); | ||
| 260 | KeyMap::SetKeyMapping({Settings::values.pad_l_key, keyboard_id}, Service::HID::PAD_L); | ||
| 261 | KeyMap::SetKeyMapping({Settings::values.pad_x_key, keyboard_id}, Service::HID::PAD_X); | ||
| 262 | KeyMap::SetKeyMapping({Settings::values.pad_y_key, keyboard_id}, Service::HID::PAD_Y); | ||
| 263 | |||
| 264 | KeyMap::SetKeyMapping({Settings::values.pad_zl_key, keyboard_id}, Service::HID::PAD_ZL); | ||
| 265 | KeyMap::SetKeyMapping({Settings::values.pad_zr_key, keyboard_id}, Service::HID::PAD_ZR); | ||
| 266 | |||
| 267 | // KeyMap::SetKeyMapping({Settings::values.pad_touch_key, keyboard_id}, Service::HID::PAD_TOUCH); | ||
| 268 | |||
| 269 | KeyMap::SetKeyMapping({Settings::values.pad_cright_key, keyboard_id}, Service::HID::PAD_C_RIGHT); | ||
| 270 | KeyMap::SetKeyMapping({Settings::values.pad_cleft_key, keyboard_id}, Service::HID::PAD_C_LEFT); | ||
| 271 | KeyMap::SetKeyMapping({Settings::values.pad_cup_key, keyboard_id}, Service::HID::PAD_C_UP); | ||
| 272 | KeyMap::SetKeyMapping({Settings::values.pad_cdown_key, keyboard_id}, Service::HID::PAD_C_DOWN); | ||
| 273 | KeyMap::SetKeyMapping({Settings::values.pad_sright_key, keyboard_id}, Service::HID::PAD_CIRCLE_RIGHT); | ||
| 274 | KeyMap::SetKeyMapping({Settings::values.pad_sleft_key, keyboard_id}, Service::HID::PAD_CIRCLE_LEFT); | ||
| 275 | KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, Service::HID::PAD_CIRCLE_UP); | ||
| 276 | KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, Service::HID::PAD_CIRCLE_DOWN); | ||
| 277 | } | 254 | } |
| 278 | 255 | ||
| 279 | void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) | 256 | void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) |
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index 5c056446e..5716634ee 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp | |||
| @@ -21,31 +21,21 @@ Config::Config() { | |||
| 21 | Reload(); | 21 | Reload(); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | static const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> defaults = { | ||
| 25 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, | ||
| 26 | Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2, | ||
| 27 | Qt::Key_M, Qt::Key_N, Qt::Key_B, | ||
| 28 | Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, | ||
| 29 | Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, | ||
| 30 | Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L | ||
| 31 | }; | ||
| 32 | |||
| 24 | void Config::ReadValues() { | 33 | void Config::ReadValues() { |
| 25 | qt_config->beginGroup("Controls"); | 34 | qt_config->beginGroup("Controls"); |
| 26 | Settings::values.pad_a_key = qt_config->value("pad_a", Qt::Key_A).toInt(); | 35 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { |
| 27 | Settings::values.pad_b_key = qt_config->value("pad_b", Qt::Key_S).toInt(); | 36 | Settings::values.input_mappings[Settings::NativeInput::All[i]] = |
| 28 | Settings::values.pad_x_key = qt_config->value("pad_x", Qt::Key_Z).toInt(); | 37 | qt_config->value(QString::fromStdString(Settings::NativeInput::Mapping[i]), defaults[i]).toInt(); |
| 29 | Settings::values.pad_y_key = qt_config->value("pad_y", Qt::Key_X).toInt(); | 38 | } |
| 30 | Settings::values.pad_l_key = qt_config->value("pad_l", Qt::Key_Q).toInt(); | ||
| 31 | Settings::values.pad_r_key = qt_config->value("pad_r", Qt::Key_W).toInt(); | ||
| 32 | Settings::values.pad_zl_key = qt_config->value("pad_zl", Qt::Key_1).toInt(); | ||
| 33 | Settings::values.pad_zr_key = qt_config->value("pad_zr", Qt::Key_2).toInt(); | ||
| 34 | Settings::values.pad_start_key = qt_config->value("pad_start", Qt::Key_M).toInt(); | ||
| 35 | Settings::values.pad_select_key = qt_config->value("pad_select", Qt::Key_N).toInt(); | ||
| 36 | Settings::values.pad_home_key = qt_config->value("pad_home", Qt::Key_B).toInt(); | ||
| 37 | Settings::values.pad_dup_key = qt_config->value("pad_dup", Qt::Key_T).toInt(); | ||
| 38 | Settings::values.pad_ddown_key = qt_config->value("pad_ddown", Qt::Key_G).toInt(); | ||
| 39 | Settings::values.pad_dleft_key = qt_config->value("pad_dleft", Qt::Key_F).toInt(); | ||
| 40 | Settings::values.pad_dright_key = qt_config->value("pad_dright", Qt::Key_H).toInt(); | ||
| 41 | Settings::values.pad_sup_key = qt_config->value("pad_sup", Qt::Key_Up).toInt(); | ||
| 42 | Settings::values.pad_sdown_key = qt_config->value("pad_sdown", Qt::Key_Down).toInt(); | ||
| 43 | Settings::values.pad_sleft_key = qt_config->value("pad_sleft", Qt::Key_Left).toInt(); | ||
| 44 | Settings::values.pad_sright_key = qt_config->value("pad_sright", Qt::Key_Right).toInt(); | ||
| 45 | Settings::values.pad_cup_key = qt_config->value("pad_cup", Qt::Key_I).toInt(); | ||
| 46 | Settings::values.pad_cdown_key = qt_config->value("pad_cdown", Qt::Key_K).toInt(); | ||
| 47 | Settings::values.pad_cleft_key = qt_config->value("pad_cleft", Qt::Key_J).toInt(); | ||
| 48 | Settings::values.pad_cright_key = qt_config->value("pad_cright", Qt::Key_L).toInt(); | ||
| 49 | qt_config->endGroup(); | 39 | qt_config->endGroup(); |
| 50 | 40 | ||
| 51 | qt_config->beginGroup("Core"); | 41 | qt_config->beginGroup("Core"); |
| @@ -75,29 +65,10 @@ void Config::ReadValues() { | |||
| 75 | 65 | ||
| 76 | void Config::SaveValues() { | 66 | void Config::SaveValues() { |
| 77 | qt_config->beginGroup("Controls"); | 67 | qt_config->beginGroup("Controls"); |
| 78 | qt_config->setValue("pad_a", Settings::values.pad_a_key); | 68 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { |
| 79 | qt_config->setValue("pad_b", Settings::values.pad_b_key); | 69 | qt_config->setValue(QString::fromStdString(Settings::NativeInput::Mapping[i]), |
| 80 | qt_config->setValue("pad_x", Settings::values.pad_x_key); | 70 | Settings::values.input_mappings[Settings::NativeInput::All[i]]); |
| 81 | qt_config->setValue("pad_y", Settings::values.pad_y_key); | 71 | } |
| 82 | qt_config->setValue("pad_l", Settings::values.pad_l_key); | ||
| 83 | qt_config->setValue("pad_r", Settings::values.pad_r_key); | ||
| 84 | qt_config->setValue("pad_zl", Settings::values.pad_zl_key); | ||
| 85 | qt_config->setValue("pad_zr", Settings::values.pad_zr_key); | ||
| 86 | qt_config->setValue("pad_start", Settings::values.pad_start_key); | ||
| 87 | qt_config->setValue("pad_select", Settings::values.pad_select_key); | ||
| 88 | qt_config->setValue("pad_home", Settings::values.pad_home_key); | ||
| 89 | qt_config->setValue("pad_dup", Settings::values.pad_dup_key); | ||
| 90 | qt_config->setValue("pad_ddown", Settings::values.pad_ddown_key); | ||
| 91 | qt_config->setValue("pad_dleft", Settings::values.pad_dleft_key); | ||
| 92 | qt_config->setValue("pad_dright", Settings::values.pad_dright_key); | ||
| 93 | qt_config->setValue("pad_sup", Settings::values.pad_sup_key); | ||
| 94 | qt_config->setValue("pad_sdown", Settings::values.pad_sdown_key); | ||
| 95 | qt_config->setValue("pad_sleft", Settings::values.pad_sleft_key); | ||
| 96 | qt_config->setValue("pad_sright", Settings::values.pad_sright_key); | ||
| 97 | qt_config->setValue("pad_cup", Settings::values.pad_cup_key); | ||
| 98 | qt_config->setValue("pad_cdown", Settings::values.pad_cdown_key); | ||
| 99 | qt_config->setValue("pad_cleft", Settings::values.pad_cleft_key); | ||
| 100 | qt_config->setValue("pad_cright", Settings::values.pad_cright_key); | ||
| 101 | qt_config->endGroup(); | 72 | qt_config->endGroup(); |
| 102 | 73 | ||
| 103 | qt_config->beginGroup("Core"); | 74 | qt_config->beginGroup("Core"); |
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index b41c40a0e..1e5ef5299 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #include "common/break_points.h" | 15 | #include "common/break_points.h" |
| 16 | #include "common/symbols.h" | 16 | #include "common/symbols.h" |
| 17 | #include "core/arm/arm_interface.h" | 17 | #include "core/arm/arm_interface.h" |
| 18 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 19 | #include "core/arm/disassembler/arm_disasm.h" | 18 | #include "core/arm/disassembler/arm_disasm.h" |
| 20 | 19 | ||
| 21 | 20 | ||
| @@ -219,7 +218,7 @@ void DisassemblerWidget::OnToggleStartStop() { | |||
| 219 | } | 218 | } |
| 220 | 219 | ||
| 221 | void DisassemblerWidget::OnDebugModeEntered() { | 220 | void DisassemblerWidget::OnDebugModeEntered() { |
| 222 | ARMword next_instr = Core::g_app_core->GetPC(); | 221 | u32 next_instr = Core::g_app_core->GetPC(); |
| 223 | 222 | ||
| 224 | if (model->GetBreakPoints().IsAddressBreakPoint(next_instr)) | 223 | if (model->GetBreakPoints().IsAddressBreakPoint(next_instr)) |
| 225 | emu_thread->SetRunning(false); | 224 | emu_thread->SetRunning(false); |
diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 1da64f616..5202c168c 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <QMetaType> | 5 | #include <QMetaType> |
| 6 | #include <QPushButton> | 6 | #include <QPushButton> |
| 7 | #include <QTreeWidget> | 7 | #include <QTreeView> |
| 8 | #include <QVBoxLayout> | 8 | #include <QVBoxLayout> |
| 9 | #include <QLabel> | 9 | #include <QLabel> |
| 10 | 10 | ||
| @@ -23,7 +23,7 @@ BreakPointModel::BreakPointModel(std::shared_ptr<Pica::DebugContext> debug_conte | |||
| 23 | 23 | ||
| 24 | int BreakPointModel::columnCount(const QModelIndex& parent) const | 24 | int BreakPointModel::columnCount(const QModelIndex& parent) const |
| 25 | { | 25 | { |
| 26 | return 2; | 26 | return 1; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | int BreakPointModel::rowCount(const QModelIndex& parent) const | 29 | int BreakPointModel::rowCount(const QModelIndex& parent) const |
| @@ -38,29 +38,29 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const | |||
| 38 | switch (role) { | 38 | switch (role) { |
| 39 | case Qt::DisplayRole: | 39 | case Qt::DisplayRole: |
| 40 | { | 40 | { |
| 41 | switch (index.column()) { | 41 | if (index.column() == 0) { |
| 42 | case 0: | ||
| 43 | { | ||
| 44 | static const std::map<Pica::DebugContext::Event, QString> map = { | 42 | static const std::map<Pica::DebugContext::Event, QString> map = { |
| 45 | { Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded") }, | 43 | { Pica::DebugContext::Event::PicaCommandLoaded, tr("Pica command loaded") }, |
| 46 | { Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed") }, | 44 | { Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed") }, |
| 47 | { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") }, | 45 | { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") }, |
| 48 | { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") }, | 46 | { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") }, |
| 49 | { Pica::DebugContext::Event::VertexLoaded, tr("Vertex loaded") } | 47 | { Pica::DebugContext::Event::VertexLoaded, tr("Vertex loaded") }, |
| 48 | { Pica::DebugContext::Event::IncomingDisplayTransfer, tr("Incoming display transfer") }, | ||
| 49 | { Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed") }, | ||
| 50 | { Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped") } | ||
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | DEBUG_ASSERT(map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); | 53 | DEBUG_ASSERT(map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); |
| 53 | |||
| 54 | return (map.find(event) != map.end()) ? map.at(event) : QString(); | 54 | return (map.find(event) != map.end()) ? map.at(event) : QString(); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | case 1: | 57 | break; |
| 58 | return data(index, Role_IsEnabled).toBool() ? tr("Enabled") : tr("Disabled"); | 58 | } |
| 59 | |||
| 60 | default: | ||
| 61 | break; | ||
| 62 | } | ||
| 63 | 59 | ||
| 60 | case Qt::CheckStateRole: | ||
| 61 | { | ||
| 62 | if (index.column() == 0) | ||
| 63 | return data(index, Role_IsEnabled).toBool() ? Qt::Checked : Qt::Unchecked; | ||
| 64 | break; | 64 | break; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| @@ -84,37 +84,34 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const | |||
| 84 | return QVariant(); | 84 | return QVariant(); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | QVariant BreakPointModel::headerData(int section, Qt::Orientation orientation, int role) const | 87 | Qt::ItemFlags BreakPointModel::flags(const QModelIndex &index) const |
| 88 | { | 88 | { |
| 89 | switch(role) { | 89 | if (!index.isValid()) |
| 90 | case Qt::DisplayRole: | 90 | return 0; |
| 91 | { | ||
| 92 | if (section == 0) { | ||
| 93 | return tr("Event"); | ||
| 94 | } else if (section == 1) { | ||
| 95 | return tr("Status"); | ||
| 96 | } | ||
| 97 | |||
| 98 | break; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | 91 | ||
| 102 | return QVariant(); | 92 | Qt::ItemFlags flags = Qt::ItemIsEnabled; |
| 93 | if (index.column() == 0) | ||
| 94 | flags |= Qt::ItemIsUserCheckable; | ||
| 95 | return flags; | ||
| 103 | } | 96 | } |
| 104 | 97 | ||
| 98 | |||
| 105 | bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) | 99 | bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) |
| 106 | { | 100 | { |
| 107 | const auto event = static_cast<Pica::DebugContext::Event>(index.row()); | 101 | const auto event = static_cast<Pica::DebugContext::Event>(index.row()); |
| 108 | 102 | ||
| 109 | switch (role) { | 103 | switch (role) { |
| 110 | case Role_IsEnabled: | 104 | case Qt::CheckStateRole: |
| 111 | { | 105 | { |
| 106 | if (index.column() != 0) | ||
| 107 | return false; | ||
| 108 | |||
| 112 | auto context = context_weak.lock(); | 109 | auto context = context_weak.lock(); |
| 113 | if (!context) | 110 | if (!context) |
| 114 | return false; | 111 | return false; |
| 115 | 112 | ||
| 116 | context->breakpoints[event].enabled = value.toBool(); | 113 | context->breakpoints[event].enabled = value == Qt::Checked; |
| 117 | QModelIndex changed_index = createIndex(index.row(), 1); | 114 | QModelIndex changed_index = createIndex(index.row(), 0); |
| 118 | emit dataChanged(changed_index, changed_index); | 115 | emit dataChanged(changed_index, changed_index); |
| 119 | return true; | 116 | return true; |
| 120 | } | 117 | } |
| @@ -133,7 +130,7 @@ void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) | |||
| 133 | active_breakpoint = context->active_breakpoint; | 130 | active_breakpoint = context->active_breakpoint; |
| 134 | at_breakpoint = context->at_breakpoint; | 131 | at_breakpoint = context->at_breakpoint; |
| 135 | emit dataChanged(createIndex(static_cast<int>(event), 0), | 132 | emit dataChanged(createIndex(static_cast<int>(event), 0), |
| 136 | createIndex(static_cast<int>(event), 1)); | 133 | createIndex(static_cast<int>(event), 0)); |
| 137 | } | 134 | } |
| 138 | 135 | ||
| 139 | void BreakPointModel::OnResumed() | 136 | void BreakPointModel::OnResumed() |
| @@ -144,7 +141,7 @@ void BreakPointModel::OnResumed() | |||
| 144 | 141 | ||
| 145 | at_breakpoint = context->at_breakpoint; | 142 | at_breakpoint = context->at_breakpoint; |
| 146 | emit dataChanged(createIndex(static_cast<int>(active_breakpoint), 0), | 143 | emit dataChanged(createIndex(static_cast<int>(active_breakpoint), 0), |
| 147 | createIndex(static_cast<int>(active_breakpoint), 1)); | 144 | createIndex(static_cast<int>(active_breakpoint), 0)); |
| 148 | active_breakpoint = context->active_breakpoint; | 145 | active_breakpoint = context->active_breakpoint; |
| 149 | } | 146 | } |
| 150 | 147 | ||
| @@ -162,13 +159,15 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug | |||
| 162 | 159 | ||
| 163 | breakpoint_model = new BreakPointModel(debug_context, this); | 160 | breakpoint_model = new BreakPointModel(debug_context, this); |
| 164 | breakpoint_list = new QTreeView; | 161 | breakpoint_list = new QTreeView; |
| 162 | breakpoint_list->setRootIsDecorated(false); | ||
| 163 | breakpoint_list->setHeaderHidden(true); | ||
| 165 | breakpoint_list->setModel(breakpoint_model); | 164 | breakpoint_list->setModel(breakpoint_model); |
| 166 | 165 | ||
| 167 | toggle_breakpoint_button = new QPushButton(tr("Enable")); | ||
| 168 | toggle_breakpoint_button->setEnabled(false); | ||
| 169 | |||
| 170 | qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); | 166 | qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); |
| 171 | 167 | ||
| 168 | connect(breakpoint_list, SIGNAL(doubleClicked(const QModelIndex&)), | ||
| 169 | this, SLOT(OnItemDoubleClicked(const QModelIndex&))); | ||
| 170 | |||
| 172 | connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested())); | 171 | connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested())); |
| 173 | 172 | ||
| 174 | connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), | 173 | connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), |
| @@ -184,11 +183,6 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug | |||
| 184 | connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&,const QModelIndex&)), | 183 | connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&,const QModelIndex&)), |
| 185 | breakpoint_model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))); | 184 | breakpoint_model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))); |
| 186 | 185 | ||
| 187 | connect(breakpoint_list->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), | ||
| 188 | this, SLOT(OnBreakpointSelectionChanged(QModelIndex))); | ||
| 189 | |||
| 190 | connect(toggle_breakpoint_button, SIGNAL(clicked()), this, SLOT(OnToggleBreakpointEnabled())); | ||
| 191 | |||
| 192 | QWidget* main_widget = new QWidget; | 186 | QWidget* main_widget = new QWidget; |
| 193 | auto main_layout = new QVBoxLayout; | 187 | auto main_layout = new QVBoxLayout; |
| 194 | { | 188 | { |
| @@ -198,7 +192,6 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug | |||
| 198 | main_layout->addLayout(sub_layout); | 192 | main_layout->addLayout(sub_layout); |
| 199 | } | 193 | } |
| 200 | main_layout->addWidget(breakpoint_list); | 194 | main_layout->addWidget(breakpoint_list); |
| 201 | main_layout->addWidget(toggle_breakpoint_button); | ||
| 202 | main_widget->setLayout(main_layout); | 195 | main_widget->setLayout(main_layout); |
| 203 | 196 | ||
| 204 | setWidget(main_widget); | 197 | setWidget(main_widget); |
| @@ -234,32 +227,15 @@ void GraphicsBreakPointsWidget::OnResumeRequested() | |||
| 234 | context->Resume(); | 227 | context->Resume(); |
| 235 | } | 228 | } |
| 236 | 229 | ||
| 237 | void GraphicsBreakPointsWidget::OnBreakpointSelectionChanged(const QModelIndex& index) | 230 | void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index) |
| 238 | { | 231 | { |
| 239 | if (!index.isValid()) { | 232 | if (!index.isValid()) |
| 240 | toggle_breakpoint_button->setEnabled(false); | ||
| 241 | return; | 233 | return; |
| 242 | } | ||
| 243 | 234 | ||
| 244 | toggle_breakpoint_button->setEnabled(true); | 235 | QModelIndex check_index = breakpoint_list->model()->index(index.row(), 0); |
| 245 | UpdateToggleBreakpointButton(index); | 236 | QVariant enabled = breakpoint_list->model()->data(check_index, Qt::CheckStateRole); |
| 246 | } | 237 | QVariant new_state = Qt::Unchecked; |
| 247 | 238 | if (enabled == Qt::Unchecked) | |
| 248 | void GraphicsBreakPointsWidget::OnToggleBreakpointEnabled() | 239 | new_state = Qt::Checked; |
| 249 | { | 240 | breakpoint_list->model()->setData(check_index, new_state, Qt::CheckStateRole); |
| 250 | QModelIndex index = breakpoint_list->selectionModel()->currentIndex(); | ||
| 251 | bool new_state = !(breakpoint_model->data(index, BreakPointModel::Role_IsEnabled).toBool()); | ||
| 252 | |||
| 253 | breakpoint_model->setData(index, new_state, | ||
| 254 | BreakPointModel::Role_IsEnabled); | ||
| 255 | UpdateToggleBreakpointButton(index); | ||
| 256 | } | ||
| 257 | |||
| 258 | void GraphicsBreakPointsWidget::UpdateToggleBreakpointButton(const QModelIndex& index) | ||
| 259 | { | ||
| 260 | if (true == breakpoint_model->data(index, BreakPointModel::Role_IsEnabled).toBool()) { | ||
| 261 | toggle_breakpoint_button->setText(tr("Disable")); | ||
| 262 | } else { | ||
| 263 | toggle_breakpoint_button->setText(tr("Enable")); | ||
| 264 | } | ||
| 265 | } | 241 | } |
diff --git a/src/citra_qt/debugger/graphics_breakpoints.h b/src/citra_qt/debugger/graphics_breakpoints.h index 5b9ba324e..d900729da 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.h +++ b/src/citra_qt/debugger/graphics_breakpoints.h | |||
| @@ -31,10 +31,9 @@ public: | |||
| 31 | 31 | ||
| 32 | public slots: | 32 | public slots: |
| 33 | void OnBreakPointHit(Pica::DebugContext::Event event, void* data); | 33 | void OnBreakPointHit(Pica::DebugContext::Event event, void* data); |
| 34 | void OnItemDoubleClicked(const QModelIndex&); | ||
| 34 | void OnResumeRequested(); | 35 | void OnResumeRequested(); |
| 35 | void OnResumed(); | 36 | void OnResumed(); |
| 36 | void OnBreakpointSelectionChanged(const QModelIndex&); | ||
| 37 | void OnToggleBreakpointEnabled(); | ||
| 38 | 37 | ||
| 39 | signals: | 38 | signals: |
| 40 | void Resumed(); | 39 | void Resumed(); |
| @@ -42,11 +41,8 @@ signals: | |||
| 42 | void BreakPointsChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); | 41 | void BreakPointsChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); |
| 43 | 42 | ||
| 44 | private: | 43 | private: |
| 45 | void UpdateToggleBreakpointButton(const QModelIndex& index); | ||
| 46 | |||
| 47 | QLabel* status_text; | 44 | QLabel* status_text; |
| 48 | QPushButton* resume_button; | 45 | QPushButton* resume_button; |
| 49 | QPushButton* toggle_breakpoint_button; | ||
| 50 | 46 | ||
| 51 | BreakPointModel* breakpoint_model; | 47 | BreakPointModel* breakpoint_model; |
| 52 | QTreeView* breakpoint_list; | 48 | QTreeView* breakpoint_list; |
diff --git a/src/citra_qt/debugger/graphics_breakpoints_p.h b/src/citra_qt/debugger/graphics_breakpoints_p.h index 34e72e859..00d8d5101 100644 --- a/src/citra_qt/debugger/graphics_breakpoints_p.h +++ b/src/citra_qt/debugger/graphics_breakpoints_p.h | |||
| @@ -23,7 +23,7 @@ public: | |||
| 23 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; | 23 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; |
| 24 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; | 24 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
| 25 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; | 25 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; |
| 26 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; | 26 | Qt::ItemFlags flags(const QModelIndex &index) const; |
| 27 | 27 | ||
| 28 | bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; | 28 | bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; |
| 29 | 29 | ||
diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp index 392ff570b..7ac3ea542 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics_cmdlists.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <QPushButton> | 10 | #include <QPushButton> |
| 11 | #include <QVBoxLayout> | 11 | #include <QVBoxLayout> |
| 12 | #include <QTreeView> | 12 | #include <QTreeView> |
| 13 | #include <QHeaderView> | ||
| 13 | #include <QSpinBox> | 14 | #include <QSpinBox> |
| 14 | #include <QComboBox> | 15 | #include <QComboBox> |
| 15 | 16 | ||
| @@ -170,11 +171,11 @@ GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(p | |||
| 170 | } | 171 | } |
| 171 | 172 | ||
| 172 | int GPUCommandListModel::rowCount(const QModelIndex& parent) const { | 173 | int GPUCommandListModel::rowCount(const QModelIndex& parent) const { |
| 173 | return pica_trace.writes.size(); | 174 | return static_cast<int>(pica_trace.writes.size()); |
| 174 | } | 175 | } |
| 175 | 176 | ||
| 176 | int GPUCommandListModel::columnCount(const QModelIndex& parent) const { | 177 | int GPUCommandListModel::columnCount(const QModelIndex& parent) const { |
| 177 | return 2; | 178 | return 3; |
| 178 | } | 179 | } |
| 179 | 180 | ||
| 180 | QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { | 181 | QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { |
| @@ -187,14 +188,13 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { | |||
| 187 | 188 | ||
| 188 | if (role == Qt::DisplayRole) { | 189 | if (role == Qt::DisplayRole) { |
| 189 | QString content; | 190 | QString content; |
| 190 | if (index.column() == 0) { | 191 | switch ( index.column() ) { |
| 191 | QString content = QString::fromLatin1(Pica::Regs::GetCommandName(cmd.cmd_id).c_str()); | 192 | case 0: |
| 192 | content.append(" "); | 193 | return QString::fromLatin1(Pica::Regs::GetCommandName(cmd.cmd_id).c_str()); |
| 193 | return content; | 194 | case 1: |
| 194 | } else if (index.column() == 1) { | 195 | return QString("%1").arg(cmd.cmd_id, 3, 16, QLatin1Char('0')); |
| 195 | QString content = QString("%1 ").arg(cmd.hex, 8, 16, QLatin1Char('0')); | 196 | case 2: |
| 196 | content.append(QString("%1 ").arg(val, 8, 16, QLatin1Char('0'))); | 197 | return QString("%1").arg(val, 8, 16, QLatin1Char('0')); |
| 197 | return content; | ||
| 198 | } | 198 | } |
| 199 | } else if (role == CommandIdRole) { | 199 | } else if (role == CommandIdRole) { |
| 200 | return QVariant::fromValue<int>(cmd.cmd_id.Value()); | 200 | return QVariant::fromValue<int>(cmd.cmd_id.Value()); |
| @@ -207,10 +207,13 @@ QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientatio | |||
| 207 | switch(role) { | 207 | switch(role) { |
| 208 | case Qt::DisplayRole: | 208 | case Qt::DisplayRole: |
| 209 | { | 209 | { |
| 210 | if (section == 0) { | 210 | switch (section) { |
| 211 | case 0: | ||
| 211 | return tr("Command Name"); | 212 | return tr("Command Name"); |
| 212 | } else if (section == 1) { | 213 | case 1: |
| 213 | return tr("Data"); | 214 | return tr("Register"); |
| 215 | case 2: | ||
| 216 | return tr("New Value"); | ||
| 214 | } | 217 | } |
| 215 | 218 | ||
| 216 | break; | 219 | break; |
| @@ -299,6 +302,13 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi | |||
| 299 | list_widget->setModel(model); | 302 | list_widget->setModel(model); |
| 300 | list_widget->setFont(QFont("monospace")); | 303 | list_widget->setFont(QFont("monospace")); |
| 301 | list_widget->setRootIsDecorated(false); | 304 | list_widget->setRootIsDecorated(false); |
| 305 | list_widget->setUniformRowHeights(true); | ||
| 306 | |||
| 307 | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | ||
| 308 | list_widget->header()->setSectionResizeMode(QHeaderView::ResizeToContents); | ||
| 309 | #else | ||
| 310 | list_widget->header()->setResizeMode(QHeaderView::ResizeToContents); | ||
| 311 | #endif | ||
| 302 | 312 | ||
| 303 | connect(list_widget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)), | 313 | connect(list_widget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)), |
| 304 | this, SLOT(SetCommandInfo(const QModelIndex&))); | 314 | 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 db622d846..f42a2f4ce 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 { | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const { | 36 | int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const { |
| 37 | return info.code.size(); | 37 | return static_cast<int>(info.code.size()); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, int role) const { | 40 | 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 2ac1748b7..89b28c2f4 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 | |||
| 74 | if (parent.isValid()) { | 74 | if (parent.isValid()) { |
| 75 | return 0; | 75 | return 0; |
| 76 | } else { | 76 | } else { |
| 77 | return results.time_per_category.size() + 2; | 77 | return static_cast<int>(results.time_per_category.size() + 2); |
| 78 | } | 78 | } |
| 79 | } | 79 | } |
| 80 | 80 | ||
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 2746de779..e93e8ebb8 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp | |||
| @@ -207,7 +207,7 @@ void GMainWindow::OnDisplayTitleBars(bool show) | |||
| 207 | } | 207 | } |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | void GMainWindow::BootGame(std::string filename) { | 210 | void GMainWindow::BootGame(const std::string& filename) { |
| 211 | LOG_INFO(Frontend, "Citra starting...\n"); | 211 | LOG_INFO(Frontend, "Citra starting...\n"); |
| 212 | 212 | ||
| 213 | // Initialize the core emulation | 213 | // Initialize the core emulation |
| @@ -263,6 +263,7 @@ void GMainWindow::ShutdownGame() { | |||
| 263 | 263 | ||
| 264 | // Update the GUI | 264 | // Update the GUI |
| 265 | ui.action_Start->setEnabled(false); | 265 | ui.action_Start->setEnabled(false); |
| 266 | ui.action_Start->setText(tr("Start")); | ||
| 266 | ui.action_Pause->setEnabled(false); | 267 | ui.action_Pause->setEnabled(false); |
| 267 | ui.action_Stop->setEnabled(false); | 268 | ui.action_Stop->setEnabled(false); |
| 268 | render_window->hide(); | 269 | render_window->hide(); |
| @@ -291,6 +292,8 @@ void GMainWindow::OnStartGame() | |||
| 291 | emu_thread->SetRunning(true); | 292 | emu_thread->SetRunning(true); |
| 292 | 293 | ||
| 293 | ui.action_Start->setEnabled(false); | 294 | ui.action_Start->setEnabled(false); |
| 295 | ui.action_Start->setText(tr("Continue")); | ||
| 296 | |||
| 294 | ui.action_Pause->setEnabled(true); | 297 | ui.action_Pause->setEnabled(true); |
| 295 | ui.action_Stop->setEnabled(true); | 298 | ui.action_Stop->setEnabled(true); |
| 296 | } | 299 | } |
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 242b08c39..9fe9e0c9c 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h | |||
| @@ -55,7 +55,7 @@ signals: | |||
| 55 | void EmulationStopping(); | 55 | void EmulationStopping(); |
| 56 | 56 | ||
| 57 | private: | 57 | private: |
| 58 | void BootGame(std::string filename); | 58 | void BootGame(const std::string& filename); |
| 59 | void ShutdownGame(); | 59 | void ShutdownGame(); |
| 60 | 60 | ||
| 61 | void closeEvent(QCloseEvent* event) override; | 61 | void closeEvent(QCloseEvent* event) override; |
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 2e80809ab..b2f7f7b1d 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) | |||
| 313 | std::string output; | 313 | std::string output; |
| 314 | output.resize(size); | 314 | output.resize(size); |
| 315 | 315 | ||
| 316 | if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr)) | 316 | if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), &output[0], static_cast<int>(output.size()), nullptr, nullptr)) |
| 317 | output.clear(); | 317 | output.clear(); |
| 318 | 318 | ||
| 319 | return output; | 319 | return output; |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8267ee586..6cc60fd58 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -4,10 +4,9 @@ set(SRCS | |||
| 4 | arm/dyncom/arm_dyncom.cpp | 4 | arm/dyncom/arm_dyncom.cpp |
| 5 | arm/dyncom/arm_dyncom_dec.cpp | 5 | arm/dyncom/arm_dyncom_dec.cpp |
| 6 | arm/dyncom/arm_dyncom_interpreter.cpp | 6 | arm/dyncom/arm_dyncom_interpreter.cpp |
| 7 | arm/dyncom/arm_dyncom_run.cpp | ||
| 8 | arm/dyncom/arm_dyncom_thumb.cpp | 7 | arm/dyncom/arm_dyncom_thumb.cpp |
| 9 | arm/interpreter/arminit.cpp | 8 | arm/skyeye_common/armstate.cpp |
| 10 | arm/interpreter/armsupp.cpp | 9 | arm/skyeye_common/armsupp.cpp |
| 11 | arm/skyeye_common/vfp/vfp.cpp | 10 | arm/skyeye_common/vfp/vfp.cpp |
| 12 | arm/skyeye_common/vfp/vfpdouble.cpp | 11 | arm/skyeye_common/vfp/vfpdouble.cpp |
| 13 | arm/skyeye_common/vfp/vfpinstr.cpp | 12 | arm/skyeye_common/vfp/vfpinstr.cpp |
| @@ -132,8 +131,8 @@ set(HEADERS | |||
| 132 | arm/dyncom/arm_dyncom_run.h | 131 | arm/dyncom/arm_dyncom_run.h |
| 133 | arm/dyncom/arm_dyncom_thumb.h | 132 | arm/dyncom/arm_dyncom_thumb.h |
| 134 | arm/skyeye_common/arm_regformat.h | 133 | arm/skyeye_common/arm_regformat.h |
| 135 | arm/skyeye_common/armdefs.h | 134 | arm/skyeye_common/armstate.h |
| 136 | arm/skyeye_common/armmmu.h | 135 | arm/skyeye_common/armsupp.h |
| 137 | arm/skyeye_common/vfp/asm_vfp.h | 136 | arm/skyeye_common/vfp/asm_vfp.h |
| 138 | arm/skyeye_common/vfp/vfp.h | 137 | arm/skyeye_common/vfp/vfp.h |
| 139 | arm/skyeye_common/vfp/vfp_helper.h | 138 | 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 529c4ac70..c665f706f 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp | |||
| @@ -6,7 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/make_unique.h" | 7 | #include "common/make_unique.h" |
| 8 | 8 | ||
| 9 | #include "core/arm/skyeye_common/armdefs.h" | 9 | #include "core/arm/skyeye_common/armstate.h" |
| 10 | #include "core/arm/skyeye_common/armsupp.h" | ||
| 10 | #include "core/arm/skyeye_common/vfp/vfp.h" | 11 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 11 | 12 | ||
| 12 | #include "core/arm/dyncom/arm_dyncom.h" | 13 | #include "core/arm/dyncom/arm_dyncom.h" |
| @@ -17,26 +18,7 @@ | |||
| 17 | #include "core/core_timing.h" | 18 | #include "core/core_timing.h" |
| 18 | 19 | ||
| 19 | ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { | 20 | ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { |
| 20 | state = Common::make_unique<ARMul_State>(); | 21 | state = Common::make_unique<ARMul_State>(initial_mode); |
| 21 | |||
| 22 | ARMul_NewState(state.get()); | ||
| 23 | ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); | ||
| 24 | |||
| 25 | state->abort_model = ABORT_BASE_RESTORED; | ||
| 26 | |||
| 27 | state->bigendSig = LOW; | ||
| 28 | state->lateabtSig = LOW; | ||
| 29 | state->NirqSig = HIGH; | ||
| 30 | |||
| 31 | // Reset the core to initial state | ||
| 32 | ARMul_Reset(state.get()); | ||
| 33 | state->Emulate = RUN; | ||
| 34 | |||
| 35 | // Switch to the desired privilege mode. | ||
| 36 | switch_mode(state.get(), initial_mode); | ||
| 37 | |||
| 38 | state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack | ||
| 39 | state->Reg[15] = 0x00000000; | ||
| 40 | } | 22 | } |
| 41 | 23 | ||
| 42 | ARM_DynCom::~ARM_DynCom() { | 24 | ARM_DynCom::~ARM_DynCom() { |
| @@ -100,8 +82,8 @@ void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 e | |||
| 100 | } | 82 | } |
| 101 | 83 | ||
| 102 | void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { | 84 | void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { |
| 103 | memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); | 85 | memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers)); |
| 104 | memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); | 86 | memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers)); |
| 105 | 87 | ||
| 106 | ctx.sp = state->Reg[13]; | 88 | ctx.sp = state->Reg[13]; |
| 107 | ctx.lr = state->Reg[14]; | 89 | ctx.lr = state->Reg[14]; |
| @@ -113,8 +95,8 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { | |||
| 113 | } | 95 | } |
| 114 | 96 | ||
| 115 | void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { | 97 | void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { |
| 116 | memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); | 98 | memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers)); |
| 117 | memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); | 99 | memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers)); |
| 118 | 100 | ||
| 119 | state->Reg[13] = ctx.sp; | 101 | state->Reg[13] = ctx.sp; |
| 120 | state->Reg[14] = ctx.lr; | 102 | state->Reg[14] = ctx.lr; |
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index cc9355722..87ab6908a 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | 10 | ||
| 11 | #include "core/arm/arm_interface.h" | 11 | #include "core/arm/arm_interface.h" |
| 12 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 13 | #include "core/arm/skyeye_common/arm_regformat.h" | 12 | #include "core/arm/skyeye_common/arm_regformat.h" |
| 13 | #include "core/arm/skyeye_common/armstate.h" | ||
| 14 | 14 | ||
| 15 | namespace Core { | 15 | namespace Core { |
| 16 | struct ThreadContext; | 16 | struct ThreadContext; |
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 697be9556..ee4288314 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.cpp +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp | |||
| @@ -2,10 +2,10 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 6 | #include "core/arm/dyncom/arm_dyncom_dec.h" | 5 | #include "core/arm/dyncom/arm_dyncom_dec.h" |
| 6 | #include "core/arm/skyeye_common/armsupp.h" | ||
| 7 | 7 | ||
| 8 | const ISEITEM arm_instruction[] = { | 8 | const InstructionSetEncodingItem arm_instruction[] = { |
| 9 | { "vmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }}, | 9 | { "vmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }}, |
| 10 | { "vmls", 7, ARMVFP2, { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }}, | 10 | { "vmls", 7, ARMVFP2, { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }}, |
| 11 | { "vnmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }}, | 11 | { "vnmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }}, |
| @@ -207,7 +207,7 @@ const ISEITEM arm_instruction[] = { | |||
| 207 | { "bbl", 1, 0, { 25, 27, 0x00000005 }}, | 207 | { "bbl", 1, 0, { 25, 27, 0x00000005 }}, |
| 208 | }; | 208 | }; |
| 209 | 209 | ||
| 210 | const ISEITEM arm_exclusion_code[] = { | 210 | const InstructionSetEncodingItem arm_exclusion_code[] = { |
| 211 | { "vmla", 0, ARMVFP2, { 0 }}, | 211 | { "vmla", 0, ARMVFP2, { 0 }}, |
| 212 | { "vmls", 0, ARMVFP2, { 0 }}, | 212 | { "vmls", 0, ARMVFP2, { 0 }}, |
| 213 | { "vnmla", 0, ARMVFP2, { 0 }}, | 213 | { "vnmla", 0, ARMVFP2, { 0 }}, |
| @@ -414,14 +414,13 @@ const ISEITEM arm_exclusion_code[] = { | |||
| 414 | { "invalid", 0, INVALID, { 0 }} | 414 | { "invalid", 0, INVALID, { 0 }} |
| 415 | }; | 415 | }; |
| 416 | 416 | ||
| 417 | int decode_arm_instr(uint32_t instr, int32_t *idx) { | 417 | ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { |
| 418 | int n = 0; | 418 | int n = 0; |
| 419 | int base = 0; | 419 | int base = 0; |
| 420 | int ret = DECODE_FAILURE; | 420 | int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem); |
| 421 | int i = 0; | 421 | ARMDecodeStatus ret = ARMDecodeStatus::FAILURE; |
| 422 | int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM); | ||
| 423 | 422 | ||
| 424 | for (i = 0; i < instr_slots; i++) { | 423 | for (int i = 0; i < instr_slots; i++) { |
| 425 | n = arm_instruction[i].attribute_value; | 424 | n = arm_instruction[i].attribute_value; |
| 426 | base = 0; | 425 | base = 0; |
| 427 | 426 | ||
| @@ -438,11 +437,11 @@ int decode_arm_instr(uint32_t instr, int32_t *idx) { | |||
| 438 | n--; | 437 | n--; |
| 439 | } | 438 | } |
| 440 | 439 | ||
| 441 | // All conditions is satisfied. | 440 | // All conditions are satisfied. |
| 442 | if (n == 0) | 441 | if (n == 0) |
| 443 | ret = DECODE_SUCCESS; | 442 | ret = ARMDecodeStatus::SUCCESS; |
| 444 | 443 | ||
| 445 | if (ret == DECODE_SUCCESS) { | 444 | if (ret == ARMDecodeStatus::SUCCESS) { |
| 446 | n = arm_exclusion_code[i].attribute_value; | 445 | n = arm_exclusion_code[i].attribute_value; |
| 447 | if (n != 0) { | 446 | if (n != 0) { |
| 448 | base = 0; | 447 | base = 0; |
| @@ -454,13 +453,13 @@ int decode_arm_instr(uint32_t instr, int32_t *idx) { | |||
| 454 | n--; | 453 | n--; |
| 455 | } | 454 | } |
| 456 | 455 | ||
| 457 | // All conditions is satisfied. | 456 | // All conditions are satisfied. |
| 458 | if (n == 0) | 457 | if (n == 0) |
| 459 | ret = DECODE_FAILURE; | 458 | ret = ARMDecodeStatus::FAILURE; |
| 460 | } | 459 | } |
| 461 | } | 460 | } |
| 462 | 461 | ||
| 463 | if (ret == DECODE_SUCCESS) { | 462 | if (ret == ARMDecodeStatus::SUCCESS) { |
| 464 | *idx = i; | 463 | *idx = i; |
| 465 | return ret; | 464 | return ret; |
| 466 | } | 465 | } |
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h index 4b5f5ad7e..d7170e0fc 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.h +++ b/src/core/arm/dyncom/arm_dyncom_dec.h | |||
| @@ -4,22 +4,22 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | int decode_arm_instr(uint32_t instr, int32_t *idx); | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | enum DECODE_STATUS { | 9 | enum class ARMDecodeStatus { |
| 10 | DECODE_SUCCESS, | 10 | SUCCESS, |
| 11 | DECODE_FAILURE | 11 | FAILURE |
| 12 | }; | 12 | }; |
| 13 | 13 | ||
| 14 | struct instruction_set_encoding_item { | 14 | ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); |
| 15 | |||
| 16 | struct InstructionSetEncodingItem { | ||
| 15 | const char *name; | 17 | const char *name; |
| 16 | int attribute_value; | 18 | int attribute_value; |
| 17 | int version; | 19 | int version; |
| 18 | u32 content[21]; | 20 | u32 content[21]; |
| 19 | }; | 21 | }; |
| 20 | 22 | ||
| 21 | typedef struct instruction_set_encoding_item ISEITEM; | ||
| 22 | |||
| 23 | // ARM versions | 23 | // ARM versions |
| 24 | enum { | 24 | enum { |
| 25 | INVALID = 0, | 25 | INVALID = 0, |
| @@ -36,4 +36,4 @@ enum { | |||
| 36 | ARMV6K, | 36 | ARMV6K, |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | extern const ISEITEM arm_instruction[]; | 39 | 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 785f39566..bb0cbb4dc 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | #include "core/arm/dyncom/arm_dyncom_interpreter.h" | 17 | #include "core/arm/dyncom/arm_dyncom_interpreter.h" |
| 18 | #include "core/arm/dyncom/arm_dyncom_thumb.h" | 18 | #include "core/arm/dyncom/arm_dyncom_thumb.h" |
| 19 | #include "core/arm/dyncom/arm_dyncom_run.h" | 19 | #include "core/arm/dyncom/arm_dyncom_run.h" |
| 20 | #include "core/arm/skyeye_common/armdefs.h" | 20 | #include "core/arm/skyeye_common/armstate.h" |
| 21 | #include "core/arm/skyeye_common/armmmu.h" | 21 | #include "core/arm/skyeye_common/armsupp.h" |
| 22 | #include "core/arm/skyeye_common/vfp/vfp.h" | 22 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 23 | 23 | ||
| 24 | Common::Profiling::TimingCategory profile_execute("DynCom::Execute"); | 24 | Common::Profiling::TimingCategory profile_execute("DynCom::Execute"); |
| @@ -47,28 +47,6 @@ enum { | |||
| 47 | 47 | ||
| 48 | typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); | 48 | typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); |
| 49 | 49 | ||
| 50 | // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. | ||
| 51 | // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to | ||
| 52 | // support LDR/STREXD. | ||
| 53 | static const ARMword RESERVATION_GRANULE_MASK = 0xFFFFFFF8; | ||
| 54 | |||
| 55 | // Exclusive memory access | ||
| 56 | static int exclusive_detect(ARMul_State* state, ARMword addr) { | ||
| 57 | if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK)) | ||
| 58 | return 0; | ||
| 59 | else | ||
| 60 | return -1; | ||
| 61 | } | ||
| 62 | |||
| 63 | static void add_exclusive_addr(ARMul_State* state, ARMword addr){ | ||
| 64 | state->exclusive_tag = addr & RESERVATION_GRANULE_MASK; | ||
| 65 | return; | ||
| 66 | } | ||
| 67 | |||
| 68 | static void remove_exclusive(ARMul_State* state, ARMword addr){ | ||
| 69 | state->exclusive_tag = 0xFFFFFFFF; | ||
| 70 | } | ||
| 71 | |||
| 72 | static int CondPassed(ARMul_State* cpu, unsigned int cond) { | 50 | static int CondPassed(ARMul_State* cpu, unsigned int cond) { |
| 73 | const u32 NFLAG = cpu->NFlag; | 51 | const u32 NFLAG = cpu->NFlag; |
| 74 | const u32 ZFLAG = cpu->ZFlag; | 52 | const u32 ZFLAG = cpu->ZFlag; |
| @@ -3490,21 +3468,15 @@ enum { | |||
| 3490 | FETCH_FAILURE | 3468 | FETCH_FAILURE |
| 3491 | }; | 3469 | }; |
| 3492 | 3470 | ||
| 3493 | static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { | 3471 | static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { |
| 3494 | // Check if in Thumb mode | 3472 | // Check if in Thumb mode |
| 3495 | tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size); | 3473 | ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); |
| 3496 | if(ret == t_branch){ | 3474 | if (ret == ThumbDecodeStatus::BRANCH) { |
| 3497 | // TODO: FIXME, endian should be judged | ||
| 3498 | u32 tinstr; | ||
| 3499 | if((addr & 0x3) != 0) | ||
| 3500 | tinstr = inst >> 16; | ||
| 3501 | else | ||
| 3502 | tinstr = inst & 0xFFFF; | ||
| 3503 | |||
| 3504 | int inst_index; | 3475 | int inst_index; |
| 3505 | int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); | 3476 | int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); |
| 3477 | u32 tinstr = GetThumbInstruction(inst, addr); | ||
| 3506 | 3478 | ||
| 3507 | switch((tinstr & 0xF800) >> 11){ | 3479 | switch ((tinstr & 0xF800) >> 11) { |
| 3508 | case 26: | 3480 | case 26: |
| 3509 | case 27: | 3481 | case 27: |
| 3510 | if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ | 3482 | 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 | |||
| 3537 | *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); | 3509 | *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); |
| 3538 | break; | 3510 | break; |
| 3539 | default: | 3511 | default: |
| 3540 | ret = t_undefined; | 3512 | ret = ThumbDecodeStatus::UNDEFINED; |
| 3541 | break; | 3513 | break; |
| 3542 | } | 3514 | } |
| 3543 | } | 3515 | } |
| @@ -3549,10 +3521,6 @@ enum { | |||
| 3549 | FETCH_EXCEPTION | 3521 | FETCH_EXCEPTION |
| 3550 | }; | 3522 | }; |
| 3551 | 3523 | ||
| 3552 | typedef struct instruction_set_encoding_item ISEITEM; | ||
| 3553 | |||
| 3554 | extern const ISEITEM arm_instruction[]; | ||
| 3555 | |||
| 3556 | static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | 3524 | static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { |
| 3557 | Common::Profiling::ScopeTimer timer_decode(profile_decode); | 3525 | Common::Profiling::ScopeTimer timer_decode(profile_decode); |
| 3558 | 3526 | ||
| @@ -3574,20 +3542,19 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | |||
| 3574 | inst = Memory::Read32(phys_addr & 0xFFFFFFFC); | 3542 | inst = Memory::Read32(phys_addr & 0xFFFFFFFC); |
| 3575 | 3543 | ||
| 3576 | size++; | 3544 | size++; |
| 3577 | // If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction | 3545 | // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction |
| 3578 | if (cpu->TFlag) { | 3546 | if (cpu->TFlag) { |
| 3579 | uint32_t arm_inst; | 3547 | uint32_t arm_inst; |
| 3580 | tdstate state = decode_thumb_instr(inst, phys_addr, &arm_inst, &inst_size, &inst_base); | 3548 | ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); |
| 3581 | 3549 | ||
| 3582 | // We have translated the branch instruction of thumb in thumb decoder | 3550 | // We have translated the Thumb branch instruction in the Thumb decoder |
| 3583 | if(state == t_branch){ | 3551 | if (state == ThumbDecodeStatus::BRANCH) { |
| 3584 | goto translated; | 3552 | goto translated; |
| 3585 | } | 3553 | } |
| 3586 | inst = arm_inst; | 3554 | inst = arm_inst; |
| 3587 | } | 3555 | } |
| 3588 | 3556 | ||
| 3589 | ret = decode_arm_instr(inst, &idx); | 3557 | if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { |
| 3590 | if (ret == DECODE_FAILURE) { | ||
| 3591 | std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); | 3558 | std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); |
| 3592 | LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); | 3559 | LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); |
| 3593 | LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); | 3560 | 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) { | |||
| 3919 | #endif | 3886 | #endif |
| 3920 | arm_inst* inst_base; | 3887 | arm_inst* inst_base; |
| 3921 | unsigned int addr; | 3888 | unsigned int addr; |
| 3922 | unsigned int phys_addr; | ||
| 3923 | unsigned int num_instrs = 0; | 3889 | unsigned int num_instrs = 0; |
| 3924 | 3890 | ||
| 3925 | int ptr; | 3891 | int ptr; |
| @@ -3938,8 +3904,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 3938 | else | 3904 | else |
| 3939 | cpu->Reg[15] &= 0xfffffffc; | 3905 | cpu->Reg[15] &= 0xfffffffc; |
| 3940 | 3906 | ||
| 3941 | phys_addr = cpu->Reg[15]; | ||
| 3942 | |||
| 3943 | // Find the cached instruction cream, otherwise translate it... | 3907 | // Find the cached instruction cream, otherwise translate it... |
| 3944 | auto itr = cpu->instruction_cache.find(cpu->Reg[15]); | 3908 | auto itr = cpu->instruction_cache.find(cpu->Reg[15]); |
| 3945 | if (itr != cpu->instruction_cache.end()) { | 3909 | if (itr != cpu->instruction_cache.end()) { |
| @@ -3957,14 +3921,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 3957 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 3921 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 3958 | adc_inst* const inst_cream = (adc_inst*)inst_base->component; | 3922 | adc_inst* const inst_cream = (adc_inst*)inst_base->component; |
| 3959 | 3923 | ||
| 3924 | u32 rn_val = RN; | ||
| 3925 | if (inst_cream->Rn == 15) | ||
| 3926 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 3927 | |||
| 3960 | bool carry; | 3928 | bool carry; |
| 3961 | bool overflow; | 3929 | bool overflow; |
| 3962 | RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | 3930 | RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); |
| 3963 | 3931 | ||
| 3964 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 3932 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 3965 | if (CurrentModeHasSPSR) { | 3933 | if (CurrentModeHasSPSR) { |
| 3966 | cpu->Cpsr = cpu->Spsr_copy; | 3934 | cpu->Cpsr = cpu->Spsr_copy; |
| 3967 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 3935 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 3968 | LOAD_NZCVT; | 3936 | LOAD_NZCVT; |
| 3969 | } | 3937 | } |
| 3970 | } else if (inst_cream->S) { | 3938 | } else if (inst_cream->S) { |
| @@ -3978,7 +3946,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 3978 | goto DISPATCH; | 3946 | goto DISPATCH; |
| 3979 | } | 3947 | } |
| 3980 | } | 3948 | } |
| 3981 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 3949 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3982 | INC_PC(sizeof(adc_inst)); | 3950 | INC_PC(sizeof(adc_inst)); |
| 3983 | FETCH_INST; | 3951 | FETCH_INST; |
| 3984 | GOTO_NEXT_INST; | 3952 | GOTO_NEXT_INST; |
| @@ -3990,7 +3958,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 3990 | 3958 | ||
| 3991 | u32 rn_val = RN; | 3959 | u32 rn_val = RN; |
| 3992 | if (inst_cream->Rn == 15) | 3960 | if (inst_cream->Rn == 15) |
| 3993 | rn_val += 2 * GET_INST_SIZE(cpu); | 3961 | rn_val += 2 * cpu->GetInstructionSize(); |
| 3994 | 3962 | ||
| 3995 | bool carry; | 3963 | bool carry; |
| 3996 | bool overflow; | 3964 | bool overflow; |
| @@ -3999,7 +3967,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 3999 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 3967 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 4000 | if (CurrentModeHasSPSR) { | 3968 | if (CurrentModeHasSPSR) { |
| 4001 | cpu->Cpsr = cpu->Spsr_copy; | 3969 | cpu->Cpsr = cpu->Spsr_copy; |
| 4002 | switch_mode(cpu, cpu->Cpsr & 0x1f); | 3970 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); |
| 4003 | LOAD_NZCVT; | 3971 | LOAD_NZCVT; |
| 4004 | } | 3972 | } |
| 4005 | } else if (inst_cream->S) { | 3973 | } else if (inst_cream->S) { |
| @@ -4013,22 +3981,28 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4013 | goto DISPATCH; | 3981 | goto DISPATCH; |
| 4014 | } | 3982 | } |
| 4015 | } | 3983 | } |
| 4016 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 3984 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4017 | INC_PC(sizeof(add_inst)); | 3985 | INC_PC(sizeof(add_inst)); |
| 4018 | FETCH_INST; | 3986 | FETCH_INST; |
| 4019 | GOTO_NEXT_INST; | 3987 | GOTO_NEXT_INST; |
| 4020 | } | 3988 | } |
| 4021 | AND_INST: | 3989 | AND_INST: |
| 4022 | { | 3990 | { |
| 4023 | and_inst *inst_cream = (and_inst *)inst_base->component; | 3991 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 4024 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 3992 | and_inst* const inst_cream = (and_inst*)inst_base->component; |
| 3993 | |||
| 4025 | u32 lop = RN; | 3994 | u32 lop = RN; |
| 4026 | u32 rop = SHIFTER_OPERAND; | 3995 | u32 rop = SHIFTER_OPERAND; |
| 3996 | |||
| 3997 | if (inst_cream->Rn == 15) | ||
| 3998 | lop += 2 * cpu->GetInstructionSize(); | ||
| 3999 | |||
| 4027 | RD = lop & rop; | 4000 | RD = lop & rop; |
| 4001 | |||
| 4028 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 4002 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 4029 | if (CurrentModeHasSPSR) { | 4003 | if (CurrentModeHasSPSR) { |
| 4030 | cpu->Cpsr = cpu->Spsr_copy; | 4004 | cpu->Cpsr = cpu->Spsr_copy; |
| 4031 | switch_mode(cpu, cpu->Cpsr & 0x1f); | 4005 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); |
| 4032 | LOAD_NZCVT; | 4006 | LOAD_NZCVT; |
| 4033 | } | 4007 | } |
| 4034 | } else if (inst_cream->S) { | 4008 | } else if (inst_cream->S) { |
| @@ -4041,7 +4015,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4041 | goto DISPATCH; | 4015 | goto DISPATCH; |
| 4042 | } | 4016 | } |
| 4043 | } | 4017 | } |
| 4044 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4018 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4045 | INC_PC(sizeof(and_inst)); | 4019 | INC_PC(sizeof(and_inst)); |
| 4046 | FETCH_INST; | 4020 | FETCH_INST; |
| 4047 | GOTO_NEXT_INST; | 4021 | GOTO_NEXT_INST; |
| @@ -4057,7 +4031,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4057 | INC_PC(sizeof(bbl_inst)); | 4031 | INC_PC(sizeof(bbl_inst)); |
| 4058 | goto DISPATCH; | 4032 | goto DISPATCH; |
| 4059 | } | 4033 | } |
| 4060 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4034 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4061 | INC_PC(sizeof(bbl_inst)); | 4035 | INC_PC(sizeof(bbl_inst)); |
| 4062 | goto DISPATCH; | 4036 | goto DISPATCH; |
| 4063 | } | 4037 | } |
| @@ -4067,14 +4041,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4067 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 4041 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { |
| 4068 | u32 lop = RN; | 4042 | u32 lop = RN; |
| 4069 | if (inst_cream->Rn == 15) { | 4043 | if (inst_cream->Rn == 15) { |
| 4070 | lop += 2 * GET_INST_SIZE(cpu); | 4044 | lop += 2 * cpu->GetInstructionSize(); |
| 4071 | } | 4045 | } |
| 4072 | u32 rop = SHIFTER_OPERAND; | 4046 | u32 rop = SHIFTER_OPERAND; |
| 4073 | RD = lop & (~rop); | 4047 | RD = lop & (~rop); |
| 4074 | if ((inst_cream->S) && (inst_cream->Rd == 15)) { | 4048 | if ((inst_cream->S) && (inst_cream->Rd == 15)) { |
| 4075 | if (CurrentModeHasSPSR) { | 4049 | if (CurrentModeHasSPSR) { |
| 4076 | cpu->Cpsr = cpu->Spsr_copy; | 4050 | cpu->Cpsr = cpu->Spsr_copy; |
| 4077 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 4051 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 4078 | LOAD_NZCVT; | 4052 | LOAD_NZCVT; |
| 4079 | } | 4053 | } |
| 4080 | } else if (inst_cream->S) { | 4054 | } else if (inst_cream->S) { |
| @@ -4087,7 +4061,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4087 | goto DISPATCH; | 4061 | goto DISPATCH; |
| 4088 | } | 4062 | } |
| 4089 | } | 4063 | } |
| 4090 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4064 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4091 | INC_PC(sizeof(bic_inst)); | 4065 | INC_PC(sizeof(bic_inst)); |
| 4092 | FETCH_INST; | 4066 | FETCH_INST; |
| 4093 | GOTO_NEXT_INST; | 4067 | GOTO_NEXT_INST; |
| @@ -4098,7 +4072,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4098 | bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; | 4072 | bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; |
| 4099 | LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm); | 4073 | LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm); |
| 4100 | } | 4074 | } |
| 4101 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4075 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4102 | INC_PC(sizeof(bkpt_inst)); | 4076 | INC_PC(sizeof(bkpt_inst)); |
| 4103 | FETCH_INST; | 4077 | FETCH_INST; |
| 4104 | GOTO_NEXT_INST; | 4078 | GOTO_NEXT_INST; |
| @@ -4109,13 +4083,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4109 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 4083 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { |
| 4110 | unsigned int inst = inst_cream->inst; | 4084 | unsigned int inst = inst_cream->inst; |
| 4111 | if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { | 4085 | if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { |
| 4112 | cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu)); | 4086 | cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); |
| 4113 | if(cpu->TFlag) | 4087 | if(cpu->TFlag) |
| 4114 | cpu->Reg[14] |= 0x1; | 4088 | cpu->Reg[14] |= 0x1; |
| 4115 | cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe; | 4089 | cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe; |
| 4116 | cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1; | 4090 | cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1; |
| 4117 | } else { | 4091 | } else { |
| 4118 | cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu)); | 4092 | cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); |
| 4119 | cpu->TFlag = 0x1; | 4093 | cpu->TFlag = 0x1; |
| 4120 | int signed_int = inst_cream->val.signed_immed_24; | 4094 | int signed_int = inst_cream->val.signed_immed_24; |
| 4121 | signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int; | 4095 | signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int; |
| @@ -4125,7 +4099,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4125 | INC_PC(sizeof(blx_inst)); | 4099 | INC_PC(sizeof(blx_inst)); |
| 4126 | goto DISPATCH; | 4100 | goto DISPATCH; |
| 4127 | } | 4101 | } |
| 4128 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4102 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4129 | INC_PC(sizeof(blx_inst)); | 4103 | INC_PC(sizeof(blx_inst)); |
| 4130 | goto DISPATCH; | 4104 | goto DISPATCH; |
| 4131 | } | 4105 | } |
| @@ -4147,7 +4121,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4147 | u32 address = RM; | 4121 | u32 address = RM; |
| 4148 | 4122 | ||
| 4149 | if (inst_cream->Rm == 15) | 4123 | if (inst_cream->Rm == 15) |
| 4150 | address += 2 * GET_INST_SIZE(cpu); | 4124 | address += 2 * cpu->GetInstructionSize(); |
| 4151 | 4125 | ||
| 4152 | cpu->TFlag = address & 1; | 4126 | cpu->TFlag = address & 1; |
| 4153 | cpu->Reg[15] = address & 0xfffffffe; | 4127 | cpu->Reg[15] = address & 0xfffffffe; |
| @@ -4155,7 +4129,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4155 | goto DISPATCH; | 4129 | goto DISPATCH; |
| 4156 | } | 4130 | } |
| 4157 | 4131 | ||
| 4158 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4132 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4159 | INC_PC(sizeof(bx_inst)); | 4133 | INC_PC(sizeof(bx_inst)); |
| 4160 | goto DISPATCH; | 4134 | goto DISPATCH; |
| 4161 | } | 4135 | } |
| @@ -4167,7 +4141,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4167 | cpu->NumInstrsToExecute = 0; | 4141 | cpu->NumInstrsToExecute = 0; |
| 4168 | return num_instrs; | 4142 | return num_instrs; |
| 4169 | } | 4143 | } |
| 4170 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4144 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4171 | INC_PC(sizeof(cdp_inst)); | 4145 | INC_PC(sizeof(cdp_inst)); |
| 4172 | FETCH_INST; | 4146 | FETCH_INST; |
| 4173 | GOTO_NEXT_INST; | 4147 | GOTO_NEXT_INST; |
| @@ -4175,10 +4149,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4175 | 4149 | ||
| 4176 | CLREX_INST: | 4150 | CLREX_INST: |
| 4177 | { | 4151 | { |
| 4178 | remove_exclusive(cpu, 0); | 4152 | cpu->UnsetExclusiveMemoryAddress(); |
| 4179 | cpu->exclusive_state = 0; | 4153 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4180 | |||
| 4181 | cpu->Reg[15] += GET_INST_SIZE(cpu); | ||
| 4182 | INC_PC(sizeof(clrex_inst)); | 4154 | INC_PC(sizeof(clrex_inst)); |
| 4183 | FETCH_INST; | 4155 | FETCH_INST; |
| 4184 | GOTO_NEXT_INST; | 4156 | GOTO_NEXT_INST; |
| @@ -4189,7 +4161,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4189 | clz_inst* inst_cream = (clz_inst*)inst_base->component; | 4161 | clz_inst* inst_cream = (clz_inst*)inst_base->component; |
| 4190 | RD = clz(RM); | 4162 | RD = clz(RM); |
| 4191 | } | 4163 | } |
| 4192 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4164 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4193 | INC_PC(sizeof(clz_inst)); | 4165 | INC_PC(sizeof(clz_inst)); |
| 4194 | FETCH_INST; | 4166 | FETCH_INST; |
| 4195 | GOTO_NEXT_INST; | 4167 | GOTO_NEXT_INST; |
| @@ -4199,16 +4171,20 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4199 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 4171 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 4200 | cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; | 4172 | cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; |
| 4201 | 4173 | ||
| 4174 | u32 rn_val = RN; | ||
| 4175 | if (inst_cream->Rn == 15) | ||
| 4176 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 4177 | |||
| 4202 | bool carry; | 4178 | bool carry; |
| 4203 | bool overflow; | 4179 | bool overflow; |
| 4204 | u32 result = AddWithCarry(RN, SHIFTER_OPERAND, 0, &carry, &overflow); | 4180 | u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); |
| 4205 | 4181 | ||
| 4206 | UPDATE_NFLAG(result); | 4182 | UPDATE_NFLAG(result); |
| 4207 | UPDATE_ZFLAG(result); | 4183 | UPDATE_ZFLAG(result); |
| 4208 | cpu->CFlag = carry; | 4184 | cpu->CFlag = carry; |
| 4209 | cpu->VFlag = overflow; | 4185 | cpu->VFlag = overflow; |
| 4210 | } | 4186 | } |
| 4211 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4187 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4212 | INC_PC(sizeof(cmn_inst)); | 4188 | INC_PC(sizeof(cmn_inst)); |
| 4213 | FETCH_INST; | 4189 | FETCH_INST; |
| 4214 | GOTO_NEXT_INST; | 4190 | GOTO_NEXT_INST; |
| @@ -4220,7 +4196,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4220 | 4196 | ||
| 4221 | u32 rn_val = RN; | 4197 | u32 rn_val = RN; |
| 4222 | if (inst_cream->Rn == 15) | 4198 | if (inst_cream->Rn == 15) |
| 4223 | rn_val += 2 * GET_INST_SIZE(cpu); | 4199 | rn_val += 2 * cpu->GetInstructionSize(); |
| 4224 | 4200 | ||
| 4225 | bool carry; | 4201 | bool carry; |
| 4226 | bool overflow; | 4202 | bool overflow; |
| @@ -4231,7 +4207,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4231 | cpu->CFlag = carry; | 4207 | cpu->CFlag = carry; |
| 4232 | cpu->VFlag = overflow; | 4208 | cpu->VFlag = overflow; |
| 4233 | } | 4209 | } |
| 4234 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4210 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4235 | INC_PC(sizeof(cmp_inst)); | 4211 | INC_PC(sizeof(cmp_inst)); |
| 4236 | FETCH_INST; | 4212 | FETCH_INST; |
| 4237 | GOTO_NEXT_INST; | 4213 | GOTO_NEXT_INST; |
| @@ -4241,7 +4217,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4241 | cps_inst *inst_cream = (cps_inst *)inst_base->component; | 4217 | cps_inst *inst_cream = (cps_inst *)inst_base->component; |
| 4242 | uint32_t aif_val = 0; | 4218 | uint32_t aif_val = 0; |
| 4243 | uint32_t aif_mask = 0; | 4219 | uint32_t aif_mask = 0; |
| 4244 | if (InAPrivilegedMode(cpu)) { | 4220 | if (cpu->InAPrivilegedMode()) { |
| 4245 | if (inst_cream->imod1) { | 4221 | if (inst_cream->imod1) { |
| 4246 | if (inst_cream->A) { | 4222 | if (inst_cream->A) { |
| 4247 | aif_val |= (inst_cream->imod0 << 8); | 4223 | aif_val |= (inst_cream->imod0 << 8); |
| @@ -4260,10 +4236,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4260 | } | 4236 | } |
| 4261 | if (inst_cream->mmod) { | 4237 | if (inst_cream->mmod) { |
| 4262 | cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode; | 4238 | cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode; |
| 4263 | switch_mode(cpu, inst_cream->mode); | 4239 | cpu->ChangePrivilegeMode(inst_cream->mode); |
| 4264 | } | 4240 | } |
| 4265 | } | 4241 | } |
| 4266 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4242 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4267 | INC_PC(sizeof(cps_inst)); | 4243 | INC_PC(sizeof(cps_inst)); |
| 4268 | FETCH_INST; | 4244 | FETCH_INST; |
| 4269 | GOTO_NEXT_INST; | 4245 | GOTO_NEXT_INST; |
| @@ -4279,7 +4255,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4279 | goto DISPATCH; | 4255 | goto DISPATCH; |
| 4280 | } | 4256 | } |
| 4281 | } | 4257 | } |
| 4282 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4258 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4283 | INC_PC(sizeof(mov_inst)); | 4259 | INC_PC(sizeof(mov_inst)); |
| 4284 | FETCH_INST; | 4260 | FETCH_INST; |
| 4285 | GOTO_NEXT_INST; | 4261 | GOTO_NEXT_INST; |
| @@ -4291,14 +4267,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4291 | 4267 | ||
| 4292 | u32 lop = RN; | 4268 | u32 lop = RN; |
| 4293 | if (inst_cream->Rn == 15) { | 4269 | if (inst_cream->Rn == 15) { |
| 4294 | lop += 2 * GET_INST_SIZE(cpu); | 4270 | lop += 2 * cpu->GetInstructionSize(); |
| 4295 | } | 4271 | } |
| 4296 | u32 rop = SHIFTER_OPERAND; | 4272 | u32 rop = SHIFTER_OPERAND; |
| 4297 | RD = lop ^ rop; | 4273 | RD = lop ^ rop; |
| 4298 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 4274 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 4299 | if (CurrentModeHasSPSR) { | 4275 | if (CurrentModeHasSPSR) { |
| 4300 | cpu->Cpsr = cpu->Spsr_copy; | 4276 | cpu->Cpsr = cpu->Spsr_copy; |
| 4301 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 4277 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 4302 | LOAD_NZCVT; | 4278 | LOAD_NZCVT; |
| 4303 | } | 4279 | } |
| 4304 | } else if (inst_cream->S) { | 4280 | } else if (inst_cream->S) { |
| @@ -4311,7 +4287,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4311 | goto DISPATCH; | 4287 | goto DISPATCH; |
| 4312 | } | 4288 | } |
| 4313 | } | 4289 | } |
| 4314 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4290 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4315 | INC_PC(sizeof(eor_inst)); | 4291 | INC_PC(sizeof(eor_inst)); |
| 4316 | FETCH_INST; | 4292 | FETCH_INST; |
| 4317 | GOTO_NEXT_INST; | 4293 | GOTO_NEXT_INST; |
| @@ -4320,7 +4296,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4320 | { | 4296 | { |
| 4321 | // Instruction not implemented | 4297 | // Instruction not implemented |
| 4322 | //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); | 4298 | //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); |
| 4323 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4299 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4324 | INC_PC(sizeof(ldc_inst)); | 4300 | INC_PC(sizeof(ldc_inst)); |
| 4325 | FETCH_INST; | 4301 | FETCH_INST; |
| 4326 | GOTO_NEXT_INST; | 4302 | GOTO_NEXT_INST; |
| @@ -4335,30 +4311,30 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4335 | if (BIT(inst, 22) && !BIT(inst, 15)) { | 4311 | if (BIT(inst, 22) && !BIT(inst, 15)) { |
| 4336 | for (int i = 0; i < 13; i++) { | 4312 | for (int i = 0; i < 13; i++) { |
| 4337 | if(BIT(inst, i)) { | 4313 | if(BIT(inst, i)) { |
| 4338 | cpu->Reg[i] = ReadMemory32(cpu, addr); | 4314 | cpu->Reg[i] = cpu->ReadMemory32(addr); |
| 4339 | addr += 4; | 4315 | addr += 4; |
| 4340 | } | 4316 | } |
| 4341 | } | 4317 | } |
| 4342 | if (BIT(inst, 13)) { | 4318 | if (BIT(inst, 13)) { |
| 4343 | if (cpu->Mode == USER32MODE) | 4319 | if (cpu->Mode == USER32MODE) |
| 4344 | cpu->Reg[13] = ReadMemory32(cpu, addr); | 4320 | cpu->Reg[13] = cpu->ReadMemory32(addr); |
| 4345 | else | 4321 | else |
| 4346 | cpu->Reg_usr[0] = ReadMemory32(cpu, addr); | 4322 | cpu->Reg_usr[0] = cpu->ReadMemory32(addr); |
| 4347 | 4323 | ||
| 4348 | addr += 4; | 4324 | addr += 4; |
| 4349 | } | 4325 | } |
| 4350 | if (BIT(inst, 14)) { | 4326 | if (BIT(inst, 14)) { |
| 4351 | if (cpu->Mode == USER32MODE) | 4327 | if (cpu->Mode == USER32MODE) |
| 4352 | cpu->Reg[14] = ReadMemory32(cpu, addr); | 4328 | cpu->Reg[14] = cpu->ReadMemory32(addr); |
| 4353 | else | 4329 | else |
| 4354 | cpu->Reg_usr[1] = ReadMemory32(cpu, addr); | 4330 | cpu->Reg_usr[1] = cpu->ReadMemory32(addr); |
| 4355 | 4331 | ||
| 4356 | addr += 4; | 4332 | addr += 4; |
| 4357 | } | 4333 | } |
| 4358 | } else if (!BIT(inst, 22)) { | 4334 | } else if (!BIT(inst, 22)) { |
| 4359 | for(int i = 0; i < 16; i++ ){ | 4335 | for(int i = 0; i < 16; i++ ){ |
| 4360 | if(BIT(inst, i)){ | 4336 | if(BIT(inst, i)){ |
| 4361 | unsigned int ret = ReadMemory32(cpu, addr); | 4337 | unsigned int ret = cpu->ReadMemory32(addr); |
| 4362 | 4338 | ||
| 4363 | // For armv5t, should enter thumb when bits[0] is non-zero. | 4339 | // For armv5t, should enter thumb when bits[0] is non-zero. |
| 4364 | if(i == 15){ | 4340 | if(i == 15){ |
| @@ -4373,18 +4349,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4373 | } else if (BIT(inst, 22) && BIT(inst, 15)) { | 4349 | } else if (BIT(inst, 22) && BIT(inst, 15)) { |
| 4374 | for(int i = 0; i < 15; i++ ){ | 4350 | for(int i = 0; i < 15; i++ ){ |
| 4375 | if(BIT(inst, i)){ | 4351 | if(BIT(inst, i)){ |
| 4376 | cpu->Reg[i] = ReadMemory32(cpu, addr); | 4352 | cpu->Reg[i] = cpu->ReadMemory32(addr); |
| 4377 | addr += 4; | 4353 | addr += 4; |
| 4378 | } | 4354 | } |
| 4379 | } | 4355 | } |
| 4380 | 4356 | ||
| 4381 | if (CurrentModeHasSPSR) { | 4357 | if (CurrentModeHasSPSR) { |
| 4382 | cpu->Cpsr = cpu->Spsr_copy; | 4358 | cpu->Cpsr = cpu->Spsr_copy; |
| 4383 | switch_mode(cpu, cpu->Cpsr & 0x1f); | 4359 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); |
| 4384 | LOAD_NZCVT; | 4360 | LOAD_NZCVT; |
| 4385 | } | 4361 | } |
| 4386 | 4362 | ||
| 4387 | cpu->Reg[15] = ReadMemory32(cpu, addr); | 4363 | cpu->Reg[15] = cpu->ReadMemory32(addr); |
| 4388 | } | 4364 | } |
| 4389 | 4365 | ||
| 4390 | if (BIT(inst, 15)) { | 4366 | if (BIT(inst, 15)) { |
| @@ -4392,7 +4368,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4392 | goto DISPATCH; | 4368 | goto DISPATCH; |
| 4393 | } | 4369 | } |
| 4394 | } | 4370 | } |
| 4395 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4371 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4396 | INC_PC(sizeof(ldst_inst)); | 4372 | INC_PC(sizeof(ldst_inst)); |
| 4397 | FETCH_INST; | 4373 | FETCH_INST; |
| 4398 | GOTO_NEXT_INST; | 4374 | GOTO_NEXT_INST; |
| @@ -4410,7 +4386,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4410 | } | 4386 | } |
| 4411 | RD = operand2; | 4387 | RD = operand2; |
| 4412 | } | 4388 | } |
| 4413 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4389 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4414 | INC_PC(sizeof(sxth_inst)); | 4390 | INC_PC(sizeof(sxth_inst)); |
| 4415 | FETCH_INST; | 4391 | FETCH_INST; |
| 4416 | GOTO_NEXT_INST; | 4392 | GOTO_NEXT_INST; |
| @@ -4420,7 +4396,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4420 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | 4396 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; |
| 4421 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 4397 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 4422 | 4398 | ||
| 4423 | unsigned int value = ReadMemory32(cpu, addr); | 4399 | unsigned int value = cpu->ReadMemory32(addr); |
| 4424 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 4400 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 4425 | 4401 | ||
| 4426 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4402 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| @@ -4431,7 +4407,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4431 | goto DISPATCH; | 4407 | goto DISPATCH; |
| 4432 | } | 4408 | } |
| 4433 | 4409 | ||
| 4434 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4410 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4435 | INC_PC(sizeof(ldst_inst)); | 4411 | INC_PC(sizeof(ldst_inst)); |
| 4436 | FETCH_INST; | 4412 | FETCH_INST; |
| 4437 | GOTO_NEXT_INST; | 4413 | GOTO_NEXT_INST; |
| @@ -4442,7 +4418,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4442 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | 4418 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; |
| 4443 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 4419 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 4444 | 4420 | ||
| 4445 | unsigned int value = ReadMemory32(cpu, addr); | 4421 | unsigned int value = cpu->ReadMemory32(addr); |
| 4446 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 4422 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 4447 | 4423 | ||
| 4448 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4424 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| @@ -4453,7 +4429,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4453 | goto DISPATCH; | 4429 | goto DISPATCH; |
| 4454 | } | 4430 | } |
| 4455 | } | 4431 | } |
| 4456 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4432 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4457 | INC_PC(sizeof(ldst_inst)); | 4433 | INC_PC(sizeof(ldst_inst)); |
| 4458 | FETCH_INST; | 4434 | FETCH_INST; |
| 4459 | GOTO_NEXT_INST; | 4435 | GOTO_NEXT_INST; |
| @@ -4464,7 +4440,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4464 | uxth_inst* inst_cream = (uxth_inst*)inst_base->component; | 4440 | uxth_inst* inst_cream = (uxth_inst*)inst_base->component; |
| 4465 | RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; | 4441 | RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; |
| 4466 | } | 4442 | } |
| 4467 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4443 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4468 | INC_PC(sizeof(uxth_inst)); | 4444 | INC_PC(sizeof(uxth_inst)); |
| 4469 | FETCH_INST; | 4445 | FETCH_INST; |
| 4470 | GOTO_NEXT_INST; | 4446 | GOTO_NEXT_INST; |
| @@ -4477,7 +4453,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4477 | 4453 | ||
| 4478 | RD = RN + operand2; | 4454 | RD = RN + operand2; |
| 4479 | } | 4455 | } |
| 4480 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4456 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4481 | INC_PC(sizeof(uxtah_inst)); | 4457 | INC_PC(sizeof(uxtah_inst)); |
| 4482 | FETCH_INST; | 4458 | FETCH_INST; |
| 4483 | GOTO_NEXT_INST; | 4459 | GOTO_NEXT_INST; |
| @@ -4495,7 +4471,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4495 | goto DISPATCH; | 4471 | goto DISPATCH; |
| 4496 | } | 4472 | } |
| 4497 | } | 4473 | } |
| 4498 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4474 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4499 | INC_PC(sizeof(ldst_inst)); | 4475 | INC_PC(sizeof(ldst_inst)); |
| 4500 | FETCH_INST; | 4476 | FETCH_INST; |
| 4501 | GOTO_NEXT_INST; | 4477 | GOTO_NEXT_INST; |
| @@ -4513,7 +4489,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4513 | goto DISPATCH; | 4489 | goto DISPATCH; |
| 4514 | } | 4490 | } |
| 4515 | } | 4491 | } |
| 4516 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4492 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4517 | INC_PC(sizeof(ldst_inst)); | 4493 | INC_PC(sizeof(ldst_inst)); |
| 4518 | FETCH_INST; | 4494 | FETCH_INST; |
| 4519 | GOTO_NEXT_INST; | 4495 | GOTO_NEXT_INST; |
| @@ -4527,8 +4503,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4527 | 4503 | ||
| 4528 | // The 3DS doesn't have LPAE (Large Physical Access Extension), so it | 4504 | // The 3DS doesn't have LPAE (Large Physical Access Extension), so it |
| 4529 | // wouldn't do this as a single read. | 4505 | // wouldn't do this as a single read. |
| 4530 | cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = ReadMemory32(cpu, addr); | 4506 | cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr); |
| 4531 | cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = ReadMemory32(cpu, addr + 4); | 4507 | cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4); |
| 4532 | 4508 | ||
| 4533 | // No dispatch since this operation should not modify R15 | 4509 | // No dispatch since this operation should not modify R15 |
| 4534 | } | 4510 | } |
| @@ -4544,16 +4520,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4544 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 4520 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 4545 | unsigned int read_addr = RN; | 4521 | unsigned int read_addr = RN; |
| 4546 | 4522 | ||
| 4547 | add_exclusive_addr(cpu, read_addr); | 4523 | cpu->SetExclusiveMemoryAddress(read_addr); |
| 4548 | cpu->exclusive_state = 1; | ||
| 4549 | 4524 | ||
| 4550 | RD = ReadMemory32(cpu, read_addr); | 4525 | RD = cpu->ReadMemory32(read_addr); |
| 4551 | if (inst_cream->Rd == 15) { | 4526 | if (inst_cream->Rd == 15) { |
| 4552 | INC_PC(sizeof(generic_arm_inst)); | 4527 | INC_PC(sizeof(generic_arm_inst)); |
| 4553 | goto DISPATCH; | 4528 | goto DISPATCH; |
| 4554 | } | 4529 | } |
| 4555 | } | 4530 | } |
| 4556 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4531 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4557 | INC_PC(sizeof(generic_arm_inst)); | 4532 | INC_PC(sizeof(generic_arm_inst)); |
| 4558 | FETCH_INST; | 4533 | FETCH_INST; |
| 4559 | GOTO_NEXT_INST; | 4534 | GOTO_NEXT_INST; |
| @@ -4564,8 +4539,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4564 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 4539 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 4565 | unsigned int read_addr = RN; | 4540 | unsigned int read_addr = RN; |
| 4566 | 4541 | ||
| 4567 | add_exclusive_addr(cpu, read_addr); | 4542 | cpu->SetExclusiveMemoryAddress(read_addr); |
| 4568 | cpu->exclusive_state = 1; | ||
| 4569 | 4543 | ||
| 4570 | RD = Memory::Read8(read_addr); | 4544 | RD = Memory::Read8(read_addr); |
| 4571 | if (inst_cream->Rd == 15) { | 4545 | if (inst_cream->Rd == 15) { |
| @@ -4573,7 +4547,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4573 | goto DISPATCH; | 4547 | goto DISPATCH; |
| 4574 | } | 4548 | } |
| 4575 | } | 4549 | } |
| 4576 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4550 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4577 | INC_PC(sizeof(generic_arm_inst)); | 4551 | INC_PC(sizeof(generic_arm_inst)); |
| 4578 | FETCH_INST; | 4552 | FETCH_INST; |
| 4579 | GOTO_NEXT_INST; | 4553 | GOTO_NEXT_INST; |
| @@ -4584,16 +4558,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4584 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 4558 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 4585 | unsigned int read_addr = RN; | 4559 | unsigned int read_addr = RN; |
| 4586 | 4560 | ||
| 4587 | add_exclusive_addr(cpu, read_addr); | 4561 | cpu->SetExclusiveMemoryAddress(read_addr); |
| 4588 | cpu->exclusive_state = 1; | ||
| 4589 | 4562 | ||
| 4590 | RD = ReadMemory16(cpu, read_addr); | 4563 | RD = cpu->ReadMemory16(read_addr); |
| 4591 | if (inst_cream->Rd == 15) { | 4564 | if (inst_cream->Rd == 15) { |
| 4592 | INC_PC(sizeof(generic_arm_inst)); | 4565 | INC_PC(sizeof(generic_arm_inst)); |
| 4593 | goto DISPATCH; | 4566 | goto DISPATCH; |
| 4594 | } | 4567 | } |
| 4595 | } | 4568 | } |
| 4596 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4569 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4597 | INC_PC(sizeof(generic_arm_inst)); | 4570 | INC_PC(sizeof(generic_arm_inst)); |
| 4598 | FETCH_INST; | 4571 | FETCH_INST; |
| 4599 | GOTO_NEXT_INST; | 4572 | GOTO_NEXT_INST; |
| @@ -4604,18 +4577,17 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4604 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 4577 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 4605 | unsigned int read_addr = RN; | 4578 | unsigned int read_addr = RN; |
| 4606 | 4579 | ||
| 4607 | add_exclusive_addr(cpu, read_addr); | 4580 | cpu->SetExclusiveMemoryAddress(read_addr); |
| 4608 | cpu->exclusive_state = 1; | ||
| 4609 | 4581 | ||
| 4610 | RD = ReadMemory32(cpu, read_addr); | 4582 | RD = cpu->ReadMemory32(read_addr); |
| 4611 | RD2 = ReadMemory32(cpu, read_addr + 4); | 4583 | RD2 = cpu->ReadMemory32(read_addr + 4); |
| 4612 | 4584 | ||
| 4613 | if (inst_cream->Rd == 15) { | 4585 | if (inst_cream->Rd == 15) { |
| 4614 | INC_PC(sizeof(generic_arm_inst)); | 4586 | INC_PC(sizeof(generic_arm_inst)); |
| 4615 | goto DISPATCH; | 4587 | goto DISPATCH; |
| 4616 | } | 4588 | } |
| 4617 | } | 4589 | } |
| 4618 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4590 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4619 | INC_PC(sizeof(generic_arm_inst)); | 4591 | INC_PC(sizeof(generic_arm_inst)); |
| 4620 | FETCH_INST; | 4592 | FETCH_INST; |
| 4621 | GOTO_NEXT_INST; | 4593 | GOTO_NEXT_INST; |
| @@ -4626,13 +4598,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4626 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 4598 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 4627 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 4599 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 4628 | 4600 | ||
| 4629 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ReadMemory16(cpu, addr); | 4601 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr); |
| 4630 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4602 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 4631 | INC_PC(sizeof(ldst_inst)); | 4603 | INC_PC(sizeof(ldst_inst)); |
| 4632 | goto DISPATCH; | 4604 | goto DISPATCH; |
| 4633 | } | 4605 | } |
| 4634 | } | 4606 | } |
| 4635 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4607 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4636 | INC_PC(sizeof(ldst_inst)); | 4608 | INC_PC(sizeof(ldst_inst)); |
| 4637 | FETCH_INST; | 4609 | FETCH_INST; |
| 4638 | GOTO_NEXT_INST; | 4610 | GOTO_NEXT_INST; |
| @@ -4652,7 +4624,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4652 | goto DISPATCH; | 4624 | goto DISPATCH; |
| 4653 | } | 4625 | } |
| 4654 | } | 4626 | } |
| 4655 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4627 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4656 | INC_PC(sizeof(ldst_inst)); | 4628 | INC_PC(sizeof(ldst_inst)); |
| 4657 | FETCH_INST; | 4629 | FETCH_INST; |
| 4658 | GOTO_NEXT_INST; | 4630 | GOTO_NEXT_INST; |
| @@ -4663,7 +4635,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4663 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 4635 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 4664 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 4636 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 4665 | 4637 | ||
| 4666 | unsigned int value = ReadMemory16(cpu, addr); | 4638 | unsigned int value = cpu->ReadMemory16(addr); |
| 4667 | if (BIT(value, 15)) { | 4639 | if (BIT(value, 15)) { |
| 4668 | value |= 0xffff0000; | 4640 | value |= 0xffff0000; |
| 4669 | } | 4641 | } |
| @@ -4673,7 +4645,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4673 | goto DISPATCH; | 4645 | goto DISPATCH; |
| 4674 | } | 4646 | } |
| 4675 | } | 4647 | } |
| 4676 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4648 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4677 | INC_PC(sizeof(ldst_inst)); | 4649 | INC_PC(sizeof(ldst_inst)); |
| 4678 | FETCH_INST; | 4650 | FETCH_INST; |
| 4679 | GOTO_NEXT_INST; | 4651 | GOTO_NEXT_INST; |
| @@ -4684,7 +4656,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4684 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 4656 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 4685 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 4657 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 4686 | 4658 | ||
| 4687 | unsigned int value = ReadMemory32(cpu, addr); | 4659 | unsigned int value = cpu->ReadMemory32(addr); |
| 4688 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 4660 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 4689 | 4661 | ||
| 4690 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4662 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| @@ -4692,7 +4664,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4692 | goto DISPATCH; | 4664 | goto DISPATCH; |
| 4693 | } | 4665 | } |
| 4694 | } | 4666 | } |
| 4695 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4667 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4696 | INC_PC(sizeof(ldst_inst)); | 4668 | INC_PC(sizeof(ldst_inst)); |
| 4697 | FETCH_INST; | 4669 | FETCH_INST; |
| 4698 | GOTO_NEXT_INST; | 4670 | GOTO_NEXT_INST; |
| @@ -4707,10 +4679,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4707 | DEBUG_MSG; | 4679 | DEBUG_MSG; |
| 4708 | } else { | 4680 | } else { |
| 4709 | if (inst_cream->cp_num == 15) | 4681 | if (inst_cream->cp_num == 15) |
| 4710 | WriteCP15Register(cpu, RD, CRn, OPCODE_1, CRm, OPCODE_2); | 4682 | cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2); |
| 4711 | } | 4683 | } |
| 4712 | } | 4684 | } |
| 4713 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4685 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4714 | INC_PC(sizeof(mcr_inst)); | 4686 | INC_PC(sizeof(mcr_inst)); |
| 4715 | FETCH_INST; | 4687 | FETCH_INST; |
| 4716 | GOTO_NEXT_INST; | 4688 | GOTO_NEXT_INST; |
| @@ -4727,7 +4699,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4727 | inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); | 4699 | inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); |
| 4728 | } | 4700 | } |
| 4729 | 4701 | ||
| 4730 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4702 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4731 | INC_PC(sizeof(mcrr_inst)); | 4703 | INC_PC(sizeof(mcrr_inst)); |
| 4732 | FETCH_INST; | 4704 | FETCH_INST; |
| 4733 | GOTO_NEXT_INST; | 4705 | GOTO_NEXT_INST; |
| @@ -4752,7 +4724,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4752 | goto DISPATCH; | 4724 | goto DISPATCH; |
| 4753 | } | 4725 | } |
| 4754 | } | 4726 | } |
| 4755 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4727 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4756 | INC_PC(sizeof(mla_inst)); | 4728 | INC_PC(sizeof(mla_inst)); |
| 4757 | FETCH_INST; | 4729 | FETCH_INST; |
| 4758 | GOTO_NEXT_INST; | 4730 | GOTO_NEXT_INST; |
| @@ -4766,7 +4738,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4766 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 4738 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 4767 | if (CurrentModeHasSPSR) { | 4739 | if (CurrentModeHasSPSR) { |
| 4768 | cpu->Cpsr = cpu->Spsr_copy; | 4740 | cpu->Cpsr = cpu->Spsr_copy; |
| 4769 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 4741 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 4770 | LOAD_NZCVT; | 4742 | LOAD_NZCVT; |
| 4771 | } | 4743 | } |
| 4772 | } else if (inst_cream->S) { | 4744 | } else if (inst_cream->S) { |
| @@ -4779,7 +4751,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4779 | goto DISPATCH; | 4751 | goto DISPATCH; |
| 4780 | } | 4752 | } |
| 4781 | } | 4753 | } |
| 4782 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4754 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4783 | INC_PC(sizeof(mov_inst)); | 4755 | INC_PC(sizeof(mov_inst)); |
| 4784 | FETCH_INST; | 4756 | FETCH_INST; |
| 4785 | GOTO_NEXT_INST; | 4757 | GOTO_NEXT_INST; |
| @@ -4800,10 +4772,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4800 | goto END; | 4772 | goto END; |
| 4801 | } else { | 4773 | } else { |
| 4802 | if (inst_cream->cp_num == 15) | 4774 | if (inst_cream->cp_num == 15) |
| 4803 | RD = ReadCP15Register(cpu, CRn, OPCODE_1, CRm, OPCODE_2); | 4775 | RD = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2); |
| 4804 | } | 4776 | } |
| 4805 | } | 4777 | } |
| 4806 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4778 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4807 | INC_PC(sizeof(mrc_inst)); | 4779 | INC_PC(sizeof(mrc_inst)); |
| 4808 | FETCH_INST; | 4780 | FETCH_INST; |
| 4809 | GOTO_NEXT_INST; | 4781 | GOTO_NEXT_INST; |
| @@ -4820,7 +4792,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4820 | inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); | 4792 | inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); |
| 4821 | } | 4793 | } |
| 4822 | 4794 | ||
| 4823 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4795 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4824 | INC_PC(sizeof(mcrr_inst)); | 4796 | INC_PC(sizeof(mcrr_inst)); |
| 4825 | FETCH_INST; | 4797 | FETCH_INST; |
| 4826 | GOTO_NEXT_INST; | 4798 | GOTO_NEXT_INST; |
| @@ -4838,7 +4810,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4838 | RD = cpu->Cpsr; | 4810 | RD = cpu->Cpsr; |
| 4839 | } | 4811 | } |
| 4840 | } | 4812 | } |
| 4841 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4813 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4842 | INC_PC(sizeof(mrs_inst)); | 4814 | INC_PC(sizeof(mrs_inst)); |
| 4843 | FETCH_INST; | 4815 | FETCH_INST; |
| 4844 | GOTO_NEXT_INST; | 4816 | GOTO_NEXT_INST; |
| @@ -4861,7 +4833,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4861 | | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); | 4833 | | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); |
| 4862 | uint32_t mask = 0; | 4834 | uint32_t mask = 0; |
| 4863 | if (!inst_cream->R) { | 4835 | if (!inst_cream->R) { |
| 4864 | if (InAPrivilegedMode(cpu)) { | 4836 | if (cpu->InAPrivilegedMode()) { |
| 4865 | if ((operand & StateMask) != 0) { | 4837 | if ((operand & StateMask) != 0) { |
| 4866 | /// UNPREDICTABLE | 4838 | /// UNPREDICTABLE |
| 4867 | DEBUG_MSG; | 4839 | DEBUG_MSG; |
| @@ -4873,7 +4845,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4873 | SAVE_NZCVT; | 4845 | SAVE_NZCVT; |
| 4874 | 4846 | ||
| 4875 | cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); | 4847 | cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); |
| 4876 | switch_mode(cpu, cpu->Cpsr & 0x1f); | 4848 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); |
| 4877 | LOAD_NZCVT; | 4849 | LOAD_NZCVT; |
| 4878 | } else { | 4850 | } else { |
| 4879 | if (CurrentModeHasSPSR) { | 4851 | if (CurrentModeHasSPSR) { |
| @@ -4882,7 +4854,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4882 | } | 4854 | } |
| 4883 | } | 4855 | } |
| 4884 | } | 4856 | } |
| 4885 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4857 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4886 | INC_PC(sizeof(msr_inst)); | 4858 | INC_PC(sizeof(msr_inst)); |
| 4887 | FETCH_INST; | 4859 | FETCH_INST; |
| 4888 | GOTO_NEXT_INST; | 4860 | GOTO_NEXT_INST; |
| @@ -4904,7 +4876,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4904 | goto DISPATCH; | 4876 | goto DISPATCH; |
| 4905 | } | 4877 | } |
| 4906 | } | 4878 | } |
| 4907 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4879 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4908 | INC_PC(sizeof(mul_inst)); | 4880 | INC_PC(sizeof(mul_inst)); |
| 4909 | FETCH_INST; | 4881 | FETCH_INST; |
| 4910 | GOTO_NEXT_INST; | 4882 | GOTO_NEXT_INST; |
| @@ -4919,7 +4891,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4919 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 4891 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 4920 | if (CurrentModeHasSPSR) { | 4892 | if (CurrentModeHasSPSR) { |
| 4921 | cpu->Cpsr = cpu->Spsr_copy; | 4893 | cpu->Cpsr = cpu->Spsr_copy; |
| 4922 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 4894 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 4923 | LOAD_NZCVT; | 4895 | LOAD_NZCVT; |
| 4924 | } | 4896 | } |
| 4925 | } else if (inst_cream->S) { | 4897 | } else if (inst_cream->S) { |
| @@ -4932,7 +4904,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4932 | goto DISPATCH; | 4904 | goto DISPATCH; |
| 4933 | } | 4905 | } |
| 4934 | } | 4906 | } |
| 4935 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4907 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4936 | INC_PC(sizeof(mvn_inst)); | 4908 | INC_PC(sizeof(mvn_inst)); |
| 4937 | FETCH_INST; | 4909 | FETCH_INST; |
| 4938 | GOTO_NEXT_INST; | 4910 | GOTO_NEXT_INST; |
| @@ -4944,12 +4916,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4944 | 4916 | ||
| 4945 | u32 lop = RN; | 4917 | u32 lop = RN; |
| 4946 | u32 rop = SHIFTER_OPERAND; | 4918 | u32 rop = SHIFTER_OPERAND; |
| 4919 | |||
| 4920 | if (inst_cream->Rn == 15) | ||
| 4921 | lop += 2 * cpu->GetInstructionSize(); | ||
| 4922 | |||
| 4947 | RD = lop | rop; | 4923 | RD = lop | rop; |
| 4948 | 4924 | ||
| 4949 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 4925 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 4950 | if (CurrentModeHasSPSR) { | 4926 | if (CurrentModeHasSPSR) { |
| 4951 | cpu->Cpsr = cpu->Spsr_copy; | 4927 | cpu->Cpsr = cpu->Spsr_copy; |
| 4952 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 4928 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 4953 | LOAD_NZCVT; | 4929 | LOAD_NZCVT; |
| 4954 | } | 4930 | } |
| 4955 | } else if (inst_cream->S) { | 4931 | } else if (inst_cream->S) { |
| @@ -4962,7 +4938,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4962 | goto DISPATCH; | 4938 | goto DISPATCH; |
| 4963 | } | 4939 | } |
| 4964 | } | 4940 | } |
| 4965 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4941 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4966 | INC_PC(sizeof(orr_inst)); | 4942 | INC_PC(sizeof(orr_inst)); |
| 4967 | FETCH_INST; | 4943 | FETCH_INST; |
| 4968 | GOTO_NEXT_INST; | 4944 | GOTO_NEXT_INST; |
| @@ -4970,7 +4946,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4970 | 4946 | ||
| 4971 | NOP_INST: | 4947 | NOP_INST: |
| 4972 | { | 4948 | { |
| 4973 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4949 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4974 | INC_PC_STUB; | 4950 | INC_PC_STUB; |
| 4975 | FETCH_INST; | 4951 | FETCH_INST; |
| 4976 | GOTO_NEXT_INST; | 4952 | GOTO_NEXT_INST; |
| @@ -4982,7 +4958,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4982 | pkh_inst *inst_cream = (pkh_inst *)inst_base->component; | 4958 | pkh_inst *inst_cream = (pkh_inst *)inst_base->component; |
| 4983 | RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000); | 4959 | RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000); |
| 4984 | } | 4960 | } |
| 4985 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4961 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4986 | INC_PC(sizeof(pkh_inst)); | 4962 | INC_PC(sizeof(pkh_inst)); |
| 4987 | FETCH_INST; | 4963 | FETCH_INST; |
| 4988 | GOTO_NEXT_INST; | 4964 | GOTO_NEXT_INST; |
| @@ -4995,7 +4971,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4995 | int shift_imm = inst_cream->imm ? inst_cream->imm : 31; | 4971 | int shift_imm = inst_cream->imm ? inst_cream->imm : 31; |
| 4996 | RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000); | 4972 | RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000); |
| 4997 | } | 4973 | } |
| 4998 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4974 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4999 | INC_PC(sizeof(pkh_inst)); | 4975 | INC_PC(sizeof(pkh_inst)); |
| 5000 | FETCH_INST; | 4976 | FETCH_INST; |
| 5001 | GOTO_NEXT_INST; | 4977 | GOTO_NEXT_INST; |
| @@ -5005,7 +4981,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5005 | { | 4981 | { |
| 5006 | // Not implemented. PLD is a hint instruction, so it's optional. | 4982 | // Not implemented. PLD is a hint instruction, so it's optional. |
| 5007 | 4983 | ||
| 5008 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4984 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5009 | INC_PC(sizeof(pld_inst)); | 4985 | INC_PC(sizeof(pld_inst)); |
| 5010 | FETCH_INST; | 4986 | FETCH_INST; |
| 5011 | GOTO_NEXT_INST; | 4987 | GOTO_NEXT_INST; |
| @@ -5078,7 +5054,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5078 | RD = result; | 5054 | RD = result; |
| 5079 | } | 5055 | } |
| 5080 | 5056 | ||
| 5081 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5057 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5082 | INC_PC(sizeof(generic_arm_inst)); | 5058 | INC_PC(sizeof(generic_arm_inst)); |
| 5083 | FETCH_INST; | 5059 | FETCH_INST; |
| 5084 | GOTO_NEXT_INST; | 5060 | GOTO_NEXT_INST; |
| @@ -5140,7 +5116,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5140 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); | 5116 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); |
| 5141 | } | 5117 | } |
| 5142 | 5118 | ||
| 5143 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5119 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5144 | INC_PC(sizeof(generic_arm_inst)); | 5120 | INC_PC(sizeof(generic_arm_inst)); |
| 5145 | FETCH_INST; | 5121 | FETCH_INST; |
| 5146 | GOTO_NEXT_INST; | 5122 | GOTO_NEXT_INST; |
| @@ -5173,7 +5149,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5173 | } | 5149 | } |
| 5174 | } | 5150 | } |
| 5175 | 5151 | ||
| 5176 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5152 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5177 | INC_PC(sizeof(rev_inst)); | 5153 | INC_PC(sizeof(rev_inst)); |
| 5178 | FETCH_INST; | 5154 | FETCH_INST; |
| 5179 | GOTO_NEXT_INST; | 5155 | GOTO_NEXT_INST; |
| @@ -5187,8 +5163,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5187 | u32 address = 0; | 5163 | u32 address = 0; |
| 5188 | inst_cream->get_addr(cpu, inst_cream->inst, address); | 5164 | inst_cream->get_addr(cpu, inst_cream->inst, address); |
| 5189 | 5165 | ||
| 5190 | cpu->Cpsr = ReadMemory32(cpu, address); | 5166 | cpu->Cpsr = cpu->ReadMemory32(address); |
| 5191 | cpu->Reg[15] = ReadMemory32(cpu, address + 4); | 5167 | cpu->Reg[15] = cpu->ReadMemory32(address + 4); |
| 5192 | 5168 | ||
| 5193 | INC_PC(sizeof(ldst_inst)); | 5169 | INC_PC(sizeof(ldst_inst)); |
| 5194 | goto DISPATCH; | 5170 | goto DISPATCH; |
| @@ -5201,7 +5177,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5201 | 5177 | ||
| 5202 | u32 rn_val = RN; | 5178 | u32 rn_val = RN; |
| 5203 | if (inst_cream->Rn == 15) | 5179 | if (inst_cream->Rn == 15) |
| 5204 | rn_val += 2 * GET_INST_SIZE(cpu); | 5180 | rn_val += 2 * cpu->GetInstructionSize(); |
| 5205 | 5181 | ||
| 5206 | bool carry; | 5182 | bool carry; |
| 5207 | bool overflow; | 5183 | bool overflow; |
| @@ -5210,7 +5186,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5210 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 5186 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 5211 | if (CurrentModeHasSPSR) { | 5187 | if (CurrentModeHasSPSR) { |
| 5212 | cpu->Cpsr = cpu->Spsr_copy; | 5188 | cpu->Cpsr = cpu->Spsr_copy; |
| 5213 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 5189 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 5214 | LOAD_NZCVT; | 5190 | LOAD_NZCVT; |
| 5215 | } | 5191 | } |
| 5216 | } else if (inst_cream->S) { | 5192 | } else if (inst_cream->S) { |
| @@ -5224,7 +5200,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5224 | goto DISPATCH; | 5200 | goto DISPATCH; |
| 5225 | } | 5201 | } |
| 5226 | } | 5202 | } |
| 5227 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5203 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5228 | INC_PC(sizeof(rsb_inst)); | 5204 | INC_PC(sizeof(rsb_inst)); |
| 5229 | FETCH_INST; | 5205 | FETCH_INST; |
| 5230 | GOTO_NEXT_INST; | 5206 | GOTO_NEXT_INST; |
| @@ -5234,14 +5210,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5234 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 5210 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 5235 | rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; | 5211 | rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; |
| 5236 | 5212 | ||
| 5213 | u32 rn_val = RN; | ||
| 5214 | if (inst_cream->Rn == 15) | ||
| 5215 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 5216 | |||
| 5237 | bool carry; | 5217 | bool carry; |
| 5238 | bool overflow; | 5218 | bool overflow; |
| 5239 | RD = AddWithCarry(~RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | 5219 | RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); |
| 5240 | 5220 | ||
| 5241 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 5221 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 5242 | if (CurrentModeHasSPSR) { | 5222 | if (CurrentModeHasSPSR) { |
| 5243 | cpu->Cpsr = cpu->Spsr_copy; | 5223 | cpu->Cpsr = cpu->Spsr_copy; |
| 5244 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 5224 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 5245 | LOAD_NZCVT; | 5225 | LOAD_NZCVT; |
| 5246 | } | 5226 | } |
| 5247 | } else if (inst_cream->S) { | 5227 | } else if (inst_cream->S) { |
| @@ -5255,7 +5235,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5255 | goto DISPATCH; | 5235 | goto DISPATCH; |
| 5256 | } | 5236 | } |
| 5257 | } | 5237 | } |
| 5258 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5238 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5259 | INC_PC(sizeof(rsc_inst)); | 5239 | INC_PC(sizeof(rsc_inst)); |
| 5260 | FETCH_INST; | 5240 | FETCH_INST; |
| 5261 | GOTO_NEXT_INST; | 5241 | GOTO_NEXT_INST; |
| @@ -5363,7 +5343,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5363 | } | 5343 | } |
| 5364 | } | 5344 | } |
| 5365 | 5345 | ||
| 5366 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5346 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5367 | INC_PC(sizeof(generic_arm_inst)); | 5347 | INC_PC(sizeof(generic_arm_inst)); |
| 5368 | FETCH_INST; | 5348 | FETCH_INST; |
| 5369 | GOTO_NEXT_INST; | 5349 | GOTO_NEXT_INST; |
| @@ -5374,14 +5354,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5374 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 5354 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 5375 | sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; | 5355 | sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; |
| 5376 | 5356 | ||
| 5357 | u32 rn_val = RN; | ||
| 5358 | if (inst_cream->Rn == 15) | ||
| 5359 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 5360 | |||
| 5377 | bool carry; | 5361 | bool carry; |
| 5378 | bool overflow; | 5362 | bool overflow; |
| 5379 | RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | 5363 | RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); |
| 5380 | 5364 | ||
| 5381 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 5365 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 5382 | if (CurrentModeHasSPSR) { | 5366 | if (CurrentModeHasSPSR) { |
| 5383 | cpu->Cpsr = cpu->Spsr_copy; | 5367 | cpu->Cpsr = cpu->Spsr_copy; |
| 5384 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 5368 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 5385 | LOAD_NZCVT; | 5369 | LOAD_NZCVT; |
| 5386 | } | 5370 | } |
| 5387 | } else if (inst_cream->S) { | 5371 | } else if (inst_cream->S) { |
| @@ -5395,7 +5379,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5395 | goto DISPATCH; | 5379 | goto DISPATCH; |
| 5396 | } | 5380 | } |
| 5397 | } | 5381 | } |
| 5398 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5382 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5399 | INC_PC(sizeof(sbc_inst)); | 5383 | INC_PC(sizeof(sbc_inst)); |
| 5400 | FETCH_INST; | 5384 | FETCH_INST; |
| 5401 | GOTO_NEXT_INST; | 5385 | GOTO_NEXT_INST; |
| @@ -5434,7 +5418,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5434 | RD = result; | 5418 | RD = result; |
| 5435 | } | 5419 | } |
| 5436 | 5420 | ||
| 5437 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5421 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5438 | INC_PC(sizeof(generic_arm_inst)); | 5422 | INC_PC(sizeof(generic_arm_inst)); |
| 5439 | FETCH_INST; | 5423 | FETCH_INST; |
| 5440 | GOTO_NEXT_INST; | 5424 | GOTO_NEXT_INST; |
| @@ -5453,7 +5437,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5453 | 5437 | ||
| 5454 | LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); | 5438 | LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); |
| 5455 | 5439 | ||
| 5456 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5440 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5457 | INC_PC(sizeof(setend_inst)); | 5441 | INC_PC(sizeof(setend_inst)); |
| 5458 | FETCH_INST; | 5442 | FETCH_INST; |
| 5459 | GOTO_NEXT_INST; | 5443 | GOTO_NEXT_INST; |
| @@ -5466,7 +5450,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5466 | LOG_TRACE(Core_ARM11, "SEV executed."); | 5450 | LOG_TRACE(Core_ARM11, "SEV executed."); |
| 5467 | } | 5451 | } |
| 5468 | 5452 | ||
| 5469 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5453 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5470 | INC_PC_STUB; | 5454 | INC_PC_STUB; |
| 5471 | FETCH_INST; | 5455 | FETCH_INST; |
| 5472 | GOTO_NEXT_INST; | 5456 | GOTO_NEXT_INST; |
| @@ -5538,7 +5522,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5538 | } | 5522 | } |
| 5539 | } | 5523 | } |
| 5540 | 5524 | ||
| 5541 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5525 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5542 | INC_PC(sizeof(generic_arm_inst)); | 5526 | INC_PC(sizeof(generic_arm_inst)); |
| 5543 | FETCH_INST; | 5527 | FETCH_INST; |
| 5544 | GOTO_NEXT_INST; | 5528 | GOTO_NEXT_INST; |
| @@ -5563,7 +5547,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5563 | if (AddOverflow(operand1 * operand2, RN, RD)) | 5547 | if (AddOverflow(operand1 * operand2, RN, RD)) |
| 5564 | cpu->Cpsr |= (1 << 27); | 5548 | cpu->Cpsr |= (1 << 27); |
| 5565 | } | 5549 | } |
| 5566 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5550 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5567 | INC_PC(sizeof(smla_inst)); | 5551 | INC_PC(sizeof(smla_inst)); |
| 5568 | FETCH_INST; | 5552 | FETCH_INST; |
| 5569 | GOTO_NEXT_INST; | 5553 | GOTO_NEXT_INST; |
| @@ -5619,7 +5603,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5619 | } | 5603 | } |
| 5620 | } | 5604 | } |
| 5621 | 5605 | ||
| 5622 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5606 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5623 | INC_PC(sizeof(smlad_inst)); | 5607 | INC_PC(sizeof(smlad_inst)); |
| 5624 | FETCH_INST; | 5608 | FETCH_INST; |
| 5625 | GOTO_NEXT_INST; | 5609 | GOTO_NEXT_INST; |
| @@ -5648,7 +5632,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5648 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | 5632 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); |
| 5649 | } | 5633 | } |
| 5650 | } | 5634 | } |
| 5651 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5635 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5652 | INC_PC(sizeof(umlal_inst)); | 5636 | INC_PC(sizeof(umlal_inst)); |
| 5653 | FETCH_INST; | 5637 | FETCH_INST; |
| 5654 | GOTO_NEXT_INST; | 5638 | GOTO_NEXT_INST; |
| @@ -5678,7 +5662,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5678 | RDHI = ((dest >> 32) & 0xFFFFFFFF); | 5662 | RDHI = ((dest >> 32) & 0xFFFFFFFF); |
| 5679 | } | 5663 | } |
| 5680 | 5664 | ||
| 5681 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5665 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5682 | INC_PC(sizeof(smlalxy_inst)); | 5666 | INC_PC(sizeof(smlalxy_inst)); |
| 5683 | FETCH_INST; | 5667 | FETCH_INST; |
| 5684 | GOTO_NEXT_INST; | 5668 | GOTO_NEXT_INST; |
| @@ -5703,7 +5687,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5703 | cpu->Cpsr |= (1 << 27); | 5687 | cpu->Cpsr |= (1 << 27); |
| 5704 | } | 5688 | } |
| 5705 | 5689 | ||
| 5706 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5690 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5707 | INC_PC(sizeof(smlad_inst)); | 5691 | INC_PC(sizeof(smlad_inst)); |
| 5708 | FETCH_INST; | 5692 | FETCH_INST; |
| 5709 | GOTO_NEXT_INST; | 5693 | GOTO_NEXT_INST; |
| @@ -5741,7 +5725,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5741 | RDHI = ((result >> 32) & 0xFFFFFFFF); | 5725 | RDHI = ((result >> 32) & 0xFFFFFFFF); |
| 5742 | } | 5726 | } |
| 5743 | 5727 | ||
| 5744 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5728 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5745 | INC_PC(sizeof(smlald_inst)); | 5729 | INC_PC(sizeof(smlald_inst)); |
| 5746 | FETCH_INST; | 5730 | FETCH_INST; |
| 5747 | GOTO_NEXT_INST; | 5731 | GOTO_NEXT_INST; |
| @@ -5777,7 +5761,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5777 | RD = ((result >> 32) & 0xFFFFFFFF); | 5761 | RD = ((result >> 32) & 0xFFFFFFFF); |
| 5778 | } | 5762 | } |
| 5779 | 5763 | ||
| 5780 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5764 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5781 | INC_PC(sizeof(smlad_inst)); | 5765 | INC_PC(sizeof(smlad_inst)); |
| 5782 | FETCH_INST; | 5766 | FETCH_INST; |
| 5783 | GOTO_NEXT_INST; | 5767 | GOTO_NEXT_INST; |
| @@ -5799,7 +5783,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5799 | operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); | 5783 | operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); |
| 5800 | RD = operand1 * operand2; | 5784 | RD = operand1 * operand2; |
| 5801 | } | 5785 | } |
| 5802 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5786 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5803 | INC_PC(sizeof(smul_inst)); | 5787 | INC_PC(sizeof(smul_inst)); |
| 5804 | FETCH_INST; | 5788 | FETCH_INST; |
| 5805 | GOTO_NEXT_INST; | 5789 | GOTO_NEXT_INST; |
| @@ -5825,7 +5809,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5825 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | 5809 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); |
| 5826 | } | 5810 | } |
| 5827 | } | 5811 | } |
| 5828 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5812 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5829 | INC_PC(sizeof(umull_inst)); | 5813 | INC_PC(sizeof(umull_inst)); |
| 5830 | FETCH_INST; | 5814 | FETCH_INST; |
| 5831 | GOTO_NEXT_INST; | 5815 | GOTO_NEXT_INST; |
| @@ -5841,7 +5825,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5841 | s64 result = (s64)rm * (s64)(s32)RN; | 5825 | s64 result = (s64)rm * (s64)(s32)RN; |
| 5842 | RD = BITS(result, 16, 47); | 5826 | RD = BITS(result, 16, 47); |
| 5843 | } | 5827 | } |
| 5844 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5828 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5845 | INC_PC(sizeof(smlad_inst)); | 5829 | INC_PC(sizeof(smlad_inst)); |
| 5846 | FETCH_INST; | 5830 | FETCH_INST; |
| 5847 | GOTO_NEXT_INST; | 5831 | GOTO_NEXT_INST; |
| @@ -5855,10 +5839,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5855 | u32 address = 0; | 5839 | u32 address = 0; |
| 5856 | inst_cream->get_addr(cpu, inst_cream->inst, address); | 5840 | inst_cream->get_addr(cpu, inst_cream->inst, address); |
| 5857 | 5841 | ||
| 5858 | WriteMemory32(cpu, address + 0, cpu->Reg[14]); | 5842 | cpu->WriteMemory32(address + 0, cpu->Reg[14]); |
| 5859 | WriteMemory32(cpu, address + 4, cpu->Spsr_copy); | 5843 | cpu->WriteMemory32(address + 4, cpu->Spsr_copy); |
| 5860 | 5844 | ||
| 5861 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5845 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5862 | INC_PC(sizeof(ldst_inst)); | 5846 | INC_PC(sizeof(ldst_inst)); |
| 5863 | FETCH_INST; | 5847 | FETCH_INST; |
| 5864 | GOTO_NEXT_INST; | 5848 | GOTO_NEXT_INST; |
| @@ -5891,7 +5875,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5891 | RD = rn_val; | 5875 | RD = rn_val; |
| 5892 | } | 5876 | } |
| 5893 | 5877 | ||
| 5894 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5878 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5895 | INC_PC(sizeof(ssat_inst)); | 5879 | INC_PC(sizeof(ssat_inst)); |
| 5896 | FETCH_INST; | 5880 | FETCH_INST; |
| 5897 | GOTO_NEXT_INST; | 5881 | GOTO_NEXT_INST; |
| @@ -5913,7 +5897,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5913 | cpu->Cpsr |= (1 << 27); | 5897 | cpu->Cpsr |= (1 << 27); |
| 5914 | } | 5898 | } |
| 5915 | 5899 | ||
| 5916 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5900 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5917 | INC_PC(sizeof(ssat_inst)); | 5901 | INC_PC(sizeof(ssat_inst)); |
| 5918 | FETCH_INST; | 5902 | FETCH_INST; |
| 5919 | GOTO_NEXT_INST; | 5903 | GOTO_NEXT_INST; |
| @@ -5923,7 +5907,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5923 | { | 5907 | { |
| 5924 | // Instruction not implemented | 5908 | // Instruction not implemented |
| 5925 | //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); | 5909 | //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); |
| 5926 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5910 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5927 | INC_PC(sizeof(stc_inst)); | 5911 | INC_PC(sizeof(stc_inst)); |
| 5928 | FETCH_INST; | 5912 | FETCH_INST; |
| 5929 | GOTO_NEXT_INST; | 5913 | GOTO_NEXT_INST; |
| @@ -5941,36 +5925,36 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5941 | if (BIT(inst_cream->inst, 22) == 1) { | 5925 | if (BIT(inst_cream->inst, 22) == 1) { |
| 5942 | for (int i = 0; i < 13; i++) { | 5926 | for (int i = 0; i < 13; i++) { |
| 5943 | if (BIT(inst_cream->inst, i)) { | 5927 | if (BIT(inst_cream->inst, i)) { |
| 5944 | WriteMemory32(cpu, addr, cpu->Reg[i]); | 5928 | cpu->WriteMemory32(addr, cpu->Reg[i]); |
| 5945 | addr += 4; | 5929 | addr += 4; |
| 5946 | } | 5930 | } |
| 5947 | } | 5931 | } |
| 5948 | if (BIT(inst_cream->inst, 13)) { | 5932 | if (BIT(inst_cream->inst, 13)) { |
| 5949 | if (cpu->Mode == USER32MODE) | 5933 | if (cpu->Mode == USER32MODE) |
| 5950 | WriteMemory32(cpu, addr, cpu->Reg[13]); | 5934 | cpu->WriteMemory32(addr, cpu->Reg[13]); |
| 5951 | else | 5935 | else |
| 5952 | WriteMemory32(cpu, addr, cpu->Reg_usr[0]); | 5936 | cpu->WriteMemory32(addr, cpu->Reg_usr[0]); |
| 5953 | 5937 | ||
| 5954 | addr += 4; | 5938 | addr += 4; |
| 5955 | } | 5939 | } |
| 5956 | if (BIT(inst_cream->inst, 14)) { | 5940 | if (BIT(inst_cream->inst, 14)) { |
| 5957 | if (cpu->Mode == USER32MODE) | 5941 | if (cpu->Mode == USER32MODE) |
| 5958 | WriteMemory32(cpu, addr, cpu->Reg[14]); | 5942 | cpu->WriteMemory32(addr, cpu->Reg[14]); |
| 5959 | else | 5943 | else |
| 5960 | WriteMemory32(cpu, addr, cpu->Reg_usr[1]); | 5944 | cpu->WriteMemory32(addr, cpu->Reg_usr[1]); |
| 5961 | 5945 | ||
| 5962 | addr += 4; | 5946 | addr += 4; |
| 5963 | } | 5947 | } |
| 5964 | if (BIT(inst_cream->inst, 15)) { | 5948 | if (BIT(inst_cream->inst, 15)) { |
| 5965 | WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8); | 5949 | cpu->WriteMemory32(addr, cpu->Reg_usr[1] + 8); |
| 5966 | } | 5950 | } |
| 5967 | } else { | 5951 | } else { |
| 5968 | for (int i = 0; i < 15; i++) { | 5952 | for (int i = 0; i < 15; i++) { |
| 5969 | if (BIT(inst_cream->inst, i)) { | 5953 | if (BIT(inst_cream->inst, i)) { |
| 5970 | if (i == Rn) | 5954 | if (i == Rn) |
| 5971 | WriteMemory32(cpu, addr, old_RN); | 5955 | cpu->WriteMemory32(addr, old_RN); |
| 5972 | else | 5956 | else |
| 5973 | WriteMemory32(cpu, addr, cpu->Reg[i]); | 5957 | cpu->WriteMemory32(addr, cpu->Reg[i]); |
| 5974 | 5958 | ||
| 5975 | addr += 4; | 5959 | addr += 4; |
| 5976 | } | 5960 | } |
| @@ -5978,10 +5962,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5978 | 5962 | ||
| 5979 | // Check PC reg | 5963 | // Check PC reg |
| 5980 | if (BIT(inst_cream->inst, 15)) | 5964 | if (BIT(inst_cream->inst, 15)) |
| 5981 | WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8); | 5965 | cpu->WriteMemory32(addr, cpu->Reg_usr[1] + 8); |
| 5982 | } | 5966 | } |
| 5983 | } | 5967 | } |
| 5984 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5968 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 5985 | INC_PC(sizeof(ldst_inst)); | 5969 | INC_PC(sizeof(ldst_inst)); |
| 5986 | FETCH_INST; | 5970 | FETCH_INST; |
| 5987 | GOTO_NEXT_INST; | 5971 | GOTO_NEXT_INST; |
| @@ -5999,7 +5983,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5999 | } | 5983 | } |
| 6000 | RD = operand2; | 5984 | RD = operand2; |
| 6001 | } | 5985 | } |
| 6002 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5986 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6003 | INC_PC(sizeof(sxtb_inst)); | 5987 | INC_PC(sizeof(sxtb_inst)); |
| 6004 | FETCH_INST; | 5988 | FETCH_INST; |
| 6005 | GOTO_NEXT_INST; | 5989 | GOTO_NEXT_INST; |
| @@ -6011,9 +5995,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6011 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 5995 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 6012 | 5996 | ||
| 6013 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; | 5997 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; |
| 6014 | WriteMemory32(cpu, addr, value); | 5998 | cpu->WriteMemory32(addr, value); |
| 6015 | } | 5999 | } |
| 6016 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6000 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6017 | INC_PC(sizeof(ldst_inst)); | 6001 | INC_PC(sizeof(ldst_inst)); |
| 6018 | FETCH_INST; | 6002 | FETCH_INST; |
| 6019 | GOTO_NEXT_INST; | 6003 | GOTO_NEXT_INST; |
| @@ -6024,7 +6008,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6024 | uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component; | 6008 | uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component; |
| 6025 | RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; | 6009 | RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; |
| 6026 | } | 6010 | } |
| 6027 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6011 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6028 | INC_PC(sizeof(uxtb_inst)); | 6012 | INC_PC(sizeof(uxtb_inst)); |
| 6029 | FETCH_INST; | 6013 | FETCH_INST; |
| 6030 | GOTO_NEXT_INST; | 6014 | GOTO_NEXT_INST; |
| @@ -6037,7 +6021,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6037 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; | 6021 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; |
| 6038 | RD = RN + operand2; | 6022 | RD = RN + operand2; |
| 6039 | } | 6023 | } |
| 6040 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6024 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6041 | INC_PC(sizeof(uxtab_inst)); | 6025 | INC_PC(sizeof(uxtab_inst)); |
| 6042 | FETCH_INST; | 6026 | FETCH_INST; |
| 6043 | GOTO_NEXT_INST; | 6027 | GOTO_NEXT_INST; |
| @@ -6050,7 +6034,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6050 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; | 6034 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; |
| 6051 | Memory::Write8(addr, value); | 6035 | Memory::Write8(addr, value); |
| 6052 | } | 6036 | } |
| 6053 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6037 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6054 | INC_PC(sizeof(ldst_inst)); | 6038 | INC_PC(sizeof(ldst_inst)); |
| 6055 | FETCH_INST; | 6039 | FETCH_INST; |
| 6056 | GOTO_NEXT_INST; | 6040 | GOTO_NEXT_INST; |
| @@ -6063,7 +6047,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6063 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; | 6047 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; |
| 6064 | Memory::Write8(addr, value); | 6048 | Memory::Write8(addr, value); |
| 6065 | } | 6049 | } |
| 6066 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6050 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6067 | INC_PC(sizeof(ldst_inst)); | 6051 | INC_PC(sizeof(ldst_inst)); |
| 6068 | FETCH_INST; | 6052 | FETCH_INST; |
| 6069 | GOTO_NEXT_INST; | 6053 | GOTO_NEXT_INST; |
| @@ -6076,10 +6060,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6076 | 6060 | ||
| 6077 | // The 3DS doesn't have the Large Physical Access Extension (LPAE) | 6061 | // The 3DS doesn't have the Large Physical Access Extension (LPAE) |
| 6078 | // so STRD wouldn't store these as a single write. | 6062 | // so STRD wouldn't store these as a single write. |
| 6079 | WriteMemory32(cpu, addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]); | 6063 | cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]); |
| 6080 | WriteMemory32(cpu, addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]); | 6064 | cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]); |
| 6081 | } | 6065 | } |
| 6082 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6066 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6083 | INC_PC(sizeof(ldst_inst)); | 6067 | INC_PC(sizeof(ldst_inst)); |
| 6084 | FETCH_INST; | 6068 | FETCH_INST; |
| 6085 | GOTO_NEXT_INST; | 6069 | GOTO_NEXT_INST; |
| @@ -6090,18 +6074,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6090 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 6074 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 6091 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | 6075 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |
| 6092 | 6076 | ||
| 6093 | if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { | 6077 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { |
| 6094 | remove_exclusive(cpu, write_addr); | 6078 | cpu->UnsetExclusiveMemoryAddress(); |
| 6095 | cpu->exclusive_state = 0; | 6079 | cpu->WriteMemory32(write_addr, RM); |
| 6096 | |||
| 6097 | WriteMemory32(cpu, write_addr, RM); | ||
| 6098 | RD = 0; | 6080 | RD = 0; |
| 6099 | } else { | 6081 | } else { |
| 6100 | // Failed to write due to mutex access | 6082 | // Failed to write due to mutex access |
| 6101 | RD = 1; | 6083 | RD = 1; |
| 6102 | } | 6084 | } |
| 6103 | } | 6085 | } |
| 6104 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6086 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6105 | INC_PC(sizeof(generic_arm_inst)); | 6087 | INC_PC(sizeof(generic_arm_inst)); |
| 6106 | FETCH_INST; | 6088 | FETCH_INST; |
| 6107 | GOTO_NEXT_INST; | 6089 | GOTO_NEXT_INST; |
| @@ -6112,10 +6094,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6112 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 6094 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 6113 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | 6095 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |
| 6114 | 6096 | ||
| 6115 | if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { | 6097 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { |
| 6116 | remove_exclusive(cpu, write_addr); | 6098 | cpu->UnsetExclusiveMemoryAddress(); |
| 6117 | cpu->exclusive_state = 0; | ||
| 6118 | |||
| 6119 | Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); | 6099 | Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); |
| 6120 | RD = 0; | 6100 | RD = 0; |
| 6121 | } else { | 6101 | } else { |
| @@ -6123,7 +6103,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6123 | RD = 1; | 6103 | RD = 1; |
| 6124 | } | 6104 | } |
| 6125 | } | 6105 | } |
| 6126 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6106 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6127 | INC_PC(sizeof(generic_arm_inst)); | 6107 | INC_PC(sizeof(generic_arm_inst)); |
| 6128 | FETCH_INST; | 6108 | FETCH_INST; |
| 6129 | GOTO_NEXT_INST; | 6109 | GOTO_NEXT_INST; |
| @@ -6134,20 +6114,19 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6134 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 6114 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 6135 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | 6115 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |
| 6136 | 6116 | ||
| 6137 | if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { | 6117 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { |
| 6138 | remove_exclusive(cpu, write_addr); | 6118 | cpu->UnsetExclusiveMemoryAddress(); |
| 6139 | cpu->exclusive_state = 0; | ||
| 6140 | 6119 | ||
| 6141 | const u32 rt = cpu->Reg[inst_cream->Rm + 0]; | 6120 | const u32 rt = cpu->Reg[inst_cream->Rm + 0]; |
| 6142 | const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; | 6121 | const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; |
| 6143 | u64 value; | 6122 | u64 value; |
| 6144 | 6123 | ||
| 6145 | if (InBigEndianMode(cpu)) | 6124 | if (cpu->InBigEndianMode()) |
| 6146 | value = (((u64)rt << 32) | rt2); | 6125 | value = (((u64)rt << 32) | rt2); |
| 6147 | else | 6126 | else |
| 6148 | value = (((u64)rt2 << 32) | rt); | 6127 | value = (((u64)rt2 << 32) | rt); |
| 6149 | 6128 | ||
| 6150 | WriteMemory64(cpu, write_addr, value); | 6129 | cpu->WriteMemory64(write_addr, value); |
| 6151 | RD = 0; | 6130 | RD = 0; |
| 6152 | } | 6131 | } |
| 6153 | else { | 6132 | else { |
| @@ -6155,7 +6134,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6155 | RD = 1; | 6134 | RD = 1; |
| 6156 | } | 6135 | } |
| 6157 | } | 6136 | } |
| 6158 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6137 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6159 | INC_PC(sizeof(generic_arm_inst)); | 6138 | INC_PC(sizeof(generic_arm_inst)); |
| 6160 | FETCH_INST; | 6139 | FETCH_INST; |
| 6161 | GOTO_NEXT_INST; | 6140 | GOTO_NEXT_INST; |
| @@ -6166,18 +6145,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6166 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 6145 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 6167 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | 6146 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |
| 6168 | 6147 | ||
| 6169 | if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { | 6148 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { |
| 6170 | remove_exclusive(cpu, write_addr); | 6149 | cpu->UnsetExclusiveMemoryAddress(); |
| 6171 | cpu->exclusive_state = 0; | 6150 | cpu->WriteMemory16(write_addr, RM); |
| 6172 | |||
| 6173 | WriteMemory16(cpu, write_addr, RM); | ||
| 6174 | RD = 0; | 6151 | RD = 0; |
| 6175 | } else { | 6152 | } else { |
| 6176 | // Failed to write due to mutex access | 6153 | // Failed to write due to mutex access |
| 6177 | RD = 1; | 6154 | RD = 1; |
| 6178 | } | 6155 | } |
| 6179 | } | 6156 | } |
| 6180 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6157 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6181 | INC_PC(sizeof(generic_arm_inst)); | 6158 | INC_PC(sizeof(generic_arm_inst)); |
| 6182 | FETCH_INST; | 6159 | FETCH_INST; |
| 6183 | GOTO_NEXT_INST; | 6160 | GOTO_NEXT_INST; |
| @@ -6189,9 +6166,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6189 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 6166 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 6190 | 6167 | ||
| 6191 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; | 6168 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; |
| 6192 | WriteMemory16(cpu, addr, value); | 6169 | cpu->WriteMemory16(addr, value); |
| 6193 | } | 6170 | } |
| 6194 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6171 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6195 | INC_PC(sizeof(ldst_inst)); | 6172 | INC_PC(sizeof(ldst_inst)); |
| 6196 | FETCH_INST; | 6173 | FETCH_INST; |
| 6197 | GOTO_NEXT_INST; | 6174 | GOTO_NEXT_INST; |
| @@ -6203,9 +6180,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6203 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 6180 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 6204 | 6181 | ||
| 6205 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; | 6182 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; |
| 6206 | WriteMemory32(cpu, addr, value); | 6183 | cpu->WriteMemory32(addr, value); |
| 6207 | } | 6184 | } |
| 6208 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6185 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6209 | INC_PC(sizeof(ldst_inst)); | 6186 | INC_PC(sizeof(ldst_inst)); |
| 6210 | FETCH_INST; | 6187 | FETCH_INST; |
| 6211 | GOTO_NEXT_INST; | 6188 | GOTO_NEXT_INST; |
| @@ -6217,7 +6194,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6217 | 6194 | ||
| 6218 | u32 rn_val = RN; | 6195 | u32 rn_val = RN; |
| 6219 | if (inst_cream->Rn == 15) | 6196 | if (inst_cream->Rn == 15) |
| 6220 | rn_val += 8; | 6197 | rn_val += 2 * cpu->GetInstructionSize(); |
| 6221 | 6198 | ||
| 6222 | bool carry; | 6199 | bool carry; |
| 6223 | bool overflow; | 6200 | bool overflow; |
| @@ -6226,7 +6203,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6226 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 6203 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 6227 | if (CurrentModeHasSPSR) { | 6204 | if (CurrentModeHasSPSR) { |
| 6228 | cpu->Cpsr = cpu->Spsr_copy; | 6205 | cpu->Cpsr = cpu->Spsr_copy; |
| 6229 | switch_mode(cpu, cpu->Spsr_copy & 0x1f); | 6206 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 6230 | LOAD_NZCVT; | 6207 | LOAD_NZCVT; |
| 6231 | } | 6208 | } |
| 6232 | } else if (inst_cream->S) { | 6209 | } else if (inst_cream->S) { |
| @@ -6240,7 +6217,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6240 | goto DISPATCH; | 6217 | goto DISPATCH; |
| 6241 | } | 6218 | } |
| 6242 | } | 6219 | } |
| 6243 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6220 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6244 | INC_PC(sizeof(sub_inst)); | 6221 | INC_PC(sizeof(sub_inst)); |
| 6245 | FETCH_INST; | 6222 | FETCH_INST; |
| 6246 | GOTO_NEXT_INST; | 6223 | GOTO_NEXT_INST; |
| @@ -6252,7 +6229,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6252 | SVC::CallSVC(inst_cream->num & 0xFFFF); | 6229 | SVC::CallSVC(inst_cream->num & 0xFFFF); |
| 6253 | } | 6230 | } |
| 6254 | 6231 | ||
| 6255 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6232 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6256 | INC_PC(sizeof(swi_inst)); | 6233 | INC_PC(sizeof(swi_inst)); |
| 6257 | FETCH_INST; | 6234 | FETCH_INST; |
| 6258 | GOTO_NEXT_INST; | 6235 | GOTO_NEXT_INST; |
| @@ -6263,12 +6240,12 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6263 | swp_inst* inst_cream = (swp_inst*)inst_base->component; | 6240 | swp_inst* inst_cream = (swp_inst*)inst_base->component; |
| 6264 | 6241 | ||
| 6265 | addr = RN; | 6242 | addr = RN; |
| 6266 | unsigned int value = ReadMemory32(cpu, addr); | 6243 | unsigned int value = cpu->ReadMemory32(addr); |
| 6267 | WriteMemory32(cpu, addr, RM); | 6244 | cpu->WriteMemory32(addr, RM); |
| 6268 | 6245 | ||
| 6269 | RD = value; | 6246 | RD = value; |
| 6270 | } | 6247 | } |
| 6271 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6248 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6272 | INC_PC(sizeof(swp_inst)); | 6249 | INC_PC(sizeof(swp_inst)); |
| 6273 | FETCH_INST; | 6250 | FETCH_INST; |
| 6274 | GOTO_NEXT_INST; | 6251 | GOTO_NEXT_INST; |
| @@ -6282,7 +6259,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6282 | Memory::Write8(addr, (RM & 0xFF)); | 6259 | Memory::Write8(addr, (RM & 0xFF)); |
| 6283 | RD = value; | 6260 | RD = value; |
| 6284 | } | 6261 | } |
| 6285 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6262 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6286 | INC_PC(sizeof(swp_inst)); | 6263 | INC_PC(sizeof(swp_inst)); |
| 6287 | FETCH_INST; | 6264 | FETCH_INST; |
| 6288 | GOTO_NEXT_INST; | 6265 | GOTO_NEXT_INST; |
| @@ -6298,7 +6275,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6298 | operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2; | 6275 | operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2; |
| 6299 | RD = RN + operand2; | 6276 | RD = RN + operand2; |
| 6300 | } | 6277 | } |
| 6301 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6278 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6302 | INC_PC(sizeof(uxtab_inst)); | 6279 | INC_PC(sizeof(uxtab_inst)); |
| 6303 | FETCH_INST; | 6280 | FETCH_INST; |
| 6304 | GOTO_NEXT_INST; | 6281 | GOTO_NEXT_INST; |
| @@ -6331,7 +6308,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6331 | } | 6308 | } |
| 6332 | } | 6309 | } |
| 6333 | 6310 | ||
| 6334 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6311 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6335 | INC_PC(sizeof(sxtab_inst)); | 6312 | INC_PC(sizeof(sxtab_inst)); |
| 6336 | FETCH_INST; | 6313 | FETCH_INST; |
| 6337 | GOTO_NEXT_INST; | 6314 | GOTO_NEXT_INST; |
| @@ -6347,7 +6324,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6347 | operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2; | 6324 | operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2; |
| 6348 | RD = RN + operand2; | 6325 | RD = RN + operand2; |
| 6349 | } | 6326 | } |
| 6350 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6327 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6351 | INC_PC(sizeof(sxtah_inst)); | 6328 | INC_PC(sizeof(sxtah_inst)); |
| 6352 | FETCH_INST; | 6329 | FETCH_INST; |
| 6353 | GOTO_NEXT_INST; | 6330 | GOTO_NEXT_INST; |
| @@ -6362,7 +6339,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6362 | u32 rop = SHIFTER_OPERAND; | 6339 | u32 rop = SHIFTER_OPERAND; |
| 6363 | 6340 | ||
| 6364 | if (inst_cream->Rn == 15) | 6341 | if (inst_cream->Rn == 15) |
| 6365 | lop += GET_INST_SIZE(cpu) * 2; | 6342 | lop += cpu->GetInstructionSize() * 2; |
| 6366 | 6343 | ||
| 6367 | u32 result = lop ^ rop; | 6344 | u32 result = lop ^ rop; |
| 6368 | 6345 | ||
| @@ -6370,7 +6347,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6370 | UPDATE_ZFLAG(result); | 6347 | UPDATE_ZFLAG(result); |
| 6371 | UPDATE_CFLAG_WITH_SC; | 6348 | UPDATE_CFLAG_WITH_SC; |
| 6372 | } | 6349 | } |
| 6373 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6350 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6374 | INC_PC(sizeof(teq_inst)); | 6351 | INC_PC(sizeof(teq_inst)); |
| 6375 | FETCH_INST; | 6352 | FETCH_INST; |
| 6376 | GOTO_NEXT_INST; | 6353 | GOTO_NEXT_INST; |
| @@ -6384,7 +6361,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6384 | u32 rop = SHIFTER_OPERAND; | 6361 | u32 rop = SHIFTER_OPERAND; |
| 6385 | 6362 | ||
| 6386 | if (inst_cream->Rn == 15) | 6363 | if (inst_cream->Rn == 15) |
| 6387 | lop += GET_INST_SIZE(cpu) * 2; | 6364 | lop += cpu->GetInstructionSize() * 2; |
| 6388 | 6365 | ||
| 6389 | u32 result = lop & rop; | 6366 | u32 result = lop & rop; |
| 6390 | 6367 | ||
| @@ -6392,7 +6369,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6392 | UPDATE_ZFLAG(result); | 6369 | UPDATE_ZFLAG(result); |
| 6393 | UPDATE_CFLAG_WITH_SC; | 6370 | UPDATE_CFLAG_WITH_SC; |
| 6394 | } | 6371 | } |
| 6395 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6372 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6396 | INC_PC(sizeof(tst_inst)); | 6373 | INC_PC(sizeof(tst_inst)); |
| 6397 | FETCH_INST; | 6374 | FETCH_INST; |
| 6398 | GOTO_NEXT_INST; | 6375 | GOTO_NEXT_INST; |
| @@ -6563,7 +6540,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6563 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); | 6540 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); |
| 6564 | } | 6541 | } |
| 6565 | 6542 | ||
| 6566 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6543 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6567 | INC_PC(sizeof(generic_arm_inst)); | 6544 | INC_PC(sizeof(generic_arm_inst)); |
| 6568 | FETCH_INST; | 6545 | FETCH_INST; |
| 6569 | GOTO_NEXT_INST; | 6546 | GOTO_NEXT_INST; |
| @@ -6643,7 +6620,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6643 | } | 6620 | } |
| 6644 | } | 6621 | } |
| 6645 | 6622 | ||
| 6646 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6623 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6647 | INC_PC(sizeof(generic_arm_inst)); | 6624 | INC_PC(sizeof(generic_arm_inst)); |
| 6648 | FETCH_INST; | 6625 | FETCH_INST; |
| 6649 | GOTO_NEXT_INST; | 6626 | GOTO_NEXT_INST; |
| @@ -6662,7 +6639,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6662 | RDLO = (result & 0xFFFFFFFF); | 6639 | RDLO = (result & 0xFFFFFFFF); |
| 6663 | RDHI = ((result >> 32) & 0xFFFFFFFF); | 6640 | RDHI = ((result >> 32) & 0xFFFFFFFF); |
| 6664 | } | 6641 | } |
| 6665 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6642 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6666 | INC_PC(sizeof(umaal_inst)); | 6643 | INC_PC(sizeof(umaal_inst)); |
| 6667 | FETCH_INST; | 6644 | FETCH_INST; |
| 6668 | GOTO_NEXT_INST; | 6645 | GOTO_NEXT_INST; |
| @@ -6685,7 +6662,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6685 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | 6662 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); |
| 6686 | } | 6663 | } |
| 6687 | } | 6664 | } |
| 6688 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6665 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6689 | INC_PC(sizeof(umlal_inst)); | 6666 | INC_PC(sizeof(umlal_inst)); |
| 6690 | FETCH_INST; | 6667 | FETCH_INST; |
| 6691 | GOTO_NEXT_INST; | 6668 | GOTO_NEXT_INST; |
| @@ -6705,7 +6682,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6705 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | 6682 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); |
| 6706 | } | 6683 | } |
| 6707 | } | 6684 | } |
| 6708 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6685 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6709 | INC_PC(sizeof(umull_inst)); | 6686 | INC_PC(sizeof(umull_inst)); |
| 6710 | FETCH_INST; | 6687 | FETCH_INST; |
| 6711 | GOTO_NEXT_INST; | 6688 | GOTO_NEXT_INST; |
| @@ -6733,7 +6710,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6733 | { | 6710 | { |
| 6734 | bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component; | 6711 | bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component; |
| 6735 | cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm; | 6712 | cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm; |
| 6736 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6713 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6737 | INC_PC(sizeof(bl_1_thumb)); | 6714 | INC_PC(sizeof(bl_1_thumb)); |
| 6738 | FETCH_INST; | 6715 | FETCH_INST; |
| 6739 | GOTO_NEXT_INST; | 6716 | GOTO_NEXT_INST; |
| @@ -6814,7 +6791,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6814 | RD = ((lo_val & 0xFFFF) | hi_val << 16); | 6791 | RD = ((lo_val & 0xFFFF) | hi_val << 16); |
| 6815 | } | 6792 | } |
| 6816 | 6793 | ||
| 6817 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6794 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6818 | INC_PC(sizeof(generic_arm_inst)); | 6795 | INC_PC(sizeof(generic_arm_inst)); |
| 6819 | FETCH_INST; | 6796 | FETCH_INST; |
| 6820 | GOTO_NEXT_INST; | 6797 | GOTO_NEXT_INST; |
| @@ -6844,7 +6821,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6844 | RD = finalDif; | 6821 | RD = finalDif; |
| 6845 | } | 6822 | } |
| 6846 | 6823 | ||
| 6847 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6824 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6848 | INC_PC(sizeof(generic_arm_inst)); | 6825 | INC_PC(sizeof(generic_arm_inst)); |
| 6849 | FETCH_INST; | 6826 | FETCH_INST; |
| 6850 | GOTO_NEXT_INST; | 6827 | GOTO_NEXT_INST; |
| @@ -6877,7 +6854,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6877 | RD = rn_val; | 6854 | RD = rn_val; |
| 6878 | } | 6855 | } |
| 6879 | 6856 | ||
| 6880 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6857 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6881 | INC_PC(sizeof(ssat_inst)); | 6858 | INC_PC(sizeof(ssat_inst)); |
| 6882 | FETCH_INST; | 6859 | FETCH_INST; |
| 6883 | GOTO_NEXT_INST; | 6860 | GOTO_NEXT_INST; |
| @@ -6899,7 +6876,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6899 | cpu->Cpsr |= (1 << 27); | 6876 | cpu->Cpsr |= (1 << 27); |
| 6900 | } | 6877 | } |
| 6901 | 6878 | ||
| 6902 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6879 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6903 | INC_PC(sizeof(ssat_inst)); | 6880 | INC_PC(sizeof(ssat_inst)); |
| 6904 | FETCH_INST; | 6881 | FETCH_INST; |
| 6905 | GOTO_NEXT_INST; | 6882 | GOTO_NEXT_INST; |
| @@ -6930,7 +6907,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6930 | } | 6907 | } |
| 6931 | } | 6908 | } |
| 6932 | 6909 | ||
| 6933 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6910 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6934 | INC_PC(sizeof(uxtab_inst)); | 6911 | INC_PC(sizeof(uxtab_inst)); |
| 6935 | FETCH_INST; | 6912 | FETCH_INST; |
| 6936 | GOTO_NEXT_INST; | 6913 | GOTO_NEXT_INST; |
| @@ -6943,7 +6920,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6943 | LOG_TRACE(Core_ARM11, "WFE executed."); | 6920 | LOG_TRACE(Core_ARM11, "WFE executed."); |
| 6944 | } | 6921 | } |
| 6945 | 6922 | ||
| 6946 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6923 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6947 | INC_PC_STUB; | 6924 | INC_PC_STUB; |
| 6948 | FETCH_INST; | 6925 | FETCH_INST; |
| 6949 | GOTO_NEXT_INST; | 6926 | GOTO_NEXT_INST; |
| @@ -6956,7 +6933,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6956 | LOG_TRACE(Core_ARM11, "WFI executed."); | 6933 | LOG_TRACE(Core_ARM11, "WFI executed."); |
| 6957 | } | 6934 | } |
| 6958 | 6935 | ||
| 6959 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6936 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6960 | INC_PC_STUB; | 6937 | INC_PC_STUB; |
| 6961 | FETCH_INST; | 6938 | FETCH_INST; |
| 6962 | GOTO_NEXT_INST; | 6939 | GOTO_NEXT_INST; |
| @@ -6969,7 +6946,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6969 | LOG_TRACE(Core_ARM11, "YIELD executed."); | 6946 | LOG_TRACE(Core_ARM11, "YIELD executed."); |
| 6970 | } | 6947 | } |
| 6971 | 6948 | ||
| 6972 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6949 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 6973 | INC_PC_STUB; | 6950 | INC_PC_STUB; |
| 6974 | FETCH_INST; | 6951 | FETCH_INST; |
| 6975 | GOTO_NEXT_INST; | 6952 | GOTO_NEXT_INST; |
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h index 1c324d29c..7a46dcc94 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.h +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h | |||
| @@ -4,6 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/arm/skyeye_common/armdefs.h" | 7 | struct ARMul_State; |
| 8 | 8 | ||
| 9 | unsigned InterpreterMainLoop(ARMul_State* state); | 9 | 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 5a9a6a788..000000000 --- a/src/core/arm/dyncom/arm_dyncom_run.cpp +++ /dev/null | |||
| @@ -1,93 +0,0 @@ | |||
| 1 | // Copyright 2012 Michael Kang, 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/arm/dyncom/arm_dyncom_run.h" | ||
| 6 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 7 | |||
| 8 | void switch_mode(ARMul_State* core, uint32_t mode) { | ||
| 9 | if (core->Mode == mode) | ||
| 10 | return; | ||
| 11 | |||
| 12 | if (mode != USERBANK) { | ||
| 13 | switch (core->Mode) { | ||
| 14 | case SYSTEM32MODE: // Shares registers with user mode | ||
| 15 | case USER32MODE: | ||
| 16 | core->Reg_usr[0] = core->Reg[13]; | ||
| 17 | core->Reg_usr[1] = core->Reg[14]; | ||
| 18 | break; | ||
| 19 | case IRQ32MODE: | ||
| 20 | core->Reg_irq[0] = core->Reg[13]; | ||
| 21 | core->Reg_irq[1] = core->Reg[14]; | ||
| 22 | core->Spsr[IRQBANK] = core->Spsr_copy; | ||
| 23 | break; | ||
| 24 | case SVC32MODE: | ||
| 25 | core->Reg_svc[0] = core->Reg[13]; | ||
| 26 | core->Reg_svc[1] = core->Reg[14]; | ||
| 27 | core->Spsr[SVCBANK] = core->Spsr_copy; | ||
| 28 | break; | ||
| 29 | case ABORT32MODE: | ||
| 30 | core->Reg_abort[0] = core->Reg[13]; | ||
| 31 | core->Reg_abort[1] = core->Reg[14]; | ||
| 32 | core->Spsr[ABORTBANK] = core->Spsr_copy; | ||
| 33 | break; | ||
| 34 | case UNDEF32MODE: | ||
| 35 | core->Reg_undef[0] = core->Reg[13]; | ||
| 36 | core->Reg_undef[1] = core->Reg[14]; | ||
| 37 | core->Spsr[UNDEFBANK] = core->Spsr_copy; | ||
| 38 | break; | ||
| 39 | case FIQ32MODE: | ||
| 40 | core->Reg_firq[0] = core->Reg[13]; | ||
| 41 | core->Reg_firq[1] = core->Reg[14]; | ||
| 42 | core->Spsr[FIQBANK] = core->Spsr_copy; | ||
| 43 | break; | ||
| 44 | } | ||
| 45 | |||
| 46 | switch (mode) { | ||
| 47 | case USER32MODE: | ||
| 48 | core->Reg[13] = core->Reg_usr[0]; | ||
| 49 | core->Reg[14] = core->Reg_usr[1]; | ||
| 50 | core->Bank = USERBANK; | ||
| 51 | break; | ||
| 52 | case IRQ32MODE: | ||
| 53 | core->Reg[13] = core->Reg_irq[0]; | ||
| 54 | core->Reg[14] = core->Reg_irq[1]; | ||
| 55 | core->Spsr_copy = core->Spsr[IRQBANK]; | ||
| 56 | core->Bank = IRQBANK; | ||
| 57 | break; | ||
| 58 | case SVC32MODE: | ||
| 59 | core->Reg[13] = core->Reg_svc[0]; | ||
| 60 | core->Reg[14] = core->Reg_svc[1]; | ||
| 61 | core->Spsr_copy = core->Spsr[SVCBANK]; | ||
| 62 | core->Bank = SVCBANK; | ||
| 63 | break; | ||
| 64 | case ABORT32MODE: | ||
| 65 | core->Reg[13] = core->Reg_abort[0]; | ||
| 66 | core->Reg[14] = core->Reg_abort[1]; | ||
| 67 | core->Spsr_copy = core->Spsr[ABORTBANK]; | ||
| 68 | core->Bank = ABORTBANK; | ||
| 69 | break; | ||
| 70 | case UNDEF32MODE: | ||
| 71 | core->Reg[13] = core->Reg_undef[0]; | ||
| 72 | core->Reg[14] = core->Reg_undef[1]; | ||
| 73 | core->Spsr_copy = core->Spsr[UNDEFBANK]; | ||
| 74 | core->Bank = UNDEFBANK; | ||
| 75 | break; | ||
| 76 | case FIQ32MODE: | ||
| 77 | core->Reg[13] = core->Reg_firq[0]; | ||
| 78 | core->Reg[14] = core->Reg_firq[1]; | ||
| 79 | core->Spsr_copy = core->Spsr[FIQBANK]; | ||
| 80 | core->Bank = FIQBANK; | ||
| 81 | break; | ||
| 82 | case SYSTEM32MODE: // Shares registers with user mode. | ||
| 83 | core->Reg[13] = core->Reg_usr[0]; | ||
| 84 | core->Reg[14] = core->Reg_usr[1]; | ||
| 85 | core->Bank = SYSTEMBANK; | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | |||
| 89 | // Set the mode bits in the APSR | ||
| 90 | core->Cpsr = (core->Cpsr & ~core->Mode) | mode; | ||
| 91 | core->Mode = mode; | ||
| 92 | } | ||
| 93 | } | ||
diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h index 85774c565..13bef17fc 100644 --- a/src/core/arm/dyncom/arm_dyncom_run.h +++ b/src/core/arm/dyncom/arm_dyncom_run.h | |||
| @@ -18,40 +18,31 @@ | |||
| 18 | 18 | ||
| 19 | #pragma once | 19 | #pragma once |
| 20 | 20 | ||
| 21 | #include "core/arm/skyeye_common/armdefs.h" | 21 | #include "core/arm/skyeye_common/armstate.h" |
| 22 | |||
| 23 | void switch_mode(ARMul_State* core, uint32_t mode); | ||
| 24 | |||
| 25 | // Note that for the 3DS, a Thumb instruction will only ever be | ||
| 26 | // two bytes in size. Thus we don't need to worry about ThumbEE | ||
| 27 | // or Thumb-2 where instructions can be 4 bytes in length. | ||
| 28 | static inline u32 GET_INST_SIZE(ARMul_State* core) { | ||
| 29 | return core->TFlag? 2 : 4; | ||
| 30 | } | ||
| 31 | 22 | ||
| 32 | /** | 23 | /** |
| 33 | * Checks if the PC is being read, and if so, word-aligns it. | 24 | * Checks if the PC is being read, and if so, word-aligns it. |
| 34 | * Used with address calculations. | 25 | * Used with address calculations. |
| 35 | * | 26 | * |
| 36 | * @param core The ARM CPU state instance. | 27 | * @param cpu The ARM CPU state instance. |
| 37 | * @param Rn The register being read. | 28 | * @param Rn The register being read. |
| 38 | * | 29 | * |
| 39 | * @return If the PC is being read, then the word-aligned PC value is returned. | 30 | * @return If the PC is being read, then the word-aligned PC value is returned. |
| 40 | * If the PC is not being read, then the value stored in the register is returned. | 31 | * If the PC is not being read, then the value stored in the register is returned. |
| 41 | */ | 32 | */ |
| 42 | static inline u32 CHECK_READ_REG15_WA(ARMul_State* core, int Rn) { | 33 | static inline u32 CHECK_READ_REG15_WA(ARMul_State* cpu, int Rn) { |
| 43 | return (Rn == 15) ? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; | 34 | return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn]; |
| 44 | } | 35 | } |
| 45 | 36 | ||
| 46 | /** | 37 | /** |
| 47 | * Reads the PC. Used for data processing operations that use the PC. | 38 | * Reads the PC. Used for data processing operations that use the PC. |
| 48 | * | 39 | * |
| 49 | * @param core The ARM CPU state instance. | 40 | * @param cpu The ARM CPU state instance. |
| 50 | * @param Rn The register being read. | 41 | * @param Rn The register being read. |
| 51 | * | 42 | * |
| 52 | * @return If the PC is being read, then the incremented PC value is returned. | 43 | * @return If the PC is being read, then the incremented PC value is returned. |
| 53 | * If the PC is not being read, then the values stored in the register is returned. | 44 | * If the PC is not being read, then the values stored in the register is returned. |
| 54 | */ | 45 | */ |
| 55 | static inline u32 CHECK_READ_REG15(ARMul_State* core, int Rn) { | 46 | static inline u32 CHECK_READ_REG15(ARMul_State* cpu, int Rn) { |
| 56 | return (Rn == 15) ? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; | 47 | return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn]; |
| 57 | } | 48 | } |
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp index f10a5b70f..29272fd5d 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp +++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp | |||
| @@ -6,20 +6,15 @@ | |||
| 6 | // ARM instruction, and using the existing ARM simulator. | 6 | // ARM instruction, and using the existing ARM simulator. |
| 7 | 7 | ||
| 8 | #include "core/arm/dyncom/arm_dyncom_thumb.h" | 8 | #include "core/arm/dyncom/arm_dyncom_thumb.h" |
| 9 | #include "core/arm/skyeye_common/armsupp.h" | ||
| 9 | 10 | ||
| 10 | // Decode a 16bit Thumb instruction. The instruction is in the low 16-bits of the tinstr field, | 11 | // Decode a 16bit Thumb instruction. The instruction is in the low 16-bits of the tinstr field, |
| 11 | // with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions | 12 | // with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions |
| 12 | // allows easier simulation of the special dual BL instruction. | 13 | // allows easier simulation of the special dual BL instruction. |
| 13 | 14 | ||
| 14 | tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | 15 | ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { |
| 15 | tdstate valid = t_uninitialized; | 16 | ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED; |
| 16 | ARMword tinstr = instr; | 17 | u32 tinstr = GetThumbInstruction(instr, addr); |
| 17 | |||
| 18 | // The endian should be judge here | ||
| 19 | if((addr & 0x3) != 0) | ||
| 20 | tinstr = instr >> 16; | ||
| 21 | else | ||
| 22 | tinstr &= 0xFFFF; | ||
| 23 | 18 | ||
| 24 | *ainstr = 0xDEADC0DE; // Debugging to catch non updates | 19 | *ainstr = 0xDEADC0DE; // Debugging to catch non updates |
| 25 | 20 | ||
| @@ -36,7 +31,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 36 | 31 | ||
| 37 | case 3: // ADD/SUB | 32 | case 3: // ADD/SUB |
| 38 | { | 33 | { |
| 39 | static const ARMword subset[4] = { | 34 | static const u32 subset[4] = { |
| 40 | 0xE0900000, // ADDS Rd,Rs,Rn | 35 | 0xE0900000, // ADDS Rd,Rs,Rn |
| 41 | 0xE0500000, // SUBS Rd,Rs,Rn | 36 | 0xE0500000, // SUBS Rd,Rs,Rn |
| 42 | 0xE2900000, // ADDS Rd,Rs,#imm3 | 37 | 0xE2900000, // ADDS Rd,Rs,#imm3 |
| @@ -55,7 +50,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 55 | case 6: // ADD | 50 | case 6: // ADD |
| 56 | case 7: // SUB | 51 | case 7: // SUB |
| 57 | { | 52 | { |
| 58 | static const ARMword subset[4] = { | 53 | static const u32 subset[4] = { |
| 59 | 0xE3B00000, // MOVS Rd,#imm8 | 54 | 0xE3B00000, // MOVS Rd,#imm8 |
| 60 | 0xE3500000, // CMP Rd,#imm8 | 55 | 0xE3500000, // CMP Rd,#imm8 |
| 61 | 0xE2900000, // ADDS Rd,Rd,#imm8 | 56 | 0xE2900000, // ADDS Rd,Rd,#imm8 |
| @@ -84,7 +79,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 84 | }; | 79 | }; |
| 85 | 80 | ||
| 86 | static const struct { | 81 | static const struct { |
| 87 | ARMword opcode; | 82 | u32 opcode; |
| 88 | otype type; | 83 | otype type; |
| 89 | } subset[16] = { | 84 | } subset[16] = { |
| 90 | { 0xE0100000, t_norm }, // ANDS Rd,Rd,Rs | 85 | { 0xE0100000, t_norm }, // ANDS Rd,Rd,Rs |
| @@ -129,8 +124,8 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 129 | break; | 124 | break; |
| 130 | } | 125 | } |
| 131 | } else { | 126 | } else { |
| 132 | ARMword Rd = ((tinstr & 0x0007) >> 0); | 127 | u32 Rd = ((tinstr & 0x0007) >> 0); |
| 133 | ARMword Rs = ((tinstr & 0x0078) >> 3); | 128 | u32 Rs = ((tinstr & 0x0078) >> 3); |
| 134 | 129 | ||
| 135 | if (tinstr & (1 << 7)) | 130 | if (tinstr & (1 << 7)) |
| 136 | Rd += 8; | 131 | Rd += 8; |
| @@ -184,7 +179,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 184 | case 10: | 179 | case 10: |
| 185 | case 11: | 180 | case 11: |
| 186 | { | 181 | { |
| 187 | static const ARMword subset[8] = { | 182 | static const u32 subset[8] = { |
| 188 | 0xE7800000, // STR Rd,[Rb,Ro] | 183 | 0xE7800000, // STR Rd,[Rb,Ro] |
| 189 | 0xE18000B0, // STRH Rd,[Rb,Ro] | 184 | 0xE18000B0, // STRH Rd,[Rb,Ro] |
| 190 | 0xE7C00000, // STRB Rd,[Rb,Ro] | 185 | 0xE7C00000, // STRB Rd,[Rb,Ro] |
| @@ -207,7 +202,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 207 | case 14: // STRB Rd,[Rb,#imm5] | 202 | case 14: // STRB Rd,[Rb,#imm5] |
| 208 | case 15: // LDRB Rd,[Rb,#imm5] | 203 | case 15: // LDRB Rd,[Rb,#imm5] |
| 209 | { | 204 | { |
| 210 | static const ARMword subset[4] = { | 205 | static const u32 subset[4] = { |
| 211 | 0xE5800000, // STR Rd,[Rb,#imm5] | 206 | 0xE5800000, // STR Rd,[Rb,#imm5] |
| 212 | 0xE5900000, // LDR Rd,[Rb,#imm5] | 207 | 0xE5900000, // LDR Rd,[Rb,#imm5] |
| 213 | 0xE5C00000, // STRB Rd,[Rb,#imm5] | 208 | 0xE5C00000, // STRB Rd,[Rb,#imm5] |
| @@ -274,7 +269,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 274 | | BITS(tinstr, 0, 3) // imm4 field; | 269 | | BITS(tinstr, 0, 3) // imm4 field; |
| 275 | | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12 | 270 | | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12 |
| 276 | } else if ((tinstr & 0x0F00) == 0x0200) { | 271 | } else if ((tinstr & 0x0F00) == 0x0200) { |
| 277 | static const ARMword subset[4] = { | 272 | static const u32 subset[4] = { |
| 278 | 0xE6BF0070, // SXTH | 273 | 0xE6BF0070, // SXTH |
| 279 | 0xE6AF0070, // SXTB | 274 | 0xE6AF0070, // SXTB |
| 280 | 0xE6FF0070, // UXTH | 275 | 0xE6FF0070, // UXTH |
| @@ -298,7 +293,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 298 | | (BIT(tinstr, 4) << 18); // enable bit | 293 | | (BIT(tinstr, 4) << 18); // enable bit |
| 299 | } | 294 | } |
| 300 | } else if ((tinstr & 0x0F00) == 0x0a00) { | 295 | } else if ((tinstr & 0x0F00) == 0x0a00) { |
| 301 | static const ARMword subset[3] = { | 296 | static const u32 subset[3] = { |
| 302 | 0xE6BF0F30, // REV | 297 | 0xE6BF0F30, // REV |
| 303 | 0xE6BF0FB0, // REV16 | 298 | 0xE6BF0FB0, // REV16 |
| 304 | 0xE6FF0FB0, // REVSH | 299 | 0xE6FF0FB0, // REVSH |
| @@ -308,7 +303,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 308 | | (BITS(tinstr, 0, 2) << 12) // Rd | 303 | | (BITS(tinstr, 0, 2) << 12) // Rd |
| 309 | | BITS(tinstr, 3, 5); // Rm | 304 | | BITS(tinstr, 3, 5); // Rm |
| 310 | } else { | 305 | } else { |
| 311 | static const ARMword subset[4] = { | 306 | static const u32 subset[4] = { |
| 312 | 0xE92D0000, // STMDB sp!,{rlist} | 307 | 0xE92D0000, // STMDB sp!,{rlist} |
| 313 | 0xE92D4000, // STMDB sp!,{rlist,lr} | 308 | 0xE92D4000, // STMDB sp!,{rlist,lr} |
| 314 | 0xE8BD0000, // LDMIA sp!,{rlist} | 309 | 0xE8BD0000, // LDMIA sp!,{rlist} |
| @@ -356,21 +351,21 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 356 | else | 351 | else |
| 357 | *ainstr |= (tinstr & 0x00FF); | 352 | *ainstr |= (tinstr & 0x00FF); |
| 358 | } else if ((tinstr & 0x0F00) != 0x0E00) | 353 | } else if ((tinstr & 0x0F00) != 0x0E00) |
| 359 | valid = t_branch; | 354 | valid = ThumbDecodeStatus::BRANCH; |
| 360 | else // UNDEFINED : cc=1110(AL) uses different format | 355 | else // UNDEFINED : cc=1110(AL) uses different format |
| 361 | valid = t_undefined; | 356 | valid = ThumbDecodeStatus::UNDEFINED; |
| 362 | 357 | ||
| 363 | break; | 358 | break; |
| 364 | 359 | ||
| 365 | case 28: // B | 360 | case 28: // B |
| 366 | valid = t_branch; | 361 | valid = ThumbDecodeStatus::BRANCH; |
| 367 | break; | 362 | break; |
| 368 | 363 | ||
| 369 | case 29: | 364 | case 29: |
| 370 | if(tinstr & 0x1) | 365 | if (tinstr & 0x1) |
| 371 | valid = t_undefined; | 366 | valid = ThumbDecodeStatus::UNDEFINED; |
| 372 | else | 367 | else |
| 373 | valid = t_branch; | 368 | valid = ThumbDecodeStatus::BRANCH; |
| 374 | break; | 369 | break; |
| 375 | 370 | ||
| 376 | case 30: // BL instruction 1 | 371 | case 30: // BL instruction 1 |
| @@ -379,7 +374,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 379 | // simulation simple (from the user perspective) we check if the following instruction is | 374 | // simulation simple (from the user perspective) we check if the following instruction is |
| 380 | // the second half of this BL, and if it is we simulate it immediately | 375 | // the second half of this BL, and if it is we simulate it immediately |
| 381 | 376 | ||
| 382 | valid = t_branch; | 377 | valid = ThumbDecodeStatus::BRANCH; |
| 383 | break; | 378 | break; |
| 384 | 379 | ||
| 385 | case 31: // BL instruction 2 | 380 | case 31: // BL instruction 2 |
| @@ -388,7 +383,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 388 | // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the | 383 | // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the |
| 389 | // simulation of it on its own, with undefined results if r14 is not suitably initialised. | 384 | // simulation of it on its own, with undefined results if r14 is not suitably initialised. |
| 390 | 385 | ||
| 391 | valid = t_branch; | 386 | valid = ThumbDecodeStatus::BRANCH; |
| 392 | break; | 387 | break; |
| 393 | } | 388 | } |
| 394 | 389 | ||
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h index 8394ff156..447974363 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.h +++ b/src/core/arm/dyncom/arm_dyncom_thumb.h | |||
| @@ -26,22 +26,24 @@ | |||
| 26 | 26 | ||
| 27 | #pragma once | 27 | #pragma once |
| 28 | 28 | ||
| 29 | #include "core/arm/skyeye_common/armdefs.h" | 29 | #include "common/common_types.h" |
| 30 | 30 | ||
| 31 | enum tdstate { | 31 | enum class ThumbDecodeStatus { |
| 32 | t_undefined, // Undefined Thumb instruction | 32 | UNDEFINED, // Undefined Thumb instruction |
| 33 | t_decoded, // Instruction decoded to ARM equivalent | 33 | DECODED, // Instruction decoded to ARM equivalent |
| 34 | t_branch, // Thumb branch (already processed) | 34 | BRANCH, // Thumb branch (already processed) |
| 35 | t_uninitialized, | 35 | UNINITIALIZED, |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size); | 38 | // Translates a Thumb mode instruction into its ARM equivalent. |
| 39 | ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size); | ||
| 39 | 40 | ||
| 40 | static inline u32 get_thumb_instr(u32 instr, u32 pc) { | 41 | static inline u32 GetThumbInstruction(u32 instr, u32 address) { |
| 41 | u32 tinstr; | 42 | // Normally you would need to handle instruction endianness, |
| 42 | if ((pc & 0x3) != 0) | 43 | // however, it is fixed to little-endian on the MPCore, so |
| 43 | tinstr = instr >> 16; | 44 | // there's no need to check for this beforehand. |
| 44 | else | 45 | if ((address & 0x3) != 0) |
| 45 | tinstr = instr & 0xFFFF; | 46 | return instr >> 16; |
| 46 | return tinstr; | 47 | |
| 48 | return instr & 0xFFFF; | ||
| 47 | } | 49 | } |
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp deleted file mode 100644 index 4f7a48fab..000000000 --- a/src/core/arm/interpreter/arminit.cpp +++ /dev/null | |||
| @@ -1,128 +0,0 @@ | |||
| 1 | /* arminit.c -- ARMulator initialization: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | #include <cstring> | ||
| 19 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 20 | #include "core/arm/skyeye_common/vfp/vfp.h" | ||
| 21 | |||
| 22 | /***************************************************************************\ | ||
| 23 | * Returns a new instantiation of the ARMulator's state * | ||
| 24 | \***************************************************************************/ | ||
| 25 | ARMul_State* ARMul_NewState(ARMul_State* state) | ||
| 26 | { | ||
| 27 | state->Emulate = RUN; | ||
| 28 | state->Mode = USER32MODE; | ||
| 29 | |||
| 30 | state->lateabtSig = HIGH; | ||
| 31 | state->bigendSig = LOW; | ||
| 32 | |||
| 33 | return state; | ||
| 34 | } | ||
| 35 | |||
| 36 | /***************************************************************************\ | ||
| 37 | * Call this routine to set ARMulator to model a certain processor * | ||
| 38 | \***************************************************************************/ | ||
| 39 | |||
| 40 | void ARMul_SelectProcessor(ARMul_State* state, unsigned properties) | ||
| 41 | { | ||
| 42 | state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0; | ||
| 43 | state->is_v5 = (properties & ARM_v5_Prop) != 0; | ||
| 44 | state->is_v5e = (properties & ARM_v5e_Prop) != 0; | ||
| 45 | state->is_v6 = (properties & ARM_v6_Prop) != 0; | ||
| 46 | state->is_v7 = (properties & ARM_v7_Prop) != 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | // Resets certain MPCore CP15 values to their ARM-defined reset values. | ||
| 50 | static void ResetMPCoreCP15Registers(ARMul_State* cpu) | ||
| 51 | { | ||
| 52 | // c0 | ||
| 53 | cpu->CP15[CP15_MAIN_ID] = 0x410FB024; | ||
| 54 | cpu->CP15[CP15_TLB_TYPE] = 0x00000800; | ||
| 55 | cpu->CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111; | ||
| 56 | cpu->CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001; | ||
| 57 | cpu->CP15[CP15_DEBUG_FEATURE_0] = 0x00000002; | ||
| 58 | cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103; | ||
| 59 | cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302; | ||
| 60 | cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000; | ||
| 61 | cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000; | ||
| 62 | cpu->CP15[CP15_ISA_FEATURE_0] = 0x00100011; | ||
| 63 | cpu->CP15[CP15_ISA_FEATURE_1] = 0x12002111; | ||
| 64 | cpu->CP15[CP15_ISA_FEATURE_2] = 0x11221011; | ||
| 65 | cpu->CP15[CP15_ISA_FEATURE_3] = 0x01102131; | ||
| 66 | cpu->CP15[CP15_ISA_FEATURE_4] = 0x00000141; | ||
| 67 | |||
| 68 | // c1 | ||
| 69 | cpu->CP15[CP15_CONTROL] = 0x00054078; | ||
| 70 | cpu->CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F; | ||
| 71 | cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000; | ||
| 72 | |||
| 73 | // c2 | ||
| 74 | cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000; | ||
| 75 | cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000; | ||
| 76 | cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000; | ||
| 77 | |||
| 78 | // c3 | ||
| 79 | cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000; | ||
| 80 | |||
| 81 | // c7 | ||
| 82 | cpu->CP15[CP15_PHYS_ADDRESS] = 0x00000000; | ||
| 83 | |||
| 84 | // c9 | ||
| 85 | cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0; | ||
| 86 | |||
| 87 | // c10 | ||
| 88 | cpu->CP15[CP15_TLB_LOCKDOWN] = 0x00000000; | ||
| 89 | cpu->CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4; | ||
| 90 | cpu->CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0; | ||
| 91 | |||
| 92 | // c13 | ||
| 93 | cpu->CP15[CP15_PID] = 0x00000000; | ||
| 94 | cpu->CP15[CP15_CONTEXT_ID] = 0x00000000; | ||
| 95 | cpu->CP15[CP15_THREAD_UPRW] = 0x00000000; | ||
| 96 | cpu->CP15[CP15_THREAD_URO] = 0x00000000; | ||
| 97 | cpu->CP15[CP15_THREAD_PRW] = 0x00000000; | ||
| 98 | |||
| 99 | // c15 | ||
| 100 | cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000; | ||
| 101 | cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000; | ||
| 102 | cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000; | ||
| 103 | cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000; | ||
| 104 | cpu->CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; | ||
| 105 | } | ||
| 106 | |||
| 107 | /***************************************************************************\ | ||
| 108 | * Call this routine to set up the initial machine state (or perform a RESET * | ||
| 109 | \***************************************************************************/ | ||
| 110 | void ARMul_Reset(ARMul_State* state) | ||
| 111 | { | ||
| 112 | VFPInit(state); | ||
| 113 | |||
| 114 | state->Reg[15] = 0; | ||
| 115 | state->Cpsr = INTBITS | SVC32MODE; | ||
| 116 | state->Mode = SVC32MODE; | ||
| 117 | state->Bank = SVCBANK; | ||
| 118 | |||
| 119 | ResetMPCoreCP15Registers(state); | ||
| 120 | |||
| 121 | state->NresetSig = HIGH; | ||
| 122 | state->NfiqSig = HIGH; | ||
| 123 | state->NirqSig = HIGH; | ||
| 124 | state->NtransSig = (state->Mode & 3) ? HIGH : LOW; | ||
| 125 | state->abortSig = LOW; | ||
| 126 | |||
| 127 | state->NumInstrs = 0; | ||
| 128 | } | ||
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp deleted file mode 100644 index 83f7f3e2c..000000000 --- a/src/core/arm/interpreter/armsupp.cpp +++ /dev/null | |||
| @@ -1,637 +0,0 @@ | |||
| 1 | /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | #include "common/logging/log.h" | ||
| 19 | |||
| 20 | #include "core/mem_map.h" | ||
| 21 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 22 | #include "core/arm/skyeye_common/arm_regformat.h" | ||
| 23 | |||
| 24 | // Unsigned sum of absolute difference | ||
| 25 | u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) | ||
| 26 | { | ||
| 27 | if (left > right) | ||
| 28 | return left - right; | ||
| 29 | |||
| 30 | return right - left; | ||
| 31 | } | ||
| 32 | |||
| 33 | // Add with carry, indicates if a carry-out or signed overflow occurred. | ||
| 34 | u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) | ||
| 35 | { | ||
| 36 | u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; | ||
| 37 | s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; | ||
| 38 | u64 result = (unsigned_sum & 0xFFFFFFFF); | ||
| 39 | |||
| 40 | if (carry_out_occurred) | ||
| 41 | *carry_out_occurred = (result != unsigned_sum); | ||
| 42 | |||
| 43 | if (overflow_occurred) | ||
| 44 | *overflow_occurred = ((s64)(s32)result != signed_sum); | ||
| 45 | |||
| 46 | return (u32)result; | ||
| 47 | } | ||
| 48 | |||
| 49 | // Compute whether an addition of A and B, giving RESULT, overflowed. | ||
| 50 | bool AddOverflow(ARMword a, ARMword b, ARMword result) | ||
| 51 | { | ||
| 52 | return ((NEG(a) && NEG(b) && POS(result)) || | ||
| 53 | (POS(a) && POS(b) && NEG(result))); | ||
| 54 | } | ||
| 55 | |||
| 56 | // Compute whether a subtraction of A and B, giving RESULT, overflowed. | ||
| 57 | bool SubOverflow(ARMword a, ARMword b, ARMword result) | ||
| 58 | { | ||
| 59 | return ((NEG(a) && POS(b) && POS(result)) || | ||
| 60 | (POS(a) && NEG(b) && NEG(result))); | ||
| 61 | } | ||
| 62 | |||
| 63 | // Returns true if the Q flag should be set as a result of overflow. | ||
| 64 | bool ARMul_AddOverflowQ(ARMword a, ARMword b) | ||
| 65 | { | ||
| 66 | u32 result = a + b; | ||
| 67 | if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) | ||
| 68 | return true; | ||
| 69 | |||
| 70 | return false; | ||
| 71 | } | ||
| 72 | |||
| 73 | // 8-bit signed saturated addition | ||
| 74 | u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) | ||
| 75 | { | ||
| 76 | u8 result = left + right; | ||
| 77 | |||
| 78 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { | ||
| 79 | if (left & 0x80) | ||
| 80 | result = 0x80; | ||
| 81 | else | ||
| 82 | result = 0x7F; | ||
| 83 | } | ||
| 84 | |||
| 85 | return result; | ||
| 86 | } | ||
| 87 | |||
| 88 | // 8-bit signed saturated subtraction | ||
| 89 | u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) | ||
| 90 | { | ||
| 91 | u8 result = left - right; | ||
| 92 | |||
| 93 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { | ||
| 94 | if (left & 0x80) | ||
| 95 | result = 0x80; | ||
| 96 | else | ||
| 97 | result = 0x7F; | ||
| 98 | } | ||
| 99 | |||
| 100 | return result; | ||
| 101 | } | ||
| 102 | |||
| 103 | // 16-bit signed saturated addition | ||
| 104 | u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) | ||
| 105 | { | ||
| 106 | u16 result = left + right; | ||
| 107 | |||
| 108 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { | ||
| 109 | if (left & 0x8000) | ||
| 110 | result = 0x8000; | ||
| 111 | else | ||
| 112 | result = 0x7FFF; | ||
| 113 | } | ||
| 114 | |||
| 115 | return result; | ||
| 116 | } | ||
| 117 | |||
| 118 | // 16-bit signed saturated subtraction | ||
| 119 | u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) | ||
| 120 | { | ||
| 121 | u16 result = left - right; | ||
| 122 | |||
| 123 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { | ||
| 124 | if (left & 0x8000) | ||
| 125 | result = 0x8000; | ||
| 126 | else | ||
| 127 | result = 0x7FFF; | ||
| 128 | } | ||
| 129 | |||
| 130 | return result; | ||
| 131 | } | ||
| 132 | |||
| 133 | // 8-bit unsigned saturated addition | ||
| 134 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) | ||
| 135 | { | ||
| 136 | u8 result = left + right; | ||
| 137 | |||
| 138 | if (result < left) | ||
| 139 | result = 0xFF; | ||
| 140 | |||
| 141 | return result; | ||
| 142 | } | ||
| 143 | |||
| 144 | // 16-bit unsigned saturated addition | ||
| 145 | u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) | ||
| 146 | { | ||
| 147 | u16 result = left + right; | ||
| 148 | |||
| 149 | if (result < left) | ||
| 150 | result = 0xFFFF; | ||
| 151 | |||
| 152 | return result; | ||
| 153 | } | ||
| 154 | |||
| 155 | // 8-bit unsigned saturated subtraction | ||
| 156 | u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) | ||
| 157 | { | ||
| 158 | if (left <= right) | ||
| 159 | return 0; | ||
| 160 | |||
| 161 | return left - right; | ||
| 162 | } | ||
| 163 | |||
| 164 | // 16-bit unsigned saturated subtraction | ||
| 165 | u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) | ||
| 166 | { | ||
| 167 | if (left <= right) | ||
| 168 | return 0; | ||
| 169 | |||
| 170 | return left - right; | ||
| 171 | } | ||
| 172 | |||
| 173 | // Signed saturation. | ||
| 174 | u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | ||
| 175 | { | ||
| 176 | const u32 max = (1 << shift) - 1; | ||
| 177 | const s32 top = (value >> shift); | ||
| 178 | |||
| 179 | if (top > 0) { | ||
| 180 | *saturation_occurred = true; | ||
| 181 | return max; | ||
| 182 | } | ||
| 183 | else if (top < -1) { | ||
| 184 | *saturation_occurred = true; | ||
| 185 | return ~max; | ||
| 186 | } | ||
| 187 | |||
| 188 | *saturation_occurred = false; | ||
| 189 | return (u32)value; | ||
| 190 | } | ||
| 191 | |||
| 192 | // Unsigned saturation | ||
| 193 | u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | ||
| 194 | { | ||
| 195 | const u32 max = (1 << shift) - 1; | ||
| 196 | |||
| 197 | if (value < 0) { | ||
| 198 | *saturation_occurred = true; | ||
| 199 | return 0; | ||
| 200 | } else if ((u32)value > max) { | ||
| 201 | *saturation_occurred = true; | ||
| 202 | return max; | ||
| 203 | } | ||
| 204 | |||
| 205 | *saturation_occurred = false; | ||
| 206 | return (u32)value; | ||
| 207 | } | ||
| 208 | |||
| 209 | // Whether or not the given CPU is in big endian mode (E bit is set) | ||
| 210 | bool InBigEndianMode(ARMul_State* cpu) | ||
| 211 | { | ||
| 212 | return (cpu->Cpsr & (1 << 9)) != 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | // Whether or not the given CPU is in a mode other than user mode. | ||
| 216 | bool InAPrivilegedMode(ARMul_State* cpu) | ||
| 217 | { | ||
| 218 | return (cpu->Mode != USER32MODE); | ||
| 219 | } | ||
| 220 | |||
| 221 | // Reads from the CP15 registers. Used with implementation of the MRC instruction. | ||
| 222 | // Note that since the 3DS does not have the hypervisor extensions, these registers | ||
| 223 | // are not implemented. | ||
| 224 | u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | ||
| 225 | { | ||
| 226 | // Unprivileged registers | ||
| 227 | if (crn == 13 && opcode_1 == 0 && crm == 0) | ||
| 228 | { | ||
| 229 | if (opcode_2 == 2) | ||
| 230 | return cpu->CP15[CP15_THREAD_UPRW]; | ||
| 231 | |||
| 232 | if (opcode_2 == 3) | ||
| 233 | return cpu->CP15[CP15_THREAD_URO]; | ||
| 234 | } | ||
| 235 | |||
| 236 | if (InAPrivilegedMode(cpu)) | ||
| 237 | { | ||
| 238 | if (crn == 0 && opcode_1 == 0) | ||
| 239 | { | ||
| 240 | if (crm == 0) | ||
| 241 | { | ||
| 242 | if (opcode_2 == 0) | ||
| 243 | return cpu->CP15[CP15_MAIN_ID]; | ||
| 244 | |||
| 245 | if (opcode_2 == 1) | ||
| 246 | return cpu->CP15[CP15_CACHE_TYPE]; | ||
| 247 | |||
| 248 | if (opcode_2 == 3) | ||
| 249 | return cpu->CP15[CP15_TLB_TYPE]; | ||
| 250 | |||
| 251 | if (opcode_2 == 5) | ||
| 252 | return cpu->CP15[CP15_CPU_ID]; | ||
| 253 | } | ||
| 254 | else if (crm == 1) | ||
| 255 | { | ||
| 256 | if (opcode_2 == 0) | ||
| 257 | return cpu->CP15[CP15_PROCESSOR_FEATURE_0]; | ||
| 258 | |||
| 259 | if (opcode_2 == 1) | ||
| 260 | return cpu->CP15[CP15_PROCESSOR_FEATURE_1]; | ||
| 261 | |||
| 262 | if (opcode_2 == 2) | ||
| 263 | return cpu->CP15[CP15_DEBUG_FEATURE_0]; | ||
| 264 | |||
| 265 | if (opcode_2 == 4) | ||
| 266 | return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0]; | ||
| 267 | |||
| 268 | if (opcode_2 == 5) | ||
| 269 | return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1]; | ||
| 270 | |||
| 271 | if (opcode_2 == 6) | ||
| 272 | return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2]; | ||
| 273 | |||
| 274 | if (opcode_2 == 7) | ||
| 275 | return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3]; | ||
| 276 | } | ||
| 277 | else if (crm == 2) | ||
| 278 | { | ||
| 279 | if (opcode_2 == 0) | ||
| 280 | return cpu->CP15[CP15_ISA_FEATURE_0]; | ||
| 281 | |||
| 282 | if (opcode_2 == 1) | ||
| 283 | return cpu->CP15[CP15_ISA_FEATURE_1]; | ||
| 284 | |||
| 285 | if (opcode_2 == 2) | ||
| 286 | return cpu->CP15[CP15_ISA_FEATURE_2]; | ||
| 287 | |||
| 288 | if (opcode_2 == 3) | ||
| 289 | return cpu->CP15[CP15_ISA_FEATURE_3]; | ||
| 290 | |||
| 291 | if (opcode_2 == 4) | ||
| 292 | return cpu->CP15[CP15_ISA_FEATURE_4]; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | if (crn == 1 && opcode_1 == 0 && crm == 0) | ||
| 297 | { | ||
| 298 | if (opcode_2 == 0) | ||
| 299 | return cpu->CP15[CP15_CONTROL]; | ||
| 300 | |||
| 301 | if (opcode_2 == 1) | ||
| 302 | return cpu->CP15[CP15_AUXILIARY_CONTROL]; | ||
| 303 | |||
| 304 | if (opcode_2 == 2) | ||
| 305 | return cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; | ||
| 306 | } | ||
| 307 | |||
| 308 | if (crn == 2 && opcode_1 == 0 && crm == 0) | ||
| 309 | { | ||
| 310 | if (opcode_2 == 0) | ||
| 311 | return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0]; | ||
| 312 | |||
| 313 | if (opcode_2 == 1) | ||
| 314 | return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1]; | ||
| 315 | |||
| 316 | if (opcode_2 == 2) | ||
| 317 | return cpu->CP15[CP15_TRANSLATION_BASE_CONTROL]; | ||
| 318 | } | ||
| 319 | |||
| 320 | if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 321 | return cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL]; | ||
| 322 | |||
| 323 | if (crn == 5 && opcode_1 == 0 && crm == 0) | ||
| 324 | { | ||
| 325 | if (opcode_2 == 0) | ||
| 326 | return cpu->CP15[CP15_FAULT_STATUS]; | ||
| 327 | |||
| 328 | if (opcode_2 == 1) | ||
| 329 | return cpu->CP15[CP15_INSTR_FAULT_STATUS]; | ||
| 330 | } | ||
| 331 | |||
| 332 | if (crn == 6 && opcode_1 == 0 && crm == 0) | ||
| 333 | { | ||
| 334 | if (opcode_2 == 0) | ||
| 335 | return cpu->CP15[CP15_FAULT_ADDRESS]; | ||
| 336 | |||
| 337 | if (opcode_2 == 1) | ||
| 338 | return cpu->CP15[CP15_WFAR]; | ||
| 339 | } | ||
| 340 | |||
| 341 | if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0) | ||
| 342 | return cpu->CP15[CP15_PHYS_ADDRESS]; | ||
| 343 | |||
| 344 | if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 345 | return cpu->CP15[CP15_DATA_CACHE_LOCKDOWN]; | ||
| 346 | |||
| 347 | if (crn == 10 && opcode_1 == 0) | ||
| 348 | { | ||
| 349 | if (crm == 0 && opcode_2 == 0) | ||
| 350 | return cpu->CP15[CP15_TLB_LOCKDOWN]; | ||
| 351 | |||
| 352 | if (crm == 2) | ||
| 353 | { | ||
| 354 | if (opcode_2 == 0) | ||
| 355 | return cpu->CP15[CP15_PRIMARY_REGION_REMAP]; | ||
| 356 | |||
| 357 | if (opcode_2 == 1) | ||
| 358 | return cpu->CP15[CP15_NORMAL_REGION_REMAP]; | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | if (crn == 13 && crm == 0) | ||
| 363 | { | ||
| 364 | if (opcode_2 == 0) | ||
| 365 | return cpu->CP15[CP15_PID]; | ||
| 366 | |||
| 367 | if (opcode_2 == 1) | ||
| 368 | return cpu->CP15[CP15_CONTEXT_ID]; | ||
| 369 | |||
| 370 | if (opcode_2 == 4) | ||
| 371 | return cpu->CP15[CP15_THREAD_PRW]; | ||
| 372 | } | ||
| 373 | |||
| 374 | if (crn == 15) | ||
| 375 | { | ||
| 376 | if (opcode_1 == 0 && crm == 12) | ||
| 377 | { | ||
| 378 | if (opcode_2 == 0) | ||
| 379 | return cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; | ||
| 380 | |||
| 381 | if (opcode_2 == 1) | ||
| 382 | return cpu->CP15[CP15_CYCLE_COUNTER]; | ||
| 383 | |||
| 384 | if (opcode_2 == 2) | ||
| 385 | return cpu->CP15[CP15_COUNT_0]; | ||
| 386 | |||
| 387 | if (opcode_2 == 3) | ||
| 388 | return cpu->CP15[CP15_COUNT_1]; | ||
| 389 | } | ||
| 390 | |||
| 391 | if (opcode_1 == 5 && opcode_2 == 2) | ||
| 392 | { | ||
| 393 | if (crm == 5) | ||
| 394 | return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; | ||
| 395 | |||
| 396 | if (crm == 6) | ||
| 397 | return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS]; | ||
| 398 | |||
| 399 | if (crm == 7) | ||
| 400 | return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE]; | ||
| 401 | } | ||
| 402 | |||
| 403 | if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||
| 404 | return cpu->CP15[CP15_TLB_DEBUG_CONTROL]; | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); | ||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | |||
| 412 | // Write to the CP15 registers. Used with implementation of the MCR instruction. | ||
| 413 | // Note that since the 3DS does not have the hypervisor extensions, these registers | ||
| 414 | // are not implemented. | ||
| 415 | void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | ||
| 416 | { | ||
| 417 | if (InAPrivilegedMode(cpu)) | ||
| 418 | { | ||
| 419 | if (crn == 1 && opcode_1 == 0 && crm == 0) | ||
| 420 | { | ||
| 421 | if (opcode_2 == 0) | ||
| 422 | cpu->CP15[CP15_CONTROL] = value; | ||
| 423 | else if (opcode_2 == 1) | ||
| 424 | cpu->CP15[CP15_AUXILIARY_CONTROL] = value; | ||
| 425 | else if (opcode_2 == 2) | ||
| 426 | cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; | ||
| 427 | } | ||
| 428 | else if (crn == 2 && opcode_1 == 0 && crm == 0) | ||
| 429 | { | ||
| 430 | if (opcode_2 == 0) | ||
| 431 | cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; | ||
| 432 | else if (opcode_2 == 1) | ||
| 433 | cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; | ||
| 434 | else if (opcode_2 == 2) | ||
| 435 | cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = value; | ||
| 436 | } | ||
| 437 | else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 438 | { | ||
| 439 | cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; | ||
| 440 | } | ||
| 441 | else if (crn == 5 && opcode_1 == 0 && crm == 0) | ||
| 442 | { | ||
| 443 | if (opcode_2 == 0) | ||
| 444 | cpu->CP15[CP15_FAULT_STATUS] = value; | ||
| 445 | else if (opcode_2 == 1) | ||
| 446 | cpu->CP15[CP15_INSTR_FAULT_STATUS] = value; | ||
| 447 | } | ||
| 448 | else if (crn == 6 && opcode_1 == 0 && crm == 0) | ||
| 449 | { | ||
| 450 | if (opcode_2 == 0) | ||
| 451 | cpu->CP15[CP15_FAULT_ADDRESS] = value; | ||
| 452 | else if (opcode_2 == 1) | ||
| 453 | cpu->CP15[CP15_WFAR] = value; | ||
| 454 | } | ||
| 455 | else if (crn == 7 && opcode_1 == 0) | ||
| 456 | { | ||
| 457 | if (crm == 0 && opcode_2 == 4) | ||
| 458 | { | ||
| 459 | cpu->CP15[CP15_WAIT_FOR_INTERRUPT] = value; | ||
| 460 | } | ||
| 461 | else if (crm == 4 && opcode_2 == 0) | ||
| 462 | { | ||
| 463 | // NOTE: Not entirely accurate. This should do permission checks. | ||
| 464 | cpu->CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); | ||
| 465 | } | ||
| 466 | else if (crm == 5) | ||
| 467 | { | ||
| 468 | if (opcode_2 == 0) | ||
| 469 | cpu->CP15[CP15_INVALIDATE_INSTR_CACHE] = value; | ||
| 470 | else if (opcode_2 == 1) | ||
| 471 | cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value; | ||
| 472 | else if (opcode_2 == 2) | ||
| 473 | cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value; | ||
| 474 | else if (opcode_2 == 6) | ||
| 475 | cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; | ||
| 476 | else if (opcode_2 == 7) | ||
| 477 | cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; | ||
| 478 | } | ||
| 479 | else if (crm == 6) | ||
| 480 | { | ||
| 481 | if (opcode_2 == 0) | ||
| 482 | cpu->CP15[CP15_INVALIDATE_DATA_CACHE] = value; | ||
| 483 | else if (opcode_2 == 1) | ||
| 484 | cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | ||
| 485 | else if (opcode_2 == 2) | ||
| 486 | cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | ||
| 487 | } | ||
| 488 | else if (crm == 7 && opcode_2 == 0) | ||
| 489 | { | ||
| 490 | cpu->CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; | ||
| 491 | } | ||
| 492 | else if (crm == 10) | ||
| 493 | { | ||
| 494 | if (opcode_2 == 0) | ||
| 495 | cpu->CP15[CP15_CLEAN_DATA_CACHE] = value; | ||
| 496 | else if (opcode_2 == 1) | ||
| 497 | cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; | ||
| 498 | else if (opcode_2 == 2) | ||
| 499 | cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; | ||
| 500 | } | ||
| 501 | else if (crm == 14) | ||
| 502 | { | ||
| 503 | if (opcode_2 == 0) | ||
| 504 | cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; | ||
| 505 | else if (opcode_2 == 1) | ||
| 506 | cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | ||
| 507 | else if (opcode_2 == 2) | ||
| 508 | cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | ||
| 509 | } | ||
| 510 | } | ||
| 511 | else if (crn == 8 && opcode_1 == 0) | ||
| 512 | { | ||
| 513 | LOG_WARNING(Core_ARM11, "TLB operations not fully implemented."); | ||
| 514 | |||
| 515 | if (crm == 5) | ||
| 516 | { | ||
| 517 | if (opcode_2 == 0) | ||
| 518 | cpu->CP15[CP15_INVALIDATE_ITLB] = value; | ||
| 519 | else if (opcode_2 == 1) | ||
| 520 | cpu->CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value; | ||
| 521 | else if (opcode_2 == 2) | ||
| 522 | cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; | ||
| 523 | else if (opcode_2 == 3) | ||
| 524 | cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; | ||
| 525 | } | ||
| 526 | else if (crm == 6) | ||
| 527 | { | ||
| 528 | if (opcode_2 == 0) | ||
| 529 | cpu->CP15[CP15_INVALIDATE_DTLB] = value; | ||
| 530 | else if (opcode_2 == 1) | ||
| 531 | cpu->CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value; | ||
| 532 | else if (opcode_2 == 2) | ||
| 533 | cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; | ||
| 534 | else if (opcode_2 == 3) | ||
| 535 | cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; | ||
| 536 | } | ||
| 537 | else if (crm == 7) | ||
| 538 | { | ||
| 539 | if (opcode_2 == 0) | ||
| 540 | cpu->CP15[CP15_INVALIDATE_UTLB] = value; | ||
| 541 | else if (opcode_2 == 1) | ||
| 542 | cpu->CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value; | ||
| 543 | else if (opcode_2 == 2) | ||
| 544 | cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value; | ||
| 545 | else if (opcode_2 == 3) | ||
| 546 | cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; | ||
| 547 | } | ||
| 548 | } | ||
| 549 | else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 550 | { | ||
| 551 | cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = value; | ||
| 552 | } | ||
| 553 | else if (crn == 10 && opcode_1 == 0) | ||
| 554 | { | ||
| 555 | if (crm == 0 && opcode_2 == 0) | ||
| 556 | { | ||
| 557 | cpu->CP15[CP15_TLB_LOCKDOWN] = value; | ||
| 558 | } | ||
| 559 | else if (crm == 2) | ||
| 560 | { | ||
| 561 | if (opcode_2 == 0) | ||
| 562 | cpu->CP15[CP15_PRIMARY_REGION_REMAP] = value; | ||
| 563 | else if (opcode_2 == 1) | ||
| 564 | cpu->CP15[CP15_NORMAL_REGION_REMAP] = value; | ||
| 565 | } | ||
| 566 | } | ||
| 567 | else if (crn == 13 && opcode_1 == 0 && crm == 0) | ||
| 568 | { | ||
| 569 | if (opcode_2 == 0) | ||
| 570 | cpu->CP15[CP15_PID] = value; | ||
| 571 | else if (opcode_2 == 1) | ||
| 572 | cpu->CP15[CP15_CONTEXT_ID] = value; | ||
| 573 | else if (opcode_2 == 3) | ||
| 574 | cpu->CP15[CP15_THREAD_URO] = value; | ||
| 575 | else if (opcode_2 == 4) | ||
| 576 | cpu->CP15[CP15_THREAD_PRW] = value; | ||
| 577 | } | ||
| 578 | else if (crn == 15) | ||
| 579 | { | ||
| 580 | if (opcode_1 == 0 && crm == 12) | ||
| 581 | { | ||
| 582 | if (opcode_2 == 0) | ||
| 583 | cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; | ||
| 584 | else if (opcode_2 == 1) | ||
| 585 | cpu->CP15[CP15_CYCLE_COUNTER] = value; | ||
| 586 | else if (opcode_2 == 2) | ||
| 587 | cpu->CP15[CP15_COUNT_0] = value; | ||
| 588 | else if (opcode_2 == 3) | ||
| 589 | cpu->CP15[CP15_COUNT_1] = value; | ||
| 590 | } | ||
| 591 | else if (opcode_1 == 5) | ||
| 592 | { | ||
| 593 | if (crm == 4) | ||
| 594 | { | ||
| 595 | if (opcode_2 == 2) | ||
| 596 | cpu->CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; | ||
| 597 | else if (opcode_2 == 4) | ||
| 598 | cpu->CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; | ||
| 599 | } | ||
| 600 | else if (crm == 5 && opcode_2 == 2) | ||
| 601 | { | ||
| 602 | cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; | ||
| 603 | } | ||
| 604 | else if (crm == 6 && opcode_2 == 2) | ||
| 605 | { | ||
| 606 | cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; | ||
| 607 | } | ||
| 608 | else if (crm == 7 && opcode_2 == 2) | ||
| 609 | { | ||
| 610 | cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; | ||
| 611 | } | ||
| 612 | } | ||
| 613 | else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||
| 614 | { | ||
| 615 | cpu->CP15[CP15_TLB_DEBUG_CONTROL] = value; | ||
| 616 | } | ||
| 617 | } | ||
| 618 | } | ||
| 619 | |||
| 620 | // Unprivileged registers | ||
| 621 | if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) | ||
| 622 | { | ||
| 623 | cpu->CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; | ||
| 624 | } | ||
| 625 | else if (crn == 7 && opcode_1 == 0 && crm == 10) | ||
| 626 | { | ||
| 627 | if (opcode_2 == 4) | ||
| 628 | cpu->CP15[CP15_DATA_SYNC_BARRIER] = value; | ||
| 629 | else if (opcode_2 == 5) | ||
| 630 | cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value; | ||
| 631 | |||
| 632 | } | ||
| 633 | else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) | ||
| 634 | { | ||
| 635 | cpu->CP15[CP15_THREAD_UPRW] = value; | ||
| 636 | } | ||
| 637 | } | ||
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h deleted file mode 100644 index d2c901100..000000000 --- a/src/core/arm/skyeye_common/armdefs.h +++ /dev/null | |||
| @@ -1,318 +0,0 @@ | |||
| 1 | /* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | #pragma once | ||
| 19 | |||
| 20 | #include <unordered_map> | ||
| 21 | |||
| 22 | #include "common/common_types.h" | ||
| 23 | #include "core/arm/skyeye_common/arm_regformat.h" | ||
| 24 | |||
| 25 | #define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) | ||
| 26 | #define BIT(s, n) ((s >> (n)) & 1) | ||
| 27 | |||
| 28 | // Signal levels | ||
| 29 | enum { | ||
| 30 | LOW = 0, | ||
| 31 | HIGH = 1, | ||
| 32 | LOWHIGH = 1, | ||
| 33 | HIGHLOW = 2 | ||
| 34 | }; | ||
| 35 | |||
| 36 | // Cache types | ||
| 37 | enum { | ||
| 38 | NONCACHE = 0, | ||
| 39 | DATACACHE = 1, | ||
| 40 | INSTCACHE = 2, | ||
| 41 | }; | ||
| 42 | |||
| 43 | // Abort models | ||
| 44 | enum { | ||
| 45 | ABORT_BASE_RESTORED = 0, | ||
| 46 | ABORT_EARLY = 1, | ||
| 47 | ABORT_BASE_UPDATED = 2 | ||
| 48 | }; | ||
| 49 | |||
| 50 | #define POS(i) ( (~(i)) >> 31 ) | ||
| 51 | #define NEG(i) ( (i) >> 31 ) | ||
| 52 | |||
| 53 | typedef u64 ARMdword; // must be 64 bits wide | ||
| 54 | typedef u32 ARMword; // must be 32 bits wide | ||
| 55 | typedef u16 ARMhword; // must be 16 bits wide | ||
| 56 | typedef u8 ARMbyte; // must be 8 bits wide | ||
| 57 | |||
| 58 | #define VFP_REG_NUM 64 | ||
| 59 | struct ARMul_State | ||
| 60 | { | ||
| 61 | ARMword Emulate; // To start and stop emulation | ||
| 62 | |||
| 63 | // Order of the following register should not be modified | ||
| 64 | ARMword Reg[16]; // The current register file | ||
| 65 | ARMword Cpsr; // The current PSR | ||
| 66 | ARMword Spsr_copy; | ||
| 67 | ARMword phys_pc; | ||
| 68 | ARMword Reg_usr[2]; | ||
| 69 | ARMword Reg_svc[2]; // R13_SVC R14_SVC | ||
| 70 | ARMword Reg_abort[2]; // R13_ABORT R14_ABORT | ||
| 71 | ARMword Reg_undef[2]; // R13 UNDEF R14 UNDEF | ||
| 72 | ARMword Reg_irq[2]; // R13_IRQ R14_IRQ | ||
| 73 | ARMword Reg_firq[7]; // R8---R14 FIRQ | ||
| 74 | ARMword Spsr[7]; // The exception psr's | ||
| 75 | ARMword Mode; // The current mode | ||
| 76 | ARMword Bank; // The current register bank | ||
| 77 | ARMword exclusive_tag; // The address for which the local monitor is in exclusive access mode | ||
| 78 | ARMword exclusive_state; | ||
| 79 | ARMword exclusive_result; | ||
| 80 | ARMword CP15[CP15_REGISTER_COUNT]; | ||
| 81 | |||
| 82 | // FPSID, FPSCR, and FPEXC | ||
| 83 | ARMword VFP[VFP_SYSTEM_REGISTER_COUNT]; | ||
| 84 | // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31). | ||
| 85 | // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31), | ||
| 86 | // and only 32 singleword registers are accessible (S0-S31). | ||
| 87 | ARMword ExtReg[VFP_REG_NUM]; | ||
| 88 | /* ---- End of the ordered registers ---- */ | ||
| 89 | |||
| 90 | ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed | ||
| 91 | unsigned int shifter_carry_out; | ||
| 92 | |||
| 93 | // Add armv6 flags dyf:2010-08-09 | ||
| 94 | ARMword GEFlag, EFlag, AFlag, QFlag; | ||
| 95 | |||
| 96 | ARMword TFlag; // Thumb state | ||
| 97 | |||
| 98 | unsigned long long NumInstrs; // The number of instructions executed | ||
| 99 | unsigned NumInstrsToExecute; | ||
| 100 | |||
| 101 | unsigned NresetSig; // Reset the processor | ||
| 102 | unsigned NfiqSig; | ||
| 103 | unsigned NirqSig; | ||
| 104 | |||
| 105 | unsigned abortSig; | ||
| 106 | unsigned NtransSig; | ||
| 107 | unsigned bigendSig; | ||
| 108 | unsigned syscallSig; | ||
| 109 | |||
| 110 | /* 2004-05-09 chy | ||
| 111 | ---------------------------------------------------------- | ||
| 112 | read ARM Architecture Reference Manual | ||
| 113 | 2.6.5 Data Abort | ||
| 114 | There are three Abort Model in ARM arch. | ||
| 115 | |||
| 116 | Early Abort Model: used in some ARMv3 and earlier implementations. In this | ||
| 117 | model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and | ||
| 118 | the base register was unchanged for all other instructions. (oldest) | ||
| 119 | |||
| 120 | Base Restored Abort Model: If a Data Abort occurs in an instruction which | ||
| 121 | specifies base register writeback, the value in the base register is | ||
| 122 | unchanged. (strongarm, xscale) | ||
| 123 | |||
| 124 | Base Updated Abort Model: If a Data Abort occurs in an instruction which | ||
| 125 | specifies base register writeback, the base register writeback still occurs. | ||
| 126 | (arm720T) | ||
| 127 | |||
| 128 | read PART B | ||
| 129 | chap2 The System Control Coprocessor CP15 | ||
| 130 | 2.4 Register1:control register | ||
| 131 | L(bit 6): in some ARMv3 and earlier implementations, the abort model of the | ||
| 132 | processor could be configured: | ||
| 133 | 0=early Abort Model Selected(now obsolete) | ||
| 134 | 1=Late Abort Model selceted(same as Base Updated Abort Model) | ||
| 135 | |||
| 136 | on later processors, this bit reads as 1 and ignores writes. | ||
| 137 | ------------------------------------------------------------- | ||
| 138 | So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model) | ||
| 139 | if lateabtSig=0, then it means Base Restored Abort Model | ||
| 140 | */ | ||
| 141 | unsigned lateabtSig; | ||
| 142 | |||
| 143 | // For differentiating ARM core emulaiton. | ||
| 144 | bool is_v4; // Are we emulating a v4 architecture (or higher)? | ||
| 145 | bool is_v5; // Are we emulating a v5 architecture? | ||
| 146 | bool is_v5e; // Are we emulating a v5e architecture? | ||
| 147 | bool is_v6; // Are we emulating a v6 architecture? | ||
| 148 | bool is_v7; // Are we emulating a v7 architecture? | ||
| 149 | |||
| 150 | // ARM_ARM A2-18 | ||
| 151 | // 0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model | ||
| 152 | int abort_model; | ||
| 153 | |||
| 154 | // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per | ||
| 155 | // process for our purposes), not per ARMul_State (which tracks CPU core state). | ||
| 156 | std::unordered_map<u32, int> instruction_cache; | ||
| 157 | }; | ||
| 158 | |||
| 159 | /***************************************************************************\ | ||
| 160 | * Types of ARM we know about * | ||
| 161 | \***************************************************************************/ | ||
| 162 | |||
| 163 | enum { | ||
| 164 | ARM_v4_Prop = 0x01, | ||
| 165 | ARM_v5_Prop = 0x02, | ||
| 166 | ARM_v5e_Prop = 0x04, | ||
| 167 | ARM_v6_Prop = 0x08, | ||
| 168 | ARM_v7_Prop = 0x10, | ||
| 169 | }; | ||
| 170 | |||
| 171 | /***************************************************************************\ | ||
| 172 | * The hardware vector addresses * | ||
| 173 | \***************************************************************************/ | ||
| 174 | |||
| 175 | enum { | ||
| 176 | ARMResetV = 0, | ||
| 177 | ARMUndefinedInstrV = 4, | ||
| 178 | ARMSWIV = 8, | ||
| 179 | ARMPrefetchAbortV = 12, | ||
| 180 | ARMDataAbortV = 16, | ||
| 181 | ARMAddrExceptnV = 20, | ||
| 182 | ARMIRQV = 24, | ||
| 183 | ARMFIQV = 28, | ||
| 184 | ARMErrorV = 32, // This is an offset, not an address! | ||
| 185 | |||
| 186 | ARMul_ResetV = ARMResetV, | ||
| 187 | ARMul_UndefinedInstrV = ARMUndefinedInstrV, | ||
| 188 | ARMul_SWIV = ARMSWIV, | ||
| 189 | ARMul_PrefetchAbortV = ARMPrefetchAbortV, | ||
| 190 | ARMul_DataAbortV = ARMDataAbortV, | ||
| 191 | ARMul_AddrExceptnV = ARMAddrExceptnV, | ||
| 192 | ARMul_IRQV = ARMIRQV, | ||
| 193 | ARMul_FIQV = ARMFIQV | ||
| 194 | }; | ||
| 195 | |||
| 196 | /***************************************************************************\ | ||
| 197 | * Mode and Bank Constants * | ||
| 198 | \***************************************************************************/ | ||
| 199 | |||
| 200 | enum PrivilegeMode { | ||
| 201 | USER32MODE = 16, | ||
| 202 | FIQ32MODE = 17, | ||
| 203 | IRQ32MODE = 18, | ||
| 204 | SVC32MODE = 19, | ||
| 205 | ABORT32MODE = 23, | ||
| 206 | UNDEF32MODE = 27, | ||
| 207 | SYSTEM32MODE = 31 | ||
| 208 | }; | ||
| 209 | |||
| 210 | enum { | ||
| 211 | USERBANK = 0, | ||
| 212 | FIQBANK = 1, | ||
| 213 | IRQBANK = 2, | ||
| 214 | SVCBANK = 3, | ||
| 215 | ABORTBANK = 4, | ||
| 216 | UNDEFBANK = 5, | ||
| 217 | DUMMYBANK = 6, | ||
| 218 | SYSTEMBANK = 7 | ||
| 219 | }; | ||
| 220 | |||
| 221 | /***************************************************************************\ | ||
| 222 | * Definitons of things in the emulator * | ||
| 223 | \***************************************************************************/ | ||
| 224 | extern void ARMul_Reset(ARMul_State* state); | ||
| 225 | extern ARMul_State* ARMul_NewState(ARMul_State* state); | ||
| 226 | |||
| 227 | /***************************************************************************\ | ||
| 228 | * Definitons of things in the co-processor interface * | ||
| 229 | \***************************************************************************/ | ||
| 230 | |||
| 231 | enum { | ||
| 232 | ARMul_FIRST = 0, | ||
| 233 | ARMul_TRANSFER = 1, | ||
| 234 | ARMul_BUSY = 2, | ||
| 235 | ARMul_DATA = 3, | ||
| 236 | ARMul_INTERRUPT = 4, | ||
| 237 | ARMul_DONE = 0, | ||
| 238 | ARMul_CANT = 1, | ||
| 239 | ARMul_INC = 3 | ||
| 240 | }; | ||
| 241 | |||
| 242 | /***************************************************************************\ | ||
| 243 | * Definitons of things in the host environment * | ||
| 244 | \***************************************************************************/ | ||
| 245 | |||
| 246 | enum ConditionCode { | ||
| 247 | EQ = 0, | ||
| 248 | NE = 1, | ||
| 249 | CS = 2, | ||
| 250 | CC = 3, | ||
| 251 | MI = 4, | ||
| 252 | PL = 5, | ||
| 253 | VS = 6, | ||
| 254 | VC = 7, | ||
| 255 | HI = 8, | ||
| 256 | LS = 9, | ||
| 257 | GE = 10, | ||
| 258 | LT = 11, | ||
| 259 | GT = 12, | ||
| 260 | LE = 13, | ||
| 261 | AL = 14, | ||
| 262 | NV = 15, | ||
| 263 | }; | ||
| 264 | |||
| 265 | // Flags for use with the APSR. | ||
| 266 | enum : u32 { | ||
| 267 | NBIT = (1U << 31U), | ||
| 268 | ZBIT = (1 << 30), | ||
| 269 | CBIT = (1 << 29), | ||
| 270 | VBIT = (1 << 28), | ||
| 271 | QBIT = (1 << 27), | ||
| 272 | JBIT = (1 << 24), | ||
| 273 | EBIT = (1 << 9), | ||
| 274 | ABIT = (1 << 8), | ||
| 275 | IBIT = (1 << 7), | ||
| 276 | FBIT = (1 << 6), | ||
| 277 | TBIT = (1 << 5), | ||
| 278 | |||
| 279 | // Masks for groups of bits in the APSR. | ||
| 280 | MODEBITS = 0x1F, | ||
| 281 | INTBITS = 0x1C0, | ||
| 282 | }; | ||
| 283 | |||
| 284 | // Values for Emulate. | ||
| 285 | enum { | ||
| 286 | STOP = 0, // Stop | ||
| 287 | CHANGEMODE = 1, // Change mode | ||
| 288 | ONCE = 2, // Execute just one iteration | ||
| 289 | RUN = 3 // Continuous execution | ||
| 290 | }; | ||
| 291 | |||
| 292 | |||
| 293 | extern bool AddOverflow(ARMword, ARMword, ARMword); | ||
| 294 | extern bool SubOverflow(ARMword, ARMword, ARMword); | ||
| 295 | |||
| 296 | extern void ARMul_SelectProcessor(ARMul_State*, unsigned); | ||
| 297 | |||
| 298 | extern u32 AddWithCarry(u32, u32, u32, bool*, bool*); | ||
| 299 | extern bool ARMul_AddOverflowQ(ARMword, ARMword); | ||
| 300 | |||
| 301 | extern u8 ARMul_SignedSaturatedAdd8(u8, u8); | ||
| 302 | extern u8 ARMul_SignedSaturatedSub8(u8, u8); | ||
| 303 | extern u16 ARMul_SignedSaturatedAdd16(u16, u16); | ||
| 304 | extern u16 ARMul_SignedSaturatedSub16(u16, u16); | ||
| 305 | |||
| 306 | extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8); | ||
| 307 | extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16); | ||
| 308 | extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); | ||
| 309 | extern u16 ARMul_UnsignedSaturatedSub16(u16, u16); | ||
| 310 | extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); | ||
| 311 | extern u32 ARMul_SignedSatQ(s32, u8, bool*); | ||
| 312 | extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); | ||
| 313 | |||
| 314 | extern bool InBigEndianMode(ARMul_State*); | ||
| 315 | extern bool InAPrivilegedMode(ARMul_State*); | ||
| 316 | |||
| 317 | extern u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); | ||
| 318 | 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 c67d7209b..000000000 --- a/src/core/arm/skyeye_common/armmmu.h +++ /dev/null | |||
| @@ -1,103 +0,0 @@ | |||
| 1 | /* | ||
| 2 | armmmu.c - Memory Management Unit emulation. | ||
| 3 | ARMulator extensions for the ARM7100 family. | ||
| 4 | Copyright (C) 1999 Ben Williamson | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #pragma once | ||
| 22 | |||
| 23 | #include "common/swap.h" | ||
| 24 | |||
| 25 | #include "core/memory.h" | ||
| 26 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 27 | |||
| 28 | // Register numbers in the MMU | ||
| 29 | enum | ||
| 30 | { | ||
| 31 | MMU_ID = 0, | ||
| 32 | MMU_CONTROL = 1, | ||
| 33 | MMU_TRANSLATION_TABLE_BASE = 2, | ||
| 34 | MMU_DOMAIN_ACCESS_CONTROL = 3, | ||
| 35 | MMU_FAULT_STATUS = 5, | ||
| 36 | MMU_FAULT_ADDRESS = 6, | ||
| 37 | MMU_CACHE_OPS = 7, | ||
| 38 | MMU_TLB_OPS = 8, | ||
| 39 | MMU_CACHE_LOCKDOWN = 9, | ||
| 40 | MMU_TLB_LOCKDOWN = 10, | ||
| 41 | MMU_PID = 13, | ||
| 42 | |||
| 43 | // MMU_V4 | ||
| 44 | MMU_V4_CACHE_OPS = 7, | ||
| 45 | MMU_V4_TLB_OPS = 8, | ||
| 46 | |||
| 47 | // MMU_V3 | ||
| 48 | MMU_V3_FLUSH_TLB = 5, | ||
| 49 | MMU_V3_FLUSH_TLB_ENTRY = 6, | ||
| 50 | MMU_V3_FLUSH_CACHE = 7, | ||
| 51 | }; | ||
| 52 | |||
| 53 | // Reads data in big/little endian format based on the | ||
| 54 | // state of the E (endian) bit in the emulated CPU's APSR. | ||
| 55 | inline u16 ReadMemory16(ARMul_State* cpu, u32 address) { | ||
| 56 | u16 data = Memory::Read16(address); | ||
| 57 | |||
| 58 | if (InBigEndianMode(cpu)) | ||
| 59 | data = Common::swap16(data); | ||
| 60 | |||
| 61 | return data; | ||
| 62 | } | ||
| 63 | |||
| 64 | inline u32 ReadMemory32(ARMul_State* cpu, u32 address) { | ||
| 65 | u32 data = Memory::Read32(address); | ||
| 66 | |||
| 67 | if (InBigEndianMode(cpu)) | ||
| 68 | data = Common::swap32(data); | ||
| 69 | |||
| 70 | return data; | ||
| 71 | } | ||
| 72 | |||
| 73 | inline u64 ReadMemory64(ARMul_State* cpu, u32 address) { | ||
| 74 | u64 data = Memory::Read64(address); | ||
| 75 | |||
| 76 | if (InBigEndianMode(cpu)) | ||
| 77 | data = Common::swap64(data); | ||
| 78 | |||
| 79 | return data; | ||
| 80 | } | ||
| 81 | |||
| 82 | // Writes data in big/little endian format based on the | ||
| 83 | // state of the E (endian) bit in the emulated CPU's APSR. | ||
| 84 | inline void WriteMemory16(ARMul_State* cpu, u32 address, u16 data) { | ||
| 85 | if (InBigEndianMode(cpu)) | ||
| 86 | data = Common::swap16(data); | ||
| 87 | |||
| 88 | Memory::Write16(address, data); | ||
| 89 | } | ||
| 90 | |||
| 91 | inline void WriteMemory32(ARMul_State* cpu, u32 address, u32 data) { | ||
| 92 | if (InBigEndianMode(cpu)) | ||
| 93 | data = Common::swap32(data); | ||
| 94 | |||
| 95 | Memory::Write32(address, data); | ||
| 96 | } | ||
| 97 | |||
| 98 | inline void WriteMemory64(ARMul_State* cpu, u32 address, u64 data) { | ||
| 99 | if (InBigEndianMode(cpu)) | ||
| 100 | data = Common::swap64(data); | ||
| 101 | |||
| 102 | Memory::Write64(address, data); | ||
| 103 | } | ||
diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp new file mode 100644 index 000000000..ccb2eb0eb --- /dev/null +++ b/src/core/arm/skyeye_common/armstate.cpp | |||
| @@ -0,0 +1,657 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/swap.h" | ||
| 6 | #include "common/logging/log.h" | ||
| 7 | #include "core/mem_map.h" | ||
| 8 | #include "core/memory.h" | ||
| 9 | #include "core/arm/skyeye_common/armstate.h" | ||
| 10 | #include "core/arm/skyeye_common/vfp/vfp.h" | ||
| 11 | |||
| 12 | ARMul_State::ARMul_State(PrivilegeMode initial_mode) | ||
| 13 | { | ||
| 14 | Reset(); | ||
| 15 | ChangePrivilegeMode(initial_mode); | ||
| 16 | } | ||
| 17 | |||
| 18 | void ARMul_State::ChangePrivilegeMode(u32 new_mode) | ||
| 19 | { | ||
| 20 | if (Mode == new_mode) | ||
| 21 | return; | ||
| 22 | |||
| 23 | if (new_mode != USERBANK) { | ||
| 24 | switch (Mode) { | ||
| 25 | case SYSTEM32MODE: // Shares registers with user mode | ||
| 26 | case USER32MODE: | ||
| 27 | Reg_usr[0] = Reg[13]; | ||
| 28 | Reg_usr[1] = Reg[14]; | ||
| 29 | break; | ||
| 30 | case IRQ32MODE: | ||
| 31 | Reg_irq[0] = Reg[13]; | ||
| 32 | Reg_irq[1] = Reg[14]; | ||
| 33 | Spsr[IRQBANK] = Spsr_copy; | ||
| 34 | break; | ||
| 35 | case SVC32MODE: | ||
| 36 | Reg_svc[0] = Reg[13]; | ||
| 37 | Reg_svc[1] = Reg[14]; | ||
| 38 | Spsr[SVCBANK] = Spsr_copy; | ||
| 39 | break; | ||
| 40 | case ABORT32MODE: | ||
| 41 | Reg_abort[0] = Reg[13]; | ||
| 42 | Reg_abort[1] = Reg[14]; | ||
| 43 | Spsr[ABORTBANK] = Spsr_copy; | ||
| 44 | break; | ||
| 45 | case UNDEF32MODE: | ||
| 46 | Reg_undef[0] = Reg[13]; | ||
| 47 | Reg_undef[1] = Reg[14]; | ||
| 48 | Spsr[UNDEFBANK] = Spsr_copy; | ||
| 49 | break; | ||
| 50 | case FIQ32MODE: | ||
| 51 | Reg_firq[0] = Reg[13]; | ||
| 52 | Reg_firq[1] = Reg[14]; | ||
| 53 | Spsr[FIQBANK] = Spsr_copy; | ||
| 54 | break; | ||
| 55 | } | ||
| 56 | |||
| 57 | switch (new_mode) { | ||
| 58 | case USER32MODE: | ||
| 59 | Reg[13] = Reg_usr[0]; | ||
| 60 | Reg[14] = Reg_usr[1]; | ||
| 61 | Bank = USERBANK; | ||
| 62 | break; | ||
| 63 | case IRQ32MODE: | ||
| 64 | Reg[13] = Reg_irq[0]; | ||
| 65 | Reg[14] = Reg_irq[1]; | ||
| 66 | Spsr_copy = Spsr[IRQBANK]; | ||
| 67 | Bank = IRQBANK; | ||
| 68 | break; | ||
| 69 | case SVC32MODE: | ||
| 70 | Reg[13] = Reg_svc[0]; | ||
| 71 | Reg[14] = Reg_svc[1]; | ||
| 72 | Spsr_copy = Spsr[SVCBANK]; | ||
| 73 | Bank = SVCBANK; | ||
| 74 | break; | ||
| 75 | case ABORT32MODE: | ||
| 76 | Reg[13] = Reg_abort[0]; | ||
| 77 | Reg[14] = Reg_abort[1]; | ||
| 78 | Spsr_copy = Spsr[ABORTBANK]; | ||
| 79 | Bank = ABORTBANK; | ||
| 80 | break; | ||
| 81 | case UNDEF32MODE: | ||
| 82 | Reg[13] = Reg_undef[0]; | ||
| 83 | Reg[14] = Reg_undef[1]; | ||
| 84 | Spsr_copy = Spsr[UNDEFBANK]; | ||
| 85 | Bank = UNDEFBANK; | ||
| 86 | break; | ||
| 87 | case FIQ32MODE: | ||
| 88 | Reg[13] = Reg_firq[0]; | ||
| 89 | Reg[14] = Reg_firq[1]; | ||
| 90 | Spsr_copy = Spsr[FIQBANK]; | ||
| 91 | Bank = FIQBANK; | ||
| 92 | break; | ||
| 93 | case SYSTEM32MODE: // Shares registers with user mode. | ||
| 94 | Reg[13] = Reg_usr[0]; | ||
| 95 | Reg[14] = Reg_usr[1]; | ||
| 96 | Bank = SYSTEMBANK; | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | |||
| 100 | // Set the mode bits in the APSR | ||
| 101 | Cpsr = (Cpsr & ~Mode) | new_mode; | ||
| 102 | Mode = new_mode; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | // Performs a reset | ||
| 107 | void ARMul_State::Reset() | ||
| 108 | { | ||
| 109 | VFPInit(this); | ||
| 110 | |||
| 111 | // Set stack pointer to the top of the stack | ||
| 112 | Reg[13] = 0x10000000; | ||
| 113 | Reg[15] = 0; | ||
| 114 | |||
| 115 | Cpsr = INTBITS | SVC32MODE; | ||
| 116 | Mode = SVC32MODE; | ||
| 117 | Bank = SVCBANK; | ||
| 118 | |||
| 119 | ResetMPCoreCP15Registers(); | ||
| 120 | |||
| 121 | NresetSig = HIGH; | ||
| 122 | NfiqSig = HIGH; | ||
| 123 | NirqSig = HIGH; | ||
| 124 | NtransSig = (Mode & 3) ? HIGH : LOW; | ||
| 125 | abortSig = LOW; | ||
| 126 | |||
| 127 | NumInstrs = 0; | ||
| 128 | Emulate = RUN; | ||
| 129 | } | ||
| 130 | |||
| 131 | // Resets certain MPCore CP15 values to their ARM-defined reset values. | ||
| 132 | void ARMul_State::ResetMPCoreCP15Registers() | ||
| 133 | { | ||
| 134 | // c0 | ||
| 135 | CP15[CP15_MAIN_ID] = 0x410FB024; | ||
| 136 | CP15[CP15_TLB_TYPE] = 0x00000800; | ||
| 137 | CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111; | ||
| 138 | CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001; | ||
| 139 | CP15[CP15_DEBUG_FEATURE_0] = 0x00000002; | ||
| 140 | CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103; | ||
| 141 | CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302; | ||
| 142 | CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000; | ||
| 143 | CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000; | ||
| 144 | CP15[CP15_ISA_FEATURE_0] = 0x00100011; | ||
| 145 | CP15[CP15_ISA_FEATURE_1] = 0x12002111; | ||
| 146 | CP15[CP15_ISA_FEATURE_2] = 0x11221011; | ||
| 147 | CP15[CP15_ISA_FEATURE_3] = 0x01102131; | ||
| 148 | CP15[CP15_ISA_FEATURE_4] = 0x00000141; | ||
| 149 | |||
| 150 | // c1 | ||
| 151 | CP15[CP15_CONTROL] = 0x00054078; | ||
| 152 | CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F; | ||
| 153 | CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000; | ||
| 154 | |||
| 155 | // c2 | ||
| 156 | CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000; | ||
| 157 | CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000; | ||
| 158 | CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000; | ||
| 159 | |||
| 160 | // c3 | ||
| 161 | CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000; | ||
| 162 | |||
| 163 | // c7 | ||
| 164 | CP15[CP15_PHYS_ADDRESS] = 0x00000000; | ||
| 165 | |||
| 166 | // c9 | ||
| 167 | CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0; | ||
| 168 | |||
| 169 | // c10 | ||
| 170 | CP15[CP15_TLB_LOCKDOWN] = 0x00000000; | ||
| 171 | CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4; | ||
| 172 | CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0; | ||
| 173 | |||
| 174 | // c13 | ||
| 175 | CP15[CP15_PID] = 0x00000000; | ||
| 176 | CP15[CP15_CONTEXT_ID] = 0x00000000; | ||
| 177 | CP15[CP15_THREAD_UPRW] = 0x00000000; | ||
| 178 | CP15[CP15_THREAD_URO] = 0x00000000; | ||
| 179 | CP15[CP15_THREAD_PRW] = 0x00000000; | ||
| 180 | |||
| 181 | // c15 | ||
| 182 | CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000; | ||
| 183 | CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000; | ||
| 184 | CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000; | ||
| 185 | CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000; | ||
| 186 | CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; | ||
| 187 | } | ||
| 188 | |||
| 189 | u16 ARMul_State::ReadMemory16(u32 address) const | ||
| 190 | { | ||
| 191 | u16 data = Memory::Read16(address); | ||
| 192 | |||
| 193 | if (InBigEndianMode()) | ||
| 194 | data = Common::swap16(data); | ||
| 195 | |||
| 196 | return data; | ||
| 197 | } | ||
| 198 | |||
| 199 | u32 ARMul_State::ReadMemory32(u32 address) const | ||
| 200 | { | ||
| 201 | u32 data = Memory::Read32(address); | ||
| 202 | |||
| 203 | if (InBigEndianMode()) | ||
| 204 | data = Common::swap32(data); | ||
| 205 | |||
| 206 | return data; | ||
| 207 | } | ||
| 208 | |||
| 209 | u64 ARMul_State::ReadMemory64(u32 address) const | ||
| 210 | { | ||
| 211 | u64 data = Memory::Read64(address); | ||
| 212 | |||
| 213 | if (InBigEndianMode()) | ||
| 214 | data = Common::swap64(data); | ||
| 215 | |||
| 216 | return data; | ||
| 217 | } | ||
| 218 | |||
| 219 | void ARMul_State::WriteMemory16(u32 address, u16 data) | ||
| 220 | { | ||
| 221 | if (InBigEndianMode()) | ||
| 222 | data = Common::swap16(data); | ||
| 223 | |||
| 224 | Memory::Write16(address, data); | ||
| 225 | } | ||
| 226 | |||
| 227 | void ARMul_State::WriteMemory32(u32 address, u32 data) | ||
| 228 | { | ||
| 229 | if (InBigEndianMode()) | ||
| 230 | data = Common::swap32(data); | ||
| 231 | |||
| 232 | Memory::Write32(address, data); | ||
| 233 | } | ||
| 234 | |||
| 235 | void ARMul_State::WriteMemory64(u32 address, u64 data) | ||
| 236 | { | ||
| 237 | if (InBigEndianMode()) | ||
| 238 | data = Common::swap64(data); | ||
| 239 | |||
| 240 | Memory::Write64(address, data); | ||
| 241 | } | ||
| 242 | |||
| 243 | |||
| 244 | // Reads from the CP15 registers. Used with implementation of the MRC instruction. | ||
| 245 | // Note that since the 3DS does not have the hypervisor extensions, these registers | ||
| 246 | // are not implemented. | ||
| 247 | u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const | ||
| 248 | { | ||
| 249 | // Unprivileged registers | ||
| 250 | if (crn == 13 && opcode_1 == 0 && crm == 0) | ||
| 251 | { | ||
| 252 | if (opcode_2 == 2) | ||
| 253 | return CP15[CP15_THREAD_UPRW]; | ||
| 254 | |||
| 255 | if (opcode_2 == 3) | ||
| 256 | return CP15[CP15_THREAD_URO]; | ||
| 257 | } | ||
| 258 | |||
| 259 | if (InAPrivilegedMode()) | ||
| 260 | { | ||
| 261 | if (crn == 0 && opcode_1 == 0) | ||
| 262 | { | ||
| 263 | if (crm == 0) | ||
| 264 | { | ||
| 265 | if (opcode_2 == 0) | ||
| 266 | return CP15[CP15_MAIN_ID]; | ||
| 267 | |||
| 268 | if (opcode_2 == 1) | ||
| 269 | return CP15[CP15_CACHE_TYPE]; | ||
| 270 | |||
| 271 | if (opcode_2 == 3) | ||
| 272 | return CP15[CP15_TLB_TYPE]; | ||
| 273 | |||
| 274 | if (opcode_2 == 5) | ||
| 275 | return CP15[CP15_CPU_ID]; | ||
| 276 | } | ||
| 277 | else if (crm == 1) | ||
| 278 | { | ||
| 279 | if (opcode_2 == 0) | ||
| 280 | return CP15[CP15_PROCESSOR_FEATURE_0]; | ||
| 281 | |||
| 282 | if (opcode_2 == 1) | ||
| 283 | return CP15[CP15_PROCESSOR_FEATURE_1]; | ||
| 284 | |||
| 285 | if (opcode_2 == 2) | ||
| 286 | return CP15[CP15_DEBUG_FEATURE_0]; | ||
| 287 | |||
| 288 | if (opcode_2 == 4) | ||
| 289 | return CP15[CP15_MEMORY_MODEL_FEATURE_0]; | ||
| 290 | |||
| 291 | if (opcode_2 == 5) | ||
| 292 | return CP15[CP15_MEMORY_MODEL_FEATURE_1]; | ||
| 293 | |||
| 294 | if (opcode_2 == 6) | ||
| 295 | return CP15[CP15_MEMORY_MODEL_FEATURE_2]; | ||
| 296 | |||
| 297 | if (opcode_2 == 7) | ||
| 298 | return CP15[CP15_MEMORY_MODEL_FEATURE_3]; | ||
| 299 | } | ||
| 300 | else if (crm == 2) | ||
| 301 | { | ||
| 302 | if (opcode_2 == 0) | ||
| 303 | return CP15[CP15_ISA_FEATURE_0]; | ||
| 304 | |||
| 305 | if (opcode_2 == 1) | ||
| 306 | return CP15[CP15_ISA_FEATURE_1]; | ||
| 307 | |||
| 308 | if (opcode_2 == 2) | ||
| 309 | return CP15[CP15_ISA_FEATURE_2]; | ||
| 310 | |||
| 311 | if (opcode_2 == 3) | ||
| 312 | return CP15[CP15_ISA_FEATURE_3]; | ||
| 313 | |||
| 314 | if (opcode_2 == 4) | ||
| 315 | return CP15[CP15_ISA_FEATURE_4]; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | if (crn == 1 && opcode_1 == 0 && crm == 0) | ||
| 320 | { | ||
| 321 | if (opcode_2 == 0) | ||
| 322 | return CP15[CP15_CONTROL]; | ||
| 323 | |||
| 324 | if (opcode_2 == 1) | ||
| 325 | return CP15[CP15_AUXILIARY_CONTROL]; | ||
| 326 | |||
| 327 | if (opcode_2 == 2) | ||
| 328 | return CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; | ||
| 329 | } | ||
| 330 | |||
| 331 | if (crn == 2 && opcode_1 == 0 && crm == 0) | ||
| 332 | { | ||
| 333 | if (opcode_2 == 0) | ||
| 334 | return CP15[CP15_TRANSLATION_BASE_TABLE_0]; | ||
| 335 | |||
| 336 | if (opcode_2 == 1) | ||
| 337 | return CP15[CP15_TRANSLATION_BASE_TABLE_1]; | ||
| 338 | |||
| 339 | if (opcode_2 == 2) | ||
| 340 | return CP15[CP15_TRANSLATION_BASE_CONTROL]; | ||
| 341 | } | ||
| 342 | |||
| 343 | if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 344 | return CP15[CP15_DOMAIN_ACCESS_CONTROL]; | ||
| 345 | |||
| 346 | if (crn == 5 && opcode_1 == 0 && crm == 0) | ||
| 347 | { | ||
| 348 | if (opcode_2 == 0) | ||
| 349 | return CP15[CP15_FAULT_STATUS]; | ||
| 350 | |||
| 351 | if (opcode_2 == 1) | ||
| 352 | return CP15[CP15_INSTR_FAULT_STATUS]; | ||
| 353 | } | ||
| 354 | |||
| 355 | if (crn == 6 && opcode_1 == 0 && crm == 0) | ||
| 356 | { | ||
| 357 | if (opcode_2 == 0) | ||
| 358 | return CP15[CP15_FAULT_ADDRESS]; | ||
| 359 | |||
| 360 | if (opcode_2 == 1) | ||
| 361 | return CP15[CP15_WFAR]; | ||
| 362 | } | ||
| 363 | |||
| 364 | if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0) | ||
| 365 | return CP15[CP15_PHYS_ADDRESS]; | ||
| 366 | |||
| 367 | if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 368 | return CP15[CP15_DATA_CACHE_LOCKDOWN]; | ||
| 369 | |||
| 370 | if (crn == 10 && opcode_1 == 0) | ||
| 371 | { | ||
| 372 | if (crm == 0 && opcode_2 == 0) | ||
| 373 | return CP15[CP15_TLB_LOCKDOWN]; | ||
| 374 | |||
| 375 | if (crm == 2) | ||
| 376 | { | ||
| 377 | if (opcode_2 == 0) | ||
| 378 | return CP15[CP15_PRIMARY_REGION_REMAP]; | ||
| 379 | |||
| 380 | if (opcode_2 == 1) | ||
| 381 | return CP15[CP15_NORMAL_REGION_REMAP]; | ||
| 382 | } | ||
| 383 | } | ||
| 384 | |||
| 385 | if (crn == 13 && crm == 0) | ||
| 386 | { | ||
| 387 | if (opcode_2 == 0) | ||
| 388 | return CP15[CP15_PID]; | ||
| 389 | |||
| 390 | if (opcode_2 == 1) | ||
| 391 | return CP15[CP15_CONTEXT_ID]; | ||
| 392 | |||
| 393 | if (opcode_2 == 4) | ||
| 394 | return CP15[CP15_THREAD_PRW]; | ||
| 395 | } | ||
| 396 | |||
| 397 | if (crn == 15) | ||
| 398 | { | ||
| 399 | if (opcode_1 == 0 && crm == 12) | ||
| 400 | { | ||
| 401 | if (opcode_2 == 0) | ||
| 402 | return CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; | ||
| 403 | |||
| 404 | if (opcode_2 == 1) | ||
| 405 | return CP15[CP15_CYCLE_COUNTER]; | ||
| 406 | |||
| 407 | if (opcode_2 == 2) | ||
| 408 | return CP15[CP15_COUNT_0]; | ||
| 409 | |||
| 410 | if (opcode_2 == 3) | ||
| 411 | return CP15[CP15_COUNT_1]; | ||
| 412 | } | ||
| 413 | |||
| 414 | if (opcode_1 == 5 && opcode_2 == 2) | ||
| 415 | { | ||
| 416 | if (crm == 5) | ||
| 417 | return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; | ||
| 418 | |||
| 419 | if (crm == 6) | ||
| 420 | return CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS]; | ||
| 421 | |||
| 422 | if (crm == 7) | ||
| 423 | return CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE]; | ||
| 424 | } | ||
| 425 | |||
| 426 | if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||
| 427 | return CP15[CP15_TLB_DEBUG_CONTROL]; | ||
| 428 | } | ||
| 429 | } | ||
| 430 | |||
| 431 | LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); | ||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | |||
| 435 | // Write to the CP15 registers. Used with implementation of the MCR instruction. | ||
| 436 | // Note that since the 3DS does not have the hypervisor extensions, these registers | ||
| 437 | // are not implemented. | ||
| 438 | void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | ||
| 439 | { | ||
| 440 | if (InAPrivilegedMode()) | ||
| 441 | { | ||
| 442 | if (crn == 1 && opcode_1 == 0 && crm == 0) | ||
| 443 | { | ||
| 444 | if (opcode_2 == 0) | ||
| 445 | CP15[CP15_CONTROL] = value; | ||
| 446 | else if (opcode_2 == 1) | ||
| 447 | CP15[CP15_AUXILIARY_CONTROL] = value; | ||
| 448 | else if (opcode_2 == 2) | ||
| 449 | CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; | ||
| 450 | } | ||
| 451 | else if (crn == 2 && opcode_1 == 0 && crm == 0) | ||
| 452 | { | ||
| 453 | if (opcode_2 == 0) | ||
| 454 | CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; | ||
| 455 | else if (opcode_2 == 1) | ||
| 456 | CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; | ||
| 457 | else if (opcode_2 == 2) | ||
| 458 | CP15[CP15_TRANSLATION_BASE_CONTROL] = value; | ||
| 459 | } | ||
| 460 | else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 461 | { | ||
| 462 | CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; | ||
| 463 | } | ||
| 464 | else if (crn == 5 && opcode_1 == 0 && crm == 0) | ||
| 465 | { | ||
| 466 | if (opcode_2 == 0) | ||
| 467 | CP15[CP15_FAULT_STATUS] = value; | ||
| 468 | else if (opcode_2 == 1) | ||
| 469 | CP15[CP15_INSTR_FAULT_STATUS] = value; | ||
| 470 | } | ||
| 471 | else if (crn == 6 && opcode_1 == 0 && crm == 0) | ||
| 472 | { | ||
| 473 | if (opcode_2 == 0) | ||
| 474 | CP15[CP15_FAULT_ADDRESS] = value; | ||
| 475 | else if (opcode_2 == 1) | ||
| 476 | CP15[CP15_WFAR] = value; | ||
| 477 | } | ||
| 478 | else if (crn == 7 && opcode_1 == 0) | ||
| 479 | { | ||
| 480 | if (crm == 0 && opcode_2 == 4) | ||
| 481 | { | ||
| 482 | CP15[CP15_WAIT_FOR_INTERRUPT] = value; | ||
| 483 | } | ||
| 484 | else if (crm == 4 && opcode_2 == 0) | ||
| 485 | { | ||
| 486 | // NOTE: Not entirely accurate. This should do permission checks. | ||
| 487 | CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); | ||
| 488 | } | ||
| 489 | else if (crm == 5) | ||
| 490 | { | ||
| 491 | if (opcode_2 == 0) | ||
| 492 | CP15[CP15_INVALIDATE_INSTR_CACHE] = value; | ||
| 493 | else if (opcode_2 == 1) | ||
| 494 | CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value; | ||
| 495 | else if (opcode_2 == 2) | ||
| 496 | CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value; | ||
| 497 | else if (opcode_2 == 6) | ||
| 498 | CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; | ||
| 499 | else if (opcode_2 == 7) | ||
| 500 | CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; | ||
| 501 | } | ||
| 502 | else if (crm == 6) | ||
| 503 | { | ||
| 504 | if (opcode_2 == 0) | ||
| 505 | CP15[CP15_INVALIDATE_DATA_CACHE] = value; | ||
| 506 | else if (opcode_2 == 1) | ||
| 507 | CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | ||
| 508 | else if (opcode_2 == 2) | ||
| 509 | CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | ||
| 510 | } | ||
| 511 | else if (crm == 7 && opcode_2 == 0) | ||
| 512 | { | ||
| 513 | CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; | ||
| 514 | } | ||
| 515 | else if (crm == 10) | ||
| 516 | { | ||
| 517 | if (opcode_2 == 0) | ||
| 518 | CP15[CP15_CLEAN_DATA_CACHE] = value; | ||
| 519 | else if (opcode_2 == 1) | ||
| 520 | CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; | ||
| 521 | else if (opcode_2 == 2) | ||
| 522 | CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; | ||
| 523 | } | ||
| 524 | else if (crm == 14) | ||
| 525 | { | ||
| 526 | if (opcode_2 == 0) | ||
| 527 | CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; | ||
| 528 | else if (opcode_2 == 1) | ||
| 529 | CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | ||
| 530 | else if (opcode_2 == 2) | ||
| 531 | CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | ||
| 532 | } | ||
| 533 | } | ||
| 534 | else if (crn == 8 && opcode_1 == 0) | ||
| 535 | { | ||
| 536 | if (crm == 5) | ||
| 537 | { | ||
| 538 | if (opcode_2 == 0) | ||
| 539 | CP15[CP15_INVALIDATE_ITLB] = value; | ||
| 540 | else if (opcode_2 == 1) | ||
| 541 | CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value; | ||
| 542 | else if (opcode_2 == 2) | ||
| 543 | CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; | ||
| 544 | else if (opcode_2 == 3) | ||
| 545 | CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; | ||
| 546 | } | ||
| 547 | else if (crm == 6) | ||
| 548 | { | ||
| 549 | if (opcode_2 == 0) | ||
| 550 | CP15[CP15_INVALIDATE_DTLB] = value; | ||
| 551 | else if (opcode_2 == 1) | ||
| 552 | CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value; | ||
| 553 | else if (opcode_2 == 2) | ||
| 554 | CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; | ||
| 555 | else if (opcode_2 == 3) | ||
| 556 | CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; | ||
| 557 | } | ||
| 558 | else if (crm == 7) | ||
| 559 | { | ||
| 560 | if (opcode_2 == 0) | ||
| 561 | CP15[CP15_INVALIDATE_UTLB] = value; | ||
| 562 | else if (opcode_2 == 1) | ||
| 563 | CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value; | ||
| 564 | else if (opcode_2 == 2) | ||
| 565 | CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value; | ||
| 566 | else if (opcode_2 == 3) | ||
| 567 | CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 571 | { | ||
| 572 | CP15[CP15_DATA_CACHE_LOCKDOWN] = value; | ||
| 573 | } | ||
| 574 | else if (crn == 10 && opcode_1 == 0) | ||
| 575 | { | ||
| 576 | if (crm == 0 && opcode_2 == 0) | ||
| 577 | { | ||
| 578 | CP15[CP15_TLB_LOCKDOWN] = value; | ||
| 579 | } | ||
| 580 | else if (crm == 2) | ||
| 581 | { | ||
| 582 | if (opcode_2 == 0) | ||
| 583 | CP15[CP15_PRIMARY_REGION_REMAP] = value; | ||
| 584 | else if (opcode_2 == 1) | ||
| 585 | CP15[CP15_NORMAL_REGION_REMAP] = value; | ||
| 586 | } | ||
| 587 | } | ||
| 588 | else if (crn == 13 && opcode_1 == 0 && crm == 0) | ||
| 589 | { | ||
| 590 | if (opcode_2 == 0) | ||
| 591 | CP15[CP15_PID] = value; | ||
| 592 | else if (opcode_2 == 1) | ||
| 593 | CP15[CP15_CONTEXT_ID] = value; | ||
| 594 | else if (opcode_2 == 3) | ||
| 595 | CP15[CP15_THREAD_URO] = value; | ||
| 596 | else if (opcode_2 == 4) | ||
| 597 | CP15[CP15_THREAD_PRW] = value; | ||
| 598 | } | ||
| 599 | else if (crn == 15) | ||
| 600 | { | ||
| 601 | if (opcode_1 == 0 && crm == 12) | ||
| 602 | { | ||
| 603 | if (opcode_2 == 0) | ||
| 604 | CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; | ||
| 605 | else if (opcode_2 == 1) | ||
| 606 | CP15[CP15_CYCLE_COUNTER] = value; | ||
| 607 | else if (opcode_2 == 2) | ||
| 608 | CP15[CP15_COUNT_0] = value; | ||
| 609 | else if (opcode_2 == 3) | ||
| 610 | CP15[CP15_COUNT_1] = value; | ||
| 611 | } | ||
| 612 | else if (opcode_1 == 5) | ||
| 613 | { | ||
| 614 | if (crm == 4) | ||
| 615 | { | ||
| 616 | if (opcode_2 == 2) | ||
| 617 | CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; | ||
| 618 | else if (opcode_2 == 4) | ||
| 619 | CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; | ||
| 620 | } | ||
| 621 | else if (crm == 5 && opcode_2 == 2) | ||
| 622 | { | ||
| 623 | CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; | ||
| 624 | } | ||
| 625 | else if (crm == 6 && opcode_2 == 2) | ||
| 626 | { | ||
| 627 | CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; | ||
| 628 | } | ||
| 629 | else if (crm == 7 && opcode_2 == 2) | ||
| 630 | { | ||
| 631 | CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; | ||
| 632 | } | ||
| 633 | } | ||
| 634 | else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||
| 635 | { | ||
| 636 | CP15[CP15_TLB_DEBUG_CONTROL] = value; | ||
| 637 | } | ||
| 638 | } | ||
| 639 | } | ||
| 640 | |||
| 641 | // Unprivileged registers | ||
| 642 | if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) | ||
| 643 | { | ||
| 644 | CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; | ||
| 645 | } | ||
| 646 | else if (crn == 7 && opcode_1 == 0 && crm == 10) | ||
| 647 | { | ||
| 648 | if (opcode_2 == 4) | ||
| 649 | CP15[CP15_DATA_SYNC_BARRIER] = value; | ||
| 650 | else if (opcode_2 == 5) | ||
| 651 | CP15[CP15_DATA_MEMORY_BARRIER] = value; | ||
| 652 | } | ||
| 653 | else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) | ||
| 654 | { | ||
| 655 | CP15[CP15_THREAD_UPRW] = value; | ||
| 656 | } | ||
| 657 | } | ||
diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h new file mode 100644 index 000000000..b364e2621 --- /dev/null +++ b/src/core/arm/skyeye_common/armstate.h | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | /* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | #pragma once | ||
| 19 | |||
| 20 | #include <array> | ||
| 21 | #include <unordered_map> | ||
| 22 | |||
| 23 | #include "common/common_types.h" | ||
| 24 | #include "core/arm/skyeye_common/arm_regformat.h" | ||
| 25 | |||
| 26 | // Signal levels | ||
| 27 | enum { | ||
| 28 | LOW = 0, | ||
| 29 | HIGH = 1, | ||
| 30 | LOWHIGH = 1, | ||
| 31 | HIGHLOW = 2 | ||
| 32 | }; | ||
| 33 | |||
| 34 | // Cache types | ||
| 35 | enum { | ||
| 36 | NONCACHE = 0, | ||
| 37 | DATACACHE = 1, | ||
| 38 | INSTCACHE = 2, | ||
| 39 | }; | ||
| 40 | |||
| 41 | // ARM privilege modes | ||
| 42 | enum PrivilegeMode { | ||
| 43 | USER32MODE = 16, | ||
| 44 | FIQ32MODE = 17, | ||
| 45 | IRQ32MODE = 18, | ||
| 46 | SVC32MODE = 19, | ||
| 47 | ABORT32MODE = 23, | ||
| 48 | UNDEF32MODE = 27, | ||
| 49 | SYSTEM32MODE = 31 | ||
| 50 | }; | ||
| 51 | |||
| 52 | // ARM privilege mode register banks | ||
| 53 | enum { | ||
| 54 | USERBANK = 0, | ||
| 55 | FIQBANK = 1, | ||
| 56 | IRQBANK = 2, | ||
| 57 | SVCBANK = 3, | ||
| 58 | ABORTBANK = 4, | ||
| 59 | UNDEFBANK = 5, | ||
| 60 | DUMMYBANK = 6, | ||
| 61 | SYSTEMBANK = 7 | ||
| 62 | }; | ||
| 63 | |||
| 64 | // Hardware vector addresses | ||
| 65 | enum { | ||
| 66 | ARMResetV = 0, | ||
| 67 | ARMUndefinedInstrV = 4, | ||
| 68 | ARMSWIV = 8, | ||
| 69 | ARMPrefetchAbortV = 12, | ||
| 70 | ARMDataAbortV = 16, | ||
| 71 | ARMAddrExceptnV = 20, | ||
| 72 | ARMIRQV = 24, | ||
| 73 | ARMFIQV = 28, | ||
| 74 | ARMErrorV = 32, // This is an offset, not an address! | ||
| 75 | |||
| 76 | ARMul_ResetV = ARMResetV, | ||
| 77 | ARMul_UndefinedInstrV = ARMUndefinedInstrV, | ||
| 78 | ARMul_SWIV = ARMSWIV, | ||
| 79 | ARMul_PrefetchAbortV = ARMPrefetchAbortV, | ||
| 80 | ARMul_DataAbortV = ARMDataAbortV, | ||
| 81 | ARMul_AddrExceptnV = ARMAddrExceptnV, | ||
| 82 | ARMul_IRQV = ARMIRQV, | ||
| 83 | ARMul_FIQV = ARMFIQV | ||
| 84 | }; | ||
| 85 | |||
| 86 | // Coprocessor status values | ||
| 87 | enum { | ||
| 88 | ARMul_FIRST = 0, | ||
| 89 | ARMul_TRANSFER = 1, | ||
| 90 | ARMul_BUSY = 2, | ||
| 91 | ARMul_DATA = 3, | ||
| 92 | ARMul_INTERRUPT = 4, | ||
| 93 | ARMul_DONE = 0, | ||
| 94 | ARMul_CANT = 1, | ||
| 95 | ARMul_INC = 3 | ||
| 96 | }; | ||
| 97 | |||
| 98 | // Instruction condition codes | ||
| 99 | enum ConditionCode { | ||
| 100 | EQ = 0, | ||
| 101 | NE = 1, | ||
| 102 | CS = 2, | ||
| 103 | CC = 3, | ||
| 104 | MI = 4, | ||
| 105 | PL = 5, | ||
| 106 | VS = 6, | ||
| 107 | VC = 7, | ||
| 108 | HI = 8, | ||
| 109 | LS = 9, | ||
| 110 | GE = 10, | ||
| 111 | LT = 11, | ||
| 112 | GT = 12, | ||
| 113 | LE = 13, | ||
| 114 | AL = 14, | ||
| 115 | NV = 15, | ||
| 116 | }; | ||
| 117 | |||
| 118 | // Flags for use with the APSR. | ||
| 119 | enum : u32 { | ||
| 120 | NBIT = (1U << 31U), | ||
| 121 | ZBIT = (1 << 30), | ||
| 122 | CBIT = (1 << 29), | ||
| 123 | VBIT = (1 << 28), | ||
| 124 | QBIT = (1 << 27), | ||
| 125 | JBIT = (1 << 24), | ||
| 126 | EBIT = (1 << 9), | ||
| 127 | ABIT = (1 << 8), | ||
| 128 | IBIT = (1 << 7), | ||
| 129 | FBIT = (1 << 6), | ||
| 130 | TBIT = (1 << 5), | ||
| 131 | |||
| 132 | // Masks for groups of bits in the APSR. | ||
| 133 | MODEBITS = 0x1F, | ||
| 134 | INTBITS = 0x1C0, | ||
| 135 | }; | ||
| 136 | |||
| 137 | // Values for Emulate. | ||
| 138 | enum { | ||
| 139 | STOP = 0, // Stop | ||
| 140 | CHANGEMODE = 1, // Change mode | ||
| 141 | ONCE = 2, // Execute just one iteration | ||
| 142 | RUN = 3 // Continuous execution | ||
| 143 | }; | ||
| 144 | |||
| 145 | |||
| 146 | struct ARMul_State final | ||
| 147 | { | ||
| 148 | public: | ||
| 149 | explicit ARMul_State(PrivilegeMode initial_mode); | ||
| 150 | |||
| 151 | void ChangePrivilegeMode(u32 new_mode); | ||
| 152 | void Reset(); | ||
| 153 | |||
| 154 | // Reads/writes data in big/little endian format based on the | ||
| 155 | // state of the E (endian) bit in the APSR. | ||
| 156 | u16 ReadMemory16(u32 address) const; | ||
| 157 | u32 ReadMemory32(u32 address) const; | ||
| 158 | u64 ReadMemory64(u32 address) const; | ||
| 159 | void WriteMemory16(u32 address, u16 data); | ||
| 160 | void WriteMemory32(u32 address, u32 data); | ||
| 161 | void WriteMemory64(u32 address, u64 data); | ||
| 162 | |||
| 163 | u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; | ||
| 164 | void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); | ||
| 165 | |||
| 166 | // Exclusive memory access functions | ||
| 167 | bool IsExclusiveMemoryAccess(u32 address) const { | ||
| 168 | return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK); | ||
| 169 | } | ||
| 170 | void SetExclusiveMemoryAddress(u32 address) { | ||
| 171 | exclusive_tag = address & RESERVATION_GRANULE_MASK; | ||
| 172 | exclusive_state = true; | ||
| 173 | } | ||
| 174 | void UnsetExclusiveMemoryAddress() { | ||
| 175 | exclusive_tag = 0xFFFFFFFF; | ||
| 176 | exclusive_state = false; | ||
| 177 | } | ||
| 178 | |||
| 179 | // Whether or not the given CPU is in big endian mode (E bit is set) | ||
| 180 | bool InBigEndianMode() const { | ||
| 181 | return (Cpsr & (1 << 9)) != 0; | ||
| 182 | } | ||
| 183 | // Whether or not the given CPU is in a mode other than user mode. | ||
| 184 | bool InAPrivilegedMode() const { | ||
| 185 | return (Mode != USER32MODE); | ||
| 186 | } | ||
| 187 | // Note that for the 3DS, a Thumb instruction will only ever be | ||
| 188 | // two bytes in size. Thus we don't need to worry about ThumbEE | ||
| 189 | // or Thumb-2 where instructions can be 4 bytes in length. | ||
| 190 | u32 GetInstructionSize() const { | ||
| 191 | return TFlag ? 2 : 4; | ||
| 192 | } | ||
| 193 | |||
| 194 | std::array<u32, 16> Reg; // The current register file | ||
| 195 | std::array<u32, 2> Reg_usr; | ||
| 196 | std::array<u32, 2> Reg_svc; // R13_SVC R14_SVC | ||
| 197 | std::array<u32, 2> Reg_abort; // R13_ABORT R14_ABORT | ||
| 198 | std::array<u32, 2> Reg_undef; // R13 UNDEF R14 UNDEF | ||
| 199 | std::array<u32, 2> Reg_irq; // R13_IRQ R14_IRQ | ||
| 200 | std::array<u32, 7> Reg_firq; // R8---R14 FIRQ | ||
| 201 | std::array<u32, 7> Spsr; // The exception psr's | ||
| 202 | std::array<u32, CP15_REGISTER_COUNT> CP15; | ||
| 203 | |||
| 204 | // FPSID, FPSCR, and FPEXC | ||
| 205 | std::array<u32, VFP_SYSTEM_REGISTER_COUNT> VFP; | ||
| 206 | |||
| 207 | // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31). | ||
| 208 | // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31), | ||
| 209 | // and only 32 singleword registers are accessible (S0-S31). | ||
| 210 | std::array<u32, 64> ExtReg; | ||
| 211 | |||
| 212 | u32 Emulate; // To start and stop emulation | ||
| 213 | u32 Cpsr; // The current PSR | ||
| 214 | u32 Spsr_copy; | ||
| 215 | u32 phys_pc; | ||
| 216 | |||
| 217 | u32 Mode; // The current mode | ||
| 218 | u32 Bank; // The current register bank | ||
| 219 | |||
| 220 | u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed | ||
| 221 | unsigned int shifter_carry_out; | ||
| 222 | |||
| 223 | u32 TFlag; // Thumb state | ||
| 224 | |||
| 225 | unsigned long long NumInstrs; // The number of instructions executed | ||
| 226 | unsigned NumInstrsToExecute; | ||
| 227 | |||
| 228 | unsigned NresetSig; // Reset the processor | ||
| 229 | unsigned NfiqSig; | ||
| 230 | unsigned NirqSig; | ||
| 231 | |||
| 232 | unsigned abortSig; | ||
| 233 | unsigned NtransSig; | ||
| 234 | unsigned bigendSig; | ||
| 235 | unsigned syscallSig; | ||
| 236 | |||
| 237 | // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per | ||
| 238 | // process for our purposes), not per ARMul_State (which tracks CPU core state). | ||
| 239 | std::unordered_map<u32, int> instruction_cache; | ||
| 240 | |||
| 241 | private: | ||
| 242 | void ResetMPCoreCP15Registers(); | ||
| 243 | |||
| 244 | // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. | ||
| 245 | // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to | ||
| 246 | // support LDR/STREXD. | ||
| 247 | static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; | ||
| 248 | |||
| 249 | u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode | ||
| 250 | u32 exclusive_result; | ||
| 251 | bool exclusive_state; | ||
| 252 | }; | ||
diff --git a/src/core/arm/skyeye_common/armsupp.cpp b/src/core/arm/skyeye_common/armsupp.cpp new file mode 100644 index 000000000..d31fb9449 --- /dev/null +++ b/src/core/arm/skyeye_common/armsupp.cpp | |||
| @@ -0,0 +1,208 @@ | |||
| 1 | /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | #include "common/logging/log.h" | ||
| 19 | |||
| 20 | #include "core/mem_map.h" | ||
| 21 | #include "core/arm/skyeye_common/arm_regformat.h" | ||
| 22 | #include "core/arm/skyeye_common/armstate.h" | ||
| 23 | #include "core/arm/skyeye_common/armsupp.h" | ||
| 24 | |||
| 25 | // Unsigned sum of absolute difference | ||
| 26 | u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) | ||
| 27 | { | ||
| 28 | if (left > right) | ||
| 29 | return left - right; | ||
| 30 | |||
| 31 | return right - left; | ||
| 32 | } | ||
| 33 | |||
| 34 | // Add with carry, indicates if a carry-out or signed overflow occurred. | ||
| 35 | u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) | ||
| 36 | { | ||
| 37 | u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; | ||
| 38 | s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; | ||
| 39 | u64 result = (unsigned_sum & 0xFFFFFFFF); | ||
| 40 | |||
| 41 | if (carry_out_occurred) | ||
| 42 | *carry_out_occurred = (result != unsigned_sum); | ||
| 43 | |||
| 44 | if (overflow_occurred) | ||
| 45 | *overflow_occurred = ((s64)(s32)result != signed_sum); | ||
| 46 | |||
| 47 | return (u32)result; | ||
| 48 | } | ||
| 49 | |||
| 50 | // Compute whether an addition of A and B, giving RESULT, overflowed. | ||
| 51 | bool AddOverflow(u32 a, u32 b, u32 result) | ||
| 52 | { | ||
| 53 | return ((NEG(a) && NEG(b) && POS(result)) || | ||
| 54 | (POS(a) && POS(b) && NEG(result))); | ||
| 55 | } | ||
| 56 | |||
| 57 | // Compute whether a subtraction of A and B, giving RESULT, overflowed. | ||
| 58 | bool SubOverflow(u32 a, u32 b, u32 result) | ||
| 59 | { | ||
| 60 | return ((NEG(a) && POS(b) && POS(result)) || | ||
| 61 | (POS(a) && NEG(b) && NEG(result))); | ||
| 62 | } | ||
| 63 | |||
| 64 | // Returns true if the Q flag should be set as a result of overflow. | ||
| 65 | bool ARMul_AddOverflowQ(u32 a, u32 b) | ||
| 66 | { | ||
| 67 | u32 result = a + b; | ||
| 68 | if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) | ||
| 69 | return true; | ||
| 70 | |||
| 71 | return false; | ||
| 72 | } | ||
| 73 | |||
| 74 | // 8-bit signed saturated addition | ||
| 75 | u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) | ||
| 76 | { | ||
| 77 | u8 result = left + right; | ||
| 78 | |||
| 79 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { | ||
| 80 | if (left & 0x80) | ||
| 81 | result = 0x80; | ||
| 82 | else | ||
| 83 | result = 0x7F; | ||
| 84 | } | ||
| 85 | |||
| 86 | return result; | ||
| 87 | } | ||
| 88 | |||
| 89 | // 8-bit signed saturated subtraction | ||
| 90 | u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) | ||
| 91 | { | ||
| 92 | u8 result = left - right; | ||
| 93 | |||
| 94 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { | ||
| 95 | if (left & 0x80) | ||
| 96 | result = 0x80; | ||
| 97 | else | ||
| 98 | result = 0x7F; | ||
| 99 | } | ||
| 100 | |||
| 101 | return result; | ||
| 102 | } | ||
| 103 | |||
| 104 | // 16-bit signed saturated addition | ||
| 105 | u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) | ||
| 106 | { | ||
| 107 | u16 result = left + right; | ||
| 108 | |||
| 109 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { | ||
| 110 | if (left & 0x8000) | ||
| 111 | result = 0x8000; | ||
| 112 | else | ||
| 113 | result = 0x7FFF; | ||
| 114 | } | ||
| 115 | |||
| 116 | return result; | ||
| 117 | } | ||
| 118 | |||
| 119 | // 16-bit signed saturated subtraction | ||
| 120 | u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) | ||
| 121 | { | ||
| 122 | u16 result = left - right; | ||
| 123 | |||
| 124 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { | ||
| 125 | if (left & 0x8000) | ||
| 126 | result = 0x8000; | ||
| 127 | else | ||
| 128 | result = 0x7FFF; | ||
| 129 | } | ||
| 130 | |||
| 131 | return result; | ||
| 132 | } | ||
| 133 | |||
| 134 | // 8-bit unsigned saturated addition | ||
| 135 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) | ||
| 136 | { | ||
| 137 | u8 result = left + right; | ||
| 138 | |||
| 139 | if (result < left) | ||
| 140 | result = 0xFF; | ||
| 141 | |||
| 142 | return result; | ||
| 143 | } | ||
| 144 | |||
| 145 | // 16-bit unsigned saturated addition | ||
| 146 | u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) | ||
| 147 | { | ||
| 148 | u16 result = left + right; | ||
| 149 | |||
| 150 | if (result < left) | ||
| 151 | result = 0xFFFF; | ||
| 152 | |||
| 153 | return result; | ||
| 154 | } | ||
| 155 | |||
| 156 | // 8-bit unsigned saturated subtraction | ||
| 157 | u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) | ||
| 158 | { | ||
| 159 | if (left <= right) | ||
| 160 | return 0; | ||
| 161 | |||
| 162 | return left - right; | ||
| 163 | } | ||
| 164 | |||
| 165 | // 16-bit unsigned saturated subtraction | ||
| 166 | u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) | ||
| 167 | { | ||
| 168 | if (left <= right) | ||
| 169 | return 0; | ||
| 170 | |||
| 171 | return left - right; | ||
| 172 | } | ||
| 173 | |||
| 174 | // Signed saturation. | ||
| 175 | u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | ||
| 176 | { | ||
| 177 | const u32 max = (1 << shift) - 1; | ||
| 178 | const s32 top = (value >> shift); | ||
| 179 | |||
| 180 | if (top > 0) { | ||
| 181 | *saturation_occurred = true; | ||
| 182 | return max; | ||
| 183 | } | ||
| 184 | else if (top < -1) { | ||
| 185 | *saturation_occurred = true; | ||
| 186 | return ~max; | ||
| 187 | } | ||
| 188 | |||
| 189 | *saturation_occurred = false; | ||
| 190 | return (u32)value; | ||
| 191 | } | ||
| 192 | |||
| 193 | // Unsigned saturation | ||
| 194 | u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | ||
| 195 | { | ||
| 196 | const u32 max = (1 << shift) - 1; | ||
| 197 | |||
| 198 | if (value < 0) { | ||
| 199 | *saturation_occurred = true; | ||
| 200 | return 0; | ||
| 201 | } else if ((u32)value > max) { | ||
| 202 | *saturation_occurred = true; | ||
| 203 | return max; | ||
| 204 | } | ||
| 205 | |||
| 206 | *saturation_occurred = false; | ||
| 207 | return (u32)value; | ||
| 208 | } | ||
diff --git a/src/core/arm/skyeye_common/armsupp.h b/src/core/arm/skyeye_common/armsupp.h new file mode 100644 index 000000000..391309fa8 --- /dev/null +++ b/src/core/arm/skyeye_common/armsupp.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) | ||
| 10 | #define BIT(s, n) ((s >> (n)) & 1) | ||
| 11 | |||
| 12 | #define POS(i) ( (~(i)) >> 31 ) | ||
| 13 | #define NEG(i) ( (i) >> 31 ) | ||
| 14 | |||
| 15 | bool AddOverflow(u32, u32, u32); | ||
| 16 | bool SubOverflow(u32, u32, u32); | ||
| 17 | |||
| 18 | u32 AddWithCarry(u32, u32, u32, bool*, bool*); | ||
| 19 | bool ARMul_AddOverflowQ(u32, u32); | ||
| 20 | |||
| 21 | u8 ARMul_SignedSaturatedAdd8(u8, u8); | ||
| 22 | u8 ARMul_SignedSaturatedSub8(u8, u8); | ||
| 23 | u16 ARMul_SignedSaturatedAdd16(u16, u16); | ||
| 24 | u16 ARMul_SignedSaturatedSub16(u16, u16); | ||
| 25 | |||
| 26 | u8 ARMul_UnsignedSaturatedAdd8(u8, u8); | ||
| 27 | u16 ARMul_UnsignedSaturatedAdd16(u16, u16); | ||
| 28 | u8 ARMul_UnsignedSaturatedSub8(u8, u8); | ||
| 29 | u16 ARMul_UnsignedSaturatedSub16(u16, u16); | ||
| 30 | u8 ARMul_UnsignedAbsoluteDifference(u8, u8); | ||
| 31 | u32 ARMul_SignedSatQ(s32, u8, bool*); | ||
| 32 | 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 1ffc1f9af..26f303de4 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.cpp +++ b/src/core/arm/skyeye_common/vfp/vfp.cpp | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include "common/common_funcs.h" | 23 | #include "common/common_funcs.h" |
| 24 | #include "common/logging/log.h" | 24 | #include "common/logging/log.h" |
| 25 | 25 | ||
| 26 | #include "core/arm/skyeye_common/armdefs.h" | 26 | #include "core/arm/skyeye_common/armstate.h" |
| 27 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | 27 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" |
| 28 | #include "core/arm/skyeye_common/vfp/vfp.h" | 28 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 29 | 29 | ||
| @@ -43,7 +43,7 @@ void VFPInit(ARMul_State* state) | |||
| 43 | state->VFP[VFP_MVFR1] = 0; | 43 | state->VFP[VFP_MVFR1] = 0; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) | 46 | void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) |
| 47 | { | 47 | { |
| 48 | if (to_arm) | 48 | if (to_arm) |
| 49 | { | 49 | { |
| @@ -55,7 +55,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* | |||
| 55 | } | 55 | } |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) | 58 | void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) |
| 59 | { | 59 | { |
| 60 | if (to_arm) | 60 | if (to_arm) |
| 61 | { | 61 | { |
| @@ -68,7 +68,7 @@ void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword | |||
| 68 | state->ExtReg[n*2] = *value1; | 68 | state->ExtReg[n*2] = *value1; |
| 69 | } | 69 | } |
| 70 | } | 70 | } |
| 71 | void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) | 71 | void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) |
| 72 | { | 72 | { |
| 73 | if (to_arm) | 73 | if (to_arm) |
| 74 | { | 74 | { |
| @@ -82,7 +82,7 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor | |||
| 82 | } | 82 | } |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) | 85 | void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) |
| 86 | { | 86 | { |
| 87 | if (single) | 87 | if (single) |
| 88 | { | 88 | { |
| @@ -95,7 +95,7 @@ void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) | |||
| 95 | state->ExtReg[d*2] = 0; | 95 | state->ExtReg[d*2] = 0; |
| 96 | } | 96 | } |
| 97 | } | 97 | } |
| 98 | void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword m) | 98 | void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) |
| 99 | { | 99 | { |
| 100 | if (single) | 100 | if (single) |
| 101 | { | 101 | { |
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h index 80ca93ccd..88908da9f 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 | |||
| 36 | u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); | 36 | u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); |
| 37 | u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); | 37 | u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); |
| 38 | 38 | ||
| 39 | void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); | 39 | void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value); |
| 40 | void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); | 40 | void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2); |
| 41 | void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); | 41 | void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2); |
| 42 | void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); | 42 | void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm); |
| 43 | void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); | 43 | 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 2007d6dc4..91a8d4d57 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 @@ | |||
| 34 | 34 | ||
| 35 | #include <cstdio> | 35 | #include <cstdio> |
| 36 | #include "common/common_types.h" | 36 | #include "common/common_types.h" |
| 37 | #include "core/arm/skyeye_common/armdefs.h" | 37 | #include "core/arm/skyeye_common/armstate.h" |
| 38 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | 38 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" |
| 39 | 39 | ||
| 40 | #define do_div(n, base) {n/=base;} | 40 | #define do_div(n, base) {n/=base;} |
| @@ -415,7 +415,7 @@ struct op { | |||
| 415 | u32 flags; | 415 | u32 flags; |
| 416 | }; | 416 | }; |
| 417 | 417 | ||
| 418 | static inline u32 fls(ARMword x) | 418 | static inline u32 fls(u32 x) |
| 419 | { | 419 | { |
| 420 | int r = 32; | 420 | int r = 32; |
| 421 | 421 | ||
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index f91049585..1d844a66e 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) | |||
| 70 | 70 | ||
| 71 | static void vfp_double_normalise_denormal(struct vfp_double *vd) | 71 | static void vfp_double_normalise_denormal(struct vfp_double *vd) |
| 72 | { | 72 | { |
| 73 | int bits = 31 - fls((ARMword)(vd->significand >> 32)); | 73 | int bits = 31 - fls((u32)(vd->significand >> 32)); |
| 74 | if (bits == 31) | 74 | if (bits == 31) |
| 75 | bits = 63 - fls((ARMword)vd->significand); | 75 | bits = 63 - fls((u32)vd->significand); |
| 76 | 76 | ||
| 77 | vfp_double_dump("normalise_denormal: in", vd); | 77 | vfp_double_dump("normalise_denormal: in", vd); |
| 78 | 78 | ||
| @@ -109,9 +109,9 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, | |||
| 109 | exponent = vd->exponent; | 109 | exponent = vd->exponent; |
| 110 | significand = vd->significand; | 110 | significand = vd->significand; |
| 111 | 111 | ||
| 112 | shift = 32 - fls((ARMword)(significand >> 32)); | 112 | shift = 32 - fls((u32)(significand >> 32)); |
| 113 | if (shift == 32) | 113 | if (shift == 32) |
| 114 | shift = 64 - fls((ARMword)significand); | 114 | shift = 64 - fls((u32)significand); |
| 115 | if (shift) { | 115 | if (shift) { |
| 116 | exponent -= shift; | 116 | exponent -= shift; |
| 117 | significand <<= shift; | 117 | significand <<= shift; |
| @@ -566,7 +566,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 566 | /* | 566 | /* |
| 567 | * 2^0 <= m < 2^32-2^8 | 567 | * 2^0 <= m < 2^32-2^8 |
| 568 | */ | 568 | */ |
| 569 | d = (ARMword)((vdm.significand << 1) >> shift); | 569 | d = (u32)((vdm.significand << 1) >> shift); |
| 570 | rem = vdm.significand << (65 - shift); | 570 | rem = vdm.significand << (65 - shift); |
| 571 | 571 | ||
| 572 | if (rmode == FPSCR_ROUND_NEAREST) { | 572 | if (rmode == FPSCR_ROUND_NEAREST) { |
| @@ -647,7 +647,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 647 | int shift = 1023 + 63 - vdm.exponent; /* 58 */ | 647 | int shift = 1023 + 63 - vdm.exponent; /* 58 */ |
| 648 | u64 rem, incr = 0; | 648 | u64 rem, incr = 0; |
| 649 | 649 | ||
| 650 | d = (ARMword)((vdm.significand << 1) >> shift); | 650 | d = (u32)((vdm.significand << 1) >> shift); |
| 651 | rem = vdm.significand << (65 - shift); | 651 | rem = vdm.significand << (65 - shift); |
| 652 | 652 | ||
| 653 | if (rmode == FPSCR_ROUND_NEAREST) { | 653 | 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 8efcbab1c..9b99fc5bc 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: | |||
| 51 | 51 | ||
| 52 | CHECK_VFP_CDP_RET; | 52 | CHECK_VFP_CDP_RET; |
| 53 | } | 53 | } |
| 54 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 54 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 55 | INC_PC(sizeof(vmla_inst)); | 55 | INC_PC(sizeof(vmla_inst)); |
| 56 | FETCH_INST; | 56 | FETCH_INST; |
| 57 | GOTO_NEXT_INST; | 57 | GOTO_NEXT_INST; |
| @@ -100,7 +100,7 @@ VMLS_INST: | |||
| 100 | 100 | ||
| 101 | CHECK_VFP_CDP_RET; | 101 | CHECK_VFP_CDP_RET; |
| 102 | } | 102 | } |
| 103 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 103 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 104 | INC_PC(sizeof(vmls_inst)); | 104 | INC_PC(sizeof(vmls_inst)); |
| 105 | FETCH_INST; | 105 | FETCH_INST; |
| 106 | GOTO_NEXT_INST; | 106 | GOTO_NEXT_INST; |
| @@ -149,7 +149,7 @@ VNMLA_INST: | |||
| 149 | 149 | ||
| 150 | CHECK_VFP_CDP_RET; | 150 | CHECK_VFP_CDP_RET; |
| 151 | } | 151 | } |
| 152 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 152 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 153 | INC_PC(sizeof(vnmla_inst)); | 153 | INC_PC(sizeof(vnmla_inst)); |
| 154 | FETCH_INST; | 154 | FETCH_INST; |
| 155 | GOTO_NEXT_INST; | 155 | GOTO_NEXT_INST; |
| @@ -199,7 +199,7 @@ VNMLS_INST: | |||
| 199 | 199 | ||
| 200 | CHECK_VFP_CDP_RET; | 200 | CHECK_VFP_CDP_RET; |
| 201 | } | 201 | } |
| 202 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 202 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 203 | INC_PC(sizeof(vnmls_inst)); | 203 | INC_PC(sizeof(vnmls_inst)); |
| 204 | FETCH_INST; | 204 | FETCH_INST; |
| 205 | GOTO_NEXT_INST; | 205 | GOTO_NEXT_INST; |
| @@ -248,7 +248,7 @@ VNMUL_INST: | |||
| 248 | 248 | ||
| 249 | CHECK_VFP_CDP_RET; | 249 | CHECK_VFP_CDP_RET; |
| 250 | } | 250 | } |
| 251 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 251 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 252 | INC_PC(sizeof(vnmul_inst)); | 252 | INC_PC(sizeof(vnmul_inst)); |
| 253 | FETCH_INST; | 253 | FETCH_INST; |
| 254 | GOTO_NEXT_INST; | 254 | GOTO_NEXT_INST; |
| @@ -297,7 +297,7 @@ VMUL_INST: | |||
| 297 | 297 | ||
| 298 | CHECK_VFP_CDP_RET; | 298 | CHECK_VFP_CDP_RET; |
| 299 | } | 299 | } |
| 300 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 300 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 301 | INC_PC(sizeof(vmul_inst)); | 301 | INC_PC(sizeof(vmul_inst)); |
| 302 | FETCH_INST; | 302 | FETCH_INST; |
| 303 | GOTO_NEXT_INST; | 303 | GOTO_NEXT_INST; |
| @@ -346,7 +346,7 @@ VADD_INST: | |||
| 346 | 346 | ||
| 347 | CHECK_VFP_CDP_RET; | 347 | CHECK_VFP_CDP_RET; |
| 348 | } | 348 | } |
| 349 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 349 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 350 | INC_PC(sizeof(vadd_inst)); | 350 | INC_PC(sizeof(vadd_inst)); |
| 351 | FETCH_INST; | 351 | FETCH_INST; |
| 352 | GOTO_NEXT_INST; | 352 | GOTO_NEXT_INST; |
| @@ -395,7 +395,7 @@ VSUB_INST: | |||
| 395 | 395 | ||
| 396 | CHECK_VFP_CDP_RET; | 396 | CHECK_VFP_CDP_RET; |
| 397 | } | 397 | } |
| 398 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 398 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 399 | INC_PC(sizeof(vsub_inst)); | 399 | INC_PC(sizeof(vsub_inst)); |
| 400 | FETCH_INST; | 400 | FETCH_INST; |
| 401 | GOTO_NEXT_INST; | 401 | GOTO_NEXT_INST; |
| @@ -444,7 +444,7 @@ VDIV_INST: | |||
| 444 | 444 | ||
| 445 | CHECK_VFP_CDP_RET; | 445 | CHECK_VFP_CDP_RET; |
| 446 | } | 446 | } |
| 447 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 447 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 448 | INC_PC(sizeof(vdiv_inst)); | 448 | INC_PC(sizeof(vdiv_inst)); |
| 449 | FETCH_INST; | 449 | FETCH_INST; |
| 450 | GOTO_NEXT_INST; | 450 | GOTO_NEXT_INST; |
| @@ -492,7 +492,7 @@ VMOVI_INST: | |||
| 492 | 492 | ||
| 493 | VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); | 493 | VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); |
| 494 | } | 494 | } |
| 495 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 495 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 496 | INC_PC(sizeof(vmovi_inst)); | 496 | INC_PC(sizeof(vmovi_inst)); |
| 497 | FETCH_INST; | 497 | FETCH_INST; |
| 498 | GOTO_NEXT_INST; | 498 | GOTO_NEXT_INST; |
| @@ -536,7 +536,7 @@ VMOVR_INST: | |||
| 536 | 536 | ||
| 537 | VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); | 537 | VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); |
| 538 | } | 538 | } |
| 539 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 539 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 540 | INC_PC(sizeof(vmovr_inst)); | 540 | INC_PC(sizeof(vmovr_inst)); |
| 541 | FETCH_INST; | 541 | FETCH_INST; |
| 542 | GOTO_NEXT_INST; | 542 | GOTO_NEXT_INST; |
| @@ -585,7 +585,7 @@ VABS_INST: | |||
| 585 | 585 | ||
| 586 | CHECK_VFP_CDP_RET; | 586 | CHECK_VFP_CDP_RET; |
| 587 | } | 587 | } |
| 588 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 588 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 589 | INC_PC(sizeof(vabs_inst)); | 589 | INC_PC(sizeof(vabs_inst)); |
| 590 | FETCH_INST; | 590 | FETCH_INST; |
| 591 | GOTO_NEXT_INST; | 591 | GOTO_NEXT_INST; |
| @@ -635,7 +635,7 @@ VNEG_INST: | |||
| 635 | 635 | ||
| 636 | CHECK_VFP_CDP_RET; | 636 | CHECK_VFP_CDP_RET; |
| 637 | } | 637 | } |
| 638 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 638 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 639 | INC_PC(sizeof(vneg_inst)); | 639 | INC_PC(sizeof(vneg_inst)); |
| 640 | FETCH_INST; | 640 | FETCH_INST; |
| 641 | GOTO_NEXT_INST; | 641 | GOTO_NEXT_INST; |
| @@ -684,7 +684,7 @@ VSQRT_INST: | |||
| 684 | 684 | ||
| 685 | CHECK_VFP_CDP_RET; | 685 | CHECK_VFP_CDP_RET; |
| 686 | } | 686 | } |
| 687 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 687 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 688 | INC_PC(sizeof(vsqrt_inst)); | 688 | INC_PC(sizeof(vsqrt_inst)); |
| 689 | FETCH_INST; | 689 | FETCH_INST; |
| 690 | GOTO_NEXT_INST; | 690 | GOTO_NEXT_INST; |
| @@ -733,7 +733,7 @@ VCMP_INST: | |||
| 733 | 733 | ||
| 734 | CHECK_VFP_CDP_RET; | 734 | CHECK_VFP_CDP_RET; |
| 735 | } | 735 | } |
| 736 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 736 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 737 | INC_PC(sizeof(vcmp_inst)); | 737 | INC_PC(sizeof(vcmp_inst)); |
| 738 | FETCH_INST; | 738 | FETCH_INST; |
| 739 | GOTO_NEXT_INST; | 739 | GOTO_NEXT_INST; |
| @@ -782,7 +782,7 @@ VCMP2_INST: | |||
| 782 | 782 | ||
| 783 | CHECK_VFP_CDP_RET; | 783 | CHECK_VFP_CDP_RET; |
| 784 | } | 784 | } |
| 785 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 785 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 786 | INC_PC(sizeof(vcmp2_inst)); | 786 | INC_PC(sizeof(vcmp2_inst)); |
| 787 | FETCH_INST; | 787 | FETCH_INST; |
| 788 | GOTO_NEXT_INST; | 788 | GOTO_NEXT_INST; |
| @@ -831,7 +831,7 @@ VCVTBDS_INST: | |||
| 831 | 831 | ||
| 832 | CHECK_VFP_CDP_RET; | 832 | CHECK_VFP_CDP_RET; |
| 833 | } | 833 | } |
| 834 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 834 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 835 | INC_PC(sizeof(vcvtbds_inst)); | 835 | INC_PC(sizeof(vcvtbds_inst)); |
| 836 | FETCH_INST; | 836 | FETCH_INST; |
| 837 | GOTO_NEXT_INST; | 837 | GOTO_NEXT_INST; |
| @@ -882,7 +882,7 @@ VCVTBFF_INST: | |||
| 882 | 882 | ||
| 883 | CHECK_VFP_CDP_RET; | 883 | CHECK_VFP_CDP_RET; |
| 884 | } | 884 | } |
| 885 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 885 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 886 | INC_PC(sizeof(vcvtbff_inst)); | 886 | INC_PC(sizeof(vcvtbff_inst)); |
| 887 | FETCH_INST; | 887 | FETCH_INST; |
| 888 | GOTO_NEXT_INST; | 888 | GOTO_NEXT_INST; |
| @@ -931,7 +931,7 @@ VCVTBFI_INST: | |||
| 931 | 931 | ||
| 932 | CHECK_VFP_CDP_RET; | 932 | CHECK_VFP_CDP_RET; |
| 933 | } | 933 | } |
| 934 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 934 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 935 | INC_PC(sizeof(vcvtbfi_inst)); | 935 | INC_PC(sizeof(vcvtbfi_inst)); |
| 936 | FETCH_INST; | 936 | FETCH_INST; |
| 937 | GOTO_NEXT_INST; | 937 | GOTO_NEXT_INST; |
| @@ -981,7 +981,7 @@ VMOVBRS_INST: | |||
| 981 | 981 | ||
| 982 | VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); | 982 | VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); |
| 983 | } | 983 | } |
| 984 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 984 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 985 | INC_PC(sizeof(vmovbrs_inst)); | 985 | INC_PC(sizeof(vmovbrs_inst)); |
| 986 | FETCH_INST; | 986 | FETCH_INST; |
| 987 | GOTO_NEXT_INST; | 987 | GOTO_NEXT_INST; |
| @@ -1032,7 +1032,7 @@ VMSR_INST: | |||
| 1032 | { | 1032 | { |
| 1033 | cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; | 1033 | cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; |
| 1034 | } | 1034 | } |
| 1035 | else if (InAPrivilegedMode(cpu)) | 1035 | else if (cpu->InAPrivilegedMode()) |
| 1036 | { | 1036 | { |
| 1037 | if (reg == 8) | 1037 | if (reg == 8) |
| 1038 | cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; | 1038 | cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; |
| @@ -1042,7 +1042,7 @@ VMSR_INST: | |||
| 1042 | cpu->VFP[VFP_FPINST2] = cpu->Reg[rt]; | 1042 | cpu->VFP[VFP_FPINST2] = cpu->Reg[rt]; |
| 1043 | } | 1043 | } |
| 1044 | } | 1044 | } |
| 1045 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1045 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1046 | INC_PC(sizeof(vmsr_inst)); | 1046 | INC_PC(sizeof(vmsr_inst)); |
| 1047 | FETCH_INST; | 1047 | FETCH_INST; |
| 1048 | GOTO_NEXT_INST; | 1048 | GOTO_NEXT_INST; |
| @@ -1090,7 +1090,7 @@ VMOVBRC_INST: | |||
| 1090 | 1090 | ||
| 1091 | cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t]; | 1091 | cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t]; |
| 1092 | } | 1092 | } |
| 1093 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1093 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1094 | INC_PC(sizeof(vmovbrc_inst)); | 1094 | INC_PC(sizeof(vmovbrc_inst)); |
| 1095 | FETCH_INST; | 1095 | FETCH_INST; |
| 1096 | GOTO_NEXT_INST; | 1096 | GOTO_NEXT_INST; |
| @@ -1163,7 +1163,7 @@ VMRS_INST: | |||
| 1163 | { | 1163 | { |
| 1164 | cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; | 1164 | cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; |
| 1165 | } | 1165 | } |
| 1166 | else if (InAPrivilegedMode(cpu)) | 1166 | else if (cpu->InAPrivilegedMode()) |
| 1167 | { | 1167 | { |
| 1168 | if (reg == 8) | 1168 | if (reg == 8) |
| 1169 | cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; | 1169 | cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; |
| @@ -1173,7 +1173,7 @@ VMRS_INST: | |||
| 1173 | cpu->Reg[rt] = cpu->VFP[VFP_FPINST2]; | 1173 | cpu->Reg[rt] = cpu->VFP[VFP_FPINST2]; |
| 1174 | } | 1174 | } |
| 1175 | } | 1175 | } |
| 1176 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1176 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1177 | INC_PC(sizeof(vmrs_inst)); | 1177 | INC_PC(sizeof(vmrs_inst)); |
| 1178 | FETCH_INST; | 1178 | FETCH_INST; |
| 1179 | GOTO_NEXT_INST; | 1179 | GOTO_NEXT_INST; |
| @@ -1221,7 +1221,7 @@ VMOVBCR_INST: | |||
| 1221 | 1221 | ||
| 1222 | cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; | 1222 | cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; |
| 1223 | } | 1223 | } |
| 1224 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1224 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1225 | INC_PC(sizeof(vmovbcr_inst)); | 1225 | INC_PC(sizeof(vmovbcr_inst)); |
| 1226 | FETCH_INST; | 1226 | FETCH_INST; |
| 1227 | GOTO_NEXT_INST; | 1227 | GOTO_NEXT_INST; |
| @@ -1274,7 +1274,7 @@ VMOVBRRSS_INST: | |||
| 1274 | VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, | 1274 | VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, |
| 1275 | &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]); | 1275 | &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]); |
| 1276 | } | 1276 | } |
| 1277 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1277 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1278 | INC_PC(sizeof(vmovbrrss_inst)); | 1278 | INC_PC(sizeof(vmovbrrss_inst)); |
| 1279 | FETCH_INST; | 1279 | FETCH_INST; |
| 1280 | GOTO_NEXT_INST; | 1280 | GOTO_NEXT_INST; |
| @@ -1322,7 +1322,7 @@ VMOVBRRD_INST: | |||
| 1322 | VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, | 1322 | VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, |
| 1323 | &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); | 1323 | &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); |
| 1324 | } | 1324 | } |
| 1325 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1325 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1326 | INC_PC(sizeof(vmovbrrd_inst)); | 1326 | INC_PC(sizeof(vmovbrrd_inst)); |
| 1327 | FETCH_INST; | 1327 | FETCH_INST; |
| 1328 | GOTO_NEXT_INST; | 1328 | GOTO_NEXT_INST; |
| @@ -1378,23 +1378,23 @@ VSTR_INST: | |||
| 1378 | 1378 | ||
| 1379 | if (inst_cream->single) | 1379 | if (inst_cream->single) |
| 1380 | { | 1380 | { |
| 1381 | WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]); | 1381 | cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]); |
| 1382 | } | 1382 | } |
| 1383 | else | 1383 | else |
| 1384 | { | 1384 | { |
| 1385 | const u32 word1 = cpu->ExtReg[inst_cream->d*2+0]; | 1385 | const u32 word1 = cpu->ExtReg[inst_cream->d*2+0]; |
| 1386 | const u32 word2 = cpu->ExtReg[inst_cream->d*2+1]; | 1386 | const u32 word2 = cpu->ExtReg[inst_cream->d*2+1]; |
| 1387 | 1387 | ||
| 1388 | if (InBigEndianMode(cpu)) { | 1388 | if (cpu->InBigEndianMode()) { |
| 1389 | WriteMemory32(cpu, addr + 0, word2); | 1389 | cpu->WriteMemory32(addr + 0, word2); |
| 1390 | WriteMemory32(cpu, addr + 4, word1); | 1390 | cpu->WriteMemory32(addr + 4, word1); |
| 1391 | } else { | 1391 | } else { |
| 1392 | WriteMemory32(cpu, addr + 0, word1); | 1392 | cpu->WriteMemory32(addr + 0, word1); |
| 1393 | WriteMemory32(cpu, addr + 4, word2); | 1393 | cpu->WriteMemory32(addr + 4, word2); |
| 1394 | } | 1394 | } |
| 1395 | } | 1395 | } |
| 1396 | } | 1396 | } |
| 1397 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1397 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1398 | INC_PC(sizeof(vstr_inst)); | 1398 | INC_PC(sizeof(vstr_inst)); |
| 1399 | FETCH_INST; | 1399 | FETCH_INST; |
| 1400 | GOTO_NEXT_INST; | 1400 | GOTO_NEXT_INST; |
| @@ -1444,7 +1444,7 @@ VPUSH_INST: | |||
| 1444 | { | 1444 | { |
| 1445 | if (inst_cream->single) | 1445 | if (inst_cream->single) |
| 1446 | { | 1446 | { |
| 1447 | WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); | 1447 | cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); |
| 1448 | addr += 4; | 1448 | addr += 4; |
| 1449 | } | 1449 | } |
| 1450 | else | 1450 | else |
| @@ -1452,12 +1452,12 @@ VPUSH_INST: | |||
| 1452 | const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; | 1452 | const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; |
| 1453 | const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; | 1453 | const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; |
| 1454 | 1454 | ||
| 1455 | if (InBigEndianMode(cpu)) { | 1455 | if (cpu->InBigEndianMode()) { |
| 1456 | WriteMemory32(cpu, addr + 0, word2); | 1456 | cpu->WriteMemory32(addr + 0, word2); |
| 1457 | WriteMemory32(cpu, addr + 4, word1); | 1457 | cpu->WriteMemory32(addr + 4, word1); |
| 1458 | } else { | 1458 | } else { |
| 1459 | WriteMemory32(cpu, addr + 0, word1); | 1459 | cpu->WriteMemory32(addr + 0, word1); |
| 1460 | WriteMemory32(cpu, addr + 4, word2); | 1460 | cpu->WriteMemory32(addr + 4, word2); |
| 1461 | } | 1461 | } |
| 1462 | 1462 | ||
| 1463 | addr += 8; | 1463 | addr += 8; |
| @@ -1466,7 +1466,7 @@ VPUSH_INST: | |||
| 1466 | 1466 | ||
| 1467 | cpu->Reg[R13] -= inst_cream->imm32; | 1467 | cpu->Reg[R13] -= inst_cream->imm32; |
| 1468 | } | 1468 | } |
| 1469 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1469 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1470 | INC_PC(sizeof(vpush_inst)); | 1470 | INC_PC(sizeof(vpush_inst)); |
| 1471 | FETCH_INST; | 1471 | FETCH_INST; |
| 1472 | GOTO_NEXT_INST; | 1472 | GOTO_NEXT_INST; |
| @@ -1522,7 +1522,7 @@ VSTM_INST: /* encoding 1 */ | |||
| 1522 | { | 1522 | { |
| 1523 | if (inst_cream->single) | 1523 | if (inst_cream->single) |
| 1524 | { | 1524 | { |
| 1525 | WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); | 1525 | cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); |
| 1526 | addr += 4; | 1526 | addr += 4; |
| 1527 | } | 1527 | } |
| 1528 | else | 1528 | else |
| @@ -1530,12 +1530,12 @@ VSTM_INST: /* encoding 1 */ | |||
| 1530 | const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; | 1530 | const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; |
| 1531 | const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; | 1531 | const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; |
| 1532 | 1532 | ||
| 1533 | if (InBigEndianMode(cpu)) { | 1533 | if (cpu->InBigEndianMode()) { |
| 1534 | WriteMemory32(cpu, addr + 0, word2); | 1534 | cpu->WriteMemory32(addr + 0, word2); |
| 1535 | WriteMemory32(cpu, addr + 4, word1); | 1535 | cpu->WriteMemory32(addr + 4, word1); |
| 1536 | } else { | 1536 | } else { |
| 1537 | WriteMemory32(cpu, addr + 0, word1); | 1537 | cpu->WriteMemory32(addr + 0, word1); |
| 1538 | WriteMemory32(cpu, addr + 4, word2); | 1538 | cpu->WriteMemory32(addr + 4, word2); |
| 1539 | } | 1539 | } |
| 1540 | 1540 | ||
| 1541 | addr += 8; | 1541 | addr += 8; |
| @@ -1597,15 +1597,15 @@ VPOP_INST: | |||
| 1597 | { | 1597 | { |
| 1598 | if (inst_cream->single) | 1598 | if (inst_cream->single) |
| 1599 | { | 1599 | { |
| 1600 | cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); | 1600 | cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); |
| 1601 | addr += 4; | 1601 | addr += 4; |
| 1602 | } | 1602 | } |
| 1603 | else | 1603 | else |
| 1604 | { | 1604 | { |
| 1605 | const u32 word1 = ReadMemory32(cpu, addr + 0); | 1605 | const u32 word1 = cpu->ReadMemory32(addr + 0); |
| 1606 | const u32 word2 = ReadMemory32(cpu, addr + 4); | 1606 | const u32 word2 = cpu->ReadMemory32(addr + 4); |
| 1607 | 1607 | ||
| 1608 | if (InBigEndianMode(cpu)) { | 1608 | if (cpu->InBigEndianMode()) { |
| 1609 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | 1609 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; |
| 1610 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | 1610 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; |
| 1611 | } else { | 1611 | } else { |
| @@ -1618,7 +1618,7 @@ VPOP_INST: | |||
| 1618 | } | 1618 | } |
| 1619 | cpu->Reg[R13] += inst_cream->imm32; | 1619 | cpu->Reg[R13] += inst_cream->imm32; |
| 1620 | } | 1620 | } |
| 1621 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1621 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1622 | INC_PC(sizeof(vpop_inst)); | 1622 | INC_PC(sizeof(vpop_inst)); |
| 1623 | FETCH_INST; | 1623 | FETCH_INST; |
| 1624 | GOTO_NEXT_INST; | 1624 | GOTO_NEXT_INST; |
| @@ -1670,14 +1670,14 @@ VLDR_INST: | |||
| 1670 | 1670 | ||
| 1671 | if (inst_cream->single) | 1671 | if (inst_cream->single) |
| 1672 | { | 1672 | { |
| 1673 | cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr); | 1673 | cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr); |
| 1674 | } | 1674 | } |
| 1675 | else | 1675 | else |
| 1676 | { | 1676 | { |
| 1677 | const u32 word1 = ReadMemory32(cpu, addr + 0); | 1677 | const u32 word1 = cpu->ReadMemory32(addr + 0); |
| 1678 | const u32 word2 = ReadMemory32(cpu, addr + 4); | 1678 | const u32 word2 = cpu->ReadMemory32(addr + 4); |
| 1679 | 1679 | ||
| 1680 | if (InBigEndianMode(cpu)) { | 1680 | if (cpu->InBigEndianMode()) { |
| 1681 | cpu->ExtReg[inst_cream->d*2+0] = word2; | 1681 | cpu->ExtReg[inst_cream->d*2+0] = word2; |
| 1682 | cpu->ExtReg[inst_cream->d*2+1] = word1; | 1682 | cpu->ExtReg[inst_cream->d*2+1] = word1; |
| 1683 | } else { | 1683 | } else { |
| @@ -1686,7 +1686,7 @@ VLDR_INST: | |||
| 1686 | } | 1686 | } |
| 1687 | } | 1687 | } |
| 1688 | } | 1688 | } |
| 1689 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1689 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1690 | INC_PC(sizeof(vldr_inst)); | 1690 | INC_PC(sizeof(vldr_inst)); |
| 1691 | FETCH_INST; | 1691 | FETCH_INST; |
| 1692 | GOTO_NEXT_INST; | 1692 | GOTO_NEXT_INST; |
| @@ -1742,15 +1742,15 @@ VLDM_INST: | |||
| 1742 | { | 1742 | { |
| 1743 | if (inst_cream->single) | 1743 | if (inst_cream->single) |
| 1744 | { | 1744 | { |
| 1745 | cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); | 1745 | cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); |
| 1746 | addr += 4; | 1746 | addr += 4; |
| 1747 | } | 1747 | } |
| 1748 | else | 1748 | else |
| 1749 | { | 1749 | { |
| 1750 | const u32 word1 = ReadMemory32(cpu, addr + 0); | 1750 | const u32 word1 = cpu->ReadMemory32(addr + 0); |
| 1751 | const u32 word2 = ReadMemory32(cpu, addr + 4); | 1751 | const u32 word2 = cpu->ReadMemory32(addr + 4); |
| 1752 | 1752 | ||
| 1753 | if (InBigEndianMode(cpu)) { | 1753 | if (cpu->InBigEndianMode()) { |
| 1754 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | 1754 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; |
| 1755 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | 1755 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; |
| 1756 | } else { | 1756 | } else { |
| @@ -1766,7 +1766,7 @@ VLDM_INST: | |||
| 1766 | cpu->Reg[inst_cream->n] - inst_cream->imm32); | 1766 | cpu->Reg[inst_cream->n] - inst_cream->imm32); |
| 1767 | } | 1767 | } |
| 1768 | } | 1768 | } |
| 1769 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1769 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1770 | INC_PC(sizeof(vldm_inst)); | 1770 | INC_PC(sizeof(vldm_inst)); |
| 1771 | FETCH_INST; | 1771 | FETCH_INST; |
| 1772 | GOTO_NEXT_INST; | 1772 | GOTO_NEXT_INST; |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 72006a53e..20f2da0fe 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -502,7 +502,7 @@ void Advance() { | |||
| 502 | Core::g_app_core->down_count += diff; | 502 | Core::g_app_core->down_count += diff; |
| 503 | } | 503 | } |
| 504 | if (advance_callback) | 504 | if (advance_callback) |
| 505 | advance_callback(cycles_executed); | 505 | advance_callback(static_cast<int>(cycles_executed)); |
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | void LogPendingEvents() { | 508 | void LogPendingEvents() { |
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp index 826f6cbb6..bc2a1829e 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) | |||
| 89 | return result; | 89 | return result; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | bool IsLibraryAppletRunning() { | ||
| 93 | // Check the applets map for instances of any applet | ||
| 94 | for (auto itr = applets.begin(); itr != applets.end(); ++itr) | ||
| 95 | if (itr->second != nullptr) | ||
| 96 | return true; | ||
| 97 | return false; | ||
| 98 | } | ||
| 99 | |||
| 92 | void Init() { | 100 | void Init() { |
| 93 | // Register the applet update callback | 101 | // Register the applet update callback |
| 94 | applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent); | 102 | applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent); |
| 95 | } | 103 | } |
| 96 | 104 | ||
| 97 | void Shutdown() { | 105 | void Shutdown() { |
| 106 | CoreTiming::RemoveEvent(applet_update_event); | ||
| 98 | } | 107 | } |
| 99 | 108 | ||
| 100 | } | 109 | } |
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h index b235d0b8a..af442f81d 100644 --- a/src/core/hle/applets/applet.h +++ b/src/core/hle/applets/applet.h | |||
| @@ -67,6 +67,9 @@ protected: | |||
| 67 | Service::APT::AppletId id; ///< Id of this Applet | 67 | Service::APT::AppletId id; ///< Id of this Applet |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | /// Returns whether a library applet is currently running | ||
| 71 | bool IsLibraryAppletRunning(); | ||
| 72 | |||
| 70 | /// Initializes the HLE applets | 73 | /// Initializes the HLE applets |
| 71 | void Init(); | 74 | void Init(); |
| 72 | 75 | ||
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 9294789ec..1a0518926 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() { | |||
| 133 | FuncReturn(func(PARAM(0)).raw); | 133 | FuncReturn(func(PARAM(0)).raw); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | template<ResultCode func(s64*, u32, u32*, s32)> void Wrap(){ | 136 | template<ResultCode func(s64*, u32, u32*, u32)> void Wrap(){ |
| 137 | FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)), | 137 | FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)), |
| 138 | (s32)PARAM(3)).raw); | 138 | (s32)PARAM(3)).raw); |
| 139 | } | 139 | } |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 8b49fc7df..29ea6d531 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include "common/thread_queue_list.h" | 13 | #include "common/thread_queue_list.h" |
| 14 | 14 | ||
| 15 | #include "core/arm/arm_interface.h" | 15 | #include "core/arm/arm_interface.h" |
| 16 | #include "core/arm/skyeye_common/armdefs.h" | 16 | #include "core/arm/skyeye_common/armstate.h" |
| 17 | #include "core/core.h" | 17 | #include "core/core.h" |
| 18 | #include "core/core_timing.h" | 18 | #include "core/core_timing.h" |
| 19 | #include "core/hle/hle.h" | 19 | #include "core/hle/hle.h" |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 7332478fb..64f3bc7e9 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | 6 | ||
| 7 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | #include "core/hle/service/am/am.h" | ||
| 8 | #include "core/hle/service/am/am_app.h" | 9 | #include "core/hle/service/am/am_app.h" |
| 9 | #include "core/hle/service/am/am_net.h" | 10 | #include "core/hle/service/am/am_net.h" |
| 10 | #include "core/hle/service/am/am_sys.h" | 11 | #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 b1af0e9d8..aa391f3b2 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[] = { | |||
| 28 | {0x08130000, nullptr, "GetTotalContents"}, | 28 | {0x08130000, nullptr, "GetTotalContents"}, |
| 29 | {0x08140042, nullptr, "GetContentIndexes"}, | 29 | {0x08140042, nullptr, "GetContentIndexes"}, |
| 30 | {0x08150044, nullptr, "GetContentsInfo"}, | 30 | {0x08150044, nullptr, "GetContentsInfo"}, |
| 31 | {0x08190108, nullptr, "Unknown"}, | 31 | {0x08180042, nullptr, "GetCTCert"}, |
| 32 | {0x08190108, nullptr, "SetCertificates"}, | ||
| 32 | {0x081B00C2, nullptr, "InstallTitlesFinish"}, | 33 | {0x081B00C2, nullptr, "InstallTitlesFinish"}, |
| 33 | }; | 34 | }; |
| 34 | 35 | ||
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 7b6ab4ce0..35402341b 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) { | |||
| 101 | 101 | ||
| 102 | void GetLockHandle(Service::Interface* self) { | 102 | void GetLockHandle(Service::Interface* self) { |
| 103 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 103 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 104 | u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field | 104 | // Bits [0:2] are the applet type (System, Library, etc) |
| 105 | // Bit 5 tells the application that there's a pending APT parameter, | ||
| 106 | // this will cause the app to wait until parameter_event is signaled. | ||
| 107 | u32 applet_attributes = cmd_buff[1]; | ||
| 105 | 108 | ||
| 106 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 109 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 107 | 110 | ||
| 108 | // Not sure what these parameters are used for, but retail apps check that they are 0 after | 111 | cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable. |
| 109 | // GetLockHandle has been called. | 112 | cmd_buff[3] = 0; // Least significant bit = power button state |
| 110 | cmd_buff[2] = 0; // Applet Attributes, this value is passed to Enable. | 113 | cmd_buff[4] = IPC::CopyHandleDesc(); |
| 111 | cmd_buff[3] = 0; | ||
| 112 | cmd_buff[4] = 0; | ||
| 113 | |||
| 114 | cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); | 114 | cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); |
| 115 | LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]); | 115 | |
| 116 | LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], applet_attributes); | ||
| 116 | } | 117 | } |
| 117 | 118 | ||
| 118 | void Enable(Service::Interface* self) { | 119 | void Enable(Service::Interface* self) { |
| @@ -139,13 +140,16 @@ void IsRegistered(Service::Interface* self) { | |||
| 139 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 140 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 140 | u32 app_id = cmd_buff[1]; | 141 | u32 app_id = cmd_buff[1]; |
| 141 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 142 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 142 | /// TODO(Subv): It is currently unknown what this value (0x400) means, | 143 | |
| 143 | /// but i believe it is used as a global "LibraryApplet" id, to verify if there's | 144 | // TODO(Subv): An application is considered "registered" if it has already called APT::Enable |
| 144 | /// any LibApplet currently running. This is not verified. | 145 | // handle this properly once we implement multiprocess support. |
| 145 | if (app_id != 0x400) | 146 | cmd_buff[2] = 0; // Set to not registered by default |
| 147 | |||
| 148 | if (app_id == static_cast<u32>(AppletId::AnyLibraryApplet)) { | ||
| 149 | cmd_buff[2] = HLE::Applets::IsLibraryAppletRunning() ? 1 : 0; | ||
| 150 | } else if (auto applet = HLE::Applets::Applet::Get(static_cast<AppletId>(app_id))) { | ||
| 146 | cmd_buff[2] = 1; // Set to registered | 151 | cmd_buff[2] = 1; // Set to registered |
| 147 | else | 152 | } |
| 148 | cmd_buff[2] = 0; // Set to not registered | ||
| 149 | LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); | 153 | LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); |
| 150 | } | 154 | } |
| 151 | 155 | ||
| @@ -330,7 +334,26 @@ void GetAppCpuTimeLimit(Service::Interface* self) { | |||
| 330 | void PrepareToStartLibraryApplet(Service::Interface* self) { | 334 | void PrepareToStartLibraryApplet(Service::Interface* self) { |
| 331 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 335 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 332 | AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); | 336 | AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); |
| 333 | cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; | 337 | auto applet = HLE::Applets::Applet::Get(applet_id); |
| 338 | if (applet) { | ||
| 339 | LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); | ||
| 340 | cmd_buff[1] = RESULT_SUCCESS.raw; | ||
| 341 | } else { | ||
| 342 | cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; | ||
| 343 | } | ||
| 344 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); | ||
| 345 | } | ||
| 346 | |||
| 347 | void PreloadLibraryApplet(Service::Interface* self) { | ||
| 348 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 349 | AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); | ||
| 350 | auto applet = HLE::Applets::Applet::Get(applet_id); | ||
| 351 | if (applet) { | ||
| 352 | LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); | ||
| 353 | cmd_buff[1] = RESULT_SUCCESS.raw; | ||
| 354 | } else { | ||
| 355 | cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; | ||
| 356 | } | ||
| 334 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); | 357 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); |
| 335 | } | 358 | } |
| 336 | 359 | ||
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 72972d05b..4a72b6b5c 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 { | |||
| 62 | Extrapad = 0x208, | 62 | Extrapad = 0x208, |
| 63 | Memolib = 0x209, | 63 | Memolib = 0x209, |
| 64 | Application = 0x300, | 64 | Application = 0x300, |
| 65 | AnyLibraryApplet = 0x400, | ||
| 65 | SoftwareKeyboard2 = 0x401, | 66 | SoftwareKeyboard2 = 0x401, |
| 66 | }; | 67 | }; |
| 67 | 68 | ||
| @@ -96,8 +97,26 @@ void GetSharedFont(Service::Interface* self); | |||
| 96 | */ | 97 | */ |
| 97 | void NotifyToWait(Service::Interface* self); | 98 | void NotifyToWait(Service::Interface* self); |
| 98 | 99 | ||
| 100 | /** | ||
| 101 | * APT::GetLockHandle service function | ||
| 102 | * Inputs: | ||
| 103 | * 1 : Applet attributes | ||
| 104 | * Outputs: | ||
| 105 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 106 | * 2 : Applet attributes | ||
| 107 | * 3 : Power button state | ||
| 108 | * 4 : IPC handle descriptor | ||
| 109 | * 5 : APT mutex handle | ||
| 110 | */ | ||
| 99 | void GetLockHandle(Service::Interface* self); | 111 | void GetLockHandle(Service::Interface* self); |
| 100 | 112 | ||
| 113 | /** | ||
| 114 | * APT::Enable service function | ||
| 115 | * Inputs: | ||
| 116 | * 1 : Applet attributes | ||
| 117 | * Outputs: | ||
| 118 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 119 | */ | ||
| 101 | void Enable(Service::Interface* self); | 120 | void Enable(Service::Interface* self); |
| 102 | 121 | ||
| 103 | /** | 122 | /** |
| @@ -284,6 +303,17 @@ void GetAppCpuTimeLimit(Service::Interface* self); | |||
| 284 | void PrepareToStartLibraryApplet(Service::Interface* self); | 303 | void PrepareToStartLibraryApplet(Service::Interface* self); |
| 285 | 304 | ||
| 286 | /** | 305 | /** |
| 306 | * APT::PreloadLibraryApplet service function | ||
| 307 | * Inputs: | ||
| 308 | * 0 : Command header [0x00160040] | ||
| 309 | * 1 : Id of the applet to start | ||
| 310 | * Outputs: | ||
| 311 | * 0 : Return header | ||
| 312 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 313 | */ | ||
| 314 | void PreloadLibraryApplet(Service::Interface* self); | ||
| 315 | |||
| 316 | /** | ||
| 287 | * APT::StartLibraryApplet service function | 317 | * APT::StartLibraryApplet service function |
| 288 | * Inputs: | 318 | * Inputs: |
| 289 | * 0 : Command header [0x001E0084] | 319 | * 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 88de339f9..22800c56f 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[] = { | |||
| 21 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, | 21 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, |
| 22 | {0x000E0080, GlanceParameter, "GlanceParameter"}, | 22 | {0x000E0080, GlanceParameter, "GlanceParameter"}, |
| 23 | {0x000F0100, CancelParameter, "CancelParameter"}, | 23 | {0x000F0100, CancelParameter, "CancelParameter"}, |
| 24 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, | ||
| 24 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, | 25 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, |
| 25 | {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, | 26 | {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, |
| 26 | {0x003B0040, nullptr, "CancelLibraryApplet?"}, | 27 | {0x003B0040, nullptr, "CancelLibraryApplet?"}, |
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index 396d1f04a..3ac6ff94f 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[] = { | |||
| 32 | {0x00130000, nullptr, "GetPreparationState"}, | 32 | {0x00130000, nullptr, "GetPreparationState"}, |
| 33 | {0x00140040, nullptr, "SetPreparationState"}, | 33 | {0x00140040, nullptr, "SetPreparationState"}, |
| 34 | {0x00150140, nullptr, "PrepareToStartApplication"}, | 34 | {0x00150140, nullptr, "PrepareToStartApplication"}, |
| 35 | {0x00160040, nullptr, "PreloadLibraryApplet"}, | 35 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, |
| 36 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, | 36 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, |
| 37 | {0x00180040, nullptr, "PrepareToStartLibraryApplet"}, | 37 | {0x00180040, PrepareToStartLibraryApplet,"PrepareToStartLibraryApplet"}, |
| 38 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, | 38 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, |
| 39 | {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, | 39 | {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, |
| 40 | {0x001B00C4, nullptr, "StartApplication"}, | 40 | {0x001B00C4, nullptr, "StartApplication"}, |
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index b724cd72b..146bfd595 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[] = { | |||
| 33 | {0x00130000, nullptr, "GetPreparationState"}, | 33 | {0x00130000, nullptr, "GetPreparationState"}, |
| 34 | {0x00140040, nullptr, "SetPreparationState"}, | 34 | {0x00140040, nullptr, "SetPreparationState"}, |
| 35 | {0x00150140, nullptr, "PrepareToStartApplication"}, | 35 | {0x00150140, nullptr, "PrepareToStartApplication"}, |
| 36 | {0x00160040, nullptr, "PreloadLibraryApplet"}, | 36 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, |
| 37 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, | 37 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, |
| 38 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, | 38 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, |
| 39 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, | 39 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, |
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 8b40ba376..e93c1b436 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "core/hw/lcd.h" | 14 | #include "core/hw/lcd.h" |
| 15 | 15 | ||
| 16 | #include "video_core/gpu_debugger.h" | 16 | #include "video_core/gpu_debugger.h" |
| 17 | #include "video_core/debug_utils/debug_utils.h" | ||
| 17 | #include "video_core/renderer_base.h" | 18 | #include "video_core/renderer_base.h" |
| 18 | #include "video_core/video_core.h" | 19 | #include "video_core/video_core.h" |
| 19 | 20 | ||
| @@ -226,6 +227,9 @@ void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | |||
| 226 | &info.format); | 227 | &info.format); |
| 227 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4, | 228 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4, |
| 228 | &info.shown_fb); | 229 | &info.shown_fb); |
| 230 | |||
| 231 | if (Pica::g_debug_context) | ||
| 232 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); | ||
| 229 | } | 233 | } |
| 230 | 234 | ||
| 231 | /** | 235 | /** |
| @@ -391,19 +395,24 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 391 | case CommandId::SET_MEMORY_FILL: | 395 | case CommandId::SET_MEMORY_FILL: |
| 392 | { | 396 | { |
| 393 | auto& params = command.memory_fill; | 397 | auto& params = command.memory_fill; |
| 394 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), | 398 | |
| 395 | Memory::VirtualToPhysicalAddress(params.start1) >> 3); | 399 | if (params.start1 != 0) { |
| 396 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), | 400 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), |
| 397 | Memory::VirtualToPhysicalAddress(params.end1) >> 3); | 401 | Memory::VirtualToPhysicalAddress(params.start1) >> 3); |
| 398 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1); | 402 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), |
| 399 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), params.control1); | 403 | Memory::VirtualToPhysicalAddress(params.end1) >> 3); |
| 400 | 404 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1); | |
| 401 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), | 405 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), params.control1); |
| 402 | Memory::VirtualToPhysicalAddress(params.start2) >> 3); | 406 | } |
| 403 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), | 407 | |
| 404 | Memory::VirtualToPhysicalAddress(params.end2) >> 3); | 408 | if (params.start2 != 0) { |
| 405 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2); | 409 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), |
| 406 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), params.control2); | 410 | Memory::VirtualToPhysicalAddress(params.start2) >> 3); |
| 411 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), | ||
| 412 | Memory::VirtualToPhysicalAddress(params.end2) >> 3); | ||
| 413 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2); | ||
| 414 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), params.control2); | ||
| 415 | } | ||
| 407 | break; | 416 | break; |
| 408 | } | 417 | } |
| 409 | 418 | ||
| @@ -448,6 +457,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 448 | default: | 457 | default: |
| 449 | LOG_ERROR(Service_GSP, "unknown command 0x%08X", (int)command.id.Value()); | 458 | LOG_ERROR(Service_GSP, "unknown command 0x%08X", (int)command.id.Value()); |
| 450 | } | 459 | } |
| 460 | |||
| 461 | if (Pica::g_debug_context) | ||
| 462 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed, (void*)&command); | ||
| 451 | } | 463 | } |
| 452 | 464 | ||
| 453 | /** | 465 | /** |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 70caa7d80..c35b13b25 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; | |||
| 35 | static u32 next_pad_index; | 35 | static u32 next_pad_index; |
| 36 | static u32 next_touch_index; | 36 | static u32 next_touch_index; |
| 37 | 37 | ||
| 38 | const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = { | ||
| 39 | Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y, | ||
| 40 | Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR, | ||
| 41 | Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE, | ||
| 42 | Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT, | ||
| 43 | Service::HID::PAD_CIRCLE_UP, Service::HID::PAD_CIRCLE_DOWN, Service::HID::PAD_CIRCLE_LEFT, Service::HID::PAD_CIRCLE_RIGHT, | ||
| 44 | Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT | ||
| 45 | }; | ||
| 46 | |||
| 47 | |||
| 38 | // TODO(peachum): | 48 | // TODO(peachum): |
| 39 | // Add a method for setting analog input from joystick device for the circle Pad. | 49 | // Add a method for setting analog input from joystick device for the circle Pad. |
| 40 | // | 50 | // |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index d50d479f8..517f4f2ae 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #ifndef _MSC_VER | 9 | #ifndef _MSC_VER |
| 10 | #include <cstddef> | 10 | #include <cstddef> |
| 11 | #endif | 11 | #endif |
| 12 | 12 | #include "core/settings.h" | |
| 13 | #include "common/bit_field.h" | 13 | #include "common/bit_field.h" |
| 14 | #include "common/common_funcs.h" | 14 | #include "common/common_funcs.h" |
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| @@ -157,6 +157,9 @@ const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; | |||
| 157 | const PadState PAD_CIRCLE_UP = {{1u << 30}}; | 157 | const PadState PAD_CIRCLE_UP = {{1u << 30}}; |
| 158 | const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; | 158 | const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; |
| 159 | 159 | ||
| 160 | |||
| 161 | extern const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping; | ||
| 162 | |||
| 160 | /** | 163 | /** |
| 161 | * HID::GetIPCHandles service function | 164 | * HID::GetIPCHandles service function |
| 162 | * Inputs: | 165 | * Inputs: |
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index d0e166fdf..d768a3fc7 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) { | |||
| 481 | 481 | ||
| 482 | char name[128]; | 482 | char name[128]; |
| 483 | gethostname(name, sizeof(name)); | 483 | gethostname(name, sizeof(name)); |
| 484 | hostent* host = gethostbyname(name); | 484 | addrinfo hints = {}; |
| 485 | in_addr* addr = reinterpret_cast<in_addr*>(host->h_addr); | 485 | addrinfo* res; |
| 486 | |||
| 487 | hints.ai_family = AF_INET; | ||
| 488 | getaddrinfo(name, NULL, &hints, &res); | ||
| 489 | sockaddr_in* sock_addr = reinterpret_cast<sockaddr_in*>(res->ai_addr); | ||
| 490 | in_addr* addr = &sock_addr->sin_addr; | ||
| 486 | 491 | ||
| 487 | cmd_buffer[2] = addr->s_addr; | 492 | cmd_buffer[2] = addr->s_addr; |
| 488 | cmd_buffer[1] = 0; | 493 | cmd_buffer[1] = 0; |
| 494 | freeaddrinfo(res); | ||
| 489 | } | 495 | } |
| 490 | 496 | ||
| 491 | static void Close(Service::Interface* self) { | 497 | static void Close(Service::Interface* self) { |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index bdede964e..bb64fdfb7 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 | |||
| 334 | 334 | ||
| 335 | /// Get resource limit current values | 335 | /// Get resource limit current values |
| 336 | static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, | 336 | static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, |
| 337 | s32 name_count) { | 337 | u32 name_count) { |
| 338 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", | 338 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", |
| 339 | resource_limit_handle, names, name_count); | 339 | resource_limit_handle, names, name_count); |
| 340 | 340 | ||
| @@ -350,7 +350,7 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim | |||
| 350 | 350 | ||
| 351 | /// Get resource limit max values | 351 | /// Get resource limit max values |
| 352 | static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, | 352 | static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, |
| 353 | s32 name_count) { | 353 | u32 name_count) { |
| 354 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", | 354 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", |
| 355 | resource_limit_handle, names, name_count); | 355 | resource_limit_handle, names, name_count); |
| 356 | 356 | ||
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 2a338e8fc..3ccbc03b2 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) { | |||
| 151 | { | 151 | { |
| 152 | const auto& config = g_regs.display_transfer_config; | 152 | const auto& config = g_regs.display_transfer_config; |
| 153 | if (config.trigger & 1) { | 153 | if (config.trigger & 1) { |
| 154 | |||
| 155 | if (Pica::g_debug_context) | ||
| 156 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer, nullptr); | ||
| 157 | |||
| 154 | u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); | 158 | u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); |
| 155 | u8* dst_pointer = Memory::GetPhysicalPointer(config.GetPhysicalOutputAddress()); | 159 | u8* dst_pointer = Memory::GetPhysicalPointer(config.GetPhysicalOutputAddress()); |
| 156 | 160 | ||
diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp index f80e26ecd..082a4db82 100644 --- a/src/core/hw/y2r.cpp +++ b/src/core/hw/y2r.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/vector_math.h" | 14 | #include "common/vector_math.h" |
| 15 | 15 | ||
| 16 | #include "core/hle/service/y2r_u.h" | 16 | #include "core/hle/service/y2r_u.h" |
| 17 | #include "core/hw/y2r.h" | ||
| 17 | #include "core/memory.h" | 18 | #include "core/memory.h" |
| 18 | 19 | ||
| 19 | namespace HW { | 20 | namespace HW { |
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index d043fa9bd..530837d08 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 | |||
| 191 | *pos = (addr); | 191 | *pos = (addr); |
| 192 | break; | 192 | break; |
| 193 | case 1: | 193 | case 1: |
| 194 | *pos = (addr - in_addr); | 194 | *pos = static_cast<u32>(addr - in_addr); |
| 195 | break; | 195 | break; |
| 196 | default: | 196 | default: |
| 197 | break; //this should never happen | 197 | break; //this should never happen |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 9ef2f8900..f5b349a77 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -56,18 +56,18 @@ static FileType IdentifyFile(FileUtil::IOFile& file) { | |||
| 56 | static FileType GuessFromExtension(const std::string& extension_) { | 56 | static FileType GuessFromExtension(const std::string& extension_) { |
| 57 | std::string extension = Common::ToLower(extension_); | 57 | std::string extension = Common::ToLower(extension_); |
| 58 | 58 | ||
| 59 | if (extension == ".elf") | 59 | if (extension == ".elf" || extension == ".axf") |
| 60 | return FileType::ELF; | 60 | return FileType::ELF; |
| 61 | else if (extension == ".axf") | 61 | |
| 62 | return FileType::ELF; | 62 | if (extension == ".cci" || extension == ".3ds") |
| 63 | else if (extension == ".cxi") | ||
| 64 | return FileType::CXI; | ||
| 65 | else if (extension == ".cci") | ||
| 66 | return FileType::CCI; | ||
| 67 | else if (extension == ".3ds") | ||
| 68 | return FileType::CCI; | 63 | return FileType::CCI; |
| 69 | else if (extension == ".3dsx") | 64 | |
| 65 | if (extension == ".cxi") | ||
| 66 | return FileType::CXI; | ||
| 67 | |||
| 68 | if (extension == ".3dsx") | ||
| 70 | return FileType::THREEDSX; | 69 | return FileType::THREEDSX; |
| 70 | |||
| 71 | return FileType::Unknown; | 71 | return FileType::Unknown; |
| 72 | } | 72 | } |
| 73 | 73 | ||
diff --git a/src/core/settings.h b/src/core/settings.h index 5a70d157a..2775ee257 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -5,34 +5,42 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <array> | ||
| 8 | 9 | ||
| 9 | namespace Settings { | 10 | namespace Settings { |
| 10 | 11 | ||
| 12 | namespace NativeInput { | ||
| 13 | enum Values { | ||
| 14 | A, B, X, Y, | ||
| 15 | L, R, ZL, ZR, | ||
| 16 | START, SELECT, HOME, | ||
| 17 | DUP, DDOWN, DLEFT, DRIGHT, | ||
| 18 | SUP, SDOWN, SLEFT, SRIGHT, | ||
| 19 | CUP, CDOWN, CLEFT, CRIGHT, | ||
| 20 | NUM_INPUTS | ||
| 21 | }; | ||
| 22 | static const std::array<const char*, NUM_INPUTS> Mapping = { | ||
| 23 | "pad_a", "pad_b", "pad_x", "pad_y", | ||
| 24 | "pad_l", "pad_r", "pad_zl", "pad_zr", | ||
| 25 | "pad_start", "pad_select", "pad_home", | ||
| 26 | "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", | ||
| 27 | "pad_sup", "pad_sdown", "pad_sleft", "pad_sright", | ||
| 28 | "pad_cup", "pad_cdown", "pad_cleft", "pad_cright" | ||
| 29 | }; | ||
| 30 | static const std::array<Values, NUM_INPUTS> All = { | ||
| 31 | A, B, X, Y, | ||
| 32 | L, R, ZL, ZR, | ||
| 33 | START, SELECT, HOME, | ||
| 34 | DUP, DDOWN, DLEFT, DRIGHT, | ||
| 35 | SUP, SDOWN, SLEFT, SRIGHT, | ||
| 36 | CUP, CDOWN, CLEFT, CRIGHT | ||
| 37 | }; | ||
| 38 | } | ||
| 39 | |||
| 40 | |||
| 11 | struct Values { | 41 | struct Values { |
| 12 | // Controls | 42 | // Controls |
| 13 | int pad_a_key; | 43 | std::array<int, NativeInput::NUM_INPUTS> input_mappings; |
| 14 | int pad_b_key; | ||
| 15 | int pad_x_key; | ||
| 16 | int pad_y_key; | ||
| 17 | int pad_l_key; | ||
| 18 | int pad_r_key; | ||
| 19 | int pad_zl_key; | ||
| 20 | int pad_zr_key; | ||
| 21 | int pad_start_key; | ||
| 22 | int pad_select_key; | ||
| 23 | int pad_home_key; | ||
| 24 | int pad_dup_key; | ||
| 25 | int pad_ddown_key; | ||
| 26 | int pad_dleft_key; | ||
| 27 | int pad_dright_key; | ||
| 28 | int pad_sup_key; | ||
| 29 | int pad_sdown_key; | ||
| 30 | int pad_sleft_key; | ||
| 31 | int pad_sright_key; | ||
| 32 | int pad_cup_key; | ||
| 33 | int pad_cdown_key; | ||
| 34 | int pad_cleft_key; | ||
| 35 | int pad_cright_key; | ||
| 36 | 44 | ||
| 37 | // Core | 45 | // Core |
| 38 | int frame_skip; | 46 | int frame_skip; |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 5c7f4ae18..162108301 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -2,7 +2,6 @@ set(SRCS | |||
| 2 | renderer_opengl/generated/gl_3_2_core.c | 2 | renderer_opengl/generated/gl_3_2_core.c |
| 3 | renderer_opengl/gl_rasterizer.cpp | 3 | renderer_opengl/gl_rasterizer.cpp |
| 4 | renderer_opengl/gl_rasterizer_cache.cpp | 4 | renderer_opengl/gl_rasterizer_cache.cpp |
| 5 | renderer_opengl/gl_resource_manager.cpp | ||
| 6 | renderer_opengl/gl_shader_util.cpp | 5 | renderer_opengl/gl_shader_util.cpp |
| 7 | renderer_opengl/gl_state.cpp | 6 | renderer_opengl/gl_state.cpp |
| 8 | renderer_opengl/renderer_opengl.cpp | 7 | renderer_opengl/renderer_opengl.cpp |
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index bbe7e63dc..36c3b9947 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) { | |||
| 50 | regs[id] = (old_value & ~mask) | (value & mask); | 50 | regs[id] = (old_value & ~mask) | (value & mask); |
| 51 | 51 | ||
| 52 | if (g_debug_context) | 52 | if (g_debug_context) |
| 53 | g_debug_context->OnEvent(DebugContext::Event::CommandLoaded, reinterpret_cast<void*>(&id)); | 53 | g_debug_context->OnEvent(DebugContext::Event::PicaCommandLoaded, reinterpret_cast<void*>(&id)); |
| 54 | 54 | ||
| 55 | DebugUtils::OnPicaRegWrite(id, regs[id]); | 55 | DebugUtils::OnPicaRegWrite(id, regs[id]); |
| 56 | 56 | ||
| @@ -103,7 +103,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 103 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c): | 103 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c): |
| 104 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d): | 104 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d): |
| 105 | { | 105 | { |
| 106 | unsigned index = id - PICA_REG_INDEX(command_buffer.trigger[0]); | 106 | unsigned index = static_cast<unsigned>(id - PICA_REG_INDEX(command_buffer.trigger[0])); |
| 107 | u32* head_ptr = (u32*)Memory::GetPhysicalPointer(regs.command_buffer.GetPhysicalAddress(index)); | 107 | u32* head_ptr = (u32*)Memory::GetPhysicalPointer(regs.command_buffer.GetPhysicalAddress(index)); |
| 108 | g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; | 108 | g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; |
| 109 | g_state.cmd_list.length = regs.command_buffer.GetSize(index) / sizeof(u32); | 109 | 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) { | |||
| 116 | { | 116 | { |
| 117 | Common::Profiling::ScopeTimer scope_timer(category_drawing); | 117 | Common::Profiling::ScopeTimer scope_timer(category_drawing); |
| 118 | 118 | ||
| 119 | #if PICA_LOG_TEV | ||
| 119 | DebugUtils::DumpTevStageConfig(regs.GetTevStages()); | 120 | DebugUtils::DumpTevStageConfig(regs.GetTevStages()); |
| 121 | #endif | ||
| 120 | 122 | ||
| 121 | if (g_debug_context) | 123 | if (g_debug_context) |
| 122 | g_debug_context->OnEvent(DebugContext::Event::IncomingPrimitiveBatch, nullptr); | 124 | g_debug_context->OnEvent(DebugContext::Event::IncomingPrimitiveBatch, nullptr); |
| @@ -159,9 +161,11 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 159 | const u16* index_address_16 = (u16*)index_address_8; | 161 | const u16* index_address_16 = (u16*)index_address_8; |
| 160 | bool index_u16 = index_info.format != 0; | 162 | bool index_u16 = index_info.format != 0; |
| 161 | 163 | ||
| 164 | #if PICA_DUMP_GEOMETRY | ||
| 162 | DebugUtils::GeometryDumper geometry_dumper; | 165 | DebugUtils::GeometryDumper geometry_dumper; |
| 163 | PrimitiveAssembler<VertexShader::OutputVertex> primitive_assembler(regs.triangle_topology.Value()); | ||
| 164 | PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value()); | 166 | PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value()); |
| 167 | #endif | ||
| 168 | PrimitiveAssembler<VertexShader::OutputVertex> primitive_assembler(regs.triangle_topology.Value()); | ||
| 165 | 169 | ||
| 166 | if (g_debug_context) { | 170 | if (g_debug_context) { |
| 167 | for (int i = 0; i < 3; ++i) { | 171 | for (int i = 0; i < 3; ++i) { |
| @@ -267,6 +271,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 267 | if (g_debug_context) | 271 | if (g_debug_context) |
| 268 | g_debug_context->OnEvent(DebugContext::Event::VertexLoaded, (void*)&input); | 272 | g_debug_context->OnEvent(DebugContext::Event::VertexLoaded, (void*)&input); |
| 269 | 273 | ||
| 274 | #if PICA_DUMP_GEOMETRY | ||
| 270 | // NOTE: When dumping geometry, we simply assume that the first input attribute | 275 | // NOTE: When dumping geometry, we simply assume that the first input attribute |
| 271 | // corresponds to the position for now. | 276 | // corresponds to the position for now. |
| 272 | DebugUtils::GeometryDumper::Vertex dumped_vertex = { | 277 | DebugUtils::GeometryDumper::Vertex dumped_vertex = { |
| @@ -276,6 +281,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 276 | dumping_primitive_assembler.SubmitVertex(dumped_vertex, | 281 | dumping_primitive_assembler.SubmitVertex(dumped_vertex, |
| 277 | std::bind(&DebugUtils::GeometryDumper::AddTriangle, | 282 | std::bind(&DebugUtils::GeometryDumper::AddTriangle, |
| 278 | &geometry_dumper, _1, _2, _3)); | 283 | &geometry_dumper, _1, _2, _3)); |
| 284 | #endif | ||
| 279 | 285 | ||
| 280 | // Send to vertex shader | 286 | // Send to vertex shader |
| 281 | VertexShader::OutputVertex output = VertexShader::RunShader(input, attribute_config.GetNumTotalAttributes(), g_state.regs.vs, g_state.vs); | 287 | 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) { | |||
| 308 | VideoCore::g_renderer->hw_rasterizer->DrawTriangles(); | 314 | VideoCore::g_renderer->hw_rasterizer->DrawTriangles(); |
| 309 | } | 315 | } |
| 310 | 316 | ||
| 317 | #if PICA_DUMP_GEOMETRY | ||
| 311 | geometry_dumper.Dump(); | 318 | geometry_dumper.Dump(); |
| 319 | #endif | ||
| 312 | 320 | ||
| 313 | if (g_debug_context) { | 321 | if (g_debug_context) { |
| 314 | g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr); | 322 | g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr); |
| @@ -424,7 +432,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 424 | VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id); | 432 | VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id); |
| 425 | 433 | ||
| 426 | if (g_debug_context) | 434 | if (g_debug_context) |
| 427 | g_debug_context->OnEvent(DebugContext::Event::CommandProcessed, reinterpret_cast<void*>(&id)); | 435 | g_debug_context->OnEvent(DebugContext::Event::PicaCommandProcessed, reinterpret_cast<void*>(&id)); |
| 428 | } | 436 | } |
| 429 | 437 | ||
| 430 | void ProcessCommandList(const u32* list, u32 size) { | 438 | 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 d24c0f11e..e9a858411 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) { | |||
| 85 | vertices.push_back(v1); | 85 | vertices.push_back(v1); |
| 86 | vertices.push_back(v2); | 86 | vertices.push_back(v2); |
| 87 | 87 | ||
| 88 | int num_vertices = vertices.size(); | 88 | int num_vertices = (int)vertices.size(); |
| 89 | faces.push_back({ num_vertices-3, num_vertices-2, num_vertices-1 }); | 89 | faces.push_back({ num_vertices-3, num_vertices-2, num_vertices-1 }); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | void GeometryDumper::Dump() { | 92 | void GeometryDumper::Dump() { |
| 93 | // NOTE: Permanently enabling this just trashes the hard disk for no reason. | ||
| 94 | // Hence, this is currently disabled. | ||
| 95 | return; | ||
| 96 | |||
| 97 | static int index = 0; | 93 | static int index = 0; |
| 98 | std::string filename = std::string("geometry_dump") + std::to_string(++index) + ".obj"; | 94 | std::string filename = std::string("geometry_dump") + std::to_string(++index) + ".obj"; |
| 99 | 95 | ||
| @@ -116,10 +112,6 @@ void GeometryDumper::Dump() { | |||
| 116 | void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, | 112 | void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, |
| 117 | u32 main_offset, const Regs::VSOutputAttributes* output_attributes) | 113 | u32 main_offset, const Regs::VSOutputAttributes* output_attributes) |
| 118 | { | 114 | { |
| 119 | // NOTE: Permanently enabling this just trashes hard disks for no reason. | ||
| 120 | // Hence, this is currently disabled. | ||
| 121 | return; | ||
| 122 | |||
| 123 | struct StuffToWrite { | 115 | struct StuffToWrite { |
| 124 | u8* pointer; | 116 | u8* pointer; |
| 125 | u32 size; | 117 | u32 size; |
| @@ -241,8 +233,8 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data | |||
| 241 | 233 | ||
| 242 | dvle.main_offset_words = main_offset; | 234 | dvle.main_offset_words = main_offset; |
| 243 | dvle.output_register_table_offset = write_offset - dvlb.dvle_offset; | 235 | dvle.output_register_table_offset = write_offset - dvlb.dvle_offset; |
| 244 | dvle.output_register_table_size = output_info_table.size(); | 236 | dvle.output_register_table_size = static_cast<uint32_t>(output_info_table.size()); |
| 245 | QueueForWriting((u8*)output_info_table.data(), output_info_table.size() * sizeof(OutputRegisterInfo)); | 237 | QueueForWriting((u8*)output_info_table.data(), static_cast<u32>(output_info_table.size() * sizeof(OutputRegisterInfo))); |
| 246 | 238 | ||
| 247 | // TODO: Create a label table for "main" | 239 | // TODO: Create a label table for "main" |
| 248 | 240 | ||
| @@ -497,31 +489,31 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture | |||
| 497 | // Lookup base value | 489 | // Lookup base value |
| 498 | Math::Vec3<int> ret; | 490 | Math::Vec3<int> ret; |
| 499 | if (differential_mode) { | 491 | if (differential_mode) { |
| 500 | ret.r() = differential.r; | 492 | ret.r() = static_cast<int>(differential.r); |
| 501 | ret.g() = differential.g; | 493 | ret.g() = static_cast<int>(differential.g); |
| 502 | ret.b() = differential.b; | 494 | ret.b() = static_cast<int>(differential.b); |
| 503 | if (x >= 2) { | 495 | if (x >= 2) { |
| 504 | ret.r() += differential.dr; | 496 | ret.r() += static_cast<int>(differential.dr); |
| 505 | ret.g() += differential.dg; | 497 | ret.g() += static_cast<int>(differential.dg); |
| 506 | ret.b() += differential.db; | 498 | ret.b() += static_cast<int>(differential.db); |
| 507 | } | 499 | } |
| 508 | ret.r() = Color::Convert5To8(ret.r()); | 500 | ret.r() = Color::Convert5To8(ret.r()); |
| 509 | ret.g() = Color::Convert5To8(ret.g()); | 501 | ret.g() = Color::Convert5To8(ret.g()); |
| 510 | ret.b() = Color::Convert5To8(ret.b()); | 502 | ret.b() = Color::Convert5To8(ret.b()); |
| 511 | } else { | 503 | } else { |
| 512 | if (x < 2) { | 504 | if (x < 2) { |
| 513 | ret.r() = Color::Convert4To8(separate.r1); | 505 | ret.r() = Color::Convert4To8(static_cast<u8>(separate.r1)); |
| 514 | ret.g() = Color::Convert4To8(separate.g1); | 506 | ret.g() = Color::Convert4To8(static_cast<u8>(separate.g1)); |
| 515 | ret.b() = Color::Convert4To8(separate.b1); | 507 | ret.b() = Color::Convert4To8(static_cast<u8>(separate.b1)); |
| 516 | } else { | 508 | } else { |
| 517 | ret.r() = Color::Convert4To8(separate.r2); | 509 | ret.r() = Color::Convert4To8(static_cast<u8>(separate.r2)); |
| 518 | ret.g() = Color::Convert4To8(separate.g2); | 510 | ret.g() = Color::Convert4To8(static_cast<u8>(separate.g2)); |
| 519 | ret.b() = Color::Convert4To8(separate.b2); | 511 | ret.b() = Color::Convert4To8(static_cast<u8>(separate.b2)); |
| 520 | } | 512 | } |
| 521 | } | 513 | } |
| 522 | 514 | ||
| 523 | // Add modifier | 515 | // Add modifier |
| 524 | unsigned table_index = (x < 2) ? table_index_1.Value() : table_index_2.Value(); | 516 | unsigned table_index = static_cast<int>((x < 2) ? table_index_1.Value() : table_index_2.Value()); |
| 525 | 517 | ||
| 526 | static const std::array<std::array<u8, 2>, 8> etc1_modifier_table = {{ | 518 | static const std::array<std::array<u8, 2>, 8> etc1_modifier_table = {{ |
| 527 | { 2, 8 }, { 5, 17 }, { 9, 29 }, { 13, 42 }, | 519 | { 2, 8 }, { 5, 17 }, { 9, 29 }, { 13, 42 }, |
| @@ -565,10 +557,6 @@ TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config, | |||
| 565 | } | 557 | } |
| 566 | 558 | ||
| 567 | void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { | 559 | void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { |
| 568 | // NOTE: Permanently enabling this just trashes hard disks for no reason. | ||
| 569 | // Hence, this is currently disabled. | ||
| 570 | return; | ||
| 571 | |||
| 572 | #ifndef HAVE_PNG | 560 | #ifndef HAVE_PNG |
| 573 | return; | 561 | return; |
| 574 | #else | 562 | #else |
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h index 2573292e2..81eea30a9 100644 --- a/src/video_core/debug_utils/debug_utils.h +++ b/src/video_core/debug_utils/debug_utils.h | |||
| @@ -25,11 +25,14 @@ public: | |||
| 25 | enum class Event { | 25 | enum class Event { |
| 26 | FirstEvent = 0, | 26 | FirstEvent = 0, |
| 27 | 27 | ||
| 28 | CommandLoaded = FirstEvent, | 28 | PicaCommandLoaded = FirstEvent, |
| 29 | CommandProcessed, | 29 | PicaCommandProcessed, |
| 30 | IncomingPrimitiveBatch, | 30 | IncomingPrimitiveBatch, |
| 31 | FinishedPrimitiveBatch, | 31 | FinishedPrimitiveBatch, |
| 32 | VertexLoaded, | 32 | VertexLoaded, |
| 33 | IncomingDisplayTransfer, | ||
| 34 | GSPCommandProcessed, | ||
| 35 | BufferSwapped, | ||
| 33 | 36 | ||
| 34 | NumEvents | 37 | NumEvents |
| 35 | }; | 38 | }; |
| @@ -154,6 +157,11 @@ extern std::shared_ptr<DebugContext> g_debug_context; // TODO: Get rid of this g | |||
| 154 | 157 | ||
| 155 | namespace DebugUtils { | 158 | namespace DebugUtils { |
| 156 | 159 | ||
| 160 | #define PICA_DUMP_GEOMETRY 0 | ||
| 161 | #define PICA_DUMP_SHADERS 0 | ||
| 162 | #define PICA_DUMP_TEXTURES 0 | ||
| 163 | #define PICA_LOG_TEV 0 | ||
| 164 | |||
| 157 | // Simple utility class for dumping geometry data to an OBJ file | 165 | // Simple utility class for dumping geometry data to an OBJ file |
| 158 | class GeometryDumper { | 166 | class GeometryDumper { |
| 159 | public: | 167 | public: |
diff --git a/src/video_core/pica.cpp b/src/video_core/pica.cpp index 543d9c443..17cb66780 100644 --- a/src/video_core/pica.cpp +++ b/src/video_core/pica.cpp | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <string.h> | 5 | #include <cstring> |
| 6 | #include <unordered_map> | ||
| 6 | 7 | ||
| 7 | #include "pica.h" | 8 | #include "pica.h" |
| 8 | 9 | ||
| @@ -10,6 +11,75 @@ namespace Pica { | |||
| 10 | 11 | ||
| 11 | State g_state; | 12 | State g_state; |
| 12 | 13 | ||
| 14 | std::string Regs::GetCommandName(int index) { | ||
| 15 | static std::unordered_map<u32, std::string> map; | ||
| 16 | |||
| 17 | if (map.empty()) { | ||
| 18 | #define ADD_FIELD(name) \ | ||
| 19 | map.insert({static_cast<u32>(PICA_REG_INDEX(name)), #name}); \ | ||
| 20 | /* TODO: change to Regs::name when VS2015 and other compilers support it */ \ | ||
| 21 | for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \ | ||
| 22 | map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ | ||
| 23 | |||
| 24 | ADD_FIELD(trigger_irq); | ||
| 25 | ADD_FIELD(cull_mode); | ||
| 26 | ADD_FIELD(viewport_size_x); | ||
| 27 | ADD_FIELD(viewport_size_y); | ||
| 28 | ADD_FIELD(viewport_depth_range); | ||
| 29 | ADD_FIELD(viewport_depth_far_plane); | ||
| 30 | ADD_FIELD(viewport_corner); | ||
| 31 | ADD_FIELD(texture0_enable); | ||
| 32 | ADD_FIELD(texture0); | ||
| 33 | ADD_FIELD(texture0_format); | ||
| 34 | ADD_FIELD(texture1); | ||
| 35 | ADD_FIELD(texture1_format); | ||
| 36 | ADD_FIELD(texture2); | ||
| 37 | ADD_FIELD(texture2_format); | ||
| 38 | ADD_FIELD(tev_stage0); | ||
| 39 | ADD_FIELD(tev_stage1); | ||
| 40 | ADD_FIELD(tev_stage2); | ||
| 41 | ADD_FIELD(tev_stage3); | ||
| 42 | ADD_FIELD(tev_combiner_buffer_input); | ||
| 43 | ADD_FIELD(tev_stage4); | ||
| 44 | ADD_FIELD(tev_stage5); | ||
| 45 | ADD_FIELD(tev_combiner_buffer_color); | ||
| 46 | ADD_FIELD(output_merger); | ||
| 47 | ADD_FIELD(framebuffer); | ||
| 48 | ADD_FIELD(vertex_attributes); | ||
| 49 | ADD_FIELD(index_array); | ||
| 50 | ADD_FIELD(num_vertices); | ||
| 51 | ADD_FIELD(trigger_draw); | ||
| 52 | ADD_FIELD(trigger_draw_indexed); | ||
| 53 | ADD_FIELD(vs_default_attributes_setup); | ||
| 54 | ADD_FIELD(command_buffer); | ||
| 55 | ADD_FIELD(triangle_topology); | ||
| 56 | ADD_FIELD(gs.bool_uniforms); | ||
| 57 | ADD_FIELD(gs.int_uniforms); | ||
| 58 | ADD_FIELD(gs.main_offset); | ||
| 59 | ADD_FIELD(gs.input_register_map); | ||
| 60 | ADD_FIELD(gs.uniform_setup); | ||
| 61 | ADD_FIELD(gs.program); | ||
| 62 | ADD_FIELD(gs.swizzle_patterns); | ||
| 63 | ADD_FIELD(vs.bool_uniforms); | ||
| 64 | ADD_FIELD(vs.int_uniforms); | ||
| 65 | ADD_FIELD(vs.main_offset); | ||
| 66 | ADD_FIELD(vs.input_register_map); | ||
| 67 | ADD_FIELD(vs.uniform_setup); | ||
| 68 | ADD_FIELD(vs.program); | ||
| 69 | ADD_FIELD(vs.swizzle_patterns); | ||
| 70 | |||
| 71 | #undef ADD_FIELD | ||
| 72 | } | ||
| 73 | |||
| 74 | // Return empty string if no match is found | ||
| 75 | auto it = map.find(index); | ||
| 76 | if (it != map.end()) { | ||
| 77 | return it->second; | ||
| 78 | } else { | ||
| 79 | return std::string(); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 13 | void Init() { | 83 | void Init() { |
| 14 | } | 84 | } |
| 15 | 85 | ||
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index aec6f0660..34b02b2f8 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cmath> | 8 | #include <cmath> |
| 9 | #include <cstddef> | 9 | #include <cstddef> |
| 10 | #include <map> | ||
| 11 | #include <string> | 10 | #include <string> |
| 12 | 11 | ||
| 13 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| @@ -908,69 +907,7 @@ struct Regs { | |||
| 908 | 907 | ||
| 909 | // Map register indices to names readable by humans | 908 | // Map register indices to names readable by humans |
| 910 | // Used for debugging purposes, so performance is not an issue here | 909 | // Used for debugging purposes, so performance is not an issue here |
| 911 | static std::string GetCommandName(int index) { | 910 | static std::string GetCommandName(int index); |
| 912 | std::map<u32, std::string> map; | ||
| 913 | |||
| 914 | #define ADD_FIELD(name) \ | ||
| 915 | do { \ | ||
| 916 | map.insert({PICA_REG_INDEX(name), #name}); \ | ||
| 917 | /* TODO: change to Regs::name when VS2015 and other compilers support it */ \ | ||
| 918 | for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \ | ||
| 919 | map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ | ||
| 920 | } while(false) | ||
| 921 | |||
| 922 | ADD_FIELD(trigger_irq); | ||
| 923 | ADD_FIELD(cull_mode); | ||
| 924 | ADD_FIELD(viewport_size_x); | ||
| 925 | ADD_FIELD(viewport_size_y); | ||
| 926 | ADD_FIELD(viewport_depth_range); | ||
| 927 | ADD_FIELD(viewport_depth_far_plane); | ||
| 928 | ADD_FIELD(viewport_corner); | ||
| 929 | ADD_FIELD(texture0_enable); | ||
| 930 | ADD_FIELD(texture0); | ||
| 931 | ADD_FIELD(texture0_format); | ||
| 932 | ADD_FIELD(texture1); | ||
| 933 | ADD_FIELD(texture1_format); | ||
| 934 | ADD_FIELD(texture2); | ||
| 935 | ADD_FIELD(texture2_format); | ||
| 936 | ADD_FIELD(tev_stage0); | ||
| 937 | ADD_FIELD(tev_stage1); | ||
| 938 | ADD_FIELD(tev_stage2); | ||
| 939 | ADD_FIELD(tev_stage3); | ||
| 940 | ADD_FIELD(tev_combiner_buffer_input); | ||
| 941 | ADD_FIELD(tev_stage4); | ||
| 942 | ADD_FIELD(tev_stage5); | ||
| 943 | ADD_FIELD(tev_combiner_buffer_color); | ||
| 944 | ADD_FIELD(output_merger); | ||
| 945 | ADD_FIELD(framebuffer); | ||
| 946 | ADD_FIELD(vertex_attributes); | ||
| 947 | ADD_FIELD(index_array); | ||
| 948 | ADD_FIELD(num_vertices); | ||
| 949 | ADD_FIELD(trigger_draw); | ||
| 950 | ADD_FIELD(trigger_draw_indexed); | ||
| 951 | ADD_FIELD(vs_default_attributes_setup); | ||
| 952 | ADD_FIELD(command_buffer); | ||
| 953 | ADD_FIELD(triangle_topology); | ||
| 954 | ADD_FIELD(gs.bool_uniforms); | ||
| 955 | ADD_FIELD(gs.int_uniforms); | ||
| 956 | ADD_FIELD(gs.main_offset); | ||
| 957 | ADD_FIELD(gs.input_register_map); | ||
| 958 | ADD_FIELD(gs.uniform_setup); | ||
| 959 | ADD_FIELD(gs.program); | ||
| 960 | ADD_FIELD(gs.swizzle_patterns); | ||
| 961 | ADD_FIELD(vs.bool_uniforms); | ||
| 962 | ADD_FIELD(vs.int_uniforms); | ||
| 963 | ADD_FIELD(vs.main_offset); | ||
| 964 | ADD_FIELD(vs.input_register_map); | ||
| 965 | ADD_FIELD(vs.uniform_setup); | ||
| 966 | ADD_FIELD(vs.program); | ||
| 967 | ADD_FIELD(vs.swizzle_patterns); | ||
| 968 | |||
| 969 | #undef ADD_FIELD | ||
| 970 | |||
| 971 | // Return empty string if no match is found | ||
| 972 | return map[index]; | ||
| 973 | } | ||
| 974 | 911 | ||
| 975 | static inline size_t NumIds() { | 912 | static inline size_t NumIds() { |
| 976 | return sizeof(Regs) / sizeof(u32); | 913 | return sizeof(Regs) / sizeof(u32); |
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index e2b90ad1c..68b7cc05d 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp | |||
| @@ -462,7 +462,9 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, | |||
| 462 | 462 | ||
| 463 | // TODO: Apply the min and mag filters to the texture | 463 | // TODO: Apply the min and mag filters to the texture |
| 464 | texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info); | 464 | texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info); |
| 465 | #if PICA_DUMP_TEXTURES | ||
| 465 | DebugUtils::DumpTexture(texture.config, texture_data); | 466 | DebugUtils::DumpTexture(texture.config, texture_data); |
| 467 | #endif | ||
| 466 | } | 468 | } |
| 467 | } | 469 | } |
| 468 | 470 | ||
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 8f4ae28a4..000000000 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ /dev/null | |||
| @@ -1,111 +0,0 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 6 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 7 | |||
| 8 | // Textures | ||
| 9 | OGLTexture::OGLTexture() : handle(0) { | ||
| 10 | } | ||
| 11 | |||
| 12 | OGLTexture::~OGLTexture() { | ||
| 13 | Release(); | ||
| 14 | } | ||
| 15 | |||
| 16 | void OGLTexture::Create() { | ||
| 17 | if (handle != 0) { | ||
| 18 | return; | ||
| 19 | } | ||
| 20 | |||
| 21 | glGenTextures(1, &handle); | ||
| 22 | } | ||
| 23 | |||
| 24 | void OGLTexture::Release() { | ||
| 25 | glDeleteTextures(1, &handle); | ||
| 26 | handle = 0; | ||
| 27 | } | ||
| 28 | |||
| 29 | // Shaders | ||
| 30 | OGLShader::OGLShader() : handle(0) { | ||
| 31 | } | ||
| 32 | |||
| 33 | OGLShader::~OGLShader() { | ||
| 34 | Release(); | ||
| 35 | } | ||
| 36 | |||
| 37 | void OGLShader::Create(const char* vert_shader, const char* frag_shader) { | ||
| 38 | if (handle != 0) { | ||
| 39 | return; | ||
| 40 | } | ||
| 41 | |||
| 42 | handle = ShaderUtil::LoadShaders(vert_shader, frag_shader); | ||
| 43 | } | ||
| 44 | |||
| 45 | void OGLShader::Release() { | ||
| 46 | glDeleteProgram(handle); | ||
| 47 | handle = 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | // Buffer objects | ||
| 51 | OGLBuffer::OGLBuffer() : handle(0) { | ||
| 52 | } | ||
| 53 | |||
| 54 | OGLBuffer::~OGLBuffer() { | ||
| 55 | Release(); | ||
| 56 | } | ||
| 57 | |||
| 58 | void OGLBuffer::Create() { | ||
| 59 | if (handle != 0) { | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | |||
| 63 | glGenBuffers(1, &handle); | ||
| 64 | } | ||
| 65 | |||
| 66 | void OGLBuffer::Release() { | ||
| 67 | glDeleteBuffers(1, &handle); | ||
| 68 | handle = 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | // Vertex array objects | ||
| 72 | OGLVertexArray::OGLVertexArray() : handle(0) { | ||
| 73 | } | ||
| 74 | |||
| 75 | OGLVertexArray::~OGLVertexArray() { | ||
| 76 | Release(); | ||
| 77 | } | ||
| 78 | |||
| 79 | void OGLVertexArray::Create() { | ||
| 80 | if (handle != 0) { | ||
| 81 | return; | ||
| 82 | } | ||
| 83 | |||
| 84 | glGenVertexArrays(1, &handle); | ||
| 85 | } | ||
| 86 | |||
| 87 | void OGLVertexArray::Release() { | ||
| 88 | glDeleteVertexArrays(1, &handle); | ||
| 89 | handle = 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | // Framebuffers | ||
| 93 | OGLFramebuffer::OGLFramebuffer() : handle(0) { | ||
| 94 | } | ||
| 95 | |||
| 96 | OGLFramebuffer::~OGLFramebuffer() { | ||
| 97 | Release(); | ||
| 98 | } | ||
| 99 | |||
| 100 | void OGLFramebuffer::Create() { | ||
| 101 | if (handle != 0) { | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | glGenFramebuffers(1, &handle); | ||
| 106 | } | ||
| 107 | |||
| 108 | void OGLFramebuffer::Release() { | ||
| 109 | glDeleteFramebuffers(1, &handle); | ||
| 110 | handle = 0; | ||
| 111 | } | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 975720d0a..6f9dc012d 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 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <utility> | ||
| 8 | |||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 8 | 10 | ||
| 9 | #include "generated/gl_3_2_core.h" | 11 | #include "video_core/renderer_opengl/generated/gl_3_2_core.h" |
| 12 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 10 | 13 | ||
| 11 | class OGLTexture : public NonCopyable { | 14 | class OGLTexture : private NonCopyable { |
| 12 | public: | 15 | public: |
| 13 | OGLTexture(); | 16 | OGLTexture() = default; |
| 14 | ~OGLTexture(); | 17 | OGLTexture(OGLTexture&& o) { std::swap(handle, o.handle); } |
| 18 | ~OGLTexture() { Release(); } | ||
| 19 | OGLTexture& operator=(OGLTexture&& o) { std::swap(handle, o.handle); return *this; } | ||
| 15 | 20 | ||
| 16 | /// Creates a new internal OpenGL resource and stores the handle | 21 | /// Creates a new internal OpenGL resource and stores the handle |
| 17 | void Create(); | 22 | void Create() { |
| 23 | if (handle != 0) return; | ||
| 24 | glGenTextures(1, &handle); | ||
| 25 | } | ||
| 18 | 26 | ||
| 19 | /// Deletes the internal OpenGL resource | 27 | /// Deletes the internal OpenGL resource |
| 20 | void Release(); | 28 | void Release() { |
| 29 | if (handle == 0) return; | ||
| 30 | glDeleteTextures(1, &handle); | ||
| 31 | handle = 0; | ||
| 32 | } | ||
| 21 | 33 | ||
| 22 | GLuint handle; | 34 | GLuint handle = 0; |
| 23 | }; | 35 | }; |
| 24 | 36 | ||
| 25 | class OGLShader : public NonCopyable { | 37 | class OGLShader : private NonCopyable { |
| 26 | public: | 38 | public: |
| 27 | OGLShader(); | 39 | OGLShader() = default; |
| 28 | ~OGLShader(); | 40 | OGLShader(OGLShader&& o) { std::swap(handle, o.handle); } |
| 41 | ~OGLShader() { Release(); } | ||
| 42 | OGLShader& operator=(OGLShader&& o) { std::swap(handle, o.handle); return *this; } | ||
| 29 | 43 | ||
| 30 | /// Creates a new internal OpenGL resource and stores the handle | 44 | /// Creates a new internal OpenGL resource and stores the handle |
| 31 | void Create(const char* vert_shader, const char* frag_shader); | 45 | void Create(const char* vert_shader, const char* frag_shader) { |
| 46 | if (handle != 0) return; | ||
| 47 | handle = ShaderUtil::LoadShaders(vert_shader, frag_shader); | ||
| 48 | } | ||
| 32 | 49 | ||
| 33 | /// Deletes the internal OpenGL resource | 50 | /// Deletes the internal OpenGL resource |
| 34 | void Release(); | 51 | void Release() { |
| 52 | if (handle == 0) return; | ||
| 53 | glDeleteProgram(handle); | ||
| 54 | handle = 0; | ||
| 55 | } | ||
| 35 | 56 | ||
| 36 | GLuint handle; | 57 | GLuint handle = 0; |
| 37 | }; | 58 | }; |
| 38 | 59 | ||
| 39 | class OGLBuffer : public NonCopyable { | 60 | class OGLBuffer : private NonCopyable { |
| 40 | public: | 61 | public: |
| 41 | OGLBuffer(); | 62 | OGLBuffer() = default; |
| 42 | ~OGLBuffer(); | 63 | OGLBuffer(OGLBuffer&& o) { std::swap(handle, o.handle); } |
| 64 | ~OGLBuffer() { Release(); } | ||
| 65 | OGLBuffer& operator=(OGLBuffer&& o) { std::swap(handle, o.handle); return *this; } | ||
| 43 | 66 | ||
| 44 | /// Creates a new internal OpenGL resource and stores the handle | 67 | /// Creates a new internal OpenGL resource and stores the handle |
| 45 | void Create(); | 68 | void Create() { |
| 69 | if (handle != 0) return; | ||
| 70 | glGenBuffers(1, &handle); | ||
| 71 | } | ||
| 46 | 72 | ||
| 47 | /// Deletes the internal OpenGL resource | 73 | /// Deletes the internal OpenGL resource |
| 48 | void Release(); | 74 | void Release() { |
| 75 | if (handle == 0) return; | ||
| 76 | glDeleteBuffers(1, &handle); | ||
| 77 | handle = 0; | ||
| 78 | } | ||
| 49 | 79 | ||
| 50 | GLuint handle; | 80 | GLuint handle = 0; |
| 51 | }; | 81 | }; |
| 52 | 82 | ||
| 53 | class OGLVertexArray : public NonCopyable { | 83 | class OGLVertexArray : private NonCopyable { |
| 54 | public: | 84 | public: |
| 55 | OGLVertexArray(); | 85 | OGLVertexArray() = default; |
| 56 | ~OGLVertexArray(); | 86 | OGLVertexArray(OGLVertexArray&& o) { std::swap(handle, o.handle); } |
| 87 | ~OGLVertexArray() { Release(); } | ||
| 88 | OGLVertexArray& operator=(OGLVertexArray&& o) { std::swap(handle, o.handle); return *this; } | ||
| 57 | 89 | ||
| 58 | /// Creates a new internal OpenGL resource and stores the handle | 90 | /// Creates a new internal OpenGL resource and stores the handle |
| 59 | void Create(); | 91 | void Create() { |
| 92 | if (handle != 0) return; | ||
| 93 | glGenVertexArrays(1, &handle); | ||
| 94 | } | ||
| 60 | 95 | ||
| 61 | /// Deletes the internal OpenGL resource | 96 | /// Deletes the internal OpenGL resource |
| 62 | void Release(); | 97 | void Release() { |
| 98 | if (handle == 0) return; | ||
| 99 | glDeleteVertexArrays(1, &handle); | ||
| 100 | handle = 0; | ||
| 101 | } | ||
| 63 | 102 | ||
| 64 | GLuint handle; | 103 | GLuint handle = 0; |
| 65 | }; | 104 | }; |
| 66 | 105 | ||
| 67 | class OGLFramebuffer : public NonCopyable { | 106 | class OGLFramebuffer : private NonCopyable { |
| 68 | public: | 107 | public: |
| 69 | OGLFramebuffer(); | 108 | OGLFramebuffer() = default; |
| 70 | ~OGLFramebuffer(); | 109 | OGLFramebuffer(OGLFramebuffer&& o) { std::swap(handle, o.handle); } |
| 110 | ~OGLFramebuffer() { Release(); } | ||
| 111 | OGLFramebuffer& operator=(OGLFramebuffer&& o) { std::swap(handle, o.handle); return *this; } | ||
| 71 | 112 | ||
| 72 | /// Creates a new internal OpenGL resource and stores the handle | 113 | /// Creates a new internal OpenGL resource and stores the handle |
| 73 | void Create(); | 114 | void Create() { |
| 115 | if (handle != 0) return; | ||
| 116 | glGenFramebuffers(1, &handle); | ||
| 117 | } | ||
| 74 | 118 | ||
| 75 | /// Deletes the internal OpenGL resource | 119 | /// Deletes the internal OpenGL resource |
| 76 | void Release(); | 120 | void Release() { |
| 121 | if (handle == 0) return; | ||
| 122 | glDeleteFramebuffers(1, &handle); | ||
| 123 | handle = 0; | ||
| 124 | } | ||
| 77 | 125 | ||
| 78 | GLuint handle; | 126 | GLuint handle = 0; |
| 79 | }; | 127 | }; |
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp index ff114fc3a..5f66f3455 100644 --- a/src/video_core/vertex_shader.cpp +++ b/src/video_core/vertex_shader.cpp | |||
| @@ -2,8 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <stack> | 5 | #include <boost/container/static_vector.hpp> |
| 6 | |||
| 7 | #include <boost/range/algorithm.hpp> | 6 | #include <boost/range/algorithm.hpp> |
| 8 | 7 | ||
| 9 | #include <common/file_util.h> | 8 | #include <common/file_util.h> |
| @@ -27,7 +26,7 @@ namespace Pica { | |||
| 27 | namespace VertexShader { | 26 | namespace VertexShader { |
| 28 | 27 | ||
| 29 | struct VertexShaderState { | 28 | struct VertexShaderState { |
| 30 | const u32* program_counter; | 29 | u32 program_counter; |
| 31 | 30 | ||
| 32 | const float24* input_register_table[16]; | 31 | const float24* input_register_table[16]; |
| 33 | Math::Vec4<float24> output_registers[16]; | 32 | Math::Vec4<float24> output_registers[16]; |
| @@ -53,7 +52,7 @@ struct VertexShaderState { | |||
| 53 | }; | 52 | }; |
| 54 | 53 | ||
| 55 | // TODO: Is there a maximal size for this? | 54 | // TODO: Is there a maximal size for this? |
| 56 | std::stack<CallStackElement> call_stack; | 55 | boost::container::static_vector<CallStackElement, 16> call_stack; |
| 57 | 56 | ||
| 58 | struct { | 57 | struct { |
| 59 | u32 max_offset; // maximum program counter ever reached | 58 | u32 max_offset; // maximum program counter ever reached |
| @@ -71,15 +70,15 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 71 | 70 | ||
| 72 | while (true) { | 71 | while (true) { |
| 73 | if (!state.call_stack.empty()) { | 72 | if (!state.call_stack.empty()) { |
| 74 | auto& top = state.call_stack.top(); | 73 | auto& top = state.call_stack.back(); |
| 75 | if (state.program_counter - program_code.data() == top.final_address) { | 74 | if (state.program_counter == top.final_address) { |
| 76 | state.address_registers[2] += top.loop_increment; | 75 | state.address_registers[2] += top.loop_increment; |
| 77 | 76 | ||
| 78 | if (top.repeat_counter-- == 0) { | 77 | if (top.repeat_counter-- == 0) { |
| 79 | state.program_counter = &program_code[top.return_address]; | 78 | state.program_counter = top.return_address; |
| 80 | state.call_stack.pop(); | 79 | state.call_stack.pop_back(); |
| 81 | } else { | 80 | } else { |
| 82 | state.program_counter = &program_code[top.loop_address]; | 81 | state.program_counter = top.loop_address; |
| 83 | } | 82 | } |
| 84 | 83 | ||
| 85 | // TODO: Is "trying again" accurate to hardware? | 84 | // TODO: Is "trying again" accurate to hardware? |
| @@ -88,17 +87,16 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | bool exit_loop = false; | 89 | bool exit_loop = false; |
| 91 | const Instruction& instr = *(const Instruction*)state.program_counter; | 90 | const Instruction instr = { program_code[state.program_counter] }; |
| 92 | const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id]; | 91 | const SwizzlePattern swizzle = { swizzle_data[instr.common.operand_desc_id] }; |
| 93 | 92 | ||
| 94 | static auto call = [&program_code](VertexShaderState& state, u32 offset, u32 num_instructions, | 93 | static auto call = [](VertexShaderState& state, u32 offset, u32 num_instructions, |
| 95 | u32 return_offset, u8 repeat_count, u8 loop_increment) { | 94 | u32 return_offset, u8 repeat_count, u8 loop_increment) { |
| 96 | state.program_counter = &program_code[offset] - 1; // -1 to make sure when incrementing the PC we end up at the correct offset | 95 | state.program_counter = offset - 1; // -1 to make sure when incrementing the PC we end up at the correct offset |
| 97 | state.call_stack.push({ offset + num_instructions, return_offset, repeat_count, loop_increment, offset }); | 96 | ASSERT(state.call_stack.size() < state.call_stack.capacity()); |
| 97 | state.call_stack.push_back({ offset + num_instructions, return_offset, repeat_count, loop_increment, offset }); | ||
| 98 | }; | 98 | }; |
| 99 | u32 binary_offset = state.program_counter - program_code.data(); | 99 | state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + state.program_counter); |
| 100 | |||
| 101 | state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + binary_offset); | ||
| 102 | 100 | ||
| 103 | auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* { | 101 | auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* { |
| 104 | switch (source_reg.GetRegisterType()) { | 102 | switch (source_reg.GetRegisterType()) { |
| @@ -442,13 +440,13 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 442 | 440 | ||
| 443 | case OpCode::Id::JMPC: | 441 | case OpCode::Id::JMPC: |
| 444 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { | 442 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { |
| 445 | state.program_counter = &program_code[instr.flow_control.dest_offset] - 1; | 443 | state.program_counter = instr.flow_control.dest_offset - 1; |
| 446 | } | 444 | } |
| 447 | break; | 445 | break; |
| 448 | 446 | ||
| 449 | case OpCode::Id::JMPU: | 447 | case OpCode::Id::JMPU: |
| 450 | if (uniforms.b[instr.flow_control.bool_uniform_id]) { | 448 | if (uniforms.b[instr.flow_control.bool_uniform_id]) { |
| 451 | state.program_counter = &program_code[instr.flow_control.dest_offset] - 1; | 449 | state.program_counter = instr.flow_control.dest_offset - 1; |
| 452 | } | 450 | } |
| 453 | break; | 451 | break; |
| 454 | 452 | ||
| @@ -456,7 +454,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 456 | call(state, | 454 | call(state, |
| 457 | instr.flow_control.dest_offset, | 455 | instr.flow_control.dest_offset, |
| 458 | instr.flow_control.num_instructions, | 456 | instr.flow_control.num_instructions, |
| 459 | binary_offset + 1, 0, 0); | 457 | state.program_counter + 1, 0, 0); |
| 460 | break; | 458 | break; |
| 461 | 459 | ||
| 462 | case OpCode::Id::CALLU: | 460 | case OpCode::Id::CALLU: |
| @@ -464,7 +462,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 464 | call(state, | 462 | call(state, |
| 465 | instr.flow_control.dest_offset, | 463 | instr.flow_control.dest_offset, |
| 466 | instr.flow_control.num_instructions, | 464 | instr.flow_control.num_instructions, |
| 467 | binary_offset + 1, 0, 0); | 465 | state.program_counter + 1, 0, 0); |
| 468 | } | 466 | } |
| 469 | break; | 467 | break; |
| 470 | 468 | ||
| @@ -473,7 +471,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 473 | call(state, | 471 | call(state, |
| 474 | instr.flow_control.dest_offset, | 472 | instr.flow_control.dest_offset, |
| 475 | instr.flow_control.num_instructions, | 473 | instr.flow_control.num_instructions, |
| 476 | binary_offset + 1, 0, 0); | 474 | state.program_counter + 1, 0, 0); |
| 477 | } | 475 | } |
| 478 | break; | 476 | break; |
| 479 | 477 | ||
| @@ -483,8 +481,8 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 483 | case OpCode::Id::IFU: | 481 | case OpCode::Id::IFU: |
| 484 | if (uniforms.b[instr.flow_control.bool_uniform_id]) { | 482 | if (uniforms.b[instr.flow_control.bool_uniform_id]) { |
| 485 | call(state, | 483 | call(state, |
| 486 | binary_offset + 1, | 484 | state.program_counter + 1, |
| 487 | instr.flow_control.dest_offset - binary_offset - 1, | 485 | instr.flow_control.dest_offset - state.program_counter - 1, |
| 488 | instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); | 486 | instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); |
| 489 | } else { | 487 | } else { |
| 490 | call(state, | 488 | call(state, |
| @@ -501,8 +499,8 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 501 | 499 | ||
| 502 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { | 500 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { |
| 503 | call(state, | 501 | call(state, |
| 504 | binary_offset + 1, | 502 | state.program_counter + 1, |
| 505 | instr.flow_control.dest_offset - binary_offset - 1, | 503 | instr.flow_control.dest_offset - state.program_counter - 1, |
| 506 | instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); | 504 | instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, 0); |
| 507 | } else { | 505 | } else { |
| 508 | call(state, | 506 | call(state, |
| @@ -519,8 +517,8 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 519 | state.address_registers[2] = uniforms.i[instr.flow_control.int_uniform_id].y; | 517 | state.address_registers[2] = uniforms.i[instr.flow_control.int_uniform_id].y; |
| 520 | 518 | ||
| 521 | call(state, | 519 | call(state, |
| 522 | binary_offset + 1, | 520 | state.program_counter + 1, |
| 523 | instr.flow_control.dest_offset - binary_offset + 1, | 521 | instr.flow_control.dest_offset - state.program_counter + 1, |
| 524 | instr.flow_control.dest_offset + 1, | 522 | instr.flow_control.dest_offset + 1, |
| 525 | uniforms.i[instr.flow_control.int_uniform_id].x, | 523 | uniforms.i[instr.flow_control.int_uniform_id].x, |
| 526 | uniforms.i[instr.flow_control.int_uniform_id].z); | 524 | uniforms.i[instr.flow_control.int_uniform_id].z); |
| @@ -551,8 +549,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes, const Regs: | |||
| 551 | 549 | ||
| 552 | VertexShaderState state; | 550 | VertexShaderState state; |
| 553 | 551 | ||
| 554 | const u32* main = &setup.program_code[config.main_offset]; | 552 | state.program_counter = config.main_offset; |
| 555 | state.program_counter = (u32*)main; | ||
| 556 | state.debug.max_offset = 0; | 553 | state.debug.max_offset = 0; |
| 557 | state.debug.max_opdesc_id = 0; | 554 | state.debug.max_opdesc_id = 0; |
| 558 | 555 | ||
| @@ -582,9 +579,11 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes, const Regs: | |||
| 582 | state.conditional_code[1] = false; | 579 | state.conditional_code[1] = false; |
| 583 | 580 | ||
| 584 | ProcessShaderCode(state); | 581 | ProcessShaderCode(state); |
| 582 | #if PICA_DUMP_SHADERS | ||
| 585 | DebugUtils::DumpShader(setup.program_code.data(), state.debug.max_offset, setup.swizzle_data.data(), | 583 | DebugUtils::DumpShader(setup.program_code.data(), state.debug.max_offset, setup.swizzle_data.data(), |
| 586 | state.debug.max_opdesc_id, config.main_offset, | 584 | state.debug.max_opdesc_id, config.main_offset, |
| 587 | g_state.regs.vs_output_attributes); // TODO: Don't hardcode VS here | 585 | g_state.regs.vs_output_attributes); // TODO: Don't hardcode VS here |
| 586 | #endif | ||
| 588 | 587 | ||
| 589 | // Setup output data | 588 | // Setup output data |
| 590 | OutputVertex ret; | 589 | OutputVertex ret; |