summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra/config.cpp36
-rw-r--r--src/citra/default_ini.h4
-rw-r--r--src/citra/emu_window/emu_window_glfw.cpp29
-rw-r--r--src/citra_qt/bootmanager.cpp29
-rw-r--r--src/citra_qt/config.cpp63
-rw-r--r--src/citra_qt/debugger/disassembler.cpp3
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints.cpp112
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints.h6
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints_p.h2
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.cpp36
-rw-r--r--src/citra_qt/debugger/graphics_vertex_shader.cpp2
-rw-r--r--src/citra_qt/debugger/profiler.cpp2
-rw-r--r--src/citra_qt/main.cpp5
-rw-r--r--src/citra_qt/main.h2
-rw-r--r--src/common/string_util.cpp2
-rw-r--r--src/core/CMakeLists.txt9
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp32
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp27
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h16
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp505
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.h2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.cpp93
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.h23
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp49
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h30
-rw-r--r--src/core/arm/interpreter/arminit.cpp128
-rw-r--r--src/core/arm/interpreter/armsupp.cpp637
-rw-r--r--src/core/arm/skyeye_common/armdefs.h318
-rw-r--r--src/core/arm/skyeye_common/armmmu.h103
-rw-r--r--src/core/arm/skyeye_common/armstate.cpp657
-rw-r--r--src/core/arm/skyeye_common/armstate.h252
-rw-r--r--src/core/arm/skyeye_common/armsupp.cpp208
-rw-r--r--src/core/arm/skyeye_common/armsupp.h32
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp12
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h10
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h4
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp12
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp126
-rw-r--r--src/core/core_timing.cpp2
-rw-r--r--src/core/hle/applets/applet.cpp9
-rw-r--r--src/core/hle/applets/applet.h3
-rw-r--r--src/core/hle/function_wrappers.h2
-rw-r--r--src/core/hle/kernel/thread.cpp2
-rw-r--r--src/core/hle/service/am/am.cpp1
-rw-r--r--src/core/hle/service/am/am_net.cpp3
-rw-r--r--src/core/hle/service/apt/apt.cpp53
-rw-r--r--src/core/hle/service/apt/apt.h30
-rw-r--r--src/core/hle/service/apt/apt_a.cpp1
-rw-r--r--src/core/hle/service/apt/apt_s.cpp4
-rw-r--r--src/core/hle/service/apt/apt_u.cpp2
-rw-r--r--src/core/hle/service/gsp_gpu.cpp38
-rw-r--r--src/core/hle/service/hid/hid.cpp10
-rw-r--r--src/core/hle/service/hid/hid.h5
-rw-r--r--src/core/hle/service/soc_u.cpp10
-rw-r--r--src/core/hle/svc.cpp4
-rw-r--r--src/core/hw/gpu.cpp4
-rw-r--r--src/core/hw/y2r.cpp1
-rw-r--r--src/core/loader/3dsx.cpp2
-rw-r--r--src/core/loader/loader.cpp18
-rw-r--r--src/core/settings.h54
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/command_processor.cpp16
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp44
-rw-r--r--src/video_core/debug_utils/debug_utils.h12
-rw-r--r--src/video_core/pica.cpp72
-rw-r--r--src/video_core/pica.h65
-rw-r--r--src/video_core/rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.cpp111
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h110
-rw-r--r--src/video_core/vertex_shader.cpp59
71 files changed, 2070 insertions, 2300 deletions
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
43static 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
43void Config::ReadValues() { 52void 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 =
33pad_cright = 33pad_cright =
34 34
35[Core] 35[Core]
36# The refresh rate for the GPU
37# Defaults to 30
38gpu_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.
42frame_skip = 38frame_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
152void EmuWindow_GLFW::ReloadSetKeymaps() { 152void 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
181void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { 158void 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
249void GRenderWindow::ReloadSetKeymaps() 249void 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
279void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) 256void 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
24static 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
24void Config::ReadValues() { 33void 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
76void Config::SaveValues() { 66void 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
221void DisassemblerWidget::OnDebugModeEntered() { 220void 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
24int BreakPointModel::columnCount(const QModelIndex& parent) const 24int BreakPointModel::columnCount(const QModelIndex& parent) const
25{ 25{
26 return 2; 26 return 1;
27} 27}
28 28
29int BreakPointModel::rowCount(const QModelIndex& parent) const 29int 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
87QVariant BreakPointModel::headerData(int section, Qt::Orientation orientation, int role) const 87Qt::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
105bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) 99bool 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
139void BreakPointModel::OnResumed() 136void 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
237void GraphicsBreakPointsWidget::OnBreakpointSelectionChanged(const QModelIndex& index) 230void 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)
248void 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
258void 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
32public slots: 32public 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
39signals: 38signals:
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
44private: 43private:
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
172int GPUCommandListModel::rowCount(const QModelIndex& parent) const { 173int 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
176int GPUCommandListModel::columnCount(const QModelIndex& parent) const { 177int GPUCommandListModel::columnCount(const QModelIndex& parent) const {
177 return 2; 178 return 3;
178} 179}
179 180
180QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { 181QVariant 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
36int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const { 36int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const {
37 return info.code.size(); 37 return static_cast<int>(info.code.size());
38} 38}
39 39
40QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, int role) const { 40QVariant 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
210void GMainWindow::BootGame(std::string filename) { 210void 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
57private: 57private:
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
19ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { 20ARM_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
42ARM_DynCom::~ARM_DynCom() { 24ARM_DynCom::~ARM_DynCom() {
@@ -100,8 +82,8 @@ void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 e
100} 82}
101 83
102void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { 84void 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
115void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { 97void 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
15namespace Core { 15namespace Core {
16struct ThreadContext; 16struct 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
8const ISEITEM arm_instruction[] = { 8const 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
210const ISEITEM arm_exclusion_code[] = { 210const 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
417int decode_arm_instr(uint32_t instr, int32_t *idx) { 417ARMDecodeStatus 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
7int decode_arm_instr(uint32_t instr, int32_t *idx); 7#include "common/common_types.h"
8 8
9enum DECODE_STATUS { 9enum class ARMDecodeStatus {
10 DECODE_SUCCESS, 10 SUCCESS,
11 DECODE_FAILURE 11 FAILURE
12}; 12};
13 13
14struct instruction_set_encoding_item { 14ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx);
15
16struct 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
21typedef struct instruction_set_encoding_item ISEITEM;
22
23// ARM versions 23// ARM versions
24enum { 24enum {
25 INVALID = 0, 25 INVALID = 0,
@@ -36,4 +36,4 @@ enum {
36 ARMV6K, 36 ARMV6K,
37}; 37};
38 38
39extern const ISEITEM arm_instruction[]; 39extern 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
24Common::Profiling::TimingCategory profile_execute("DynCom::Execute"); 24Common::Profiling::TimingCategory profile_execute("DynCom::Execute");
@@ -47,28 +47,6 @@ enum {
47 47
48typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); 48typedef 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.
53static const ARMword RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
54
55// Exclusive memory access
56static 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
63static void add_exclusive_addr(ARMul_State* state, ARMword addr){
64 state->exclusive_tag = addr & RESERVATION_GRANULE_MASK;
65 return;
66}
67
68static void remove_exclusive(ARMul_State* state, ARMword addr){
69 state->exclusive_tag = 0xFFFFFFFF;
70}
71
72static int CondPassed(ARMul_State* cpu, unsigned int cond) { 50static 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
3493static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { 3471static 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
3552typedef struct instruction_set_encoding_item ISEITEM;
3553
3554extern const ISEITEM arm_instruction[];
3555
3556static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { 3524static 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" 7struct ARMul_State;
8 8
9unsigned InterpreterMainLoop(ARMul_State* state); 9unsigned 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
8void 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
23void 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.
28static 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 */
42static inline u32 CHECK_READ_REG15_WA(ARMul_State* core, int Rn) { 33static 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 */
55static inline u32 CHECK_READ_REG15(ARMul_State* core, int Rn) { 46static 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
14tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { 15ThumbDecodeStatus 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
31enum tdstate { 31enum 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
38tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size); 38// Translates a Thumb mode instruction into its ARM equivalent.
39ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
39 40
40static inline u32 get_thumb_instr(u32 instr, u32 pc) { 41static 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\***************************************************************************/
25ARMul_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
40void 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.
50static 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\***************************************************************************/
110void 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
25u8 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.
34u32 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.
50bool 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.
57bool 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.
64bool 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
74u8 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
89u8 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
104u16 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
119u16 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
134u8 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
145u16 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
156u8 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
165u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
166{
167 if (left <= right)
168 return 0;
169
170 return left - right;
171}
172
173// Signed saturation.
174u32 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
193u32 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)
210bool 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.
216bool 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.
224u32 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.
415void 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
29enum {
30 LOW = 0,
31 HIGH = 1,
32 LOWHIGH = 1,
33 HIGHLOW = 2
34};
35
36// Cache types
37enum {
38 NONCACHE = 0,
39 DATACACHE = 1,
40 INSTCACHE = 2,
41};
42
43// Abort models
44enum {
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
53typedef u64 ARMdword; // must be 64 bits wide
54typedef u32 ARMword; // must be 32 bits wide
55typedef u16 ARMhword; // must be 16 bits wide
56typedef u8 ARMbyte; // must be 8 bits wide
57
58#define VFP_REG_NUM 64
59struct 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----------------------------------------------------------
112read ARM Architecture Reference Manual
1132.6.5 Data Abort
114There are three Abort Model in ARM arch.
115
116Early Abort Model: used in some ARMv3 and earlier implementations. In this
117model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
118the base register was unchanged for all other instructions. (oldest)
119
120Base Restored Abort Model: If a Data Abort occurs in an instruction which
121specifies base register writeback, the value in the base register is
122unchanged. (strongarm, xscale)
123
124Base Updated Abort Model: If a Data Abort occurs in an instruction which
125specifies base register writeback, the base register writeback still occurs.
126(arm720T)
127
128read PART B
129chap2 The System Control Coprocessor CP15
1302.4 Register1:control register
131L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
132processor could be configured:
1330=early Abort Model Selected(now obsolete)
1341=Late Abort Model selceted(same as Base Updated Abort Model)
135
136on later processors, this bit reads as 1 and ignores writes.
137-------------------------------------------------------------
138So, 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
163enum {
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
175enum {
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
200enum PrivilegeMode {
201 USER32MODE = 16,
202 FIQ32MODE = 17,
203 IRQ32MODE = 18,
204 SVC32MODE = 19,
205 ABORT32MODE = 23,
206 UNDEF32MODE = 27,
207 SYSTEM32MODE = 31
208};
209
210enum {
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\***************************************************************************/
224extern void ARMul_Reset(ARMul_State* state);
225extern ARMul_State* ARMul_NewState(ARMul_State* state);
226
227/***************************************************************************\
228* Definitons of things in the co-processor interface *
229\***************************************************************************/
230
231enum {
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
246enum 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.
266enum : 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.
285enum {
286 STOP = 0, // Stop
287 CHANGEMODE = 1, // Change mode
288 ONCE = 2, // Execute just one iteration
289 RUN = 3 // Continuous execution
290};
291
292
293extern bool AddOverflow(ARMword, ARMword, ARMword);
294extern bool SubOverflow(ARMword, ARMword, ARMword);
295
296extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
297
298extern u32 AddWithCarry(u32, u32, u32, bool*, bool*);
299extern bool ARMul_AddOverflowQ(ARMword, ARMword);
300
301extern u8 ARMul_SignedSaturatedAdd8(u8, u8);
302extern u8 ARMul_SignedSaturatedSub8(u8, u8);
303extern u16 ARMul_SignedSaturatedAdd16(u16, u16);
304extern u16 ARMul_SignedSaturatedSub16(u16, u16);
305
306extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8);
307extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
308extern u8 ARMul_UnsignedSaturatedSub8(u8, u8);
309extern u16 ARMul_UnsignedSaturatedSub16(u16, u16);
310extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
311extern u32 ARMul_SignedSatQ(s32, u8, bool*);
312extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
313
314extern bool InBigEndianMode(ARMul_State*);
315extern bool InAPrivilegedMode(ARMul_State*);
316
317extern u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
318extern 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
29enum
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.
55inline 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
64inline 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
73inline 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.
84inline 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
91inline 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
98inline 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
12ARMul_State::ARMul_State(PrivilegeMode initial_mode)
13{
14 Reset();
15 ChangePrivilegeMode(initial_mode);
16}
17
18void 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
107void 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.
132void 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
189u16 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
199u32 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
209u64 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
219void ARMul_State::WriteMemory16(u32 address, u16 data)
220{
221 if (InBigEndianMode())
222 data = Common::swap16(data);
223
224 Memory::Write16(address, data);
225}
226
227void ARMul_State::WriteMemory32(u32 address, u32 data)
228{
229 if (InBigEndianMode())
230 data = Common::swap32(data);
231
232 Memory::Write32(address, data);
233}
234
235void 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.
247u32 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.
438void 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
27enum {
28 LOW = 0,
29 HIGH = 1,
30 LOWHIGH = 1,
31 HIGHLOW = 2
32};
33
34// Cache types
35enum {
36 NONCACHE = 0,
37 DATACACHE = 1,
38 INSTCACHE = 2,
39};
40
41// ARM privilege modes
42enum 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
53enum {
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
65enum {
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
87enum {
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
99enum 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.
119enum : 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.
138enum {
139 STOP = 0, // Stop
140 CHANGEMODE = 1, // Change mode
141 ONCE = 2, // Execute just one iteration
142 RUN = 3 // Continuous execution
143};
144
145
146struct ARMul_State final
147{
148public:
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
241private:
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
26u8 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.
35u32 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.
51bool 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.
58bool 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.
65bool 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
75u8 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
90u8 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
105u16 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
120u16 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
135u8 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
146u16 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
157u8 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
166u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
167{
168 if (left <= right)
169 return 0;
170
171 return left - right;
172}
173
174// Signed saturation.
175u32 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
194u32 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
15bool AddOverflow(u32, u32, u32);
16bool SubOverflow(u32, u32, u32);
17
18u32 AddWithCarry(u32, u32, u32, bool*, bool*);
19bool ARMul_AddOverflowQ(u32, u32);
20
21u8 ARMul_SignedSaturatedAdd8(u8, u8);
22u8 ARMul_SignedSaturatedSub8(u8, u8);
23u16 ARMul_SignedSaturatedAdd16(u16, u16);
24u16 ARMul_SignedSaturatedSub16(u16, u16);
25
26u8 ARMul_UnsignedSaturatedAdd8(u8, u8);
27u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
28u8 ARMul_UnsignedSaturatedSub8(u8, u8);
29u16 ARMul_UnsignedSaturatedSub16(u16, u16);
30u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
31u32 ARMul_SignedSatQ(s32, u8, bool*);
32u32 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
46void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) 46void 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
58void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) 58void 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}
71void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) 71void 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
85void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) 85void 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}
98void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword m) 98void 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
36u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 36u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
37u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 37u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
38 38
39void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); 39void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value);
40void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); 40void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2);
41void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); 41void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2);
42void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); 42void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm);
43void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); 43void 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
418static inline u32 fls(ARMword x) 418static 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
71static void vfp_double_normalise_denormal(struct vfp_double *vd) 71static 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
508void LogPendingEvents() { 508void 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
92bool 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
92void Init() { 100void 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
97void Shutdown() { 105void 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
71bool IsLibraryAppletRunning();
72
70/// Initializes the HLE applets 73/// Initializes the HLE applets
71void Init(); 74void 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
136template<ResultCode func(s64*, u32, u32*, s32)> void Wrap(){ 136template<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
102void GetLockHandle(Service::Interface* self) { 102void 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
118void Enable(Service::Interface* self) { 119void 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) {
330void PrepareToStartLibraryApplet(Service::Interface* self) { 334void 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
347void 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 */
97void NotifyToWait(Service::Interface* self); 98void 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 */
99void GetLockHandle(Service::Interface* self); 111void 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 */
101void Enable(Service::Interface* self); 120void Enable(Service::Interface* self);
102 121
103/** 122/**
@@ -284,6 +303,17 @@ void GetAppCpuTimeLimit(Service::Interface* self);
284void PrepareToStartLibraryApplet(Service::Interface* self); 303void 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 */
314void 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;
35static u32 next_pad_index; 35static u32 next_pad_index;
36static u32 next_touch_index; 36static u32 next_touch_index;
37 37
38const 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}};
157const PadState PAD_CIRCLE_UP = {{1u << 30}}; 157const PadState PAD_CIRCLE_UP = {{1u << 30}};
158const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; 158const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
159 159
160
161extern 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
491static void Close(Service::Interface* self) { 497static 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
336static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, 336static 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
352static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, 352static 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
19namespace HW { 20namespace 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) {
56static FileType GuessFromExtension(const std::string& extension_) { 56static 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
9namespace Settings { 10namespace Settings {
10 11
12namespace NativeInput {
13enum 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};
22static 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};
30static 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
11struct Values { 41struct 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
430void ProcessCommandList(const u32* list, u32 size) { 438void 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
92void GeometryDumper::Dump() { 92void 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() {
116void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, 112void 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
567void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { 559void 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
155namespace DebugUtils { 158namespace 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
158class GeometryDumper { 166class GeometryDumper {
159public: 167public:
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
11State g_state; 12State g_state;
12 13
14std::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
13void Init() { 83void 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
9OGLTexture::OGLTexture() : handle(0) {
10}
11
12OGLTexture::~OGLTexture() {
13 Release();
14}
15
16void OGLTexture::Create() {
17 if (handle != 0) {
18 return;
19 }
20
21 glGenTextures(1, &handle);
22}
23
24void OGLTexture::Release() {
25 glDeleteTextures(1, &handle);
26 handle = 0;
27}
28
29// Shaders
30OGLShader::OGLShader() : handle(0) {
31}
32
33OGLShader::~OGLShader() {
34 Release();
35}
36
37void 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
45void OGLShader::Release() {
46 glDeleteProgram(handle);
47 handle = 0;
48}
49
50// Buffer objects
51OGLBuffer::OGLBuffer() : handle(0) {
52}
53
54OGLBuffer::~OGLBuffer() {
55 Release();
56}
57
58void OGLBuffer::Create() {
59 if (handle != 0) {
60 return;
61 }
62
63 glGenBuffers(1, &handle);
64}
65
66void OGLBuffer::Release() {
67 glDeleteBuffers(1, &handle);
68 handle = 0;
69}
70
71// Vertex array objects
72OGLVertexArray::OGLVertexArray() : handle(0) {
73}
74
75OGLVertexArray::~OGLVertexArray() {
76 Release();
77}
78
79void OGLVertexArray::Create() {
80 if (handle != 0) {
81 return;
82 }
83
84 glGenVertexArrays(1, &handle);
85}
86
87void OGLVertexArray::Release() {
88 glDeleteVertexArrays(1, &handle);
89 handle = 0;
90}
91
92// Framebuffers
93OGLFramebuffer::OGLFramebuffer() : handle(0) {
94}
95
96OGLFramebuffer::~OGLFramebuffer() {
97 Release();
98}
99
100void OGLFramebuffer::Create() {
101 if (handle != 0) {
102 return;
103 }
104
105 glGenFramebuffers(1, &handle);
106}
107
108void 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
11class OGLTexture : public NonCopyable { 14class OGLTexture : private NonCopyable {
12public: 15public:
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
25class OGLShader : public NonCopyable { 37class OGLShader : private NonCopyable {
26public: 38public:
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
39class OGLBuffer : public NonCopyable { 60class OGLBuffer : private NonCopyable {
40public: 61public:
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
53class OGLVertexArray : public NonCopyable { 83class OGLVertexArray : private NonCopyable {
54public: 84public:
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
67class OGLFramebuffer : public NonCopyable { 106class OGLFramebuffer : private NonCopyable {
68public: 107public:
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 {
27namespace VertexShader { 26namespace VertexShader {
28 27
29struct VertexShaderState { 28struct 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;