summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra/config.cpp7
-rw-r--r--src/citra/config.h1
-rw-r--r--src/citra/default_ini.h4
-rw-r--r--src/citra/emu_window/emu_window_glfw.h8
-rw-r--r--src/citra_qt/bootmanager.cpp25
-rw-r--r--src/citra_qt/bootmanager.hxx16
-rw-r--r--src/citra_qt/config.cpp17
-rw-r--r--src/citra_qt/config.h3
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.hxx2
-rw-r--r--src/citra_qt/main.cpp13
-rw-r--r--src/citra_qt/main.hxx2
-rw-r--r--src/common/console_listener.h2
-rw-r--r--src/common/key_map.h2
-rw-r--r--src/common/log_manager.h4
-rw-r--r--src/common/string_util.cpp158
-rw-r--r--src/common/string_util.h8
-rw-r--r--src/common/swap.h1
-rw-r--r--src/core/CMakeLists.txt40
-rw-r--r--src/core/arm/arm_interface.h2
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp11
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h14
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp115
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.h2
-rw-r--r--src/core/arm/interpreter/arm_interpreter.h22
-rw-r--r--src/core/arm/interpreter/armemu.cpp276
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp476
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h24
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h9
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp2055
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp1944
-rw-r--r--src/core/core.cpp17
-rw-r--r--src/core/core.h17
-rw-r--r--src/core/file_sys/archive.h106
-rw-r--r--src/core/file_sys/archive_romfs.cpp12
-rw-r--r--src/core/file_sys/archive_romfs.h7
-rw-r--r--src/core/file_sys/archive_sdmc.cpp9
-rw-r--r--src/core/file_sys/archive_sdmc.h7
-rw-r--r--src/core/file_sys/directory_sdmc.cpp2
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp8
-rw-r--r--src/core/hle/kernel/archive.cpp51
-rw-r--r--src/core/hle/kernel/archive.h12
-rw-r--r--src/core/hle/kernel/event.cpp8
-rw-r--r--src/core/hle/kernel/mutex.cpp10
-rw-r--r--src/core/hle/kernel/shared_memory.cpp8
-rw-r--r--src/core/hle/kernel/thread.cpp8
-rw-r--r--src/core/hle/service/ac_u.cpp44
-rw-r--r--src/core/hle/service/ac_u.h29
-rw-r--r--src/core/hle/service/apt_u.cpp (renamed from src/core/hle/service/apt.cpp)111
-rw-r--r--src/core/hle/service/apt_u.h (renamed from src/core/hle/service/apt.h)2
-rw-r--r--src/core/hle/service/cfg_u.cpp36
-rw-r--r--src/core/hle/service/cfg_u.h27
-rw-r--r--src/core/hle/service/dsp_dsp.cpp52
-rw-r--r--src/core/hle/service/dsp_dsp.h27
-rw-r--r--src/core/hle/service/err_f.cpp27
-rw-r--r--src/core/hle/service/err_f.h27
-rw-r--r--src/core/hle/service/frd_u.cpp35
-rw-r--r--src/core/hle/service/frd_u.h27
-rw-r--r--src/core/hle/service/fs_user.cpp (renamed from src/core/hle/service/fs.cpp)202
-rw-r--r--src/core/hle/service/fs_user.h (renamed from src/core/hle/service/fs.h)2
-rw-r--r--src/core/hle/service/gsp_gpu.cpp (renamed from src/core/hle/service/gsp.cpp)2
-rw-r--r--src/core/hle/service/gsp_gpu.h (renamed from src/core/hle/service/gsp.h)2
-rw-r--r--src/core/hle/service/hid_user.cpp (renamed from src/core/hle/service/hid.cpp)6
-rw-r--r--src/core/hle/service/hid_user.h (renamed from src/core/hle/service/hid.h)2
-rw-r--r--src/core/hle/service/mic_u.cpp43
-rw-r--r--src/core/hle/service/mic_u.h29
-rw-r--r--src/core/hle/service/ndm_u.cpp (renamed from src/core/hle/service/ndm.cpp)2
-rw-r--r--src/core/hle/service/ndm_u.h (renamed from src/core/hle/service/ndm.h)2
-rw-r--r--src/core/hle/service/nwm_uds.cpp35
-rw-r--r--src/core/hle/service/nwm_uds.h29
-rw-r--r--src/core/hle/service/ptm_u.cpp42
-rw-r--r--src/core/hle/service/ptm_u.h29
-rw-r--r--src/core/hle/service/service.cpp30
-rw-r--r--src/core/hle/service/service.h10
-rw-r--r--src/core/hle/service/soc_u.cpp58
-rw-r--r--src/core/hle/service/soc_u.h27
-rw-r--r--src/core/hle/service/srv.cpp2
-rw-r--r--src/core/hle/service/srv.h2
-rw-r--r--src/core/hle/service/ssl_c.cpp31
-rw-r--r--src/core/hle/service/ssl_c.h27
-rw-r--r--src/core/hle/svc.cpp6
-rw-r--r--src/core/hw/gpu.cpp13
-rw-r--r--src/core/hw/gpu.h3
-rw-r--r--src/core/hw/hw.cpp4
-rw-r--r--src/core/hw/ndma.cpp4
-rw-r--r--src/core/settings.h6
-rw-r--r--src/video_core/clipper.cpp4
-rw-r--r--src/video_core/command_processor.cpp2
-rw-r--r--src/video_core/gpu_debugger.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h8
89 files changed, 4137 insertions, 2518 deletions
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 65edcfc9f..f45d09fc2 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -7,6 +7,7 @@
7#include "citra/default_ini.h" 7#include "citra/default_ini.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "core/settings.h" 9#include "core/settings.h"
10#include "core/core.h"
10 11
11#include "config.h" 12#include "config.h"
12 13
@@ -55,6 +56,11 @@ void Config::ReadControls() {
55 Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); 56 Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT);
56} 57}
57 58
59void Config::ReadCore() {
60 Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter);
61 Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 60);
62}
63
58void Config::ReadData() { 64void Config::ReadData() {
59 Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true); 65 Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true);
60} 66}
@@ -66,6 +72,7 @@ void Config::ReadMiscellaneous() {
66void Config::Reload() { 72void Config::Reload() {
67 LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file); 73 LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file);
68 ReadControls(); 74 ReadControls();
75 ReadCore();
69 ReadData(); 76 ReadData();
70 ReadMiscellaneous(); 77 ReadMiscellaneous();
71} 78}
diff --git a/src/citra/config.h b/src/citra/config.h
index 63b5978e2..19bb83700 100644
--- a/src/citra/config.h
+++ b/src/citra/config.h
@@ -16,6 +16,7 @@ class Config {
16 16
17 bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true); 17 bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true);
18 void ReadControls(); 18 void ReadControls();
19 void ReadCore();
19 void ReadData(); 20 void ReadData();
20 void ReadMiscellaneous(); 21 void ReadMiscellaneous();
21public: 22public:
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 1f0b6cad4..f1f626eed 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -26,6 +26,10 @@ pad_sdown =
26pad_sleft = 26pad_sleft =
27pad_sright = 27pad_sright =
28 28
29[Core]
30cpu_core = ## 0: Interpreter (default), 1: FastInterpreter (experimental)
31gpu_refresh_rate = ## 60 (default)
32
29[Data Storage] 33[Data Storage]
30use_virtual_sd = 34use_virtual_sd =
31 35
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h
index 638e026ef..7c3072145 100644
--- a/src/citra/emu_window/emu_window_glfw.h
+++ b/src/citra/emu_window/emu_window_glfw.h
@@ -14,16 +14,16 @@ public:
14 ~EmuWindow_GLFW(); 14 ~EmuWindow_GLFW();
15 15
16 /// Swap buffers to display the next frame 16 /// Swap buffers to display the next frame
17 void SwapBuffers(); 17 void SwapBuffers() override;
18 18
19 /// Polls window events 19 /// Polls window events
20 void PollEvents(); 20 void PollEvents() override;
21 21
22 /// Makes the graphics context current for the caller thread 22 /// Makes the graphics context current for the caller thread
23 void MakeCurrent(); 23 void MakeCurrent() override;
24 24
25 /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread 25 /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
26 void DoneCurrent(); 26 void DoneCurrent() override;
27 27
28 static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods); 28 static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods);
29 29
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 0430aa1ed..20824692d 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -33,19 +33,16 @@ void EmuThread::run()
33 stop_run = false; 33 stop_run = false;
34 while (!stop_run) 34 while (!stop_run)
35 { 35 {
36 for (int tight_loop = 0; tight_loop < 10000; ++tight_loop) 36 if (cpu_running)
37 { 37 {
38 if (cpu_running || exec_cpu_step) 38 Core::RunLoop();
39 { 39 }
40 if (exec_cpu_step) 40 else if (exec_cpu_step)
41 exec_cpu_step = false; 41 {
42 42 exec_cpu_step = false;
43 Core::SingleStep(); 43 Core::SingleStep();
44 if (!cpu_running) { 44 emit CPUStepped();
45 emit CPUStepped(); 45 yieldCurrentThread();
46 yieldCurrentThread();
47 }
48 }
49 } 46 }
50 } 47 }
51 render_window->moveContext(); 48 render_window->moveContext();
@@ -90,10 +87,10 @@ public:
90 parent_ = parent; 87 parent_ = parent;
91 } 88 }
92 89
93 void paintEvent(QPaintEvent* ev) 90 void paintEvent(QPaintEvent* ev) override
94 { 91 {
95 } 92 }
96 void resizeEvent(QResizeEvent* ev) { 93 void resizeEvent(QResizeEvent* ev) override {
97 parent_->SetClientAreaWidth(size().width()); 94 parent_->SetClientAreaWidth(size().width());
98 parent_->SetClientAreaHeight(size().height()); 95 parent_->SetClientAreaHeight(size().height());
99 } 96 }
diff --git a/src/citra_qt/bootmanager.hxx b/src/citra_qt/bootmanager.hxx
index 816ffed2e..f8afc403e 100644
--- a/src/citra_qt/bootmanager.hxx
+++ b/src/citra_qt/bootmanager.hxx
@@ -25,7 +25,7 @@ public:
25 * 25 *
26 * @warning Only call when not running! 26 * @warning Only call when not running!
27 */ 27 */
28 void run(); 28 void run() override;
29 29
30 /** 30 /**
31 * Allow the CPU to process a single instruction (if cpu is not running) 31 * Allow the CPU to process a single instruction (if cpu is not running)
@@ -89,13 +89,13 @@ public:
89 GRenderWindow(QWidget* parent = NULL); 89 GRenderWindow(QWidget* parent = NULL);
90 ~GRenderWindow(); 90 ~GRenderWindow();
91 91
92 void closeEvent(QCloseEvent*); 92 void closeEvent(QCloseEvent*) override;
93 93
94 // EmuWindow implementation 94 // EmuWindow implementation
95 void SwapBuffers(); 95 void SwapBuffers() override;
96 void MakeCurrent(); 96 void MakeCurrent() override;
97 void DoneCurrent(); 97 void DoneCurrent() override;
98 void PollEvents(); 98 void PollEvents() override;
99 99
100 void BackupGeometry(); 100 void BackupGeometry();
101 void RestoreGeometry(); 101 void RestoreGeometry();
@@ -104,8 +104,8 @@ public:
104 104
105 EmuThread& GetEmuThread(); 105 EmuThread& GetEmuThread();
106 106
107 void keyPressEvent(QKeyEvent* event); 107 void keyPressEvent(QKeyEvent* event) override;
108 void keyReleaseEvent(QKeyEvent* event); 108 void keyReleaseEvent(QKeyEvent* event) override;
109 109
110 void ReloadSetKeymaps() override; 110 void ReloadSetKeymaps() override;
111 111
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 0ebc15f13..09fce4d6f 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -6,6 +6,7 @@
6#include <QStringList> 6#include <QStringList>
7 7
8#include "core/settings.h" 8#include "core/settings.h"
9#include "core/core.h"
9#include "common/file_util.h" 10#include "common/file_util.h"
10 11
11#include "config.h" 12#include "config.h"
@@ -64,6 +65,20 @@ void Config::SaveControls() {
64 qt_config->endGroup(); 65 qt_config->endGroup();
65} 66}
66 67
68void Config::ReadCore() {
69 qt_config->beginGroup("Core");
70 Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt();
71 Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 60).toInt();
72 qt_config->endGroup();
73}
74
75void Config::SaveCore() {
76 qt_config->beginGroup("Core");
77 qt_config->setValue("cpu_core", Settings::values.cpu_core);
78 qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate);
79 qt_config->endGroup();
80}
81
67void Config::ReadData() { 82void Config::ReadData() {
68 qt_config->beginGroup("Data Storage"); 83 qt_config->beginGroup("Data Storage");
69 Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); 84 Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
@@ -90,12 +105,14 @@ void Config::SaveMiscellaneous() {
90 105
91void Config::Reload() { 106void Config::Reload() {
92 ReadControls(); 107 ReadControls();
108 ReadCore();
93 ReadData(); 109 ReadData();
94 ReadMiscellaneous(); 110 ReadMiscellaneous();
95} 111}
96 112
97void Config::Save() { 113void Config::Save() {
98 SaveControls(); 114 SaveControls();
115 SaveCore();
99 SaveData(); 116 SaveData();
100 SaveMiscellaneous(); 117 SaveMiscellaneous();
101} 118}
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h
index 979902467..8c6568cb2 100644
--- a/src/citra_qt/config.h
+++ b/src/citra_qt/config.h
@@ -14,7 +14,8 @@ class Config {
14 14
15 void ReadControls(); 15 void ReadControls();
16 void SaveControls(); 16 void SaveControls();
17 17 void ReadCore();
18 void SaveCore();
18 void ReadData(); 19 void ReadData();
19 void SaveData(); 20 void SaveData();
20 21
diff --git a/src/citra_qt/debugger/graphics_cmdlists.hxx b/src/citra_qt/debugger/graphics_cmdlists.hxx
index 479ef0326..1523e724f 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.hxx
+++ b/src/citra_qt/debugger/graphics_cmdlists.hxx
@@ -17,7 +17,7 @@ class GPUCommandListModel : public QAbstractListModel
17public: 17public:
18 GPUCommandListModel(QObject* parent); 18 GPUCommandListModel(QObject* parent);
19 19
20 int columnCount(const QModelIndex& parent = QModelIndex()) const; 20 int columnCount(const QModelIndex& parent = QModelIndex()) const override;
21 int rowCount(const QModelIndex& parent = QModelIndex()) const override; 21 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
22 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; 22 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
23 23
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index c99f92835..9a4e36adf 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -121,7 +121,10 @@ GMainWindow::GMainWindow()
121 121
122 show(); 122 show();
123 123
124 System::Init(render_window); 124 QStringList args = QApplication::arguments();
125 if (args.length() >= 2) {
126 BootGame(args[1].toStdString());
127 }
125} 128}
126 129
127GMainWindow::~GMainWindow() 130GMainWindow::~GMainWindow()
@@ -133,10 +136,11 @@ GMainWindow::~GMainWindow()
133 136
134void GMainWindow::BootGame(std::string filename) 137void GMainWindow::BootGame(std::string filename)
135{ 138{
136 NOTICE_LOG(MASTER_LOG, "citra starting...\n"); 139 NOTICE_LOG(MASTER_LOG, "Citra starting...\n");
140 System::Init(render_window);
137 141
138 if (Core::Init()) { 142 if (Core::Init()) {
139 ERROR_LOG(MASTER_LOG, "core initialization failed, exiting..."); 143 ERROR_LOG(MASTER_LOG, "Core initialization failed, exiting...");
140 Core::Stop(); 144 Core::Stop();
141 exit(1); 145 exit(1);
142 } 146 }
@@ -154,6 +158,7 @@ void GMainWindow::BootGame(std::string filename)
154 render_window->GetEmuThread().start(); 158 render_window->GetEmuThread().start();
155 159
156 render_window->show(); 160 render_window->show();
161 OnStartGame();
157} 162}
158 163
159void GMainWindow::OnMenuLoadFile() 164void GMainWindow::OnMenuLoadFile()
@@ -190,6 +195,7 @@ void GMainWindow::OnPauseGame()
190void GMainWindow::OnStopGame() 195void GMainWindow::OnStopGame()
191{ 196{
192 render_window->GetEmuThread().SetCpuRunning(false); 197 render_window->GetEmuThread().SetCpuRunning(false);
198 // TODO: Shutdown core
193 199
194 ui.action_Start->setEnabled(true); 200 ui.action_Start->setEnabled(true);
195 ui.action_Pause->setEnabled(false); 201 ui.action_Pause->setEnabled(false);
@@ -251,7 +257,6 @@ int __cdecl main(int argc, char* argv[])
251 QApplication::setAttribute(Qt::AA_X11InitThreads); 257 QApplication::setAttribute(Qt::AA_X11InitThreads);
252 QApplication app(argc, argv); 258 QApplication app(argc, argv);
253 GMainWindow main_window; 259 GMainWindow main_window;
254
255 main_window.show(); 260 main_window.show();
256 return app.exec(); 261 return app.exec();
257} 262}
diff --git a/src/citra_qt/main.hxx b/src/citra_qt/main.hxx
index a0b41f5f4..b1b40df46 100644
--- a/src/citra_qt/main.hxx
+++ b/src/citra_qt/main.hxx
@@ -32,7 +32,7 @@ public:
32private: 32private:
33 void BootGame(std::string filename); 33 void BootGame(std::string filename);
34 34
35 void closeEvent(QCloseEvent* event); 35 void closeEvent(QCloseEvent* event) override;
36 36
37private slots: 37private slots:
38 void OnStartGame(); 38 void OnStartGame();
diff --git a/src/common/console_listener.h b/src/common/console_listener.h
index 3c0e420c6..ebd90a105 100644
--- a/src/common/console_listener.h
+++ b/src/common/console_listener.h
@@ -26,7 +26,7 @@ public:
26#ifdef _WIN32 26#ifdef _WIN32
27 COORD GetCoordinates(int BytesRead, int BufferWidth); 27 COORD GetCoordinates(int BytesRead, int BufferWidth);
28#endif 28#endif
29 void Log(LogTypes::LOG_LEVELS, const char *Text); 29 void Log(LogTypes::LOG_LEVELS, const char *Text) override;
30 void ClearScreen(bool Cursor = true); 30 void ClearScreen(bool Cursor = true);
31 31
32private: 32private:
diff --git a/src/common/key_map.h b/src/common/key_map.h
index b5acfbab0..bf72362c0 100644
--- a/src/common/key_map.h
+++ b/src/common/key_map.h
@@ -4,7 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/hid.h" 7#include "core/hle/service/hid_user.h"
8 8
9namespace KeyMap { 9namespace KeyMap {
10 10
diff --git a/src/common/log_manager.h b/src/common/log_manager.h
index ce62d0361..de1d16ee5 100644
--- a/src/common/log_manager.h
+++ b/src/common/log_manager.h
@@ -30,7 +30,7 @@ class FileLogListener : public LogListener
30public: 30public:
31 FileLogListener(const char *filename); 31 FileLogListener(const char *filename);
32 32
33 void Log(LogTypes::LOG_LEVELS, const char *msg); 33 void Log(LogTypes::LOG_LEVELS, const char *msg) override;
34 34
35 bool IsValid() { return !m_logfile.fail(); } 35 bool IsValid() { return !m_logfile.fail(); }
36 bool IsEnabled() const { return m_enable; } 36 bool IsEnabled() const { return m_enable; }
@@ -47,7 +47,7 @@ private:
47class DebuggerLogListener : public LogListener 47class DebuggerLogListener : public LogListener
48{ 48{
49public: 49public:
50 void Log(LogTypes::LOG_LEVELS, const char *msg); 50 void Log(LogTypes::LOG_LEVELS, const char *msg) override;
51}; 51};
52 52
53class LogContainer 53class LogContainer
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 61f0939c4..54943d306 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -9,6 +9,7 @@
9 9
10#ifdef _WIN32 10#ifdef _WIN32
11 #include <Windows.h> 11 #include <Windows.h>
12 #include <codecvt>
12#else 13#else
13 #include <iconv.h> 14 #include <iconv.h>
14#endif 15#endif
@@ -411,7 +412,19 @@ std::string UriEncode(const std::string & sSrc)
411 412
412#ifdef _WIN32 413#ifdef _WIN32
413 414
414std::string UTF16ToUTF8(const std::wstring& input) 415std::string UTF16ToUTF8(const std::u16string& input)
416{
417 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
418 return convert.to_bytes(input);
419}
420
421std::u16string UTF8ToUTF16(const std::string& input)
422{
423 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
424 return convert.from_bytes(input);
425}
426
427static std::string UTF16ToUTF8(const std::wstring& input)
415{ 428{
416 auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr); 429 auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr);
417 430
@@ -424,7 +437,7 @@ std::string UTF16ToUTF8(const std::wstring& input)
424 return output; 437 return output;
425} 438}
426 439
427std::wstring CPToUTF16(u32 code_page, const std::string& input) 440static std::wstring CPToUTF16(u32 code_page, const std::string& input)
428{ 441{
429 auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0); 442 auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0);
430 443
@@ -437,7 +450,7 @@ std::wstring CPToUTF16(u32 code_page, const std::string& input)
437 return output; 450 return output;
438} 451}
439 452
440std::wstring UTF8ToUTF16(const std::string& input) 453std::wstring UTF8ToUTF16W(const std::string &input)
441{ 454{
442 return CPToUTF16(CP_UTF8, input); 455 return CPToUTF16(CP_UTF8, input);
443} 456}
@@ -455,61 +468,123 @@ std::string CP1252ToUTF8(const std::string& input)
455#else 468#else
456 469
457template <typename T> 470template <typename T>
458std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input) 471static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
459{ 472{
460 std::string result; 473 std::string result;
461 474
462 iconv_t const conv_desc = iconv_open("UTF-8", fromcode); 475 iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
463 if ((iconv_t)-1 == conv_desc) 476 if ((iconv_t)(-1) == conv_desc)
464 { 477 {
465 ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno)); 478 ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
479 iconv_close(conv_desc);
480 return {};
466 } 481 }
467 else
468 {
469 size_t const in_bytes = sizeof(T) * input.size();
470 size_t const out_buffer_size = 4 * in_bytes;
471 482
472 std::string out_buffer; 483 const size_t in_bytes = sizeof(T) * input.size();
473 out_buffer.resize(out_buffer_size); 484 // Multiply by 4, which is the max number of bytes to encode a codepoint
485 const size_t out_buffer_size = 4 * in_bytes;
474 486
475 auto src_buffer = &input[0]; 487 std::string out_buffer;
476 size_t src_bytes = in_bytes; 488 out_buffer.resize(out_buffer_size);
477 auto dst_buffer = &out_buffer[0];
478 size_t dst_bytes = out_buffer.size();
479 489
480 while (src_bytes != 0) 490 auto src_buffer = &input[0];
481 { 491 size_t src_bytes = in_bytes;
482 size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes, 492 auto dst_buffer = &out_buffer[0];
483 &dst_buffer, &dst_bytes); 493 size_t dst_bytes = out_buffer.size();
484 494
485 if ((size_t)-1 == iconv_result) 495 while (0 != src_bytes)
496 {
497 size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
498 &dst_buffer, &dst_bytes);
499
500 if (static_cast<size_t>(-1) == iconv_result)
501 {
502 if (EILSEQ == errno || EINVAL == errno)
486 { 503 {
487 if (EILSEQ == errno || EINVAL == errno) 504 // Try to skip the bad character
505 if (0 != src_bytes)
488 { 506 {
489 // Try to skip the bad character 507 --src_bytes;
490 if (src_bytes != 0) 508 ++src_buffer;
491 {
492 --src_bytes;
493 ++src_buffer;
494 }
495 }
496 else
497 {
498 ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
499 break;
500 } 509 }
501 } 510 }
511 else
512 {
513 ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
514 break;
515 }
502 } 516 }
517 }
503 518
504 out_buffer.resize(out_buffer_size - dst_bytes); 519 out_buffer.resize(out_buffer_size - dst_bytes);
505 out_buffer.swap(result); 520 out_buffer.swap(result);
506 521
522 iconv_close(conv_desc);
523
524 return result;
525}
526
527std::u16string UTF8ToUTF16(const std::string& input)
528{
529 std::u16string result;
530
531 iconv_t const conv_desc = iconv_open("UTF-16", "UTF-8");
532 if ((iconv_t)(-1) == conv_desc)
533 {
534 ERROR_LOG(COMMON, "Iconv initialization failure [UTF-8]: %s", strerror(errno));
507 iconv_close(conv_desc); 535 iconv_close(conv_desc);
536 return {};
508 } 537 }
538
539 const size_t in_bytes = sizeof(char) * input.size();
540 // Multiply by 4, which is the max number of bytes to encode a codepoint
541 const size_t out_buffer_size = 4 * sizeof(char16_t) * in_bytes;
542
543 std::u16string out_buffer;
544 out_buffer.resize(out_buffer_size);
545
546 char* src_buffer = const_cast<char*>(&input[0]);
547 size_t src_bytes = in_bytes;
548 char* dst_buffer = (char*)(&out_buffer[0]);
549 size_t dst_bytes = out_buffer.size();
550
551 while (0 != src_bytes)
552 {
553 size_t const iconv_result = iconv(conv_desc, &src_buffer, &src_bytes,
554 &dst_buffer, &dst_bytes);
555
556 if (static_cast<size_t>(-1) == iconv_result)
557 {
558 if (EILSEQ == errno || EINVAL == errno)
559 {
560 // Try to skip the bad character
561 if (0 != src_bytes)
562 {
563 --src_bytes;
564 ++src_buffer;
565 }
566 }
567 else
568 {
569 ERROR_LOG(COMMON, "iconv failure [UTF-8]: %s", strerror(errno));
570 break;
571 }
572 }
573 }
574
575 out_buffer.resize(out_buffer_size - dst_bytes);
576 out_buffer.swap(result);
577
578 iconv_close(conv_desc);
509 579
510 return result; 580 return result;
511} 581}
512 582
583std::string UTF16ToUTF8(const std::u16string& input)
584{
585 return CodeToUTF8("UTF-16", input);
586}
587
513std::string CP1252ToUTF8(const std::string& input) 588std::string CP1252ToUTF8(const std::string& input)
514{ 589{
515 //return CodeToUTF8("CP1252//TRANSLIT", input); 590 //return CodeToUTF8("CP1252//TRANSLIT", input);
@@ -523,19 +598,6 @@ std::string SHIFTJISToUTF8(const std::string& input)
523 return CodeToUTF8("SJIS", input); 598 return CodeToUTF8("SJIS", input);
524} 599}
525 600
526std::string UTF16ToUTF8(const std::wstring& input)
527{
528 std::string result =
529 // CodeToUTF8("UCS-2", input);
530 // CodeToUTF8("UCS-2LE", input);
531 // CodeToUTF8("UTF-16", input);
532 CodeToUTF8("UTF-16LE", input);
533
534 // TODO: why is this needed?
535 result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
536 return result;
537}
538
539#endif 601#endif
540 602
541} 603}
diff --git a/src/common/string_util.h b/src/common/string_util.h
index a41ccc691..787a5663f 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -89,20 +89,22 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
89std::string UriDecode(const std::string & sSrc); 89std::string UriDecode(const std::string & sSrc);
90std::string UriEncode(const std::string & sSrc); 90std::string UriEncode(const std::string & sSrc);
91 91
92std::string UTF16ToUTF8(const std::u16string& input);
93std::u16string UTF8ToUTF16(const std::string& input);
94
92std::string CP1252ToUTF8(const std::string& str); 95std::string CP1252ToUTF8(const std::string& str);
93std::string SHIFTJISToUTF8(const std::string& str); 96std::string SHIFTJISToUTF8(const std::string& str);
94std::string UTF16ToUTF8(const std::wstring& str);
95 97
96#ifdef _WIN32 98#ifdef _WIN32
97 99
98std::wstring UTF8ToUTF16(const std::string& str); 100std::wstring UTF8ToUTF16W(const std::string& str);
99 101
100#ifdef _UNICODE 102#ifdef _UNICODE
101inline std::string TStrToUTF8(const std::wstring& str) 103inline std::string TStrToUTF8(const std::wstring& str)
102{ return UTF16ToUTF8(str); } 104{ return UTF16ToUTF8(str); }
103 105
104inline std::wstring UTF8ToTStr(const std::string& str) 106inline std::wstring UTF8ToTStr(const std::string& str)
105{ return UTF8ToUTF16(str); } 107{ return UTF8ToUTF16W(str); }
106#else 108#else
107inline std::string TStrToUTF8(const std::string& str) 109inline std::string TStrToUTF8(const std::string& str)
108{ return str; } 110{ return str; }
diff --git a/src/common/swap.h b/src/common/swap.h
index 123019fd1..4f8f39efb 100644
--- a/src/common/swap.h
+++ b/src/common/swap.h
@@ -85,7 +85,6 @@ public:
85 return *this; 85 return *this;
86 } 86 }
87 87
88 operator long() const { return (long)swap(); }
89 operator s8() const { return (s8)swap(); } 88 operator s8() const { return (s8)swap(); }
90 operator u8() const { return (u8)swap(); } 89 operator u8() const { return (u8)swap(); }
91 operator s16() const { return (s16)swap(); } 90 operator s16() const { return (s16)swap(); }
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index aefbe3375..f41d52e80 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -30,13 +30,23 @@ set(SRCS
30 hle/kernel/mutex.cpp 30 hle/kernel/mutex.cpp
31 hle/kernel/shared_memory.cpp 31 hle/kernel/shared_memory.cpp
32 hle/kernel/thread.cpp 32 hle/kernel/thread.cpp
33 hle/service/apt.cpp 33 hle/service/ac_u.cpp
34 hle/service/fs.cpp 34 hle/service/apt_u.cpp
35 hle/service/gsp.cpp 35 hle/service/cfg_u.cpp
36 hle/service/hid.cpp 36 hle/service/dsp_dsp.cpp
37 hle/service/ndm.cpp 37 hle/service/err_f.cpp
38 hle/service/fs_user.cpp
39 hle/service/frd_u.cpp
40 hle/service/gsp_gpu.cpp
41 hle/service/hid_user.cpp
42 hle/service/mic_u.cpp
43 hle/service/ndm_u.cpp
44 hle/service/nwm_uds.cpp
45 hle/service/ptm_u.cpp
38 hle/service/service.cpp 46 hle/service/service.cpp
47 hle/service/soc_u.cpp
39 hle/service/srv.cpp 48 hle/service/srv.cpp
49 hle/service/ssl_c.cpp
40 hle/config_mem.cpp 50 hle/config_mem.cpp
41 hle/hle.cpp 51 hle/hle.cpp
42 hle/svc.cpp 52 hle/svc.cpp
@@ -91,13 +101,23 @@ set(HEADERS
91 hle/kernel/mutex.h 101 hle/kernel/mutex.h
92 hle/kernel/shared_memory.h 102 hle/kernel/shared_memory.h
93 hle/kernel/thread.h 103 hle/kernel/thread.h
94 hle/service/apt.h 104 hle/service/ac_u.h
95 hle/service/fs.h 105 hle/service/apt_u.h
96 hle/service/gsp.h 106 hle/service/cfg_u.h
97 hle/service/hid.h 107 hle/service/dsp_dsp.h
98 hle/service/ndm.h 108 hle/service/err_f.h
109 hle/service/fs_user.h
110 hle/service/frd_u.h
111 hle/service/gsp_gpu.h
112 hle/service/hid_user.h
113 hle/service/mic_u.h
114 hle/service/ndm_u.h
115 hle/service/nwm_uds.h
116 hle/service/ptm_u.h
99 hle/service/service.h 117 hle/service/service.h
118 hle/service/soc_u.h
100 hle/service/srv.h 119 hle/service/srv.h
120 hle/service/ssl_c.h
101 hle/config_mem.h 121 hle/config_mem.h
102 hle/function_wrappers.h 122 hle/function_wrappers.h
103 hle/hle.h 123 hle/hle.h
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index be677ae20..4b93d3313 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -16,7 +16,7 @@ public:
16 num_instructions = 0; 16 num_instructions = 0;
17 } 17 }
18 18
19 ~ARM_Interface() { 19 virtual ~ARM_Interface() {
20 } 20 }
21 21
22 /** 22 /**
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 669b612fc..a3ed3e31e 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -60,7 +60,7 @@ void ARM_DynCom::SetPC(u32 pc) {
60 * @return Returns current PC 60 * @return Returns current PC
61 */ 61 */
62u32 ARM_DynCom::GetPC() const { 62u32 ARM_DynCom::GetPC() const {
63 return state->pc; 63 return state->Reg[15];
64} 64}
65 65
66/** 66/**
@@ -110,9 +110,12 @@ u64 ARM_DynCom::GetTicks() const {
110 * @param num_instructions Number of instructions to executes 110 * @param num_instructions Number of instructions to executes
111 */ 111 */
112void ARM_DynCom::ExecuteInstructions(int num_instructions) { 112void ARM_DynCom::ExecuteInstructions(int num_instructions) {
113 ticks += num_instructions;
114 state->NumInstrsToExecute = num_instructions; 113 state->NumInstrsToExecute = num_instructions;
115 InterpreterMainLoop(state.get()); 114
115 // Dyncom only breaks on instruction dispatch. This only happens on every instruction when
116 // executing one instruction at a time. Otherwise, if a block is being executed, more
117 // instructions may actually be executed than specified.
118 ticks += InterpreterMainLoop(state.get());
116} 119}
117 120
118/** 121/**
@@ -126,7 +129,7 @@ void ARM_DynCom::SaveContext(ThreadContext& ctx) {
126 129
127 ctx.sp = state->Reg[13]; 130 ctx.sp = state->Reg[13];
128 ctx.lr = state->Reg[14]; 131 ctx.lr = state->Reg[14];
129 ctx.pc = state->pc; 132 ctx.pc = state->Reg[15];
130 ctx.cpsr = state->Cpsr; 133 ctx.cpsr = state->Cpsr;
131 134
132 ctx.fpscr = state->VFP[1]; 135 ctx.fpscr = state->VFP[1];
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 9f88dd139..1f8cd3a3a 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -21,7 +21,7 @@ public:
21 * Set the Program Counter to an address 21 * Set the Program Counter to an address
22 * @param addr Address to set PC to 22 * @param addr Address to set PC to
23 */ 23 */
24 void SetPC(u32 pc); 24 void SetPC(u32 pc) override;
25 25
26 /* 26 /*
27 * Get the current Program Counter 27 * Get the current Program Counter
@@ -41,7 +41,7 @@ public:
41 * @param index Register index (0-15) 41 * @param index Register index (0-15)
42 * @param value Value to set register to 42 * @param value Value to set register to
43 */ 43 */
44 void SetReg(int index, u32 value); 44 void SetReg(int index, u32 value) override;
45 45
46 /** 46 /**
47 * Get the current CPSR register 47 * Get the current CPSR register
@@ -53,7 +53,7 @@ public:
53 * Set the current CPSR register 53 * Set the current CPSR register
54 * @param cpsr Value to set CPSR to 54 * @param cpsr Value to set CPSR to
55 */ 55 */
56 void SetCPSR(u32 cpsr); 56 void SetCPSR(u32 cpsr) override;
57 57
58 /** 58 /**
59 * Returns the number of clock ticks since the last reset 59 * Returns the number of clock ticks since the last reset
@@ -65,22 +65,22 @@ public:
65 * Saves the current CPU context 65 * Saves the current CPU context
66 * @param ctx Thread context to save 66 * @param ctx Thread context to save
67 */ 67 */
68 void SaveContext(ThreadContext& ctx); 68 void SaveContext(ThreadContext& ctx) override;
69 69
70 /** 70 /**
71 * Loads a CPU context 71 * Loads a CPU context
72 * @param ctx Thread context to load 72 * @param ctx Thread context to load
73 */ 73 */
74 void LoadContext(const ThreadContext& ctx); 74 void LoadContext(const ThreadContext& ctx) override;
75 75
76 /// Prepare core for thread reschedule (if needed to correctly handle state) 76 /// Prepare core for thread reschedule (if needed to correctly handle state)
77 void PrepareReschedule(); 77 void PrepareReschedule() override;
78 78
79 /** 79 /**
80 * Executes the given number of instructions 80 * Executes the given number of instructions
81 * @param num_instructions Number of instructions to executes 81 * @param num_instructions Number of instructions to executes
82 */ 82 */
83 void ExecuteInstructions(int num_instructions); 83 void ExecuteInstructions(int num_instructions) override;
84 84
85private: 85private:
86 86
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index fe1501b59..f899e2e8a 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -3718,7 +3718,7 @@ static bool InAPrivilegedMode(arm_core_t *core)
3718} 3718}
3719 3719
3720/* r15 = r15 + 8 */ 3720/* r15 = r15 + 8 */
3721void InterpreterMainLoop(ARMul_State* state) 3721unsigned InterpreterMainLoop(ARMul_State* state)
3722{ 3722{
3723 #define CRn inst_cream->crn 3723 #define CRn inst_cream->crn
3724 #define OPCODE_2 inst_cream->opcode_2 3724 #define OPCODE_2 inst_cream->opcode_2
@@ -3747,16 +3747,22 @@ void InterpreterMainLoop(ARMul_State* state)
3747 #endif 3747 #endif
3748 3748
3749 #define FETCH_INST if (inst_base->br != NON_BRANCH) \ 3749 #define FETCH_INST if (inst_base->br != NON_BRANCH) \
3750 goto PROFILING; \ 3750 goto DISPATCH; \
3751 inst_base = (arm_inst *)&inst_buf[ptr] 3751 inst_base = (arm_inst *)&inst_buf[ptr]
3752#define INC_PC(l) ptr += sizeof(arm_inst) + l 3752#define INC_PC(l) ptr += sizeof(arm_inst) + l
3753 3753
3754// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a 3754// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
3755// clunky switch statement. 3755// clunky switch statement.
3756#if defined __GNUC__ || defined __clang__ 3756#if defined __GNUC__ || defined __clang__
3757#define GOTO_NEXT_INST goto *InstLabel[inst_base->idx] 3757#define GOTO_NEXT_INST \
3758 if (num_instrs >= cpu->NumInstrsToExecute) goto END; \
3759 num_instrs++; \
3760 goto *InstLabel[inst_base->idx]
3758#else 3761#else
3759#define GOTO_NEXT_INST switch(inst_base->idx) { \ 3762#define GOTO_NEXT_INST \
3763 if (num_instrs >= cpu->NumInstrsToExecute) goto END; \
3764 num_instrs++; \
3765 switch(inst_base->idx) { \
3760 case 0: goto VMLA_INST; \ 3766 case 0: goto VMLA_INST; \
3761 case 1: goto VMLS_INST; \ 3767 case 1: goto VMLS_INST; \
3762 case 2: goto VNMLA_INST; \ 3768 case 2: goto VNMLA_INST; \
@@ -4028,20 +4034,15 @@ void InterpreterMainLoop(ARMul_State* state)
4028 unsigned int addr; 4034 unsigned int addr;
4029 unsigned int phys_addr; 4035 unsigned int phys_addr;
4030 unsigned int last_pc = 0; 4036 unsigned int last_pc = 0;
4037 unsigned int num_instrs = 0;
4031 fault_t fault; 4038 fault_t fault;
4032 static unsigned int last_physical_base = 0, last_logical_base = 0; 4039 static unsigned int last_physical_base = 0, last_logical_base = 0;
4033 int ptr; 4040 int ptr;
4041 bool single_step = (cpu->NumInstrsToExecute == 1);
4034 4042
4035 LOAD_NZCVT; 4043 LOAD_NZCVT;
4036 DISPATCH: 4044 DISPATCH:
4037 { 4045 {
4038 if (cpu->NumInstrsToExecute == 0)
4039 return;
4040
4041 cpu->NumInstrsToExecute--;
4042
4043 //NOTICE_LOG(ARM11, "instr!");
4044
4045 if (!cpu->NirqSig) { 4046 if (!cpu->NirqSig) {
4046 if (!(cpu->Cpsr & 0x80)) { 4047 if (!(cpu->Cpsr & 0x80)) {
4047 goto END; 4048 goto END;
@@ -4179,10 +4180,6 @@ void InterpreterMainLoop(ARMul_State* state)
4179 inst_base = (arm_inst *)&inst_buf[ptr]; 4180 inst_base = (arm_inst *)&inst_buf[ptr];
4180 GOTO_NEXT_INST; 4181 GOTO_NEXT_INST;
4181 } 4182 }
4182 PROFILING:
4183 {
4184 goto DISPATCH;
4185 }
4186 ADC_INST: 4183 ADC_INST:
4187 { 4184 {
4188 INC_ICOUNTER; 4185 INC_ICOUNTER;
@@ -4207,7 +4204,7 @@ void InterpreterMainLoop(ARMul_State* state)
4207 } 4204 }
4208 if (inst_cream->Rd == 15) { 4205 if (inst_cream->Rd == 15) {
4209 INC_PC(sizeof(adc_inst)); 4206 INC_PC(sizeof(adc_inst));
4210 goto PROFILING; 4207 goto DISPATCH;
4211 } 4208 }
4212 } 4209 }
4213 cpu->Reg[15] += GET_INST_SIZE(cpu); 4210 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4241,7 +4238,7 @@ void InterpreterMainLoop(ARMul_State* state)
4241 } 4238 }
4242 if (inst_cream->Rd == 15) { 4239 if (inst_cream->Rd == 15) {
4243 INC_PC(sizeof(add_inst)); 4240 INC_PC(sizeof(add_inst));
4244 goto PROFILING; 4241 goto DISPATCH;
4245 } 4242 }
4246 } 4243 }
4247 cpu->Reg[15] += GET_INST_SIZE(cpu); 4244 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4272,7 +4269,7 @@ void InterpreterMainLoop(ARMul_State* state)
4272 } 4269 }
4273 if (inst_cream->Rd == 15) { 4270 if (inst_cream->Rd == 15) {
4274 INC_PC(sizeof(and_inst)); 4271 INC_PC(sizeof(and_inst));
4275 goto PROFILING; 4272 goto DISPATCH;
4276 } 4273 }
4277 } 4274 }
4278 cpu->Reg[15] += GET_INST_SIZE(cpu); 4275 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4290,11 +4287,11 @@ void InterpreterMainLoop(ARMul_State* state)
4290 } 4287 }
4291 SET_PC; 4288 SET_PC;
4292 INC_PC(sizeof(bbl_inst)); 4289 INC_PC(sizeof(bbl_inst));
4293 goto PROFILING; 4290 goto DISPATCH;
4294 } 4291 }
4295 cpu->Reg[15] += GET_INST_SIZE(cpu); 4292 cpu->Reg[15] += GET_INST_SIZE(cpu);
4296 INC_PC(sizeof(bbl_inst)); 4293 INC_PC(sizeof(bbl_inst));
4297 goto PROFILING; 4294 goto DISPATCH;
4298 } 4295 }
4299 BIC_INST: 4296 BIC_INST:
4300 { 4297 {
@@ -4322,7 +4319,7 @@ void InterpreterMainLoop(ARMul_State* state)
4322 } 4319 }
4323 if (inst_cream->Rd == 15) { 4320 if (inst_cream->Rd == 15) {
4324 INC_PC(sizeof(bic_inst)); 4321 INC_PC(sizeof(bic_inst));
4325 goto PROFILING; 4322 goto DISPATCH;
4326 } 4323 }
4327 } 4324 }
4328 cpu->Reg[15] += GET_INST_SIZE(cpu); 4325 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4358,12 +4355,12 @@ void InterpreterMainLoop(ARMul_State* state)
4358 //DEBUG_MSG; 4355 //DEBUG_MSG;
4359 } 4356 }
4360 INC_PC(sizeof(blx_inst)); 4357 INC_PC(sizeof(blx_inst));
4361 goto PROFILING; 4358 goto DISPATCH;
4362 } 4359 }
4363 cpu->Reg[15] += GET_INST_SIZE(cpu); 4360 cpu->Reg[15] += GET_INST_SIZE(cpu);
4364// INC_PC(sizeof(bx_inst)); 4361// INC_PC(sizeof(bx_inst));
4365 INC_PC(sizeof(blx_inst)); 4362 INC_PC(sizeof(blx_inst));
4366 goto PROFILING; 4363 goto DISPATCH;
4367 } 4364 }
4368 BX_INST: 4365 BX_INST:
4369 { 4366 {
@@ -4376,12 +4373,12 @@ void InterpreterMainLoop(ARMul_State* state)
4376 cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe; 4373 cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe;
4377// cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; 4374// cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1;
4378 INC_PC(sizeof(bx_inst)); 4375 INC_PC(sizeof(bx_inst));
4379 goto PROFILING; 4376 goto DISPATCH;
4380 } 4377 }
4381 cpu->Reg[15] += GET_INST_SIZE(cpu); 4378 cpu->Reg[15] += GET_INST_SIZE(cpu);
4382// INC_PC(sizeof(bx_inst)); 4379// INC_PC(sizeof(bx_inst));
4383 INC_PC(sizeof(bx_inst)); 4380 INC_PC(sizeof(bx_inst));
4384 goto PROFILING; 4381 goto DISPATCH;
4385 } 4382 }
4386 BXJ_INST: 4383 BXJ_INST:
4387 CDP_INST: 4384 CDP_INST:
@@ -4393,7 +4390,8 @@ void InterpreterMainLoop(ARMul_State* state)
4393 #define CP_ACCESS_ALLOW 0 4390 #define CP_ACCESS_ALLOW 0
4394 if(CP_ACCESS_ALLOW){ 4391 if(CP_ACCESS_ALLOW){
4395 /* undefined instruction here */ 4392 /* undefined instruction here */
4396 return; 4393 cpu->NumInstrsToExecute = 0;
4394 return num_instrs;
4397 } 4395 }
4398 ERROR_LOG(ARM11, "CDP insn inst=0x%x, pc=0x%x\n", inst_cream->inst, cpu->Reg[15]); 4396 ERROR_LOG(ARM11, "CDP insn inst=0x%x, pc=0x%x\n", inst_cream->inst, cpu->Reg[15]);
4399 unsigned cpab = (cpu->CDP[inst_cream->cp_num]) (cpu, ARMul_FIRST, inst_cream->inst); 4397 unsigned cpab = (cpu->CDP[inst_cream->cp_num]) (cpu, ARMul_FIRST, inst_cream->inst);
@@ -4522,7 +4520,7 @@ void InterpreterMainLoop(ARMul_State* state)
4522// RD = RM; 4520// RD = RM;
4523 if ((inst_cream->Rd == 15)) { 4521 if ((inst_cream->Rd == 15)) {
4524 INC_PC(sizeof(mov_inst)); 4522 INC_PC(sizeof(mov_inst));
4525 goto PROFILING; 4523 goto DISPATCH;
4526 } 4524 }
4527 } 4525 }
4528// DEBUG_LOG(ARM11, "cpy inst %x\n", cpu->Reg[15]); 4526// DEBUG_LOG(ARM11, "cpy inst %x\n", cpu->Reg[15]);
@@ -4558,7 +4556,7 @@ void InterpreterMainLoop(ARMul_State* state)
4558 } 4556 }
4559 if (inst_cream->Rd == 15) { 4557 if (inst_cream->Rd == 15) {
4560 INC_PC(sizeof(eor_inst)); 4558 INC_PC(sizeof(eor_inst));
4561 goto PROFILING; 4559 goto DISPATCH;
4562 } 4560 }
4563 } 4561 }
4564 cpu->Reg[15] += GET_INST_SIZE(cpu); 4562 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4717,7 +4715,7 @@ void InterpreterMainLoop(ARMul_State* state)
4717 } 4715 }
4718 if (BIT(inst, 15)) { 4716 if (BIT(inst, 15)) {
4719 INC_PC(sizeof(ldst_inst)); 4717 INC_PC(sizeof(ldst_inst));
4720 goto PROFILING; 4718 goto DISPATCH;
4721 } 4719 }
4722 } 4720 }
4723 cpu->Reg[15] += GET_INST_SIZE(cpu); 4721 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4764,7 +4762,7 @@ void InterpreterMainLoop(ARMul_State* state)
4764 cpu->TFlag = value & 0x1; 4762 cpu->TFlag = value & 0x1;
4765 cpu->Reg[15] &= 0xFFFFFFFE; 4763 cpu->Reg[15] &= 0xFFFFFFFE;
4766 INC_PC(sizeof(ldst_inst)); 4764 INC_PC(sizeof(ldst_inst));
4767 goto PROFILING; 4765 goto DISPATCH;
4768 } 4766 }
4769 //} 4767 //}
4770 cpu->Reg[15] += GET_INST_SIZE(cpu); 4768 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4794,7 +4792,7 @@ void InterpreterMainLoop(ARMul_State* state)
4794 cpu->TFlag = value & 0x1; 4792 cpu->TFlag = value & 0x1;
4795 cpu->Reg[15] &= 0xFFFFFFFE; 4793 cpu->Reg[15] &= 0xFFFFFFFE;
4796 INC_PC(sizeof(ldst_inst)); 4794 INC_PC(sizeof(ldst_inst));
4797 goto PROFILING; 4795 goto DISPATCH;
4798 } 4796 }
4799 } 4797 }
4800 cpu->Reg[15] += GET_INST_SIZE(cpu); 4798 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4848,7 +4846,7 @@ void InterpreterMainLoop(ARMul_State* state)
4848 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4846 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4849 if (BITS(inst_cream->inst, 12, 15) == 15) { 4847 if (BITS(inst_cream->inst, 12, 15) == 15) {
4850 INC_PC(sizeof(ldst_inst)); 4848 INC_PC(sizeof(ldst_inst));
4851 goto PROFILING; 4849 goto DISPATCH;
4852 } 4850 }
4853 } 4851 }
4854 cpu->Reg[15] += GET_INST_SIZE(cpu); 4852 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4869,7 +4867,7 @@ void InterpreterMainLoop(ARMul_State* state)
4869 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4867 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4870 if (BITS(inst_cream->inst, 12, 15) == 15) { 4868 if (BITS(inst_cream->inst, 12, 15) == 15) {
4871 INC_PC(sizeof(ldst_inst)); 4869 INC_PC(sizeof(ldst_inst));
4872 goto PROFILING; 4870 goto DISPATCH;
4873 } 4871 }
4874 } 4872 }
4875 cpu->Reg[15] += GET_INST_SIZE(cpu); 4873 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4926,7 +4924,7 @@ void InterpreterMainLoop(ARMul_State* state)
4926 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4924 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4927 if (BITS(inst_cream->inst, 12, 15) == 15) { 4925 if (BITS(inst_cream->inst, 12, 15) == 15) {
4928 INC_PC(sizeof(ldst_inst)); 4926 INC_PC(sizeof(ldst_inst));
4929 goto PROFILING; 4927 goto DISPATCH;
4930 } 4928 }
4931 } 4929 }
4932 cpu->Reg[15] += GET_INST_SIZE(cpu); 4930 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4953,7 +4951,7 @@ void InterpreterMainLoop(ARMul_State* state)
4953 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4951 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4954 if (BITS(inst_cream->inst, 12, 15) == 15) { 4952 if (BITS(inst_cream->inst, 12, 15) == 15) {
4955 INC_PC(sizeof(ldst_inst)); 4953 INC_PC(sizeof(ldst_inst));
4956 goto PROFILING; 4954 goto DISPATCH;
4957 } 4955 }
4958 } 4956 }
4959 cpu->Reg[15] += GET_INST_SIZE(cpu); 4957 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -4980,7 +4978,7 @@ void InterpreterMainLoop(ARMul_State* state)
4980 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4978 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4981 if (BITS(inst_cream->inst, 12, 15) == 15) { 4979 if (BITS(inst_cream->inst, 12, 15) == 15) {
4982 INC_PC(sizeof(ldst_inst)); 4980 INC_PC(sizeof(ldst_inst));
4983 goto PROFILING; 4981 goto DISPATCH;
4984 } 4982 }
4985 } 4983 }
4986 cpu->Reg[15] += GET_INST_SIZE(cpu); 4984 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5006,7 +5004,7 @@ void InterpreterMainLoop(ARMul_State* state)
5006 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 5004 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5007 if (BITS(inst_cream->inst, 12, 15) == 15) { 5005 if (BITS(inst_cream->inst, 12, 15) == 15) {
5008 INC_PC(sizeof(ldst_inst)); 5006 INC_PC(sizeof(ldst_inst));
5009 goto PROFILING; 5007 goto DISPATCH;
5010 } 5008 }
5011 } 5009 }
5012 cpu->Reg[15] += GET_INST_SIZE(cpu); 5010 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5031,7 +5029,7 @@ void InterpreterMainLoop(ARMul_State* state)
5031 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 5029 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5032 if (BITS(inst_cream->inst, 12, 15) == 15) { 5030 if (BITS(inst_cream->inst, 12, 15) == 15) {
5033 INC_PC(sizeof(ldst_inst)); 5031 INC_PC(sizeof(ldst_inst));
5034 goto PROFILING; 5032 goto DISPATCH;
5035 } 5033 }
5036 } 5034 }
5037 cpu->Reg[15] += GET_INST_SIZE(cpu); 5035 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5058,7 +5056,7 @@ void InterpreterMainLoop(ARMul_State* state)
5058 5056
5059 if (BITS(inst_cream->inst, 12, 15) == 15) { 5057 if (BITS(inst_cream->inst, 12, 15) == 15) {
5060 INC_PC(sizeof(ldst_inst)); 5058 INC_PC(sizeof(ldst_inst));
5061 goto PROFILING; 5059 goto DISPATCH;
5062 } 5060 }
5063 } 5061 }
5064 cpu->Reg[15] += GET_INST_SIZE(cpu); 5062 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5228,7 +5226,7 @@ void InterpreterMainLoop(ARMul_State* state)
5228 } 5226 }
5229 if (inst_cream->Rd == 15) { 5227 if (inst_cream->Rd == 15) {
5230 INC_PC(sizeof(mla_inst)); 5228 INC_PC(sizeof(mla_inst));
5231 goto PROFILING; 5229 goto DISPATCH;
5232 } 5230 }
5233 } 5231 }
5234 cpu->Reg[15] += GET_INST_SIZE(cpu); 5232 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5260,7 +5258,7 @@ void InterpreterMainLoop(ARMul_State* state)
5260 } 5258 }
5261 if (inst_cream->Rd == 15) { 5259 if (inst_cream->Rd == 15) {
5262 INC_PC(sizeof(mov_inst)); 5260 INC_PC(sizeof(mov_inst));
5263 goto PROFILING; 5261 goto DISPATCH;
5264 } 5262 }
5265// return; 5263// return;
5266 } 5264 }
@@ -5422,7 +5420,7 @@ void InterpreterMainLoop(ARMul_State* state)
5422 } 5420 }
5423 if (inst_cream->Rd == 15) { 5421 if (inst_cream->Rd == 15) {
5424 INC_PC(sizeof(mul_inst)); 5422 INC_PC(sizeof(mul_inst));
5425 goto PROFILING; 5423 goto DISPATCH;
5426 } 5424 }
5427 } 5425 }
5428 cpu->Reg[15] += GET_INST_SIZE(cpu); 5426 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5451,7 +5449,7 @@ void InterpreterMainLoop(ARMul_State* state)
5451 } 5449 }
5452 if (inst_cream->Rd == 15) { 5450 if (inst_cream->Rd == 15) {
5453 INC_PC(sizeof(mvn_inst)); 5451 INC_PC(sizeof(mvn_inst));
5454 goto PROFILING; 5452 goto DISPATCH;
5455 } 5453 }
5456 } 5454 }
5457 cpu->Reg[15] += GET_INST_SIZE(cpu); 5455 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5483,7 +5481,7 @@ void InterpreterMainLoop(ARMul_State* state)
5483 } 5481 }
5484 if (inst_cream->Rd == 15) { 5482 if (inst_cream->Rd == 15) {
5485 INC_PC(sizeof(orr_inst)); 5483 INC_PC(sizeof(orr_inst));
5486 goto PROFILING; 5484 goto DISPATCH;
5487 } 5485 }
5488 } 5486 }
5489 cpu->Reg[15] += GET_INST_SIZE(cpu); 5487 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5575,7 +5573,7 @@ void InterpreterMainLoop(ARMul_State* state)
5575 } 5573 }
5576 if (inst_cream->Rd == 15) { 5574 if (inst_cream->Rd == 15) {
5577 INC_PC(sizeof(rsb_inst)); 5575 INC_PC(sizeof(rsb_inst));
5578 goto PROFILING; 5576 goto DISPATCH;
5579 } 5577 }
5580 } 5578 }
5581 cpu->Reg[15] += GET_INST_SIZE(cpu); 5579 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5612,7 +5610,7 @@ void InterpreterMainLoop(ARMul_State* state)
5612 } 5610 }
5613 if (inst_cream->Rd == 15) { 5611 if (inst_cream->Rd == 15) {
5614 INC_PC(sizeof(rsc_inst)); 5612 INC_PC(sizeof(rsc_inst));
5615 goto PROFILING; 5613 goto DISPATCH;
5616 } 5614 }
5617 } 5615 }
5618 cpu->Reg[15] += GET_INST_SIZE(cpu); 5616 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5653,7 +5651,7 @@ void InterpreterMainLoop(ARMul_State* state)
5653 } 5651 }
5654 if (inst_cream->Rd == 15) { 5652 if (inst_cream->Rd == 15) {
5655 INC_PC(sizeof(sbc_inst)); 5653 INC_PC(sizeof(sbc_inst));
5656 goto PROFILING; 5654 goto DISPATCH;
5657 } 5655 }
5658 } 5656 }
5659 cpu->Reg[15] += GET_INST_SIZE(cpu); 5657 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -6066,7 +6064,7 @@ void InterpreterMainLoop(ARMul_State* state)
6066 } 6064 }
6067 cpu->Reg[15] += GET_INST_SIZE(cpu); 6065 cpu->Reg[15] += GET_INST_SIZE(cpu);
6068 //if (BITS(inst_cream->inst, 12, 15) == 15) 6066 //if (BITS(inst_cream->inst, 12, 15) == 15)
6069 // goto PROFILING; 6067 // goto DISPATCH;
6070 INC_PC(sizeof(ldst_inst)); 6068 INC_PC(sizeof(ldst_inst));
6071 FETCH_INST; 6069 FETCH_INST;
6072 GOTO_NEXT_INST; 6070 GOTO_NEXT_INST;
@@ -6175,7 +6173,7 @@ void InterpreterMainLoop(ARMul_State* state)
6175 } 6173 }
6176 cpu->Reg[15] += GET_INST_SIZE(cpu); 6174 cpu->Reg[15] += GET_INST_SIZE(cpu);
6177 //if (BITS(inst_cream->inst, 12, 15) == 15) 6175 //if (BITS(inst_cream->inst, 12, 15) == 15)
6178 // goto PROFILING; 6176 // goto DISPATCH;
6179 INC_PC(sizeof(ldst_inst)); 6177 INC_PC(sizeof(ldst_inst));
6180 FETCH_INST; 6178 FETCH_INST;
6181 GOTO_NEXT_INST; 6179 GOTO_NEXT_INST;
@@ -6225,7 +6223,7 @@ void InterpreterMainLoop(ARMul_State* state)
6225 } 6223 }
6226 if (inst_cream->Rd == 15) { 6224 if (inst_cream->Rd == 15) {
6227 INC_PC(sizeof(sub_inst)); 6225 INC_PC(sizeof(sub_inst));
6228 goto PROFILING; 6226 goto DISPATCH;
6229 } 6227 }
6230 } 6228 }
6231 cpu->Reg[15] += GET_INST_SIZE(cpu); 6229 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -6449,7 +6447,7 @@ void InterpreterMainLoop(ARMul_State* state)
6449 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; 6447 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
6450 //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); 6448 //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]);
6451 INC_PC(sizeof(b_2_thumb)); 6449 INC_PC(sizeof(b_2_thumb));
6452 goto PROFILING; 6450 goto DISPATCH;
6453 } 6451 }
6454 B_COND_THUMB: 6452 B_COND_THUMB:
6455 { 6453 {
@@ -6461,7 +6459,7 @@ void InterpreterMainLoop(ARMul_State* state)
6461 cpu->Reg[15] += 2; 6459 cpu->Reg[15] += 2;
6462 //DEBUG_LOG(ARM11, " B_COND_THUMB: imm=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[15]); 6460 //DEBUG_LOG(ARM11, " B_COND_THUMB: imm=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[15]);
6463 INC_PC(sizeof(b_cond_thumb)); 6461 INC_PC(sizeof(b_cond_thumb));
6464 goto PROFILING; 6462 goto DISPATCH;
6465 } 6463 }
6466 BL_1_THUMB: 6464 BL_1_THUMB:
6467 { 6465 {
@@ -6487,7 +6485,7 @@ void InterpreterMainLoop(ARMul_State* state)
6487 cpu->Reg[14] = tmp; 6485 cpu->Reg[14] = tmp;
6488 //DEBUG_LOG(ARM11, " BL_2_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); 6486 //DEBUG_LOG(ARM11, " BL_2_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]);
6489 INC_PC(sizeof(bl_2_thumb)); 6487 INC_PC(sizeof(bl_2_thumb));
6490 goto PROFILING; 6488 goto DISPATCH;
6491 } 6489 }
6492 BLX_1_THUMB: 6490 BLX_1_THUMB:
6493 { 6491 {
@@ -6503,7 +6501,7 @@ void InterpreterMainLoop(ARMul_State* state)
6503 cpu->TFlag = 0; 6501 cpu->TFlag = 0;
6504 //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, r15=0x%x, \n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); 6502 //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, r15=0x%x, \n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]);
6505 INC_PC(sizeof(blx_1_thumb)); 6503 INC_PC(sizeof(blx_1_thumb));
6506 goto PROFILING; 6504 goto DISPATCH;
6507 } 6505 }
6508 6506
6509 UQADD16_INST: 6507 UQADD16_INST:
@@ -6532,12 +6530,14 @@ void InterpreterMainLoop(ARMul_State* state)
6532 cpu->AbortAddr = addr; 6530 cpu->AbortAddr = addr;
6533 cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff; 6531 cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff;
6534 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr; 6532 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr;
6535 return; 6533 cpu->NumInstrsToExecute = 0;
6534 return num_instrs;
6536 } 6535 }
6537 END: 6536 END:
6538 { 6537 {
6539 SAVE_NZCVT; 6538 SAVE_NZCVT;
6540 return; 6539 cpu->NumInstrsToExecute = 0;
6540 return num_instrs;
6541 } 6541 }
6542 INIT_INST_LENGTH: 6542 INIT_INST_LENGTH:
6543 { 6543 {
@@ -6557,7 +6557,8 @@ void InterpreterMainLoop(ARMul_State* state)
6557 DEBUG_LOG(ARM11, "%llx\n", InstLabel[1]); 6557 DEBUG_LOG(ARM11, "%llx\n", InstLabel[1]);
6558 DEBUG_LOG(ARM11, "%lld\n", (char *)InstEndLabel[1] - (char *)InstLabel[1]); 6558 DEBUG_LOG(ARM11, "%lld\n", (char *)InstEndLabel[1] - (char *)InstLabel[1]);
6559#endif 6559#endif
6560 return; 6560 cpu->NumInstrsToExecute = 0;
6561 return num_instrs;
6561 } 6562 }
6562} 6563}
6563 6564
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h
index d73f8f65f..c65eb23f7 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.h
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h
@@ -4,4 +4,4 @@
4 4
5#pragma once 5#pragma once
6 6
7void InterpreterMainLoop(ARMul_State* state); 7unsigned InterpreterMainLoop(ARMul_State* state);
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
index 49ae01a0c..ceb1be438 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -20,60 +20,60 @@ public:
20 * Set the Program Counter to an address 20 * Set the Program Counter to an address
21 * @param addr Address to set PC to 21 * @param addr Address to set PC to
22 */ 22 */
23 void SetPC(u32 pc); 23 void SetPC(u32 pc) override;
24 24
25 /* 25 /*
26 * Get the current Program Counter 26 * Get the current Program Counter
27 * @return Returns current PC 27 * @return Returns current PC
28 */ 28 */
29 u32 GetPC() const; 29 u32 GetPC() const override;
30 30
31 /** 31 /**
32 * Get an ARM register 32 * Get an ARM register
33 * @param index Register index (0-15) 33 * @param index Register index (0-15)
34 * @return Returns the value in the register 34 * @return Returns the value in the register
35 */ 35 */
36 u32 GetReg(int index) const; 36 u32 GetReg(int index) const override;
37 37
38 /** 38 /**
39 * Set an ARM register 39 * Set an ARM register
40 * @param index Register index (0-15) 40 * @param index Register index (0-15)
41 * @param value Value to set register to 41 * @param value Value to set register to
42 */ 42 */
43 void SetReg(int index, u32 value); 43 void SetReg(int index, u32 value) override;
44 44
45 /** 45 /**
46 * Get the current CPSR register 46 * Get the current CPSR register
47 * @return Returns the value of the CPSR register 47 * @return Returns the value of the CPSR register
48 */ 48 */
49 u32 GetCPSR() const; 49 u32 GetCPSR() const override;
50 50
51 /** 51 /**
52 * Set the current CPSR register 52 * Set the current CPSR register
53 * @param cpsr Value to set CPSR to 53 * @param cpsr Value to set CPSR to
54 */ 54 */
55 void SetCPSR(u32 cpsr); 55 void SetCPSR(u32 cpsr) override;
56 56
57 /** 57 /**
58 * Returns the number of clock ticks since the last reset 58 * Returns the number of clock ticks since the last reset
59 * @return Returns number of clock ticks 59 * @return Returns number of clock ticks
60 */ 60 */
61 u64 GetTicks() const; 61 u64 GetTicks() const override;
62 62
63 /** 63 /**
64 * Saves the current CPU context 64 * Saves the current CPU context
65 * @param ctx Thread context to save 65 * @param ctx Thread context to save
66 */ 66 */
67 void SaveContext(ThreadContext& ctx); 67 void SaveContext(ThreadContext& ctx) override;
68 68
69 /** 69 /**
70 * Loads a CPU context 70 * Loads a CPU context
71 * @param ctx Thread context to load 71 * @param ctx Thread context to load
72 */ 72 */
73 void LoadContext(const ThreadContext& ctx); 73 void LoadContext(const ThreadContext& ctx) override;
74 74
75 /// Prepare core for thread reschedule (if needed to correctly handle state) 75 /// Prepare core for thread reschedule (if needed to correctly handle state)
76 void PrepareReschedule(); 76 void PrepareReschedule() override;
77 77
78protected: 78protected:
79 79
@@ -81,7 +81,7 @@ protected:
81 * Executes the given number of instructions 81 * Executes the given number of instructions
82 * @param num_instructions Number of instructions to executes 82 * @param num_instructions Number of instructions to executes
83 */ 83 */
84 void ExecuteInstructions(int num_instructions); 84 void ExecuteInstructions(int num_instructions) override;
85 85
86private: 86private:
87 87
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index cdcf47ee1..73223874e 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -63,13 +63,6 @@ static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
63static void Handle_Load_Double (ARMul_State *, ARMword); 63static void Handle_Load_Double (ARMul_State *, ARMword);
64static void Handle_Store_Double (ARMul_State *, ARMword); 64static void Handle_Store_Double (ARMul_State *, ARMword);
65 65
66void
67XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far);
68int
69XScale_debug_moe (ARMul_State * state, int moe);
70unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
71 unsigned cpnum);
72
73static int 66static int
74handle_v6_insn (ARMul_State * state, ARMword instr); 67handle_v6_insn (ARMul_State * state, ARMword instr);
75 68
@@ -376,7 +369,7 @@ ARMul_Emulate26 (ARMul_State * state)
376#endif 369#endif
377{ 370{
378 /* The PC pipeline value depends on whether ARM 371 /* The PC pipeline value depends on whether ARM
379 or Thumb instructions are being 372 or Thumb instructions are being
380 d. */ 373 d. */
381 ARMword isize; 374 ARMword isize;
382 ARMword instr; /* The current instruction. */ 375 ARMword instr; /* The current instruction. */
@@ -538,6 +531,7 @@ ARMul_Emulate26 (ARMul_State * state)
538 state->AbortAddr = 1; 531 state->AbortAddr = 1;
539 532
540 instr = ARMul_LoadInstrN (state, pc, isize); 533 instr = ARMul_LoadInstrN (state, pc, isize);
534
541 //chy 2006-04-12, for ICE debug 535 //chy 2006-04-12, for ICE debug
542 have_bp=ARMul_ICE_debug(state,instr,pc); 536 have_bp=ARMul_ICE_debug(state,instr,pc);
543#if 0 537#if 0
@@ -562,6 +556,7 @@ ARMul_Emulate26 (ARMul_State * state)
562 } 556 }
563 printf("\n"); 557 printf("\n");
564#endif 558#endif
559
565 instr = ARMul_LoadInstrN (state, pc, isize); 560 instr = ARMul_LoadInstrN (state, pc, isize);
566 state->last_instr = state->CurrInstr; 561 state->last_instr = state->CurrInstr;
567 state->CurrInstr = instr; 562 state->CurrInstr = instr;
@@ -952,9 +947,8 @@ ARMul_Emulate26 (ARMul_State * state)
952 case t_decoded: 947 case t_decoded:
953 /* ARM instruction available. */ 948 /* ARM instruction available. */
954 //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp); 949 //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp);
955 950
956 if (armOp == 0xDEADC0DE) 951 if (armOp == 0xDEADC0DE) {
957 {
958 DEBUG("Failed to decode thumb opcode %04X at %08X\n", instr, pc); 952 DEBUG("Failed to decode thumb opcode %04X at %08X\n", instr, pc);
959 } 953 }
960 954
@@ -967,7 +961,6 @@ ARMul_Emulate26 (ARMul_State * state)
967 } 961 }
968 } 962 }
969#endif 963#endif
970
971 /* Check the condition codes. */ 964 /* Check the condition codes. */
972 if ((temp = TOPBITS (28)) == AL) { 965 if ((temp = TOPBITS (28)) == AL) {
973 /* Vile deed in the need for speed. */ 966 /* Vile deed in the need for speed. */
@@ -1124,6 +1117,7 @@ ARMul_Emulate26 (ARMul_State * state)
1124 1117
1125//chy 2003-08-24 now #if 0 .... #endif process cp14, cp15.reg14, I disable it... 1118//chy 2003-08-24 now #if 0 .... #endif process cp14, cp15.reg14, I disable it...
1126 1119
1120
1127 /* Actual execution of instructions begins here. */ 1121 /* Actual execution of instructions begins here. */
1128 /* If the condition codes don't match, stop here. */ 1122 /* If the condition codes don't match, stop here. */
1129 if (temp) { 1123 if (temp) {
@@ -2308,12 +2302,9 @@ mainswitch:
2308 if (state->Aborted) { 2302 if (state->Aborted) {
2309 TAKEABORT; 2303 TAKEABORT;
2310 } 2304 }
2311 if (enter) 2305 if (enter) {
2312 {
2313 state->Reg[DESTReg] = 0; 2306 state->Reg[DESTReg] = 0;
2314 } 2307 } else {
2315 else
2316 {
2317 state->Reg[DESTReg] = 1; 2308 state->Reg[DESTReg] = 1;
2318 } 2309 }
2319 break; 2310 break;
@@ -3063,7 +3054,27 @@ mainswitch:
3063 break; 3054 break;
3064 3055
3065 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ 3056 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3066 if (BIT (4)) { 3057 //ichfly PKHBT PKHTB todo check this
3058 if ((instr & 0x70) == 0x10) //pkhbt
3059 {
3060 u8 idest = BITS(12, 15);
3061 u8 rfis = BITS(16, 19);
3062 u8 rlast = BITS(0, 3);
3063 u8 ishi = BITS(7,11);
3064 state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000);
3065 break;
3066 }
3067 else if ((instr & 0x70) == 0x50)//pkhtb
3068 {
3069 u8 idest = BITS(12, 15);
3070 u8 rfis = BITS(16, 19);
3071 u8 rlast = BITS(0, 3);
3072 u8 ishi = BITS(7, 11);
3073 if (ishi == 0)ishi = 0x20;
3074 state->Reg[idest] = (((int)(state->Reg[rlast]) >> (int)(ishi))& 0xFFFF) | ((state->Reg[rfis]) & 0xFFFF0000);
3075 break;
3076 }
3077 else if (BIT (4)) {
3067#ifdef MODE32 3078#ifdef MODE32
3068 if (state->is_v6 3079 if (state->is_v6
3069 && handle_v6_insn (state, instr)) 3080 && handle_v6_insn (state, instr))
@@ -3675,7 +3686,13 @@ mainswitch:
3675 3686
3676 /* Co-Processor Data Transfers. */ 3687 /* Co-Processor Data Transfers. */
3677 case 0xc4: 3688 case 0xc4:
3678 if (state->is_v5) { 3689 if ((instr & 0x0FF00FF0) == 0xC400B10) //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0
3690 {
3691 state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)];
3692 state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)];
3693 break;
3694 }
3695 else if (state->is_v5) {
3679 /* Reading from R15 is UNPREDICTABLE. */ 3696 /* Reading from R15 is UNPREDICTABLE. */
3680 if (BITS (12, 15) == 15 || BITS (16, 19) == 15) 3697 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3681 ARMul_UndefInstr (state, instr); 3698 ARMul_UndefInstr (state, instr);
@@ -3695,13 +3712,21 @@ mainswitch:
3695 break; 3712 break;
3696 3713
3697 case 0xc5: 3714 case 0xc5:
3698 if (state->is_v5) { 3715 if ((instr & 0x00000FF0) == 0xB10) //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0
3716 {
3717 state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1];
3718 state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1];
3719 break;
3720 }
3721 else if (state->is_v5) {
3699 /* Writes to R15 are UNPREDICATABLE. */ 3722 /* Writes to R15 are UNPREDICATABLE. */
3700 if (DESTReg == 15 || LHSReg == 15) 3723 if (DESTReg == 15 || LHSReg == 15)
3701 ARMul_UndefInstr (state, instr); 3724 ARMul_UndefInstr (state, instr);
3702 /* Is access to the coprocessor allowed ? */ 3725 /* Is access to the coprocessor allowed ? */
3703 else if (!CP_ACCESS_ALLOWED(state, CPNum)) 3726 else if (!CP_ACCESS_ALLOWED(state, CPNum))
3704 ARMul_UndefInstr (state, instr); 3727 {
3728 ARMul_UndefInstr(state, instr);
3729 }
3705 else { 3730 else {
3706 /* MRRC, ARMv5TE and up */ 3731 /* MRRC, ARMv5TE and up */
3707 ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); 3732 ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg]));
@@ -4059,9 +4084,11 @@ TEST_EMULATE:
4059 // continue; 4084 // continue;
4060 else if (state->Emulate != RUN) 4085 else if (state->Emulate != RUN)
4061 break; 4086 break;
4062 } 4087
4063 while (state->NumInstrsToExecute--); 4088 }
4064 4089
4090 while (state->NumInstrsToExecute);
4091exit:
4065 state->decoded = decoded; 4092 state->decoded = decoded;
4066 state->loaded = loaded; 4093 state->loaded = loaded;
4067 state->pc = pc; 4094 state->pc = pc;
@@ -5686,12 +5713,98 @@ L_stm_s_takeabort:
5686 case 0x3f: 5713 case 0x3f:
5687 printf ("Unhandled v6 insn: rbit\n"); 5714 printf ("Unhandled v6 insn: rbit\n");
5688 break; 5715 break;
5716#endif
5689 case 0x61: 5717 case 0x61:
5690 printf ("Unhandled v6 insn: sadd/ssub\n"); 5718 if ((instr & 0xFF0) == 0xf70)//ssub16
5719 {
5720 u8 tar = BITS(12, 15);
5721 u8 src1 = BITS(16, 19);
5722 u8 src2 = BITS(0, 3);
5723 s16 a1 = (state->Reg[src1] & 0xFFFF);
5724 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5725 s16 b1 = (state->Reg[src2] & 0xFFFF);
5726 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5727 state->Reg[tar] = (a1 - a2)&0xFFFF | (((b1 - b2)&0xFFFF)<< 0x10);
5728 return 1;
5729 }
5730 else if ((instr & 0xFF0) == 0xf10)//sadd16
5731 {
5732 u8 tar = BITS(12, 15);
5733 u8 src1 = BITS(16, 19);
5734 u8 src2 = BITS(0, 3);
5735 s16 a1 = (state->Reg[src1] & 0xFFFF);
5736 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5737 s16 b1 = (state->Reg[src2] & 0xFFFF);
5738 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5739 state->Reg[tar] = (a1 + a2)&0xFFFF | (((b1 + b2)&0xFFFF)<< 0x10);
5740 return 1;
5741 }
5742 else if ((instr & 0xFF0) == 0xf50)//ssax
5743 {
5744 u8 tar = BITS(12, 15);
5745 u8 src1 = BITS(16, 19);
5746 u8 src2 = BITS(0, 3);
5747 s16 a1 = (state->Reg[src1] & 0xFFFF);
5748 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5749 s16 b1 = (state->Reg[src2] & 0xFFFF);
5750 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5751 state->Reg[tar] = (a1 - b2) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10);
5752 return 1;
5753 }
5754 else if ((instr & 0xFF0) == 0xf30)//sasx
5755 {
5756 u8 tar = BITS(12, 15);
5757 u8 src1 = BITS(16, 19);
5758 u8 src2 = BITS(0, 3);
5759 s16 a1 = (state->Reg[src1] & 0xFFFF);
5760 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5761 s16 b1 = (state->Reg[src2] & 0xFFFF);
5762 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5763 state->Reg[tar] = (a2 - b1) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10);
5764 return 1;
5765 }
5766 else printf ("Unhandled v6 insn: sadd/ssub\n");
5691 break; 5767 break;
5692 case 0x62: 5768 case 0x62:
5693 printf ("Unhandled v6 insn: qadd/qsub\n"); 5769 if ((instr & 0xFF0) == 0xf70)//QSUB16
5770 {
5771 u8 tar = BITS(12, 15);
5772 u8 src1 = BITS(16, 19);
5773 u8 src2 = BITS(0, 3);
5774 s16 a1 = (state->Reg[src1] & 0xFFFF);
5775 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5776 s16 b1 = (state->Reg[src2] & 0xFFFF);
5777 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5778 s32 res1 = (a1 - b1);
5779 s32 res2 = (a2 - b2);
5780 if (res1 > 0x7FFF) res1 = 0x7FFF;
5781 if (res2 > 0x7FFF) res2 = 0x7FFF;
5782 if (res1 < 0x7FFF) res1 = -0x8000;
5783 if (res2 < 0x7FFF) res2 = -0x8000;
5784 state->Reg[tar] = (res1 & 0xFFFF) | ((res2 & 0xFFFF) << 0x10);
5785 return 1;
5786 }
5787 else if ((instr & 0xFF0) == 0xf10)//QADD16
5788 {
5789 u8 tar = BITS(12, 15);
5790 u8 src1 = BITS(16, 19);
5791 u8 src2 = BITS(0, 3);
5792 s16 a1 = (state->Reg[src1] & 0xFFFF);
5793 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5794 s16 b1 = (state->Reg[src2] & 0xFFFF);
5795 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5796 s32 res1 = (a1 + b1);
5797 s32 res2 = (a2 + b2);
5798 if (res1 > 0x7FFF) res1 = 0x7FFF;
5799 if (res2 > 0x7FFF) res2 = 0x7FFF;
5800 if (res1 < 0x7FFF) res1 = -0x8000;
5801 if (res2 < 0x7FFF) res2 = -0x8000;
5802 state->Reg[tar] = ((res1) & 0xFFFF) | (((res2) & 0xFFFF) << 0x10);
5803 return 1;
5804 }
5805 else printf ("Unhandled v6 insn: qadd/qsub\n");
5694 break; 5806 break;
5807#if 0
5695 case 0x63: 5808 case 0x63:
5696 printf ("Unhandled v6 insn: shadd/shsub\n"); 5809 printf ("Unhandled v6 insn: shadd/shsub\n");
5697 break; 5810 break;
@@ -5709,10 +5822,65 @@ L_stm_s_takeabort:
5709 break; 5822 break;
5710#endif 5823#endif
5711 case 0x6c: 5824 case 0x6c:
5712 printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); 5825 if ((instr & 0xf03f0) == 0xf0070) //uxtb16
5826 {
5827 u8 src1 = BITS(0, 3);
5828 u8 tar = BITS(12, 15);
5829 u32 base = state->Reg[src1];
5830 u32 shamt = BITS(9,10)* 8;
5831 u32 in = ((base << (32 - shamt)) | (base >> shamt));
5832 state->Reg[tar] = in & 0x00FF00FF;
5833 return 1;
5834 }
5835 else
5836 printf ("Unhandled v6 insn: uxtb16/uxtab16\n");
5713 break; 5837 break;
5714 case 0x70: 5838 case 0x70:
5715 printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); 5839 if ((instr & 0xf0d0) == 0xf010)//smuad //ichfly
5840 {
5841 u8 tar = BITS(16, 19);
5842 u8 src1 = BITS(0, 3);
5843 u8 src2 = BITS(8, 11);
5844 u8 swap = BIT(5);
5845 s16 a1 = (state->Reg[src1] & 0xFFFF);
5846 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5847 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF);
5848 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF);
5849 state->Reg[tar] = a1*a2 + b1*b2;
5850 return 1;
5851
5852 }
5853 else if ((instr & 0xf0d0) == 0xf050)//smusd
5854 {
5855 u8 tar = BITS(16, 19);
5856 u8 src1 = BITS(0, 3);
5857 u8 src2 = BITS(8, 11);
5858 u8 swap = BIT(5);
5859 s16 a1 = (state->Reg[src1] & 0xFFFF);
5860 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5861 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF);
5862 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF);
5863 state->Reg[tar] = a1*a2 - b1*b2;
5864 return 1;
5865 }
5866 else if ((instr & 0xd0) == 0x10)//smlad
5867 {
5868 u8 tar = BITS(16, 19);
5869 u8 src1 = BITS(0, 3);
5870 u8 src2 = BITS(8, 11);
5871 u8 src3 = BITS(12, 15);
5872 u8 swap = BIT(5);
5873
5874 u32 a3 = state->Reg[src3];
5875
5876 s16 a1 = (state->Reg[src1] & 0xFFFF);
5877 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5878 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF);
5879 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF);
5880 state->Reg[tar] = a1*a2 + b1*b2 + a3;
5881 return 1;
5882 }
5883 else printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n");
5716 break; 5884 break;
5717 case 0x74: 5885 case 0x74:
5718 printf ("Unhandled v6 insn: smlald/smlsld\n"); 5886 printf ("Unhandled v6 insn: smlald/smlsld\n");
@@ -5750,13 +5918,10 @@ L_stm_s_takeabort:
5750 if (state->Aborted) { 5918 if (state->Aborted) {
5751 TAKEABORT; 5919 TAKEABORT;
5752 } 5920 }
5753 5921
5754 if (enter) 5922 if (enter) {
5755 {
5756 state->Reg[DESTReg] = 0; 5923 state->Reg[DESTReg] = 0;
5757 } 5924 } else {
5758 else
5759 {
5760 state->Reg[DESTReg] = 1; 5925 state->Reg[DESTReg] = 1;
5761 } 5926 }
5762 5927
@@ -5795,12 +5960,9 @@ L_stm_s_takeabort:
5795 } 5960 }
5796 5961
5797 5962
5798 if (enter) 5963 if (enter) {
5799 {
5800 state->Reg[DESTReg] = 0; 5964 state->Reg[DESTReg] = 0;
5801 } 5965 } else {
5802 else
5803 {
5804 state->Reg[DESTReg] = 1; 5966 state->Reg[DESTReg] = 1;
5805 } 5967 }
5806 5968
@@ -5853,8 +6015,25 @@ L_stm_s_takeabort:
5853 6015
5854 case 0x01: 6016 case 0x01:
5855 case 0xf3: 6017 case 0xf3:
5856 printf ("Unhandled v6 insn: ssat\n"); 6018 //ichfly
5857 return 0; 6019 //SSAT16
6020 {
6021 u8 tar = BITS(12,15);
6022 u8 src = BITS(0, 3);
6023 u8 val = BITS(16, 19) + 1;
6024 s16 a1 = (state->Reg[src]);
6025 s16 a2 = (state->Reg[src] >> 0x10);
6026 s16 min = (s16)(0x8000) >> (16 - val);
6027 s16 max = 0x7FFF >> (16 - val);
6028 if (min > a1) a1 = min;
6029 if (max < a1) a1 = max;
6030 if (min > a2) a2 = min;
6031 if (max < a2) a2 = max;
6032 u32 temp2 = ((u32)(a2)) << 0x10;
6033 state->Reg[tar] = (a1&0xFFFF) | (temp2);
6034 }
6035
6036 return 1;
5858 default: 6037 default:
5859 break; 6038 break;
5860 } 6039 }
@@ -5944,8 +6123,21 @@ L_stm_s_takeabort:
5944 6123
5945 case 0x01: 6124 case 0x01:
5946 case 0xf3: 6125 case 0xf3:
5947 printf ("Unhandled v6 insn: usat\n"); 6126 //ichfly
5948 return 0; 6127 //USAT16
6128 {
6129 u8 tar = BITS(12, 15);
6130 u8 src = BITS(0, 3);
6131 u8 val = BITS(16, 19);
6132 s16 a1 = (state->Reg[src]);
6133 s16 a2 = (state->Reg[src] >> 0x10);
6134 s16 max = 0xFFFF >> (16 - val);
6135 if (max < a1) a1 = max;
6136 if (max < a2) a2 = max;
6137 u32 temp2 = ((u32)(a2)) << 0x10;
6138 state->Reg[tar] = (a1 & 0xFFFF) | (temp2);
6139 }
6140 return 1;
5949 default: 6141 default:
5950 break; 6142 break;
5951 } 6143 }
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index e4fa3c20a..454f60099 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -28,230 +28,270 @@
28#include "core/arm/skyeye_common/armdefs.h" 28#include "core/arm/skyeye_common/armdefs.h"
29#include "core/arm/skyeye_common/vfp/vfp.h" 29#include "core/arm/skyeye_common/vfp/vfp.h"
30 30
31#define DEBUG DBG
32
31//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */ 33//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
32 34
33unsigned 35unsigned
34VFPInit (ARMul_State *state) 36VFPInit (ARMul_State *state)
35{ 37{
36 state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | 38 state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |
37 VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; 39 VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
38 state->VFP[VFP_OFFSET(VFP_FPEXC)] = 0; 40 state->VFP[VFP_OFFSET(VFP_FPEXC)] = 0;
39 state->VFP[VFP_OFFSET(VFP_FPSCR)] = 0; 41 state->VFP[VFP_OFFSET(VFP_FPSCR)] = 0;
40 42
41 //persistent_state = state; 43 //persistent_state = state;
42 /* Reset only specify VFP_FPEXC_EN = '0' */ 44 /* Reset only specify VFP_FPEXC_EN = '0' */
43 45
44 return No_exp; 46 return 0;
45} 47}
46 48
47unsigned 49unsigned
48VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value) 50VFPMRC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
49{ 51{
50 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ 52 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
51 int CoProc = BITS (8, 11); /* 10 or 11 */ 53 int CoProc = BITS (8, 11); /* 10 or 11 */
52 int OPC_1 = BITS (21, 23); 54 int OPC_1 = BITS (21, 23);
53 int Rt = BITS (12, 15); 55 int Rt = BITS (12, 15);
54 int CRn = BITS (16, 19); 56 int CRn = BITS (16, 19);
55 int CRm = BITS (0, 3); 57 int CRm = BITS (0, 3);
56 int OPC_2 = BITS (5, 7); 58 int OPC_2 = BITS (5, 7);
57 59
58 /* TODO check access permission */ 60 /* TODO check access permission */
59 61
60 /* CRn/opc1 CRm/opc2 */ 62 /* CRn/opc1 CRm/opc2 */
61 63
62 if (CoProc == 10 || CoProc == 11) 64 if (CoProc == 10 || CoProc == 11) {
63 { 65#define VFP_MRC_TRANS
64 #define VFP_MRC_TRANS 66#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
65 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 67#undef VFP_MRC_TRANS
66 #undef VFP_MRC_TRANS 68 }
67 } 69 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
68 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", 70 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
69 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); 71
70 72 return ARMul_CANT;
71 return ARMul_CANT;
72} 73}
73 74
74unsigned 75unsigned
75VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value) 76VFPMCR (ARMul_State * state, unsigned type, u32 instr, u32 value)
76{ 77{
77 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ 78 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
78 int CoProc = BITS (8, 11); /* 10 or 11 */ 79 int CoProc = BITS (8, 11); /* 10 or 11 */
79 int OPC_1 = BITS (21, 23); 80 int OPC_1 = BITS (21, 23);
80 int Rt = BITS (12, 15); 81 int Rt = BITS (12, 15);
81 int CRn = BITS (16, 19); 82 int CRn = BITS (16, 19);
82 int CRm = BITS (0, 3); 83 int CRm = BITS (0, 3);
83 int OPC_2 = BITS (5, 7); 84 int OPC_2 = BITS (5, 7);
84 85
85 /* TODO check access permission */ 86 /* TODO check access permission */
86 87
87 /* CRn/opc1 CRm/opc2 */ 88 /* CRn/opc1 CRm/opc2 */
88 if (CoProc == 10 || CoProc == 11) 89 if (CoProc == 10 || CoProc == 11) {
89 { 90#define VFP_MCR_TRANS
90 #define VFP_MCR_TRANS 91#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
91 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 92#undef VFP_MCR_TRANS
92 #undef VFP_MCR_TRANS 93 }
93 } 94 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
94 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", 95 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
95 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); 96
96 97 return ARMul_CANT;
97 return ARMul_CANT;
98} 98}
99 99
100unsigned 100unsigned
101VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, ARMword * value2) 101VFPMRRC (ARMul_State * state, unsigned type, u32 instr, u32 * value1, u32 * value2)
102{ 102{
103 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ 103 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
104 int CoProc = BITS (8, 11); /* 10 or 11 */ 104 int CoProc = BITS (8, 11); /* 10 or 11 */
105 int OPC_1 = BITS (4, 7); 105 int OPC_1 = BITS (4, 7);
106 int Rt = BITS (12, 15); 106 int Rt = BITS (12, 15);
107 int Rt2 = BITS (16, 19); 107 int Rt2 = BITS (16, 19);
108 int CRm = BITS (0, 3); 108 int CRm = BITS (0, 3);
109 109
110 if (CoProc == 10 || CoProc == 11) 110 if (CoProc == 10 || CoProc == 11) {
111 { 111#define VFP_MRRC_TRANS
112 #define VFP_MRRC_TRANS 112#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
113 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 113#undef VFP_MRRC_TRANS
114 #undef VFP_MRRC_TRANS 114 }
115 } 115 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
116 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", 116 instr, CoProc, OPC_1, Rt, Rt2, CRm);
117 instr, CoProc, OPC_1, Rt, Rt2, CRm); 117
118 118 return ARMul_CANT;
119 return ARMul_CANT;
120} 119}
121 120
122unsigned 121unsigned
123VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMword value2) 122VFPMCRR (ARMul_State * state, unsigned type, u32 instr, u32 value1, u32 value2)
124{ 123{
125 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ 124 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
126 int CoProc = BITS (8, 11); /* 10 or 11 */ 125 int CoProc = BITS (8, 11); /* 10 or 11 */
127 int OPC_1 = BITS (4, 7); 126 int OPC_1 = BITS (4, 7);
128 int Rt = BITS (12, 15); 127 int Rt = BITS (12, 15);
129 int Rt2 = BITS (16, 19); 128 int Rt2 = BITS (16, 19);
130 int CRm = BITS (0, 3); 129 int CRm = BITS (0, 3);
131 130
132 /* TODO check access permission */ 131 /* TODO check access permission */
133 132
134 /* CRn/opc1 CRm/opc2 */ 133 /* CRn/opc1 CRm/opc2 */
135 134
136 if (CoProc == 11 || CoProc == 10) 135 if (CoProc == 11 || CoProc == 10) {
137 { 136#define VFP_MCRR_TRANS
138 #define VFP_MCRR_TRANS 137#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
139 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 138#undef VFP_MCRR_TRANS
140 #undef VFP_MCRR_TRANS 139 }
141 } 140 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
142 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", 141 instr, CoProc, OPC_1, Rt, Rt2, CRm);
143 instr, CoProc, OPC_1, Rt, Rt2, CRm); 142
144 143 return ARMul_CANT;
145 return ARMul_CANT;
146} 144}
147 145
148unsigned 146unsigned
149VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value) 147VFPSTC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
150{ 148{
151 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */ 149 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
152 int CoProc = BITS (8, 11); /* 10 or 11 */ 150 int CoProc = BITS (8, 11); /* 10 or 11 */
153 int CRd = BITS (12, 15); 151 int CRd = BITS (12, 15);
154 int Rn = BITS (16, 19); 152 int Rn = BITS (16, 19);
155 int imm8 = BITS (0, 7); 153 int imm8 = BITS (0, 7);
156 int P = BIT(24); 154 int P = BIT(24);
157 int U = BIT(23); 155 int U = BIT(23);
158 int D = BIT(22); 156 int D = BIT(22);
159 int W = BIT(21); 157 int W = BIT(21);
160 158
161 /* TODO check access permission */ 159 /* TODO check access permission */
162 160
163 /* VSTM */ 161 /* VSTM */
164 if ( (P|U|D|W) == 0 ) 162 if ( (P|U|D|W) == 0 ) {
165 { 163 DEBUG("In %s, UNDEFINED\n", __FUNCTION__);
166 DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1); 164 exit(-1);
167 } 165 }
168 if (CoProc == 10 || CoProc == 11) 166 if (CoProc == 10 || CoProc == 11) {
169 { 167#if 1
170 #if 1 168 if (P == 0 && U == 0 && W == 0) {
171 if (P == 0 && U == 0 && W == 0) 169 DEBUG("VSTM Related encodings\n");
172 { 170 exit(-1);
173 DEBUG_LOG(ARM11, "VSTM Related encodings\n"); exit(-1); 171 }
174 } 172 if (P == U && W == 1) {
175 if (P == U && W == 1) 173 DEBUG("UNDEFINED\n");
176 { 174 exit(-1);
177 DEBUG_LOG(ARM11, "UNDEFINED\n"); exit(-1); 175 }
178 } 176#endif
179 #endif 177
180 178#define VFP_STC_TRANS
181 #define VFP_STC_TRANS 179#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
182 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 180#undef VFP_STC_TRANS
183 #undef VFP_STC_TRANS 181 }
184 } 182 DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
185 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", 183 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
186 instr, CoProc, CRd, Rn, imm8, P, U, D, W); 184
187 185 return ARMul_CANT;
188 return ARMul_CANT;
189} 186}
190 187
191unsigned 188unsigned
192VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value) 189VFPLDC (ARMul_State * state, unsigned type, u32 instr, u32 value)
193{ 190{
194 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ 191 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
195 int CoProc = BITS (8, 11); /* 10 or 11 */ 192 int CoProc = BITS (8, 11); /* 10 or 11 */
196 int CRd = BITS (12, 15); 193 int CRd = BITS (12, 15);
197 int Rn = BITS (16, 19); 194 int Rn = BITS (16, 19);
198 int imm8 = BITS (0, 7); 195 int imm8 = BITS (0, 7);
199 int P = BIT(24); 196 int P = BIT(24);
200 int U = BIT(23); 197 int U = BIT(23);
201 int D = BIT(22); 198 int D = BIT(22);
202 int W = BIT(21); 199 int W = BIT(21);
203 200
204 /* TODO check access permission */ 201 /* TODO check access permission */
205 202
206 if ( (P|U|D|W) == 0 ) 203 if ( (P|U|D|W) == 0 ) {
207 { 204 DEBUG("In %s, UNDEFINED\n", __FUNCTION__);
208 DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1); 205 exit(-1);
209 } 206 }
210 if (CoProc == 10 || CoProc == 11) 207 if (CoProc == 10 || CoProc == 11) {
211 { 208#define VFP_LDC_TRANS
212 #define VFP_LDC_TRANS 209#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
213 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 210#undef VFP_LDC_TRANS
214 #undef VFP_LDC_TRANS 211 }
215 } 212 DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
216 DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", 213 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
217 instr, CoProc, CRd, Rn, imm8, P, U, D, W); 214
218 215 return ARMul_CANT;
219 return ARMul_CANT;
220} 216}
221 217
222unsigned 218unsigned
223VFPCDP (ARMul_State * state, unsigned type, ARMword instr) 219VFPCDP (ARMul_State * state, unsigned type, u32 instr)
224{ 220{
225 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */ 221 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
226 int CoProc = BITS (8, 11); /* 10 or 11 */ 222 int CoProc = BITS (8, 11); /* 10 or 11 */
227 int OPC_1 = BITS (20, 23); 223 int OPC_1 = BITS (20, 23);
228 int CRd = BITS (12, 15); 224 int CRd = BITS (12, 15);
229 int CRn = BITS (16, 19); 225 int CRn = BITS (16, 19);
230 int CRm = BITS (0, 3); 226 int CRm = BITS (0, 3);
231 int OPC_2 = BITS (5, 7); 227 int OPC_2 = BITS (5, 7);
232 228
233 /* TODO check access permission */ 229 //ichfly
234 230 /*if ((instr & 0x0FBF0FD0) == 0x0EB70AC0) //vcvt.f64.f32 d8, s16 (s is bit 0-3 and LSB bit 22) (d is bit 12 - 15 MSB is Bit 6)
235 /* CRn/opc1 CRm/opc2 */ 231 {
236 232 struct vfp_double vdd;
237 if (CoProc == 10 || CoProc == 11) 233 struct vfp_single vsd;
238 { 234 int dn = BITS(12, 15) + (BIT(22) << 4);
239 #define VFP_CDP_TRANS 235 int sd = (BITS(0, 3) << 1) + BIT(5);
240 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 236 s32 n = vfp_get_float(state, sd);
241 #undef VFP_CDP_TRANS 237 vfp_single_unpack(&vsd, n);
242 238 if (vsd.exponent & 0x80)
243 int exceptions = 0; 239 {
244 if (CoProc == 10) 240 vdd.exponent = (vsd.exponent&~0x80) | 0x400;
245 exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); 241 }
246 else 242 else
247 exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); 243 {
248 244 vdd.exponent = vsd.exponent | 0x380;
249 vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); 245 }
250 246 vdd.sign = vsd.sign;
251 return ARMul_DONE; 247 vdd.significand = (u64)(vsd.significand & ~0xC0000000) << 32; // I have no idea why but the 2 uppern bits are not from the significand
252 } 248 vfp_put_double(state, vfp_double_pack(&vdd), dn);
253 DEBUG_LOG(ARM11, "Can't identify %x\n", instr); 249 return ARMul_DONE;
254 return ARMul_CANT; 250 }
251 if ((instr & 0x0FBF0FD0) == 0x0EB70BC0) //vcvt.f32.f64 s15, d6
252 {
253 struct vfp_double vdd;
254 struct vfp_single vsd;
255 int sd = BITS(0, 3) + (BIT(5) << 4);
256 int dn = (BITS(12, 15) << 1) + BIT(22);
257 vfp_double_unpack(&vdd, vfp_get_double(state, sd));
258 if (vdd.exponent & 0x400) //todo if the exponent is to low or to high for this convert
259 {
260 vsd.exponent = (vdd.exponent) | 0x80;
261 }
262 else
263 {
264 vsd.exponent = vdd.exponent & ~0x80;
265 }
266 vsd.exponent &= 0xFF;
267 // vsd.exponent = vdd.exponent >> 3;
268 vsd.sign = vdd.sign;
269 vsd.significand = ((u64)(vdd.significand ) >> 32)& ~0xC0000000;
270 vfp_put_float(state, vfp_single_pack(&vsd), dn);
271 return ARMul_DONE;
272 }*/
273
274 /* TODO check access permission */
275
276 /* CRn/opc1 CRm/opc2 */
277
278 if (CoProc == 10 || CoProc == 11) {
279#define VFP_CDP_TRANS
280#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
281#undef VFP_CDP_TRANS
282
283 int exceptions = 0;
284 if (CoProc == 10)
285 exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
286 else
287 exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
288
289 vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
290
291 return ARMul_DONE;
292 }
293 DEBUG("Can't identify %x\n", instr);
294 return ARMul_CANT;
255} 295}
256 296
257 297
@@ -301,29 +341,29 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
301/* Miscellaneous functions */ 341/* Miscellaneous functions */
302int32_t vfp_get_float(arm_core_t* state, unsigned int reg) 342int32_t vfp_get_float(arm_core_t* state, unsigned int reg)
303{ 343{
304 DBG("VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]); 344 DEBUG("VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]);
305 return state->ExtReg[reg]; 345 return state->ExtReg[reg];
306} 346}
307 347
308void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg) 348void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg)
309{ 349{
310 DBG("VFP put float: s%d <= [%08x]\n", reg, val); 350 DEBUG("VFP put float: s%d <= [%08x]\n", reg, val);
311 state->ExtReg[reg] = val; 351 state->ExtReg[reg] = val;
312} 352}
313 353
314uint64_t vfp_get_double(arm_core_t* state, unsigned int reg) 354uint64_t vfp_get_double(arm_core_t* state, unsigned int reg)
315{ 355{
316 uint64_t result; 356 uint64_t result;
317 result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2]; 357 result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
318 DBG("VFP get double: s[%d-%d]=[%016llx]\n", reg*2+1, reg*2, result); 358 DEBUG("VFP get double: s[%d-%d]=[%016llx]\n", reg*2+1, reg*2, result);
319 return result; 359 return result;
320} 360}
321 361
322void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg) 362void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg)
323{ 363{
324 DBG("VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg*2+1, reg*2, (uint32_t) (val>>32), (uint32_t) (val & 0xffffffff)); 364 DEBUG("VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg*2+1, reg*2, (uint32_t) (val>>32), (uint32_t) (val & 0xffffffff));
325 state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff); 365 state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff);
326 state->ExtReg[reg*2+1] = (uint32_t) (val>>32); 366 state->ExtReg[reg*2+1] = (uint32_t) (val>>32);
327} 367}
328 368
329 369
@@ -333,25 +373,25 @@ void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg)
333 */ 373 */
334void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) 374void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr)
335{ 375{
336 int si_code = 0; 376 int si_code = 0;
337 377
338 vfpdebug("VFP: raising exceptions %08x\n", exceptions); 378 vfpdebug("VFP: raising exceptions %08x\n", exceptions);
339 379
340 if (exceptions == VFP_EXCEPTION_ERROR) { 380 if (exceptions == VFP_EXCEPTION_ERROR) {
341 DEBUG_LOG(ARM11, "unhandled bounce %x\n", inst); 381 DEBUG("unhandled bounce %x\n", inst);
342 exit(-1); 382 exit(-1);
343 return; 383 return;
344 } 384 }
345 385
346 /* 386 /*
347 * If any of the status flags are set, update the FPSCR. 387 * If any of the status flags are set, update the FPSCR.
348 * Comparison instructions always return at least one of 388 * Comparison instructions always return at least one of
349 * these flags set. 389 * these flags set.
350 */ 390 */
351 if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) 391 if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
352 fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); 392 fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V);
353 393
354 fpscr |= exceptions; 394 fpscr |= exceptions;
355 395
356 state->VFP[VFP_OFFSET(VFP_FPSCR)] = fpscr; 396 state->VFP[VFP_OFFSET(VFP_FPSCR)] = fpscr;
357} 397}
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index ed627d41f..7256701f3 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -88,21 +88,21 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
88u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 88u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
89 89
90/* MRC */ 90/* MRC */
91inline void VMRS(ARMul_State * state, ARMword reg, ARMword Rt, ARMword *value); 91void VMRS(ARMul_State * state, ARMword reg, ARMword Rt, ARMword *value);
92inline void VMOVBRS(ARMul_State * state, ARMword to_arm, ARMword t, ARMword n, ARMword *value); 92void VMOVBRS(ARMul_State * state, ARMword to_arm, ARMword t, ARMword n, ARMword *value);
93inline void VMOVBRRD(ARMul_State * state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword *value1, ARMword *value2); 93void VMOVBRRD(ARMul_State * state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword *value1, ARMword *value2);
94inline void VMOVI(ARMul_State * state, ARMword single, ARMword d, ARMword imm); 94void VMOVI(ARMul_State * state, ARMword single, ARMword d, ARMword imm);
95inline void VMOVR(ARMul_State * state, ARMword single, ARMword d, ARMword imm); 95void VMOVR(ARMul_State * state, ARMword single, ARMword d, ARMword imm);
96/* MCR */ 96/* MCR */
97inline void VMSR(ARMul_State * state, ARMword reg, ARMword Rt); 97void VMSR(ARMul_State * state, ARMword reg, ARMword Rt);
98/* STC */ 98/* STC */
99inline int VSTM(ARMul_State * state, int type, ARMword instr, ARMword* value); 99int VSTM(ARMul_State * state, int type, ARMword instr, ARMword* value);
100inline int VPUSH(ARMul_State * state, int type, ARMword instr, ARMword* value); 100int VPUSH(ARMul_State * state, int type, ARMword instr, ARMword* value);
101inline int VSTR(ARMul_State * state, int type, ARMword instr, ARMword* value); 101int VSTR(ARMul_State * state, int type, ARMword instr, ARMword* value);
102/* LDC */ 102/* LDC */
103inline int VLDM(ARMul_State * state, int type, ARMword instr, ARMword value); 103int VLDM(ARMul_State * state, int type, ARMword instr, ARMword value);
104inline int VPOP(ARMul_State * state, int type, ARMword instr, ARMword value); 104int VPOP(ARMul_State * state, int type, ARMword instr, ARMword value);
105inline int VLDR(ARMul_State * state, int type, ARMword instr, ARMword value); 105int VLDR(ARMul_State * state, int type, ARMword instr, ARMword value);
106 106
107#ifdef __cplusplus 107#ifdef __cplusplus
108 } 108 }
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index 5076e59f7..b1949603a 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -44,7 +44,7 @@
44#define pr_info //printf 44#define pr_info //printf
45#define pr_debug //printf 45#define pr_debug //printf
46 46
47static u32 vfp_fls(int x); 47static u32 fls(ARMword x);
48#define do_div(n, base) {n/=base;} 48#define do_div(n, base) {n/=base;}
49 49
50/* From vfpinstr.h */ 50/* From vfpinstr.h */
@@ -502,7 +502,7 @@ struct op {
502 u32 flags; 502 u32 flags;
503}; 503};
504 504
505static u32 vfp_fls(int x) 505static u32 fls(ARMword x)
506{ 506{
507 int r = 32; 507 int r = 32;
508 508
@@ -532,4 +532,9 @@ static u32 vfp_fls(int x)
532 532
533} 533}
534 534
535u32 vfp_double_normaliseroundintern(ARMul_State* state, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func);
536u32 vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, struct vfp_double *vdm, u32 fpscr);
537u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn, struct vfp_double *vdm, u32 fpscr);
538u32 vfp_double_fcvtsinterncutting(ARMul_State* state, int sd, struct vfp_double* dm, u32 fpscr);
539
535#endif 540#endif
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index 13411ad80..765c1f6bc 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -56,163 +56,291 @@
56#include "core/arm/skyeye_common/vfp/asm_vfp.h" 56#include "core/arm/skyeye_common/vfp/asm_vfp.h"
57 57
58static struct vfp_double vfp_double_default_qnan = { 58static struct vfp_double vfp_double_default_qnan = {
59 //.exponent = 2047, 59 2047,
60 //.sign = 0, 60 0,
61 //.significand = VFP_DOUBLE_SIGNIFICAND_QNAN, 61 VFP_DOUBLE_SIGNIFICAND_QNAN,
62}; 62};
63 63
64static void vfp_double_dump(const char *str, struct vfp_double *d) 64static void vfp_double_dump(const char *str, struct vfp_double *d)
65{ 65{
66 pr_debug("VFP: %s: sign=%d exponent=%d significand=%016llx\n", 66 pr_debug("VFP: %s: sign=%d exponent=%d significand=%016llx\n",
67 str, d->sign != 0, d->exponent, d->significand); 67 str, d->sign != 0, d->exponent, d->significand);
68} 68}
69 69
70static void vfp_double_normalise_denormal(struct vfp_double *vd) 70static void vfp_double_normalise_denormal(struct vfp_double *vd)
71{ 71{
72 int bits = 31 - vfp_fls(vd->significand >> 32); 72 int bits = 31 - fls((ARMword)(vd->significand >> 32));
73 if (bits == 31) 73 if (bits == 31)
74 bits = 63 - vfp_fls(vd->significand); 74 bits = 63 - fls((ARMword)vd->significand);
75 75
76 vfp_double_dump("normalise_denormal: in", vd); 76 vfp_double_dump("normalise_denormal: in", vd);
77 77
78 if (bits) { 78 if (bits) {
79 vd->exponent -= bits - 1; 79 vd->exponent -= bits - 1;
80 vd->significand <<= bits; 80 vd->significand <<= bits;
81 } 81 }
82 82
83 vfp_double_dump("normalise_denormal: out", vd); 83 vfp_double_dump("normalise_denormal: out", vd);
84} 84}
85 85
86u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func) 86u32 vfp_double_normaliseroundintern(ARMul_State* state, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
87{ 87{
88 u64 significand, incr; 88 u64 significand, incr;
89 int exponent, shift, underflow; 89 int exponent, shift, underflow;
90 u32 rmode; 90 u32 rmode;
91 91
92 vfp_double_dump("pack: in", vd); 92 vfp_double_dump("pack: in", vd);
93 93
94 /* 94 /*
95 * Infinities and NaNs are a special case. 95 * Infinities and NaNs are a special case.
96 */ 96 */
97 if (vd->exponent == 2047 && (vd->significand == 0 || exceptions)) 97 if (vd->exponent == 2047 && (vd->significand == 0 || exceptions))
98 goto pack; 98 goto pack;
99 99
100 /* 100 /*
101 * Special-case zero. 101 * Special-case zero.
102 */ 102 */
103 if (vd->significand == 0) { 103 if (vd->significand == 0) {
104 vd->exponent = 0; 104 vd->exponent = 0;
105 goto pack; 105 goto pack;
106 } 106 }
107 107
108 exponent = vd->exponent; 108 exponent = vd->exponent;
109 significand = vd->significand; 109 significand = vd->significand;
110 110
111 shift = 32 - vfp_fls(significand >> 32); 111 shift = 32 - fls((ARMword)(significand >> 32));
112 if (shift == 32) 112 if (shift == 32)
113 shift = 64 - vfp_fls(significand); 113 shift = 64 - fls((ARMword)significand);
114 if (shift) { 114 if (shift) {
115 exponent -= shift; 115 exponent -= shift;
116 significand <<= shift; 116 significand <<= shift;
117 } 117 }
118 118
119#if 1 119#if 1
120 vd->exponent = exponent; 120 vd->exponent = exponent;
121 vd->significand = significand; 121 vd->significand = significand;
122 vfp_double_dump("pack: normalised", vd); 122 vfp_double_dump("pack: normalised", vd);
123#endif 123#endif
124 124
125 /* 125 /*
126 * Tiny number? 126 * Tiny number?
127 */ 127 */
128 underflow = exponent < 0; 128 underflow = exponent < 0;
129 if (underflow) { 129 if (underflow) {
130 significand = vfp_shiftright64jamming(significand, -exponent); 130 significand = vfp_shiftright64jamming(significand, -exponent);
131 exponent = 0; 131 exponent = 0;
132#if 1 132#if 1
133 vd->exponent = exponent; 133 vd->exponent = exponent;
134 vd->significand = significand; 134 vd->significand = significand;
135 vfp_double_dump("pack: tiny number", vd); 135 vfp_double_dump("pack: tiny number", vd);
136#endif 136#endif
137 if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1))) 137 if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1)))
138 underflow = 0; 138 underflow = 0;
139 } 139 }
140 140
141 /* 141 /*
142 * Select rounding increment. 142 * Select rounding increment.
143 */ 143 */
144 incr = 0; 144 incr = 0;
145 rmode = fpscr & FPSCR_RMODE_MASK; 145 rmode = fpscr & FPSCR_RMODE_MASK;
146 146
147 if (rmode == FPSCR_ROUND_NEAREST) { 147 if (rmode == FPSCR_ROUND_NEAREST) {
148 incr = 1ULL << VFP_DOUBLE_LOW_BITS; 148 incr = 1ULL << VFP_DOUBLE_LOW_BITS;
149 if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0) 149 if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
150 incr -= 1; 150 incr -= 1;
151 } else if (rmode == FPSCR_ROUND_TOZERO) { 151 }
152 incr = 0; 152 else if (rmode == FPSCR_ROUND_TOZERO) {
153 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0)) 153 incr = 0;
154 incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1; 154 }
155 155 else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
156 pr_debug("VFP: rounding increment = 0x%08llx\n", incr); 156 incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
157 157
158 /* 158 pr_debug("VFP: rounding increment = 0x%08llx\n", incr);
159 * Is our rounding going to overflow? 159
160 */ 160 /*
161 if ((significand + incr) < significand) { 161 * Is our rounding going to overflow?
162 exponent += 1; 162 */
163 significand = (significand >> 1) | (significand & 1); 163 if ((significand + incr) < significand) {
164 incr >>= 1; 164 exponent += 1;
165 significand = (significand >> 1) | (significand & 1);
166 incr >>= 1;
165#if 1 167#if 1
166 vd->exponent = exponent; 168 vd->exponent = exponent;
167 vd->significand = significand; 169 vd->significand = significand;
168 vfp_double_dump("pack: overflow", vd); 170 vfp_double_dump("pack: overflow", vd);
169#endif 171#endif
170 } 172 }
171 173
172 /* 174 /*
173 * If any of the low bits (which will be shifted out of the 175 * If any of the low bits (which will be shifted out of the
174 * number) are non-zero, the result is inexact. 176 * number) are non-zero, the result is inexact.
175 */ 177 */
176 if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1)) 178 if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1))
177 exceptions |= FPSCR_IXC; 179 exceptions |= FPSCR_IXC;
178 180
179 /* 181 /*
180 * Do our rounding. 182 * Do our rounding.
181 */ 183 */
182 significand += incr; 184 significand += incr;
183 185
184 /* 186 /*
185 * Infinity? 187 * Infinity?
186 */ 188 */
187 if (exponent >= 2046) { 189 if (exponent >= 2046) {
188 exceptions |= FPSCR_OFC | FPSCR_IXC; 190 exceptions |= FPSCR_OFC | FPSCR_IXC;
189 if (incr == 0) { 191 if (incr == 0) {
190 vd->exponent = 2045; 192 vd->exponent = 2045;
191 vd->significand = 0x7fffffffffffffffULL; 193 vd->significand = 0x7fffffffffffffffULL;
192 } else { 194 }
193 vd->exponent = 2047; /* infinity */ 195 else {
194 vd->significand = 0; 196 vd->exponent = 2047; /* infinity */
195 } 197 vd->significand = 0;
196 } else { 198 }
197 if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0) 199 }
198 exponent = 0; 200 else {
199 if (exponent || significand > 0x8000000000000000ULL) 201 if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
200 underflow = 0; 202 exponent = 0;
201 if (underflow) 203 if (exponent || significand > 0x8000000000000000ULL)
202 exceptions |= FPSCR_UFC; 204 underflow = 0;
203 vd->exponent = exponent; 205 if (underflow)
204 vd->significand = significand >> 1; 206 exceptions |= FPSCR_UFC;
205 } 207 vd->exponent = exponent;
206 208 vd->significand = significand >> 1;
209 }
207 pack: 210 pack:
208 vfp_double_dump("pack: final", vd); 211 return 0;
209 { 212}
210 s64 d = vfp_double_pack(vd); 213
211 pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func, 214u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
212 dd, d, exceptions); 215{
213 vfp_put_double(state, d, dd); 216 u64 significand, incr;
214 } 217 int exponent, shift, underflow;
215 return exceptions; 218 u32 rmode;
219
220 vfp_double_dump("pack: in", vd);
221
222 /*
223 * Infinities and NaNs are a special case.
224 */
225 if (vd->exponent == 2047 && (vd->significand == 0 || exceptions))
226 goto pack;
227
228 /*
229 * Special-case zero.
230 */
231 if (vd->significand == 0) {
232 vd->exponent = 0;
233 goto pack;
234 }
235
236 exponent = vd->exponent;
237 significand = vd->significand;
238
239 shift = 32 - fls((ARMword)(significand >> 32));
240 if (shift == 32)
241 shift = 64 - fls((ARMword)significand);
242 if (shift) {
243 exponent -= shift;
244 significand <<= shift;
245 }
246
247#if 1
248 vd->exponent = exponent;
249 vd->significand = significand;
250 vfp_double_dump("pack: normalised", vd);
251#endif
252
253 /*
254 * Tiny number?
255 */
256 underflow = exponent < 0;
257 if (underflow) {
258 significand = vfp_shiftright64jamming(significand, -exponent);
259 exponent = 0;
260#if 1
261 vd->exponent = exponent;
262 vd->significand = significand;
263 vfp_double_dump("pack: tiny number", vd);
264#endif
265 if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1)))
266 underflow = 0;
267 }
268
269 /*
270 * Select rounding increment.
271 */
272 incr = 0;
273 rmode = fpscr & FPSCR_RMODE_MASK;
274
275 if (rmode == FPSCR_ROUND_NEAREST) {
276 incr = 1ULL << VFP_DOUBLE_LOW_BITS;
277 if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
278 incr -= 1;
279 } else if (rmode == FPSCR_ROUND_TOZERO) {
280 incr = 0;
281 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
282 incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
283
284 pr_debug("VFP: rounding increment = 0x%08llx\n", incr);
285
286 /*
287 * Is our rounding going to overflow?
288 */
289 if ((significand + incr) < significand) {
290 exponent += 1;
291 significand = (significand >> 1) | (significand & 1);
292 incr >>= 1;
293#if 1
294 vd->exponent = exponent;
295 vd->significand = significand;
296 vfp_double_dump("pack: overflow", vd);
297#endif
298 }
299
300 /*
301 * If any of the low bits (which will be shifted out of the
302 * number) are non-zero, the result is inexact.
303 */
304 if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1))
305 exceptions |= FPSCR_IXC;
306
307 /*
308 * Do our rounding.
309 */
310 significand += incr;
311
312 /*
313 * Infinity?
314 */
315 if (exponent >= 2046) {
316 exceptions |= FPSCR_OFC | FPSCR_IXC;
317 if (incr == 0) {
318 vd->exponent = 2045;
319 vd->significand = 0x7fffffffffffffffULL;
320 } else {
321 vd->exponent = 2047; /* infinity */
322 vd->significand = 0;
323 }
324 } else {
325 if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
326 exponent = 0;
327 if (exponent || significand > 0x8000000000000000ULL)
328 underflow = 0;
329 if (underflow)
330 exceptions |= FPSCR_UFC;
331 vd->exponent = exponent;
332 vd->significand = significand >> 1;
333 }
334
335pack:
336 vfp_double_dump("pack: final", vd);
337 {
338 s64 d = vfp_double_pack(vd);
339 pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func,
340 dd, d, exceptions);
341 vfp_put_double(state, d, dd);
342 }
343 return exceptions;
216} 344}
217 345
218/* 346/*
@@ -221,43 +349,43 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd,
221 */ 349 */
222static u32 350static u32
223vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn, 351vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
224 struct vfp_double *vdm, u32 fpscr) 352 struct vfp_double *vdm, u32 fpscr)
225{ 353{
226 struct vfp_double *nan; 354 struct vfp_double *nan;
227 int tn, tm = 0; 355 int tn, tm = 0;
228 356
229 tn = vfp_double_type(vdn); 357 tn = vfp_double_type(vdn);
230 358
231 if (vdm) 359 if (vdm)
232 tm = vfp_double_type(vdm); 360 tm = vfp_double_type(vdm);
233 361
234 if (fpscr & FPSCR_DEFAULT_NAN) 362 if (fpscr & FPSCR_DEFAULT_NAN)
235 /* 363 /*
236 * Default NaN mode - always returns a quiet NaN 364 * Default NaN mode - always returns a quiet NaN
237 */ 365 */
238 nan = &vfp_double_default_qnan; 366 nan = &vfp_double_default_qnan;
239 else { 367 else {
240 /* 368 /*
241 * Contemporary mode - select the first signalling 369 * Contemporary mode - select the first signalling
242 * NAN, or if neither are signalling, the first 370 * NAN, or if neither are signalling, the first
243 * quiet NAN. 371 * quiet NAN.
244 */ 372 */
245 if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN)) 373 if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
246 nan = vdn; 374 nan = vdn;
247 else 375 else
248 nan = vdm; 376 nan = vdm;
249 /* 377 /*
250 * Make the NaN quiet. 378 * Make the NaN quiet.
251 */ 379 */
252 nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; 380 nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
253 } 381 }
254 382
255 *vdd = *nan; 383 *vdd = *nan;
256 384
257 /* 385 /*
258 * If one was a signalling NAN, raise invalid operation. 386 * If one was a signalling NAN, raise invalid operation.
259 */ 387 */
260 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG; 388 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
261} 389}
262 390
263/* 391/*
@@ -265,108 +393,108 @@ vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
265 */ 393 */
266static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 394static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
267{ 395{
268 pr_debug("In %s\n", __FUNCTION__); 396 pr_debug("In %s\n", __FUNCTION__);
269 vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd); 397 vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd);
270 return 0; 398 return 0;
271} 399}
272 400
273static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 401static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
274{ 402{
275 pr_debug("In %s\n", __FUNCTION__); 403 pr_debug("In %s\n", __FUNCTION__);
276 vfp_put_double(state, vfp_get_double(state, dm), dd); 404 vfp_put_double(state, vfp_get_double(state, dm), dd);
277 return 0; 405 return 0;
278} 406}
279 407
280static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 408static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
281{ 409{
282 pr_debug("In %s\n", __FUNCTION__); 410 pr_debug("In %s\n", __FUNCTION__);
283 vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd); 411 vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd);
284 return 0; 412 return 0;
285} 413}
286 414
287static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 415static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
288{ 416{
289 pr_debug("In %s\n", __FUNCTION__); 417 pr_debug("In %s\n", __FUNCTION__);
290 struct vfp_double vdm, vdd, *vdp; 418 vfp_double vdm, vdd, *vdp;
291 int ret, tm; 419 int ret, tm;
292 420
293 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 421 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
294 tm = vfp_double_type(&vdm); 422 tm = vfp_double_type(&vdm);
295 if (tm & (VFP_NAN|VFP_INFINITY)) { 423 if (tm & (VFP_NAN|VFP_INFINITY)) {
296 vdp = &vdd; 424 vdp = &vdd;
297 425
298 if (tm & VFP_NAN) 426 if (tm & VFP_NAN)
299 ret = vfp_propagate_nan(vdp, &vdm, NULL, fpscr); 427 ret = vfp_propagate_nan(vdp, &vdm, NULL, fpscr);
300 else if (vdm.sign == 0) { 428 else if (vdm.sign == 0) {
301 sqrt_copy: 429sqrt_copy:
302 vdp = &vdm; 430 vdp = &vdm;
303 ret = 0; 431 ret = 0;
304 } else { 432 } else {
305 sqrt_invalid: 433sqrt_invalid:
306 vdp = &vfp_double_default_qnan; 434 vdp = &vfp_double_default_qnan;
307 ret = FPSCR_IOC; 435 ret = FPSCR_IOC;
308 } 436 }
309 vfp_put_double(state, vfp_double_pack(vdp), dd); 437 vfp_put_double(state, vfp_double_pack(vdp), dd);
310 return ret; 438 return ret;
311 } 439 }
312 440
313 /* 441 /*
314 * sqrt(+/- 0) == +/- 0 442 * sqrt(+/- 0) == +/- 0
315 */ 443 */
316 if (tm & VFP_ZERO) 444 if (tm & VFP_ZERO)
317 goto sqrt_copy; 445 goto sqrt_copy;
318 446
319 /* 447 /*
320 * Normalise a denormalised number 448 * Normalise a denormalised number
321 */ 449 */
322 if (tm & VFP_DENORMAL) 450 if (tm & VFP_DENORMAL)
323 vfp_double_normalise_denormal(&vdm); 451 vfp_double_normalise_denormal(&vdm);
324 452
325 /* 453 /*
326 * sqrt(<0) = invalid 454 * sqrt(<0) = invalid
327 */ 455 */
328 if (vdm.sign) 456 if (vdm.sign)
329 goto sqrt_invalid; 457 goto sqrt_invalid;
330 458
331 vfp_double_dump("sqrt", &vdm); 459 vfp_double_dump("sqrt", &vdm);
332 460
333 /* 461 /*
334 * Estimate the square root. 462 * Estimate the square root.
335 */ 463 */
336 vdd.sign = 0; 464 vdd.sign = 0;
337 vdd.exponent = ((vdm.exponent - 1023) >> 1) + 1023; 465 vdd.exponent = ((vdm.exponent - 1023) >> 1) + 1023;
338 vdd.significand = (u64)vfp_estimate_sqrt_significand(vdm.exponent, vdm.significand >> 32) << 31; 466 vdd.significand = (u64)vfp_estimate_sqrt_significand(vdm.exponent, vdm.significand >> 32) << 31;
339 467
340 vfp_double_dump("sqrt estimate1", &vdd); 468 vfp_double_dump("sqrt estimate1", &vdd);
341 469
342 vdm.significand >>= 1 + (vdm.exponent & 1); 470 vdm.significand >>= 1 + (vdm.exponent & 1);
343 vdd.significand += 2 + vfp_estimate_div128to64(vdm.significand, 0, vdd.significand); 471 vdd.significand += 2 + vfp_estimate_div128to64(vdm.significand, 0, vdd.significand);
344 472
345 vfp_double_dump("sqrt estimate2", &vdd); 473 vfp_double_dump("sqrt estimate2", &vdd);
346 474
347 /* 475 /*
348 * And now adjust. 476 * And now adjust.
349 */ 477 */
350 if ((vdd.significand & VFP_DOUBLE_LOW_BITS_MASK) <= 5) { 478 if ((vdd.significand & VFP_DOUBLE_LOW_BITS_MASK) <= 5) {
351 if (vdd.significand < 2) { 479 if (vdd.significand < 2) {
352 vdd.significand = ~0ULL; 480 vdd.significand = ~0ULL;
353 } else { 481 } else {
354 u64 termh, terml, remh, reml; 482 u64 termh, terml, remh, reml;
355 vdm.significand <<= 2; 483 vdm.significand <<= 2;
356 mul64to128(&termh, &terml, vdd.significand, vdd.significand); 484 mul64to128(&termh, &terml, vdd.significand, vdd.significand);
357 sub128(&remh, &reml, vdm.significand, 0, termh, terml); 485 sub128(&remh, &reml, vdm.significand, 0, termh, terml);
358 while ((s64)remh < 0) { 486 while ((s64)remh < 0) {
359 vdd.significand -= 1; 487 vdd.significand -= 1;
360 shift64left(&termh, &terml, vdd.significand); 488 shift64left(&termh, &terml, vdd.significand);
361 terml |= 1; 489 terml |= 1;
362 add128(&remh, &reml, remh, reml, termh, terml); 490 add128(&remh, &reml, remh, reml, termh, terml);
363 } 491 }
364 vdd.significand |= (remh | reml) != 0; 492 vdd.significand |= (remh | reml) != 0;
365 } 493 }
366 } 494 }
367 vdd.significand = vfp_shiftright64jamming(vdd.significand, 1); 495 vdd.significand = vfp_shiftright64jamming(vdd.significand, 1);
368 496
369 return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fsqrt"); 497 return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fsqrt");
370} 498}
371 499
372/* 500/*
@@ -377,319 +505,362 @@ static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32
377 */ 505 */
378static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr) 506static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr)
379{ 507{
380 s64 d, m; 508 s64 d, m;
381 u32 ret = 0; 509 u32 ret = 0;
382 510
383 pr_debug("In %s, state=0x%x, fpscr=0x%x\n", __FUNCTION__, state, fpscr); 511 pr_debug("In %s, state=0x%x, fpscr=0x%x\n", __FUNCTION__, state, fpscr);
384 m = vfp_get_double(state, dm); 512 m = vfp_get_double(state, dm);
385 if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) { 513 if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) {
386 ret |= FPSCR_C | FPSCR_V; 514 ret |= FPSCR_C | FPSCR_V;
387 if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) 515 if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
388 /* 516 /*
389 * Signalling NaN, or signalling on quiet NaN 517 * Signalling NaN, or signalling on quiet NaN
390 */ 518 */
391 ret |= FPSCR_IOC; 519 ret |= FPSCR_IOC;
392 } 520 }
393 521
394 d = vfp_get_double(state, dd); 522 d = vfp_get_double(state, dd);
395 if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) { 523 if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) {
396 ret |= FPSCR_C | FPSCR_V; 524 ret |= FPSCR_C | FPSCR_V;
397 if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) 525 if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
398 /* 526 /*
399 * Signalling NaN, or signalling on quiet NaN 527 * Signalling NaN, or signalling on quiet NaN
400 */ 528 */
401 ret |= FPSCR_IOC; 529 ret |= FPSCR_IOC;
402 } 530 }
403 531
404 if (ret == 0) { 532 if (ret == 0) {
405 //printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m); 533 //printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m);
406 if (d == m || vfp_double_packed_abs(d | m) == 0) { 534 if (d == m || vfp_double_packed_abs(d | m) == 0) {
407 /* 535 /*
408 * equal 536 * equal
409 */ 537 */
410 ret |= FPSCR_Z | FPSCR_C; 538 ret |= FPSCR_Z | FPSCR_C;
411 //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret); 539 //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret);
412 } else if (vfp_double_packed_sign(d ^ m)) { 540 } else if (vfp_double_packed_sign(d ^ m)) {
413 /* 541 /*
414 * different signs 542 * different signs
415 */ 543 */
416 if (vfp_double_packed_sign(d)) 544 if (vfp_double_packed_sign(d))
417 /* 545 /*
418 * d is negative, so d < m 546 * d is negative, so d < m
419 */ 547 */
420 ret |= FPSCR_N; 548 ret |= FPSCR_N;
421 else 549 else
422 /* 550 /*
423 * d is positive, so d > m 551 * d is positive, so d > m
424 */ 552 */
425 ret |= FPSCR_C; 553 ret |= FPSCR_C;
426 } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) { 554 } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) {
427 /* 555 /*
428 * d < m 556 * d < m
429 */ 557 */
430 ret |= FPSCR_N; 558 ret |= FPSCR_N;
431 } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) { 559 } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) {
432 /* 560 /*
433 * d > m 561 * d > m
434 */ 562 */
435 ret |= FPSCR_C; 563 ret |= FPSCR_C;
436 } 564 }
437 } 565 }
438 pr_debug("In %s, state=0x%x, ret=0x%x\n", __FUNCTION__, state, ret); 566 pr_debug("In %s, state=0x%x, ret=0x%x\n", __FUNCTION__, state, ret);
439 567
440 return ret; 568 return ret;
441} 569}
442 570
443static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 571static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
444{ 572{
445 pr_debug("In %s\n", __FUNCTION__); 573 pr_debug("In %s\n", __FUNCTION__);
446 return vfp_compare(state, dd, 0, dm, fpscr); 574 return vfp_compare(state, dd, 0, dm, fpscr);
447} 575}
448 576
449static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 577static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
450{ 578{
451 pr_debug("In %s\n", __FUNCTION__); 579 pr_debug("In %s\n", __FUNCTION__);
452 return vfp_compare(state, dd, 1, dm, fpscr); 580 return vfp_compare(state, dd, 1, dm, fpscr);
453} 581}
454 582
455static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 583static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
456{ 584{
457 pr_debug("In %s\n", __FUNCTION__); 585 pr_debug("In %s\n", __FUNCTION__);
458 return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr); 586 return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr);
459} 587}
460 588
461static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 589static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
462{ 590{
463 pr_debug("In %s\n", __FUNCTION__); 591 pr_debug("In %s\n", __FUNCTION__);
464 return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr); 592 return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr);
593}
594
595u32 vfp_double_fcvtsinterncutting(ARMul_State* state, int sd, struct vfp_double* dm, u32 fpscr) //ichfly for internal use only
596{
597 struct vfp_single vsd;
598 int tm;
599 u32 exceptions = 0;
600
601 pr_debug("In %s\n", __FUNCTION__);
602
603 tm = vfp_double_type(dm);
604
605 /*
606 * If we have a signalling NaN, signal invalid operation.
607 */
608 if (tm == VFP_SNAN)
609 exceptions = FPSCR_IOC;
610
611 if (tm & VFP_DENORMAL)
612 vfp_double_normalise_denormal(dm);
613
614 vsd.sign = dm->sign;
615 vsd.significand = vfp_hi64to32jamming(dm->significand);
616
617 /*
618 * If we have an infinity or a NaN, the exponent must be 255
619 */
620 if (tm & (VFP_INFINITY | VFP_NAN)) {
621 vsd.exponent = 255;
622 if (tm == VFP_QNAN)
623 vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
624 goto pack_nan;
625 }
626 else if (tm & VFP_ZERO)
627 vsd.exponent = 0;
628 else
629 vsd.exponent = dm->exponent - (1023 - 127);
630
631 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fcvts");
632
633pack_nan:
634 vfp_put_float(state, vfp_single_pack(&vsd), sd);
635 return exceptions;
465} 636}
466 637
467static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 638static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
468{ 639{
469 struct vfp_double vdm; 640 struct vfp_double vdm;
470 struct vfp_single vsd; 641 struct vfp_single vsd;
471 int tm; 642 int tm;
472 u32 exceptions = 0; 643 u32 exceptions = 0;
473 644
474 pr_debug("In %s\n", __FUNCTION__); 645 pr_debug("In %s\n", __FUNCTION__);
475 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 646 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
476 647
477 tm = vfp_double_type(&vdm); 648 tm = vfp_double_type(&vdm);
478 649
479 /* 650 /*
480 * If we have a signalling NaN, signal invalid operation. 651 * If we have a signalling NaN, signal invalid operation.
481 */ 652 */
482 if (tm == VFP_SNAN) 653 if (tm == VFP_SNAN)
483 exceptions = FPSCR_IOC; 654 exceptions = FPSCR_IOC;
484 655
485 if (tm & VFP_DENORMAL) 656 if (tm & VFP_DENORMAL)
486 vfp_double_normalise_denormal(&vdm); 657 vfp_double_normalise_denormal(&vdm);
487 658
488 vsd.sign = vdm.sign; 659 vsd.sign = vdm.sign;
489 vsd.significand = vfp_hi64to32jamming(vdm.significand); 660 vsd.significand = vfp_hi64to32jamming(vdm.significand);
490 661
491 /* 662 /*
492 * If we have an infinity or a NaN, the exponent must be 255 663 * If we have an infinity or a NaN, the exponent must be 255
493 */ 664 */
494 if (tm & (VFP_INFINITY|VFP_NAN)) { 665 if (tm & (VFP_INFINITY|VFP_NAN)) {
495 vsd.exponent = 255; 666 vsd.exponent = 255;
496 if (tm == VFP_QNAN) 667 if (tm == VFP_QNAN)
497 vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN; 668 vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
498 goto pack_nan; 669 goto pack_nan;
499 } else if (tm & VFP_ZERO) 670 } else if (tm & VFP_ZERO)
500 vsd.exponent = 0; 671 vsd.exponent = 0;
501 else 672 else
502 vsd.exponent = vdm.exponent - (1023 - 127); 673 vsd.exponent = vdm.exponent - (1023 - 127);
503 674
504 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fcvts"); 675 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fcvts");
505 676
506 pack_nan: 677pack_nan:
507 vfp_put_float(state, vfp_single_pack(&vsd), sd); 678 vfp_put_float(state, vfp_single_pack(&vsd), sd);
508 return exceptions; 679 return exceptions;
509} 680}
510 681
511static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 682static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
512{ 683{
513 struct vfp_double vdm; 684 struct vfp_double vdm;
514 u32 m = vfp_get_float(state, dm); 685 u32 m = vfp_get_float(state, dm);
515 686
516 pr_debug("In %s\n", __FUNCTION__); 687 pr_debug("In %s\n", __FUNCTION__);
517 vdm.sign = 0; 688 vdm.sign = 0;
518 vdm.exponent = 1023 + 63 - 1; 689 vdm.exponent = 1023 + 63 - 1;
519 vdm.significand = (u64)m; 690 vdm.significand = (u64)m;
520 691
521 return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fuito"); 692 return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fuito");
522} 693}
523 694
524static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 695static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
525{ 696{
526 struct vfp_double vdm; 697 struct vfp_double vdm;
527 u32 m = vfp_get_float(state, dm); 698 u32 m = vfp_get_float(state, dm);
528 699
529 pr_debug("In %s\n", __FUNCTION__); 700 pr_debug("In %s\n", __FUNCTION__);
530 vdm.sign = (m & 0x80000000) >> 16; 701 vdm.sign = (m & 0x80000000) >> 16;
531 vdm.exponent = 1023 + 63 - 1; 702 vdm.exponent = 1023 + 63 - 1;
532 vdm.significand = vdm.sign ? -m : m; 703 vdm.significand = vdm.sign ? -m : m;
533 704
534 return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fsito"); 705 return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fsito");
535} 706}
536 707
537static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 708static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
538{ 709{
539 struct vfp_double vdm; 710 struct vfp_double vdm;
540 u32 d, exceptions = 0; 711 u32 d, exceptions = 0;
541 int rmode = fpscr & FPSCR_RMODE_MASK; 712 int rmode = fpscr & FPSCR_RMODE_MASK;
542 int tm; 713 int tm;
543 714
544 pr_debug("In %s\n", __FUNCTION__); 715 pr_debug("In %s\n", __FUNCTION__);
545 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 716 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
546 717
547 /* 718 /*
548 * Do we have a denormalised number? 719 * Do we have a denormalised number?
549 */ 720 */
550 tm = vfp_double_type(&vdm); 721 tm = vfp_double_type(&vdm);
551 if (tm & VFP_DENORMAL) 722 if (tm & VFP_DENORMAL)
552 exceptions |= FPSCR_IDC; 723 exceptions |= FPSCR_IDC;
553 724
554 if (tm & VFP_NAN) 725 if (tm & VFP_NAN)
555 vdm.sign = 0; 726 vdm.sign = 0;
556 727
557 if (vdm.exponent >= 1023 + 32) { 728 if (vdm.exponent >= 1023 + 32) {
558 d = vdm.sign ? 0 : 0xffffffff; 729 d = vdm.sign ? 0 : 0xffffffff;
559 exceptions = FPSCR_IOC; 730 exceptions = FPSCR_IOC;
560 } else if (vdm.exponent >= 1023 - 1) { 731 } else if (vdm.exponent >= 1023 - 1) {
561 int shift = 1023 + 63 - vdm.exponent; 732 int shift = 1023 + 63 - vdm.exponent;
562 u64 rem, incr = 0; 733 u64 rem, incr = 0;
563 734
564 /* 735 /*
565 * 2^0 <= m < 2^32-2^8 736 * 2^0 <= m < 2^32-2^8
566 */ 737 */
567 d = (vdm.significand << 1) >> shift; 738 d = (ARMword)((vdm.significand << 1) >> shift);
568 rem = vdm.significand << (65 - shift); 739 rem = vdm.significand << (65 - shift);
569 740
570 if (rmode == FPSCR_ROUND_NEAREST) { 741 if (rmode == FPSCR_ROUND_NEAREST) {
571 incr = 0x8000000000000000ULL; 742 incr = 0x8000000000000000ULL;
572 if ((d & 1) == 0) 743 if ((d & 1) == 0)
573 incr -= 1; 744 incr -= 1;
574 } else if (rmode == FPSCR_ROUND_TOZERO) { 745 } else if (rmode == FPSCR_ROUND_TOZERO) {
575 incr = 0; 746 incr = 0;
576 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) { 747 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
577 incr = ~0ULL; 748 incr = ~0ULL;
578 } 749 }
579 750
580 if ((rem + incr) < rem) { 751 if ((rem + incr) < rem) {
581 if (d < 0xffffffff) 752 if (d < 0xffffffff)
582 d += 1; 753 d += 1;
583 else 754 else
584 exceptions |= FPSCR_IOC; 755 exceptions |= FPSCR_IOC;
585 } 756 }
586 757
587 if (d && vdm.sign) { 758 if (d && vdm.sign) {
588 d = 0; 759 d = 0;
589 exceptions |= FPSCR_IOC; 760 exceptions |= FPSCR_IOC;
590 } else if (rem) 761 } else if (rem)
591 exceptions |= FPSCR_IXC; 762 exceptions |= FPSCR_IXC;
592 } else { 763 } else {
593 d = 0; 764 d = 0;
594 if (vdm.exponent | vdm.significand) { 765 if (vdm.exponent | vdm.significand) {
595 exceptions |= FPSCR_IXC; 766 exceptions |= FPSCR_IXC;
596 if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) 767 if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
597 d = 1; 768 d = 1;
598 else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { 769 else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) {
599 d = 0; 770 d = 0;
600 exceptions |= FPSCR_IOC; 771 exceptions |= FPSCR_IOC;
601 } 772 }
602 } 773 }
603 } 774 }
604 775
605 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); 776 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
606 777
607 vfp_put_float(state, d, sd); 778 vfp_put_float(state, d, sd);
608 779
609 return exceptions; 780 return exceptions;
610} 781}
611 782
612static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 783static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
613{ 784{
614 pr_debug("In %s\n", __FUNCTION__); 785 pr_debug("In %s\n", __FUNCTION__);
615 return vfp_double_ftoui(state, sd, unused, dm, FPSCR_ROUND_TOZERO); 786 return vfp_double_ftoui(state, sd, unused, dm, FPSCR_ROUND_TOZERO);
616} 787}
617 788
618static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 789static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
619{ 790{
620 struct vfp_double vdm; 791 struct vfp_double vdm;
621 u32 d, exceptions = 0; 792 u32 d, exceptions = 0;
622 int rmode = fpscr & FPSCR_RMODE_MASK; 793 int rmode = fpscr & FPSCR_RMODE_MASK;
623 int tm; 794 int tm;
624 795
625 pr_debug("In %s\n", __FUNCTION__); 796 pr_debug("In %s\n", __FUNCTION__);
626 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 797 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
627 vfp_double_dump("VDM", &vdm); 798 vfp_double_dump("VDM", &vdm);
628 799
629 /* 800 /*
630 * Do we have denormalised number? 801 * Do we have denormalised number?
631 */ 802 */
632 tm = vfp_double_type(&vdm); 803 tm = vfp_double_type(&vdm);
633 if (tm & VFP_DENORMAL) 804 if (tm & VFP_DENORMAL)
634 exceptions |= FPSCR_IDC; 805 exceptions |= FPSCR_IDC;
635 806
636 if (tm & VFP_NAN) { 807 if (tm & VFP_NAN) {
637 d = 0; 808 d = 0;
638 exceptions |= FPSCR_IOC; 809 exceptions |= FPSCR_IOC;
639 } else if (vdm.exponent >= 1023 + 32) { 810 } else if (vdm.exponent >= 1023 + 32) {
640 d = 0x7fffffff; 811 d = 0x7fffffff;
641 if (vdm.sign) 812 if (vdm.sign)
642 d = ~d; 813 d = ~d;
643 exceptions |= FPSCR_IOC; 814 exceptions |= FPSCR_IOC;
644 } else if (vdm.exponent >= 1023 - 1) { 815 } else if (vdm.exponent >= 1023 - 1) {
645 int shift = 1023 + 63 - vdm.exponent; /* 58 */ 816 int shift = 1023 + 63 - vdm.exponent; /* 58 */
646 u64 rem, incr = 0; 817 u64 rem, incr = 0;
647 818
648 d = (vdm.significand << 1) >> shift; 819 d = (ARMword)((vdm.significand << 1) >> shift);
649 rem = vdm.significand << (65 - shift); 820 rem = vdm.significand << (65 - shift);
650 821
651 if (rmode == FPSCR_ROUND_NEAREST) { 822 if (rmode == FPSCR_ROUND_NEAREST) {
652 incr = 0x8000000000000000ULL; 823 incr = 0x8000000000000000ULL;
653 if ((d & 1) == 0) 824 if ((d & 1) == 0)
654 incr -= 1; 825 incr -= 1;
655 } else if (rmode == FPSCR_ROUND_TOZERO) { 826 } else if (rmode == FPSCR_ROUND_TOZERO) {
656 incr = 0; 827 incr = 0;
657 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) { 828 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
658 incr = ~0ULL; 829 incr = ~0ULL;
659 } 830 }
660 831
661 if ((rem + incr) < rem && d < 0xffffffff) 832 if ((rem + incr) < rem && d < 0xffffffff)
662 d += 1; 833 d += 1;
663 if (d > 0x7fffffff + (vdm.sign != 0)) { 834 if (d > (0x7fffffff + (vdm.sign != 0))) {
664 d = 0x7fffffff + (vdm.sign != 0); 835 d = (0x7fffffff + (vdm.sign != 0));
665 exceptions |= FPSCR_IOC; 836 exceptions |= FPSCR_IOC;
666 } else if (rem) 837 } else if (rem)
667 exceptions |= FPSCR_IXC; 838 exceptions |= FPSCR_IXC;
668 839
669 if (vdm.sign) 840 if (vdm.sign)
670 d = -d; 841 d = -d;
671 } else { 842 } else {
672 d = 0; 843 d = 0;
673 if (vdm.exponent | vdm.significand) { 844 if (vdm.exponent | vdm.significand) {
674 exceptions |= FPSCR_IXC; 845 exceptions |= FPSCR_IXC;
675 if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) 846 if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
676 d = 1; 847 d = 1;
677 else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) 848 else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign)
678 d = -1; 849 d = -1;
679 } 850 }
680 } 851 }
681 852
682 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); 853 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
683 854
684 vfp_put_float(state, (s32)d, sd); 855 vfp_put_float(state, (s32)d, sd);
685 856
686 return exceptions; 857 return exceptions;
687} 858}
688 859
689static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 860static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
690{ 861{
691 pr_debug("In %s\n", __FUNCTION__); 862 pr_debug("In %s\n", __FUNCTION__);
692 return vfp_double_ftosi(state, dd, unused, dm, FPSCR_ROUND_TOZERO); 863 return vfp_double_ftosi(state, dd, unused, dm, FPSCR_ROUND_TOZERO);
693} 864}
694 865
695static struct op fops_ext[] = { 866static struct op fops_ext[] = {
@@ -728,197 +899,195 @@ static struct op fops_ext[] = {
728 899
729static u32 900static u32
730vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn, 901vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn,
731 struct vfp_double *vdm, u32 fpscr) 902 struct vfp_double *vdm, u32 fpscr)
732{ 903{
733 struct vfp_double *vdp; 904 struct vfp_double *vdp;
734 u32 exceptions = 0; 905 u32 exceptions = 0;
735 int tn, tm; 906 int tn, tm;
736 907
737 tn = vfp_double_type(vdn); 908 tn = vfp_double_type(vdn);
738 tm = vfp_double_type(vdm); 909 tm = vfp_double_type(vdm);
739 910
740 if (tn & tm & VFP_INFINITY) { 911 if (tn & tm & VFP_INFINITY) {
741 /* 912 /*
742 * Two infinities. Are they different signs? 913 * Two infinities. Are they different signs?
743 */ 914 */
744 if (vdn->sign ^ vdm->sign) { 915 if (vdn->sign ^ vdm->sign) {
745 /* 916 /*
746 * different signs -> invalid 917 * different signs -> invalid
747 */ 918 */
748 exceptions = FPSCR_IOC; 919 exceptions = FPSCR_IOC;
749 vdp = &vfp_double_default_qnan; 920 vdp = &vfp_double_default_qnan;
750 } else { 921 } else {
751 /* 922 /*
752 * same signs -> valid 923 * same signs -> valid
753 */ 924 */
754 vdp = vdn; 925 vdp = vdn;
755 } 926 }
756 } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) { 927 } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
757 /* 928 /*
758 * One infinity and one number -> infinity 929 * One infinity and one number -> infinity
759 */ 930 */
760 vdp = vdn; 931 vdp = vdn;
761 } else { 932 } else {
762 /* 933 /*
763 * 'n' is a NaN of some type 934 * 'n' is a NaN of some type
764 */ 935 */
765 return vfp_propagate_nan(vdd, vdn, vdm, fpscr); 936 return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
766 } 937 }
767 *vdd = *vdp; 938 *vdd = *vdp;
768 return exceptions; 939 return exceptions;
769} 940}
770 941
771static u32 942u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_double *vdm, u32 fpscr)
772vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,
773 struct vfp_double *vdm, u32 fpscr)
774{ 943{
775 u32 exp_diff; 944 u32 exp_diff;
776 u64 m_sig; 945 u64 m_sig;
777 946
778 if (vdn->significand & (1ULL << 63) || 947 if (vdn->significand & (1ULL << 63) ||
779 vdm->significand & (1ULL << 63)) { 948 vdm->significand & (1ULL << 63)) {
780 pr_info("VFP: bad FP values\n"); 949 pr_info("VFP: bad FP values in %s\n", __func__);
781 vfp_double_dump("VDN", vdn); 950 vfp_double_dump("VDN", vdn);
782 vfp_double_dump("VDM", vdm); 951 vfp_double_dump("VDM", vdm);
783 } 952 }
784 953
785 /* 954 /*
786 * Ensure that 'n' is the largest magnitude number. Note that 955 * Ensure that 'n' is the largest magnitude number. Note that
787 * if 'n' and 'm' have equal exponents, we do not swap them. 956 * if 'n' and 'm' have equal exponents, we do not swap them.
788 * This ensures that NaN propagation works correctly. 957 * This ensures that NaN propagation works correctly.
789 */ 958 */
790 if (vdn->exponent < vdm->exponent) { 959 if (vdn->exponent < vdm->exponent) {
791 struct vfp_double *t = vdn; 960 struct vfp_double *t = vdn;
792 vdn = vdm; 961 vdn = vdm;
793 vdm = t; 962 vdm = t;
794 } 963 }
795 964
796 /* 965 /*
797 * Is 'n' an infinity or a NaN? Note that 'm' may be a number, 966 * Is 'n' an infinity or a NaN? Note that 'm' may be a number,
798 * infinity or a NaN here. 967 * infinity or a NaN here.
799 */ 968 */
800 if (vdn->exponent == 2047) 969 if (vdn->exponent == 2047)
801 return vfp_double_fadd_nonnumber(vdd, vdn, vdm, fpscr); 970 return vfp_double_fadd_nonnumber(vdd, vdn, vdm, fpscr);
802 971
803 /* 972 /*
804 * We have two proper numbers, where 'vdn' is the larger magnitude. 973 * We have two proper numbers, where 'vdn' is the larger magnitude.
805 * 974 *
806 * Copy 'n' to 'd' before doing the arithmetic. 975 * Copy 'n' to 'd' before doing the arithmetic.
807 */ 976 */
808 *vdd = *vdn; 977 *vdd = *vdn;
809 978
810 /* 979 /*
811 * Align 'm' with the result. 980 * Align 'm' with the result.
812 */ 981 */
813 exp_diff = vdn->exponent - vdm->exponent; 982 exp_diff = vdn->exponent - vdm->exponent;
814 m_sig = vfp_shiftright64jamming(vdm->significand, exp_diff); 983 m_sig = vfp_shiftright64jamming(vdm->significand, exp_diff);
815 984
816 /* 985 /*
817 * If the signs are different, we are really subtracting. 986 * If the signs are different, we are really subtracting.
818 */ 987 */
819 if (vdn->sign ^ vdm->sign) { 988 if (vdn->sign ^ vdm->sign) {
820 m_sig = vdn->significand - m_sig; 989 m_sig = vdn->significand - m_sig;
821 if ((s64)m_sig < 0) { 990 if ((s64)m_sig < 0) {
822 vdd->sign = vfp_sign_negate(vdd->sign); 991 vdd->sign = vfp_sign_negate(vdd->sign);
823 m_sig = -m_sig; 992 m_sig = -m_sig;
824 } else if (m_sig == 0) { 993 } else if (m_sig == 0) {
825 vdd->sign = (fpscr & FPSCR_RMODE_MASK) == 994 vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
826 FPSCR_ROUND_MINUSINF ? 0x8000 : 0; 995 FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
827 } 996 }
828 } else { 997 } else {
829 m_sig += vdn->significand; 998 m_sig += vdn->significand;
830 } 999 }
831 vdd->significand = m_sig; 1000 vdd->significand = m_sig;
832 1001
833 return 0; 1002 return 0;
834} 1003}
835 1004
836static u32 1005u32
837vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, 1006vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
838 struct vfp_double *vdm, u32 fpscr) 1007 struct vfp_double *vdm, u32 fpscr)
839{ 1008{
840 vfp_double_dump("VDN", vdn); 1009 vfp_double_dump("VDN", vdn);
841 vfp_double_dump("VDM", vdm); 1010 vfp_double_dump("VDM", vdm);
842 1011
843 /* 1012 /*
844 * Ensure that 'n' is the largest magnitude number. Note that 1013 * Ensure that 'n' is the largest magnitude number. Note that
845 * if 'n' and 'm' have equal exponents, we do not swap them. 1014 * if 'n' and 'm' have equal exponents, we do not swap them.
846 * This ensures that NaN propagation works correctly. 1015 * This ensures that NaN propagation works correctly.
847 */ 1016 */
848 if (vdn->exponent < vdm->exponent) { 1017 if (vdn->exponent < vdm->exponent) {
849 struct vfp_double *t = vdn; 1018 struct vfp_double *t = vdn;
850 vdn = vdm; 1019 vdn = vdm;
851 vdm = t; 1020 vdm = t;
852 pr_debug("VFP: swapping M <-> N\n"); 1021 pr_debug("VFP: swapping M <-> N\n");
853 } 1022 }
854 1023
855 vdd->sign = vdn->sign ^ vdm->sign; 1024 vdd->sign = vdn->sign ^ vdm->sign;
856 1025
857 /* 1026 /*
858 * If 'n' is an infinity or NaN, handle it. 'm' may be anything. 1027 * If 'n' is an infinity or NaN, handle it. 'm' may be anything.
859 */ 1028 */
860 if (vdn->exponent == 2047) { 1029 if (vdn->exponent == 2047) {
861 if (vdn->significand || (vdm->exponent == 2047 && vdm->significand)) 1030 if (vdn->significand || (vdm->exponent == 2047 && vdm->significand))
862 return vfp_propagate_nan(vdd, vdn, vdm, fpscr); 1031 return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
863 if ((vdm->exponent | vdm->significand) == 0) { 1032 if ((vdm->exponent | vdm->significand) == 0) {
864 *vdd = vfp_double_default_qnan; 1033 *vdd = vfp_double_default_qnan;
865 return FPSCR_IOC; 1034 return FPSCR_IOC;
866 } 1035 }
867 vdd->exponent = vdn->exponent; 1036 vdd->exponent = vdn->exponent;
868 vdd->significand = 0; 1037 vdd->significand = 0;
869 return 0; 1038 return 0;
870 } 1039 }
871 1040
872 /* 1041 /*
873 * If 'm' is zero, the result is always zero. In this case, 1042 * If 'm' is zero, the result is always zero. In this case,
874 * 'n' may be zero or a number, but it doesn't matter which. 1043 * 'n' may be zero or a number, but it doesn't matter which.
875 */ 1044 */
876 if ((vdm->exponent | vdm->significand) == 0) { 1045 if ((vdm->exponent | vdm->significand) == 0) {
877 vdd->exponent = 0; 1046 vdd->exponent = 0;
878 vdd->significand = 0; 1047 vdd->significand = 0;
879 return 0; 1048 return 0;
880 } 1049 }
881 1050
882 /* 1051 /*
883 * We add 2 to the destination exponent for the same reason 1052 * We add 2 to the destination exponent for the same reason
884 * as the addition case - though this time we have +1 from 1053 * as the addition case - though this time we have +1 from
885 * each input operand. 1054 * each input operand.
886 */ 1055 */
887 vdd->exponent = vdn->exponent + vdm->exponent - 1023 + 2; 1056 vdd->exponent = vdn->exponent + vdm->exponent - 1023 + 2;
888 vdd->significand = vfp_hi64multiply64(vdn->significand, vdm->significand); 1057 vdd->significand = vfp_hi64multiply64(vdn->significand, vdm->significand);
889 1058
890 vfp_double_dump("VDD", vdd); 1059 vfp_double_dump("VDD", vdd);
891 return 0; 1060 return 0;
892} 1061}
893 1062
894#define NEG_MULTIPLY (1 << 0) 1063#define NEG_MULTIPLY (1 << 0)
895#define NEG_SUBTRACT (1 << 1) 1064#define NEG_SUBTRACT (1 << 1)
896 1065
897static u32 1066static u32
898vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, const char *func) 1067vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, char *func)
899{ 1068{
900 struct vfp_double vdd, vdp, vdn, vdm; 1069 struct vfp_double vdd, vdp, vdn, vdm;
901 u32 exceptions; 1070 u32 exceptions;
902 1071
903 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1072 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
904 if (vdn.exponent == 0 && vdn.significand) 1073 if (vdn.exponent == 0 && vdn.significand)
905 vfp_double_normalise_denormal(&vdn); 1074 vfp_double_normalise_denormal(&vdn);
906 1075
907 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1076 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
908 if (vdm.exponent == 0 && vdm.significand) 1077 if (vdm.exponent == 0 && vdm.significand)
909 vfp_double_normalise_denormal(&vdm); 1078 vfp_double_normalise_denormal(&vdm);
910 1079
911 exceptions = vfp_double_multiply(&vdp, &vdn, &vdm, fpscr); 1080 exceptions = vfp_double_multiply(&vdp, &vdn, &vdm, fpscr);
912 if (negate & NEG_MULTIPLY) 1081 if (negate & NEG_MULTIPLY)
913 vdp.sign = vfp_sign_negate(vdp.sign); 1082 vdp.sign = vfp_sign_negate(vdp.sign);
914 1083
915 vfp_double_unpack(&vdn, vfp_get_double(state, dd)); 1084 vfp_double_unpack(&vdn, vfp_get_double(state, dd));
916 if (negate & NEG_SUBTRACT) 1085 if (negate & NEG_SUBTRACT)
917 vdn.sign = vfp_sign_negate(vdn.sign); 1086 vdn.sign = vfp_sign_negate(vdn.sign);
918 1087
919 exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr); 1088 exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr);
920 1089
921 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, func); 1090 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, func);
922} 1091}
923 1092
924/* 1093/*
@@ -930,8 +1099,8 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f
930 */ 1099 */
931static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1100static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
932{ 1101{
933 pr_debug("In %s\n", __FUNCTION__); 1102 pr_debug("In %s\n", __FUNCTION__);
934 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac"); 1103 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac");
935} 1104}
936 1105
937/* 1106/*
@@ -939,8 +1108,8 @@ static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
939 */ 1108 */
940static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1109static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
941{ 1110{
942 pr_debug("In %s\n", __FUNCTION__); 1111 pr_debug("In %s\n", __FUNCTION__);
943 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac"); 1112 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac");
944} 1113}
945 1114
946/* 1115/*
@@ -948,8 +1117,8 @@ static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
948 */ 1117 */
949static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1118static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
950{ 1119{
951 pr_debug("In %s\n", __FUNCTION__); 1120 pr_debug("In %s\n", __FUNCTION__);
952 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc"); 1121 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc");
953} 1122}
954 1123
955/* 1124/*
@@ -957,8 +1126,8 @@ static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
957 */ 1126 */
958static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1127static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
959{ 1128{
960 pr_debug("In %s\n", __FUNCTION__); 1129 pr_debug("In %s\n", __FUNCTION__);
961 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); 1130 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
962} 1131}
963 1132
964/* 1133/*
@@ -966,20 +1135,20 @@ static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
966 */ 1135 */
967static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1136static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
968{ 1137{
969 struct vfp_double vdd, vdn, vdm; 1138 struct vfp_double vdd, vdn, vdm;
970 u32 exceptions; 1139 u32 exceptions;
971 1140
972 pr_debug("In %s\n", __FUNCTION__); 1141 pr_debug("In %s\n", __FUNCTION__);
973 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1142 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
974 if (vdn.exponent == 0 && vdn.significand) 1143 if (vdn.exponent == 0 && vdn.significand)
975 vfp_double_normalise_denormal(&vdn); 1144 vfp_double_normalise_denormal(&vdn);
976 1145
977 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1146 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
978 if (vdm.exponent == 0 && vdm.significand) 1147 if (vdm.exponent == 0 && vdm.significand)
979 vfp_double_normalise_denormal(&vdm); 1148 vfp_double_normalise_denormal(&vdm);
980 1149
981 exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); 1150 exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
982 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fmul"); 1151 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fmul");
983} 1152}
984 1153
985/* 1154/*
@@ -987,22 +1156,22 @@ static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
987 */ 1156 */
988static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1157static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
989{ 1158{
990 struct vfp_double vdd, vdn, vdm; 1159 struct vfp_double vdd, vdn, vdm;
991 u32 exceptions; 1160 u32 exceptions;
992 1161
993 pr_debug("In %s\n", __FUNCTION__); 1162 pr_debug("In %s\n", __FUNCTION__);
994 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1163 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
995 if (vdn.exponent == 0 && vdn.significand) 1164 if (vdn.exponent == 0 && vdn.significand)
996 vfp_double_normalise_denormal(&vdn); 1165 vfp_double_normalise_denormal(&vdn);
997 1166
998 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1167 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
999 if (vdm.exponent == 0 && vdm.significand) 1168 if (vdm.exponent == 0 && vdm.significand)
1000 vfp_double_normalise_denormal(&vdm); 1169 vfp_double_normalise_denormal(&vdm);
1001 1170
1002 exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); 1171 exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
1003 vdd.sign = vfp_sign_negate(vdd.sign); 1172 vdd.sign = vfp_sign_negate(vdd.sign);
1004 1173
1005 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fnmul"); 1174 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fnmul");
1006} 1175}
1007 1176
1008/* 1177/*
@@ -1010,21 +1179,21 @@ static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
1010 */ 1179 */
1011static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1180static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1012{ 1181{
1013 struct vfp_double vdd, vdn, vdm; 1182 struct vfp_double vdd, vdn, vdm;
1014 u32 exceptions; 1183 u32 exceptions;
1015 1184
1016 pr_debug("In %s\n", __FUNCTION__); 1185 pr_debug("In %s\n", __FUNCTION__);
1017 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1186 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1018 if (vdn.exponent == 0 && vdn.significand) 1187 if (vdn.exponent == 0 && vdn.significand)
1019 vfp_double_normalise_denormal(&vdn); 1188 vfp_double_normalise_denormal(&vdn);
1020 1189
1021 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1190 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1022 if (vdm.exponent == 0 && vdm.significand) 1191 if (vdm.exponent == 0 && vdm.significand)
1023 vfp_double_normalise_denormal(&vdm); 1192 vfp_double_normalise_denormal(&vdm);
1024 1193
1025 exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr); 1194 exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
1026 1195
1027 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fadd"); 1196 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fadd");
1028} 1197}
1029 1198
1030/* 1199/*
@@ -1032,26 +1201,26 @@ static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1032 */ 1201 */
1033static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1202static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1034{ 1203{
1035 struct vfp_double vdd, vdn, vdm; 1204 struct vfp_double vdd, vdn, vdm;
1036 u32 exceptions; 1205 u32 exceptions;
1037 1206
1038 pr_debug("In %s\n", __FUNCTION__); 1207 pr_debug("In %s\n", __FUNCTION__);
1039 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1208 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1040 if (vdn.exponent == 0 && vdn.significand) 1209 if (vdn.exponent == 0 && vdn.significand)
1041 vfp_double_normalise_denormal(&vdn); 1210 vfp_double_normalise_denormal(&vdn);
1042 1211
1043 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1212 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1044 if (vdm.exponent == 0 && vdm.significand) 1213 if (vdm.exponent == 0 && vdm.significand)
1045 vfp_double_normalise_denormal(&vdm); 1214 vfp_double_normalise_denormal(&vdm);
1046 1215
1047 /* 1216 /*
1048 * Subtraction is like addition, but with a negated operand. 1217 * Subtraction is like addition, but with a negated operand.
1049 */ 1218 */
1050 vdm.sign = vfp_sign_negate(vdm.sign); 1219 vdm.sign = vfp_sign_negate(vdm.sign);
1051 1220
1052 exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr); 1221 exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
1053 1222
1054 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fsub"); 1223 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fsub");
1055} 1224}
1056 1225
1057/* 1226/*
@@ -1059,120 +1228,120 @@ static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1059 */ 1228 */
1060static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1229static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
1061{ 1230{
1062 struct vfp_double vdd, vdn, vdm; 1231 struct vfp_double vdd, vdn, vdm;
1063 u32 exceptions = 0; 1232 u32 exceptions = 0;
1064 int tm, tn; 1233 int tm, tn;
1065 1234
1066 pr_debug("In %s\n", __FUNCTION__); 1235 pr_debug("In %s\n", __FUNCTION__);
1067 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1236 vfp_double_unpack(&vdn, vfp_get_double(state, dn));
1068 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1237 vfp_double_unpack(&vdm, vfp_get_double(state, dm));
1069 1238
1070 vdd.sign = vdn.sign ^ vdm.sign; 1239 vdd.sign = vdn.sign ^ vdm.sign;
1071 1240
1072 tn = vfp_double_type(&vdn); 1241 tn = vfp_double_type(&vdn);
1073 tm = vfp_double_type(&vdm); 1242 tm = vfp_double_type(&vdm);
1074 1243
1075 /* 1244 /*
1076 * Is n a NAN? 1245 * Is n a NAN?
1077 */ 1246 */
1078 if (tn & VFP_NAN) 1247 if (tn & VFP_NAN)
1079 goto vdn_nan; 1248 goto vdn_nan;
1080 1249
1081 /* 1250 /*
1082 * Is m a NAN? 1251 * Is m a NAN?
1083 */ 1252 */
1084 if (tm & VFP_NAN) 1253 if (tm & VFP_NAN)
1085 goto vdm_nan; 1254 goto vdm_nan;
1086 1255
1087 /* 1256 /*
1088 * If n and m are infinity, the result is invalid 1257 * If n and m are infinity, the result is invalid
1089 * If n and m are zero, the result is invalid 1258 * If n and m are zero, the result is invalid
1090 */ 1259 */
1091 if (tm & tn & (VFP_INFINITY|VFP_ZERO)) 1260 if (tm & tn & (VFP_INFINITY|VFP_ZERO))
1092 goto invalid; 1261 goto invalid;
1093 1262
1094 /* 1263 /*
1095 * If n is infinity, the result is infinity 1264 * If n is infinity, the result is infinity
1096 */ 1265 */
1097 if (tn & VFP_INFINITY) 1266 if (tn & VFP_INFINITY)
1098 goto infinity; 1267 goto infinity;
1099 1268
1100 /* 1269 /*
1101 * If m is zero, raise div0 exceptions 1270 * If m is zero, raise div0 exceptions
1102 */ 1271 */
1103 if (tm & VFP_ZERO) 1272 if (tm & VFP_ZERO)
1104 goto divzero; 1273 goto divzero;
1105 1274
1106 /* 1275 /*
1107 * If m is infinity, or n is zero, the result is zero 1276 * If m is infinity, or n is zero, the result is zero
1108 */ 1277 */
1109 if (tm & VFP_INFINITY || tn & VFP_ZERO) 1278 if (tm & VFP_INFINITY || tn & VFP_ZERO)
1110 goto zero; 1279 goto zero;
1111 1280
1112 if (tn & VFP_DENORMAL) 1281 if (tn & VFP_DENORMAL)
1113 vfp_double_normalise_denormal(&vdn); 1282 vfp_double_normalise_denormal(&vdn);
1114 if (tm & VFP_DENORMAL) 1283 if (tm & VFP_DENORMAL)
1115 vfp_double_normalise_denormal(&vdm); 1284 vfp_double_normalise_denormal(&vdm);
1116 1285
1117 /* 1286 /*
1118 * Ok, we have two numbers, we can perform division. 1287 * Ok, we have two numbers, we can perform division.
1119 */ 1288 */
1120 vdd.exponent = vdn.exponent - vdm.exponent + 1023 - 1; 1289 vdd.exponent = vdn.exponent - vdm.exponent + 1023 - 1;
1121 vdm.significand <<= 1; 1290 vdm.significand <<= 1;
1122 if (vdm.significand <= (2 * vdn.significand)) { 1291 if (vdm.significand <= (2 * vdn.significand)) {
1123 vdn.significand >>= 1; 1292 vdn.significand >>= 1;
1124 vdd.exponent++; 1293 vdd.exponent++;
1125 } 1294 }
1126 vdd.significand = vfp_estimate_div128to64(vdn.significand, 0, vdm.significand); 1295 vdd.significand = vfp_estimate_div128to64(vdn.significand, 0, vdm.significand);
1127 if ((vdd.significand & 0x1ff) <= 2) { 1296 if ((vdd.significand & 0x1ff) <= 2) {
1128 u64 termh, terml, remh, reml; 1297 u64 termh, terml, remh, reml;
1129 mul64to128(&termh, &terml, vdm.significand, vdd.significand); 1298 mul64to128(&termh, &terml, vdm.significand, vdd.significand);
1130 sub128(&remh, &reml, vdn.significand, 0, termh, terml); 1299 sub128(&remh, &reml, vdn.significand, 0, termh, terml);
1131 while ((s64)remh < 0) { 1300 while ((s64)remh < 0) {
1132 vdd.significand -= 1; 1301 vdd.significand -= 1;
1133 add128(&remh, &reml, remh, reml, 0, vdm.significand); 1302 add128(&remh, &reml, remh, reml, 0, vdm.significand);
1134 } 1303 }
1135 vdd.significand |= (reml != 0); 1304 vdd.significand |= (reml != 0);
1136 } 1305 }
1137 return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fdiv"); 1306 return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fdiv");
1138 1307
1139 vdn_nan: 1308vdn_nan:
1140 exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr); 1309 exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr);
1141 pack: 1310pack:
1142 vfp_put_double(state, vfp_double_pack(&vdd), dd); 1311 vfp_put_double(state, vfp_double_pack(&vdd), dd);
1143 return exceptions; 1312 return exceptions;
1144 1313
1145 vdm_nan: 1314vdm_nan:
1146 exceptions = vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr); 1315 exceptions = vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr);
1147 goto pack; 1316 goto pack;
1148 1317
1149 zero: 1318zero:
1150 vdd.exponent = 0; 1319 vdd.exponent = 0;
1151 vdd.significand = 0; 1320 vdd.significand = 0;
1152 goto pack; 1321 goto pack;
1153 1322
1154 divzero: 1323divzero:
1155 exceptions = FPSCR_DZC; 1324 exceptions = FPSCR_DZC;
1156 infinity: 1325infinity:
1157 vdd.exponent = 2047; 1326 vdd.exponent = 2047;
1158 vdd.significand = 0; 1327 vdd.significand = 0;
1159 goto pack; 1328 goto pack;
1160 1329
1161 invalid: 1330invalid:
1162 vfp_put_double(state, vfp_double_pack(&vfp_double_default_qnan), dd); 1331 vfp_put_double(state, vfp_double_pack(&vfp_double_default_qnan), dd);
1163 return FPSCR_IOC; 1332 return FPSCR_IOC;
1164} 1333}
1165 1334
1166static struct op fops[] = { 1335static struct op fops[] = {
1167 { vfp_double_fmac, 0 }, 1336 { vfp_double_fmac, 0 },
1168 { vfp_double_fmsc, 0 }, 1337 { vfp_double_fmsc, 0 },
1169 { vfp_double_fmul, 0 }, 1338 { vfp_double_fmul, 0 },
1170 { vfp_double_fadd, 0 }, 1339 { vfp_double_fadd, 0 },
1171 { vfp_double_fnmac, 0 }, 1340 { vfp_double_fnmac, 0 },
1172 { vfp_double_fnmsc, 0 }, 1341 { vfp_double_fnmsc, 0 },
1173 { vfp_double_fnmul, 0 }, 1342 { vfp_double_fnmul, 0 },
1174 { vfp_double_fsub, 0 }, 1343 { vfp_double_fsub, 0 },
1175 { vfp_double_fdiv, 0 }, 1344 { vfp_double_fdiv, 0 },
1176}; 1345};
1177 1346
1178#define FREG_BANK(x) ((x) & 0x0c) 1347#define FREG_BANK(x) ((x) & 0x0c)
@@ -1180,84 +1349,84 @@ static struct op fops[] = {
1180 1349
1181u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) 1350u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1182{ 1351{
1183 u32 op = inst & FOP_MASK; 1352 u32 op = inst & FOP_MASK;
1184 u32 exceptions = 0; 1353 u32 exceptions = 0;
1185 unsigned int dest; 1354 unsigned int dest;
1186 unsigned int dn = vfp_get_dn(inst); 1355 unsigned int dn = vfp_get_dn(inst);
1187 unsigned int dm; 1356 unsigned int dm;
1188 unsigned int vecitr, veclen, vecstride; 1357 unsigned int vecitr, veclen, vecstride;
1189 struct op *fop; 1358 struct op *fop;
1190 1359
1191 pr_debug("In %s\n", __FUNCTION__); 1360 pr_debug("In %s\n", __FUNCTION__);
1192 vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)); 1361 vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK));
1193 1362
1194 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)]; 1363 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
1195 1364
1196 /* 1365 /*
1197 * fcvtds takes an sN register number as destination, not dN. 1366 * fcvtds takes an sN register number as destination, not dN.
1198 * It also always operates on scalars. 1367 * It also always operates on scalars.
1199 */ 1368 */
1200 if (fop->flags & OP_SD) 1369 if (fop->flags & OP_SD)
1201 dest = vfp_get_sd(inst); 1370 dest = vfp_get_sd(inst);
1202 else 1371 else
1203 dest = vfp_get_dd(inst); 1372 dest = vfp_get_dd(inst);
1204 1373
1205 /* 1374 /*
1206 * f[us]ito takes a sN operand, not a dN operand. 1375 * f[us]ito takes a sN operand, not a dN operand.
1207 */ 1376 */
1208 if (fop->flags & OP_SM) 1377 if (fop->flags & OP_SM)
1209 dm = vfp_get_sm(inst); 1378 dm = vfp_get_sm(inst);
1210 else 1379 else
1211 dm = vfp_get_dm(inst); 1380 dm = vfp_get_dm(inst);
1212 1381
1213 /* 1382 /*
1214 * If destination bank is zero, vector length is always '1'. 1383 * If destination bank is zero, vector length is always '1'.
1215 * ARM DDI0100F C5.1.3, C5.3.2. 1384 * ARM DDI0100F C5.1.3, C5.3.2.
1216 */ 1385 */
1217 if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0)) 1386 if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0))
1218 veclen = 0; 1387 veclen = 0;
1219 else 1388 else
1220 veclen = fpscr & FPSCR_LENGTH_MASK; 1389 veclen = fpscr & FPSCR_LENGTH_MASK;
1221 1390
1222 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, 1391 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
1223 (veclen >> FPSCR_LENGTH_BIT) + 1); 1392 (veclen >> FPSCR_LENGTH_BIT) + 1);
1224 1393
1225 if (!fop->fn) { 1394 if (!fop->fn) {
1226 printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst)); 1395 printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst));
1227 goto invalid; 1396 goto invalid;
1228 } 1397 }
1229 1398
1230 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { 1399 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
1231 u32 except; 1400 u32 except;
1232 char type; 1401 char type;
1233 1402
1234 type = fop->flags & OP_SD ? 's' : 'd'; 1403 type = fop->flags & OP_SD ? 's' : 'd';
1235 if (op == FOP_EXT) 1404 if (op == FOP_EXT)
1236 pr_debug("VFP: itr%d (%c%u) = op[%u] (d%u)\n", 1405 pr_debug("VFP: itr%d (%c%u) = op[%u] (d%u)\n",
1237 vecitr >> FPSCR_LENGTH_BIT, 1406 vecitr >> FPSCR_LENGTH_BIT,
1238 type, dest, dn, dm); 1407 type, dest, dn, dm);
1239 else 1408 else
1240 pr_debug("VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)\n", 1409 pr_debug("VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)\n",
1241 vecitr >> FPSCR_LENGTH_BIT, 1410 vecitr >> FPSCR_LENGTH_BIT,
1242 type, dest, dn, FOP_TO_IDX(op), dm); 1411 type, dest, dn, FOP_TO_IDX(op), dm);
1243 1412
1244 except = fop->fn(state, dest, dn, dm, fpscr); 1413 except = fop->fn(state, dest, dn, dm, fpscr);
1245 pr_debug("VFP: itr%d: exceptions=%08x\n", 1414 pr_debug("VFP: itr%d: exceptions=%08x\n",
1246 vecitr >> FPSCR_LENGTH_BIT, except); 1415 vecitr >> FPSCR_LENGTH_BIT, except);
1247 1416
1248 exceptions |= except; 1417 exceptions |= except;
1249 1418
1250 /* 1419 /*
1251 * CHECK: It appears to be undefined whether we stop when 1420 * CHECK: It appears to be undefined whether we stop when
1252 * we encounter an exception. We continue. 1421 * we encounter an exception. We continue.
1253 */ 1422 */
1254 dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 3); 1423 dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 3);
1255 dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 3); 1424 dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 3);
1256 if (FREG_BANK(dm) != 0) 1425 if (FREG_BANK(dm) != 0)
1257 dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 3); 1426 dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 3);
1258 } 1427 }
1259 return exceptions; 1428 return exceptions;
1260 1429
1261 invalid: 1430invalid:
1262 return ~0; 1431 return ~0;
1263} 1432}
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 8bcbd4fe9..07d0c1f44 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -56,167 +56,167 @@
56#include "core/arm/skyeye_common/vfp/vfp.h" 56#include "core/arm/skyeye_common/vfp/vfp.h"
57 57
58static struct vfp_single vfp_single_default_qnan = { 58static struct vfp_single vfp_single_default_qnan = {
59 //.exponent = 255, 59 255,
60 //.sign = 0, 60 0,
61 //.significand = VFP_SINGLE_SIGNIFICAND_QNAN, 61 VFP_SINGLE_SIGNIFICAND_QNAN,
62}; 62};
63 63
64static void vfp_single_dump(const char *str, struct vfp_single *s) 64static void vfp_single_dump(const char *str, struct vfp_single *s)
65{ 65{
66 pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n", 66 pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n",
67 str, s->sign != 0, s->exponent, s->significand); 67 str, s->sign != 0, s->exponent, s->significand);
68} 68}
69 69
70static void vfp_single_normalise_denormal(struct vfp_single *vs) 70static void vfp_single_normalise_denormal(struct vfp_single *vs)
71{ 71{
72 int bits = 31 - vfp_fls(vs->significand); 72 int bits = 31 - fls(vs->significand);
73 73
74 vfp_single_dump("normalise_denormal: in", vs); 74 vfp_single_dump("normalise_denormal: in", vs);
75 75
76 if (bits) { 76 if (bits) {
77 vs->exponent -= bits - 1; 77 vs->exponent -= bits - 1;
78 vs->significand <<= bits; 78 vs->significand <<= bits;
79 } 79 }
80 80
81 vfp_single_dump("normalise_denormal: out", vs); 81 vfp_single_dump("normalise_denormal: out", vs);
82} 82}
83 83
84 84
85u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func) 85u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func)
86{ 86{
87 u32 significand, incr, rmode; 87 u32 significand, incr, rmode;
88 int exponent, shift, underflow; 88 int exponent, shift, underflow;
89 89
90 vfp_single_dump("pack: in", vs); 90 vfp_single_dump("pack: in", vs);
91 91
92 /* 92 /*
93 * Infinities and NaNs are a special case. 93 * Infinities and NaNs are a special case.
94 */ 94 */
95 if (vs->exponent == 255 && (vs->significand == 0 || exceptions)) 95 if (vs->exponent == 255 && (vs->significand == 0 || exceptions))
96 goto pack; 96 goto pack;
97 97
98 /* 98 /*
99 * Special-case zero. 99 * Special-case zero.
100 */ 100 */
101 if (vs->significand == 0) { 101 if (vs->significand == 0) {
102 vs->exponent = 0; 102 vs->exponent = 0;
103 goto pack; 103 goto pack;
104 } 104 }
105 105
106 exponent = vs->exponent; 106 exponent = vs->exponent;
107 significand = vs->significand; 107 significand = vs->significand;
108 108
109 /* 109 /*
110 * Normalise first. Note that we shift the significand up to 110 * Normalise first. Note that we shift the significand up to
111 * bit 31, so we have VFP_SINGLE_LOW_BITS + 1 below the least 111 * bit 31, so we have VFP_SINGLE_LOW_BITS + 1 below the least
112 * significant bit. 112 * significant bit.
113 */ 113 */
114 shift = 32 - vfp_fls(significand); 114 shift = 32 - fls(significand);
115 if (shift < 32 && shift) { 115 if (shift < 32 && shift) {
116 exponent -= shift; 116 exponent -= shift;
117 significand <<= shift; 117 significand <<= shift;
118 } 118 }
119 119
120#if 1 120#if 1
121 vs->exponent = exponent; 121 vs->exponent = exponent;
122 vs->significand = significand; 122 vs->significand = significand;
123 vfp_single_dump("pack: normalised", vs); 123 vfp_single_dump("pack: normalised", vs);
124#endif 124#endif
125 125
126 /* 126 /*
127 * Tiny number? 127 * Tiny number?
128 */ 128 */
129 underflow = exponent < 0; 129 underflow = exponent < 0;
130 if (underflow) { 130 if (underflow) {
131 significand = vfp_shiftright32jamming(significand, -exponent); 131 significand = vfp_shiftright32jamming(significand, -exponent);
132 exponent = 0; 132 exponent = 0;
133#if 1 133#if 1
134 vs->exponent = exponent; 134 vs->exponent = exponent;
135 vs->significand = significand; 135 vs->significand = significand;
136 vfp_single_dump("pack: tiny number", vs); 136 vfp_single_dump("pack: tiny number", vs);
137#endif 137#endif
138 if (!(significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1))) 138 if (!(significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1)))
139 underflow = 0; 139 underflow = 0;
140 } 140 }
141 141
142 /* 142 /*
143 * Select rounding increment. 143 * Select rounding increment.
144 */ 144 */
145 incr = 0; 145 incr = 0;
146 rmode = fpscr & FPSCR_RMODE_MASK; 146 rmode = fpscr & FPSCR_RMODE_MASK;
147 147
148 if (rmode == FPSCR_ROUND_NEAREST) { 148 if (rmode == FPSCR_ROUND_NEAREST) {
149 incr = 1 << VFP_SINGLE_LOW_BITS; 149 incr = 1 << VFP_SINGLE_LOW_BITS;
150 if ((significand & (1 << (VFP_SINGLE_LOW_BITS + 1))) == 0) 150 if ((significand & (1 << (VFP_SINGLE_LOW_BITS + 1))) == 0)
151 incr -= 1; 151 incr -= 1;
152 } else if (rmode == FPSCR_ROUND_TOZERO) { 152 } else if (rmode == FPSCR_ROUND_TOZERO) {
153 incr = 0; 153 incr = 0;
154 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0)) 154 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0))
155 incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1; 155 incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1;
156 156
157 pr_debug("VFP: rounding increment = 0x%08x\n", incr); 157 pr_debug("VFP: rounding increment = 0x%08x\n", incr);
158 158
159 /* 159 /*
160 * Is our rounding going to overflow? 160 * Is our rounding going to overflow?
161 */ 161 */
162 if ((significand + incr) < significand) { 162 if ((significand + incr) < significand) {
163 exponent += 1; 163 exponent += 1;
164 significand = (significand >> 1) | (significand & 1); 164 significand = (significand >> 1) | (significand & 1);
165 incr >>= 1; 165 incr >>= 1;
166#if 1 166#if 1
167 vs->exponent = exponent; 167 vs->exponent = exponent;
168 vs->significand = significand; 168 vs->significand = significand;
169 vfp_single_dump("pack: overflow", vs); 169 vfp_single_dump("pack: overflow", vs);
170#endif 170#endif
171 } 171 }
172 172
173 /* 173 /*
174 * If any of the low bits (which will be shifted out of the 174 * If any of the low bits (which will be shifted out of the
175 * number) are non-zero, the result is inexact. 175 * number) are non-zero, the result is inexact.
176 */ 176 */
177 if (significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1)) 177 if (significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1))
178 exceptions |= FPSCR_IXC; 178 exceptions |= FPSCR_IXC;
179 179
180 /* 180 /*
181 * Do our rounding. 181 * Do our rounding.
182 */ 182 */
183 significand += incr; 183 significand += incr;
184 184
185 /* 185 /*
186 * Infinity? 186 * Infinity?
187 */ 187 */
188 if (exponent >= 254) { 188 if (exponent >= 254) {
189 exceptions |= FPSCR_OFC | FPSCR_IXC; 189 exceptions |= FPSCR_OFC | FPSCR_IXC;
190 if (incr == 0) { 190 if (incr == 0) {
191 vs->exponent = 253; 191 vs->exponent = 253;
192 vs->significand = 0x7fffffff; 192 vs->significand = 0x7fffffff;
193 } else { 193 } else {
194 vs->exponent = 255; /* infinity */ 194 vs->exponent = 255; /* infinity */
195 vs->significand = 0; 195 vs->significand = 0;
196 } 196 }
197 } else { 197 } else {
198 if (significand >> (VFP_SINGLE_LOW_BITS + 1) == 0) 198 if (significand >> (VFP_SINGLE_LOW_BITS + 1) == 0)
199 exponent = 0; 199 exponent = 0;
200 if (exponent || significand > 0x80000000) 200 if (exponent || significand > 0x80000000)
201 underflow = 0; 201 underflow = 0;
202 if (underflow) 202 if (underflow)
203 exceptions |= FPSCR_UFC; 203 exceptions |= FPSCR_UFC;
204 vs->exponent = exponent; 204 vs->exponent = exponent;
205 vs->significand = significand >> 1; 205 vs->significand = significand >> 1;
206 } 206 }
207 207
208 pack: 208pack:
209 vfp_single_dump("pack: final", vs); 209 vfp_single_dump("pack: final", vs);
210 { 210 {
211 s32 d = vfp_single_pack(vs); 211 s32 d = vfp_single_pack(vs);
212#if 1 212#if 1
213 pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func, 213 pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func,
214 sd, d, exceptions); 214 sd, d, exceptions);
215#endif 215#endif
216 vfp_put_float(state, d, sd); 216 vfp_put_float(state, d, sd);
217 } 217 }
218 218
219 return exceptions; 219 return exceptions;
220} 220}
221 221
222/* 222/*
@@ -225,43 +225,43 @@ u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs,
225 */ 225 */
226static u32 226static u32
227vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, 227vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
228 struct vfp_single *vsm, u32 fpscr) 228 struct vfp_single *vsm, u32 fpscr)
229{ 229{
230 struct vfp_single *nan; 230 struct vfp_single *nan;
231 int tn, tm = 0; 231 int tn, tm = 0;
232 232
233 tn = vfp_single_type(vsn); 233 tn = vfp_single_type(vsn);
234 234
235 if (vsm) 235 if (vsm)
236 tm = vfp_single_type(vsm); 236 tm = vfp_single_type(vsm);
237 237
238 if (fpscr & FPSCR_DEFAULT_NAN) 238 if (fpscr & FPSCR_DEFAULT_NAN)
239 /* 239 /*
240 * Default NaN mode - always returns a quiet NaN 240 * Default NaN mode - always returns a quiet NaN
241 */ 241 */
242 nan = &vfp_single_default_qnan; 242 nan = &vfp_single_default_qnan;
243 else { 243 else {
244 /* 244 /*
245 * Contemporary mode - select the first signalling 245 * Contemporary mode - select the first signalling
246 * NAN, or if neither are signalling, the first 246 * NAN, or if neither are signalling, the first
247 * quiet NAN. 247 * quiet NAN.
248 */ 248 */
249 if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN)) 249 if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
250 nan = vsn; 250 nan = vsn;
251 else 251 else
252 nan = vsm; 252 nan = vsm;
253 /* 253 /*
254 * Make the NaN quiet. 254 * Make the NaN quiet.
255 */ 255 */
256 nan->significand |= VFP_SINGLE_SIGNIFICAND_QNAN; 256 nan->significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
257 } 257 }
258 258
259 *vsd = *nan; 259 *vsd = *nan;
260 260
261 /* 261 /*
262 * If one was a signalling NAN, raise invalid operation. 262 * If one was a signalling NAN, raise invalid operation.
263 */ 263 */
264 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG; 264 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
265} 265}
266 266
267 267
@@ -270,140 +270,140 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
270 */ 270 */
271static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 271static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
272{ 272{
273 vfp_put_float(state, vfp_single_packed_abs(m), sd); 273 vfp_put_float(state, vfp_single_packed_abs(m), sd);
274 return 0; 274 return 0;
275} 275}
276 276
277static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 277static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
278{ 278{
279 vfp_put_float(state, m, sd); 279 vfp_put_float(state, m, sd);
280 return 0; 280 return 0;
281} 281}
282 282
283static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 283static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
284{ 284{
285 vfp_put_float(state, vfp_single_packed_negate(m), sd); 285 vfp_put_float(state, vfp_single_packed_negate(m), sd);
286 return 0; 286 return 0;
287} 287}
288 288
289static const u16 sqrt_oddadjust[] = { 289static const u16 sqrt_oddadjust[] = {
290 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0, 290 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0,
291 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67 291 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67
292}; 292};
293 293
294static const u16 sqrt_evenadjust[] = { 294static const u16 sqrt_evenadjust[] = {
295 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e, 295 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e,
296 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002 296 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002
297}; 297};
298 298
299u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) 299u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
300{ 300{
301 int index; 301 int index;
302 u32 z, a; 302 u32 z, a;
303 303
304 if ((significand & 0xc0000000) != 0x40000000) { 304 if ((significand & 0xc0000000) != 0x40000000) {
305 pr_debug("VFP: estimate_sqrt: invalid significand\n"); 305 pr_debug("VFP: estimate_sqrt: invalid significand\n");
306 } 306 }
307 307
308 a = significand << 1; 308 a = significand << 1;
309 index = (a >> 27) & 15; 309 index = (a >> 27) & 15;
310 if (exponent & 1) { 310 if (exponent & 1) {
311 z = 0x4000 + (a >> 17) - sqrt_oddadjust[index]; 311 z = 0x4000 + (a >> 17) - sqrt_oddadjust[index];
312 z = ((a / z) << 14) + (z << 15); 312 z = ((a / z) << 14) + (z << 15);
313 a >>= 1; 313 a >>= 1;
314 } else { 314 } else {
315 z = 0x8000 + (a >> 17) - sqrt_evenadjust[index]; 315 z = 0x8000 + (a >> 17) - sqrt_evenadjust[index];
316 z = a / z + z; 316 z = a / z + z;
317 z = (z >= 0x20000) ? 0xffff8000 : (z << 15); 317 z = (z >= 0x20000) ? 0xffff8000 : (z << 15);
318 if (z <= a) 318 if (z <= a)
319 return (s32)a >> 1; 319 return (s32)a >> 1;
320 } 320 }
321 { 321 {
322 u64 v = (u64)a << 31; 322 u64 v = (u64)a << 31;
323 do_div(v, z); 323 do_div(v, z);
324 return v + (z >> 1); 324 return (u32)(v + (z >> 1));
325 } 325 }
326} 326}
327 327
328static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 328static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
329{ 329{
330 struct vfp_single vsm, vsd, *vsp; 330 struct vfp_single vsm, vsd, *vsp;
331 int ret, tm; 331 int ret, tm;
332 332
333 vfp_single_unpack(&vsm, m); 333 vfp_single_unpack(&vsm, m);
334 tm = vfp_single_type(&vsm); 334 tm = vfp_single_type(&vsm);
335 if (tm & (VFP_NAN|VFP_INFINITY)) { 335 if (tm & (VFP_NAN|VFP_INFINITY)) {
336 vsp = &vsd; 336 vsp = &vsd;
337 337
338 if (tm & VFP_NAN) 338 if (tm & VFP_NAN)
339 ret = vfp_propagate_nan(vsp, &vsm, NULL, fpscr); 339 ret = vfp_propagate_nan(vsp, &vsm, NULL, fpscr);
340 else if (vsm.sign == 0) { 340 else if (vsm.sign == 0) {
341 sqrt_copy: 341sqrt_copy:
342 vsp = &vsm; 342 vsp = &vsm;
343 ret = 0; 343 ret = 0;
344 } else { 344 } else {
345 sqrt_invalid: 345sqrt_invalid:
346 vsp = &vfp_single_default_qnan; 346 vsp = &vfp_single_default_qnan;
347 ret = FPSCR_IOC; 347 ret = FPSCR_IOC;
348 } 348 }
349 vfp_put_float(state, vfp_single_pack(vsp), sd); 349 vfp_put_float(state, vfp_single_pack(vsp), sd);
350 return ret; 350 return ret;
351 } 351 }
352 352
353 /* 353 /*
354 * sqrt(+/- 0) == +/- 0 354 * sqrt(+/- 0) == +/- 0
355 */ 355 */
356 if (tm & VFP_ZERO) 356 if (tm & VFP_ZERO)
357 goto sqrt_copy; 357 goto sqrt_copy;
358 358
359 /* 359 /*
360 * Normalise a denormalised number 360 * Normalise a denormalised number
361 */ 361 */
362 if (tm & VFP_DENORMAL) 362 if (tm & VFP_DENORMAL)
363 vfp_single_normalise_denormal(&vsm); 363 vfp_single_normalise_denormal(&vsm);
364 364
365 /* 365 /*
366 * sqrt(<0) = invalid 366 * sqrt(<0) = invalid
367 */ 367 */
368 if (vsm.sign) 368 if (vsm.sign)
369 goto sqrt_invalid; 369 goto sqrt_invalid;
370 370
371 vfp_single_dump("sqrt", &vsm); 371 vfp_single_dump("sqrt", &vsm);
372 372
373 /* 373 /*
374 * Estimate the square root. 374 * Estimate the square root.
375 */ 375 */
376 vsd.sign = 0; 376 vsd.sign = 0;
377 vsd.exponent = ((vsm.exponent - 127) >> 1) + 127; 377 vsd.exponent = ((vsm.exponent - 127) >> 1) + 127;
378 vsd.significand = vfp_estimate_sqrt_significand(vsm.exponent, vsm.significand) + 2; 378 vsd.significand = vfp_estimate_sqrt_significand(vsm.exponent, vsm.significand) + 2;
379 379
380 vfp_single_dump("sqrt estimate", &vsd); 380 vfp_single_dump("sqrt estimate", &vsd);
381 381
382 /* 382 /*
383 * And now adjust. 383 * And now adjust.
384 */ 384 */
385 if ((vsd.significand & VFP_SINGLE_LOW_BITS_MASK) <= 5) { 385 if ((vsd.significand & VFP_SINGLE_LOW_BITS_MASK) <= 5) {
386 if (vsd.significand < 2) { 386 if (vsd.significand < 2) {
387 vsd.significand = 0xffffffff; 387 vsd.significand = 0xffffffff;
388 } else { 388 } else {
389 u64 term; 389 u64 term;
390 s64 rem; 390 s64 rem;
391 vsm.significand <<= !(vsm.exponent & 1); 391 vsm.significand <<= !(vsm.exponent & 1);
392 term = (u64)vsd.significand * vsd.significand; 392 term = (u64)vsd.significand * vsd.significand;
393 rem = ((u64)vsm.significand << 32) - term; 393 rem = ((u64)vsm.significand << 32) - term;
394 394
395 pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem); 395 pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem);
396 396
397 while (rem < 0) { 397 while (rem < 0) {
398 vsd.significand -= 1; 398 vsd.significand -= 1;
399 rem += ((u64)vsd.significand << 1) | 1; 399 rem += ((u64)vsd.significand << 1) | 1;
400 } 400 }
401 vsd.significand |= rem != 0; 401 vsd.significand |= rem != 0;
402 } 402 }
403 } 403 }
404 vsd.significand = vfp_shiftright32jamming(vsd.significand, 1); 404 vsd.significand = vfp_shiftright32jamming(vsd.significand, 1);
405 405
406 return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fsqrt"); 406 return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fsqrt");
407} 407}
408 408
409/* 409/*
@@ -414,305 +414,346 @@ static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 f
414 */ 414 */
415static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr) 415static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr)
416{ 416{
417 s32 d; 417 s32 d;
418 u32 ret = 0; 418 u32 ret = 0;
419 419
420 d = vfp_get_float(state, sd); 420 d = vfp_get_float(state, sd);
421 if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) { 421 if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) {
422 ret |= FPSCR_C | FPSCR_V; 422 ret |= FPSCR_C | FPSCR_V;
423 if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) 423 if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
424 /* 424 /*
425 * Signalling NaN, or signalling on quiet NaN 425 * Signalling NaN, or signalling on quiet NaN
426 */ 426 */
427 ret |= FPSCR_IOC; 427 ret |= FPSCR_IOC;
428 } 428 }
429 429
430 if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) { 430 if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) {
431 ret |= FPSCR_C | FPSCR_V; 431 ret |= FPSCR_C | FPSCR_V;
432 if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) 432 if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
433 /* 433 /*
434 * Signalling NaN, or signalling on quiet NaN 434 * Signalling NaN, or signalling on quiet NaN
435 */ 435 */
436 ret |= FPSCR_IOC; 436 ret |= FPSCR_IOC;
437 } 437 }
438 438
439 if (ret == 0) { 439 if (ret == 0) {
440 if (d == m || vfp_single_packed_abs(d | m) == 0) { 440 if (d == m || vfp_single_packed_abs(d | m) == 0) {
441 /* 441 /*
442 * equal 442 * equal
443 */ 443 */
444 ret |= FPSCR_Z | FPSCR_C; 444 ret |= FPSCR_Z | FPSCR_C;
445 } else if (vfp_single_packed_sign(d ^ m)) { 445 } else if (vfp_single_packed_sign(d ^ m)) {
446 /* 446 /*
447 * different signs 447 * different signs
448 */ 448 */
449 if (vfp_single_packed_sign(d)) 449 if (vfp_single_packed_sign(d))
450 /* 450 /*
451 * d is negative, so d < m 451 * d is negative, so d < m
452 */ 452 */
453 ret |= FPSCR_N; 453 ret |= FPSCR_N;
454 else 454 else
455 /* 455 /*
456 * d is positive, so d > m 456 * d is positive, so d > m
457 */ 457 */
458 ret |= FPSCR_C; 458 ret |= FPSCR_C;
459 } else if ((vfp_single_packed_sign(d) != 0) ^ (d < m)) { 459 } else if ((vfp_single_packed_sign(d) != 0) ^ (d < m)) {
460 /* 460 /*
461 * d < m 461 * d < m
462 */ 462 */
463 ret |= FPSCR_N; 463 ret |= FPSCR_N;
464 } else if ((vfp_single_packed_sign(d) != 0) ^ (d > m)) { 464 } else if ((vfp_single_packed_sign(d) != 0) ^ (d > m)) {
465 /* 465 /*
466 * d > m 466 * d > m
467 */ 467 */
468 ret |= FPSCR_C; 468 ret |= FPSCR_C;
469 } 469 }
470 } 470 }
471 return ret; 471 return ret;
472} 472}
473 473
474static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 474static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
475{ 475{
476 return vfp_compare(state, sd, 0, m, fpscr); 476 return vfp_compare(state, sd, 0, m, fpscr);
477} 477}
478 478
479static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 479static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
480{ 480{
481 return vfp_compare(state, sd, 1, m, fpscr); 481 return vfp_compare(state, sd, 1, m, fpscr);
482} 482}
483 483
484static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 484static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
485{ 485{
486 return vfp_compare(state, sd, 0, 0, fpscr); 486 return vfp_compare(state, sd, 0, 0, fpscr);
487} 487}
488 488
489static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 489static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
490{ 490{
491 return vfp_compare(state, sd, 1, 0, fpscr); 491 return vfp_compare(state, sd, 1, 0, fpscr);
492}
493
494static s64 vfp_single_to_doubleintern(ARMul_State* state, s32 m, u32 fpscr) //ichfly for internal use only
495{
496 struct vfp_single vsm;
497 struct vfp_double vdd;
498 int tm;
499 u32 exceptions = 0;
500
501 vfp_single_unpack(&vsm, m);
502
503 tm = vfp_single_type(&vsm);
504
505 /*
506 * If we have a signalling NaN, signal invalid operation.
507 */
508 if (tm == VFP_SNAN)
509 exceptions = FPSCR_IOC;
510
511 if (tm & VFP_DENORMAL)
512 vfp_single_normalise_denormal(&vsm);
513
514 vdd.sign = vsm.sign;
515 vdd.significand = (u64)vsm.significand << 32;
516
517 /*
518 * If we have an infinity or NaN, the exponent must be 2047.
519 */
520 if (tm & (VFP_INFINITY | VFP_NAN)) {
521 vdd.exponent = 2047;
522 if (tm == VFP_QNAN)
523 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
524 goto pack_nan;
525 }
526 else if (tm & VFP_ZERO)
527 vdd.exponent = 0;
528 else
529 vdd.exponent = vsm.exponent + (1023 - 127);
530pack_nan:
531 vfp_double_normaliseroundintern(state, &vdd, fpscr, exceptions, "fcvtd");
532 return vfp_double_pack(&vdd);
492} 533}
493 534
494static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr) 535static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr)
495{ 536{
496 struct vfp_single vsm; 537 struct vfp_single vsm;
497 struct vfp_double vdd; 538 struct vfp_double vdd;
498 int tm; 539 int tm;
499 u32 exceptions = 0; 540 u32 exceptions = 0;
500 541
501 vfp_single_unpack(&vsm, m); 542 vfp_single_unpack(&vsm, m);
502 543
503 tm = vfp_single_type(&vsm); 544 tm = vfp_single_type(&vsm);
504 545
505 /* 546 /*
506 * If we have a signalling NaN, signal invalid operation. 547 * If we have a signalling NaN, signal invalid operation.
507 */ 548 */
508 if (tm == VFP_SNAN) 549 if (tm == VFP_SNAN)
509 exceptions = FPSCR_IOC; 550 exceptions = FPSCR_IOC;
510 551
511 if (tm & VFP_DENORMAL) 552 if (tm & VFP_DENORMAL)
512 vfp_single_normalise_denormal(&vsm); 553 vfp_single_normalise_denormal(&vsm);
513 554
514 vdd.sign = vsm.sign; 555 vdd.sign = vsm.sign;
515 vdd.significand = (u64)vsm.significand << 32; 556 vdd.significand = (u64)vsm.significand << 32;
516 557
517 /* 558 /*
518 * If we have an infinity or NaN, the exponent must be 2047. 559 * If we have an infinity or NaN, the exponent must be 2047.
519 */ 560 */
520 if (tm & (VFP_INFINITY|VFP_NAN)) { 561 if (tm & (VFP_INFINITY|VFP_NAN)) {
521 vdd.exponent = 2047; 562 vdd.exponent = 2047;
522 if (tm == VFP_QNAN) 563 if (tm == VFP_QNAN)
523 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; 564 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
524 goto pack_nan; 565 goto pack_nan;
525 } else if (tm & VFP_ZERO) 566 } else if (tm & VFP_ZERO)
526 vdd.exponent = 0; 567 vdd.exponent = 0;
527 else 568 else
528 vdd.exponent = vsm.exponent + (1023 - 127); 569 vdd.exponent = vsm.exponent + (1023 - 127);
529 570
530 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fcvtd"); 571 return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fcvtd");
531 572
532 pack_nan: 573pack_nan:
533 vfp_put_double(state, vfp_double_pack(&vdd), dd); 574 vfp_put_double(state, vfp_double_pack(&vdd), dd);
534 return exceptions; 575 return exceptions;
535} 576}
536 577
537static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 578static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
538{ 579{
539 struct vfp_single vs; 580 struct vfp_single vs;
540 581
541 vs.sign = 0; 582 vs.sign = 0;
542 vs.exponent = 127 + 31 - 1; 583 vs.exponent = 127 + 31 - 1;
543 vs.significand = (u32)m; 584 vs.significand = (u32)m;
544 585
545 return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fuito"); 586 return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fuito");
546} 587}
547 588
548static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 589static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
549{ 590{
550 struct vfp_single vs; 591 struct vfp_single vs;
551 592
552 vs.sign = (m & 0x80000000) >> 16; 593 vs.sign = (m & 0x80000000) >> 16;
553 vs.exponent = 127 + 31 - 1; 594 vs.exponent = 127 + 31 - 1;
554 vs.significand = vs.sign ? -m : m; 595 vs.significand = vs.sign ? -m : m;
555 596
556 return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fsito"); 597 return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fsito");
557} 598}
558 599
559static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 600static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
560{ 601{
561 struct vfp_single vsm; 602 struct vfp_single vsm;
562 u32 d, exceptions = 0; 603 u32 d, exceptions = 0;
563 int rmode = fpscr & FPSCR_RMODE_MASK; 604 int rmode = fpscr & FPSCR_RMODE_MASK;
564 int tm; 605 int tm;
565 606
566 vfp_single_unpack(&vsm, m); 607 vfp_single_unpack(&vsm, m);
567 vfp_single_dump("VSM", &vsm); 608 vfp_single_dump("VSM", &vsm);
568 609
569 /* 610 /*
570 * Do we have a denormalised number? 611 * Do we have a denormalised number?
571 */ 612 */
572 tm = vfp_single_type(&vsm); 613 tm = vfp_single_type(&vsm);
573 if (tm & VFP_DENORMAL) 614 if (tm & VFP_DENORMAL)
574 exceptions |= FPSCR_IDC; 615 exceptions |= FPSCR_IDC;
575 616
576 if (tm & VFP_NAN) 617 if (tm & VFP_NAN)
577 vsm.sign = 0; 618 vsm.sign = 0;
578 619
579 if (vsm.exponent >= 127 + 32) { 620 if (vsm.exponent >= 127 + 32) {
580 d = vsm.sign ? 0 : 0xffffffff; 621 d = vsm.sign ? 0 : 0xffffffff;
581 exceptions = FPSCR_IOC; 622 exceptions = FPSCR_IOC;
582 } else if (vsm.exponent >= 127 - 1) { 623 } else if (vsm.exponent >= 127 - 1) {
583 int shift = 127 + 31 - vsm.exponent; 624 int shift = 127 + 31 - vsm.exponent;
584 u32 rem, incr = 0; 625 u32 rem, incr = 0;
585 626
586 /* 627 /*
587 * 2^0 <= m < 2^32-2^8 628 * 2^0 <= m < 2^32-2^8
588 */ 629 */
589 d = (vsm.significand << 1) >> shift; 630 d = (vsm.significand << 1) >> shift;
590 rem = vsm.significand << (33 - shift); 631 rem = vsm.significand << (33 - shift);
591 632
592 if (rmode == FPSCR_ROUND_NEAREST) { 633 if (rmode == FPSCR_ROUND_NEAREST) {
593 incr = 0x80000000; 634 incr = 0x80000000;
594 if ((d & 1) == 0) 635 if ((d & 1) == 0)
595 incr -= 1; 636 incr -= 1;
596 } else if (rmode == FPSCR_ROUND_TOZERO) { 637 } else if (rmode == FPSCR_ROUND_TOZERO) {
597 incr = 0; 638 incr = 0;
598 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) { 639 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
599 incr = ~0; 640 incr = ~0;
600 } 641 }
601 642
602 if ((rem + incr) < rem) { 643 if ((rem + incr) < rem) {
603 if (d < 0xffffffff) 644 if (d < 0xffffffff)
604 d += 1; 645 d += 1;
605 else 646 else
606 exceptions |= FPSCR_IOC; 647 exceptions |= FPSCR_IOC;
607 } 648 }
608 649
609 if (d && vsm.sign) { 650 if (d && vsm.sign) {
610 d = 0; 651 d = 0;
611 exceptions |= FPSCR_IOC; 652 exceptions |= FPSCR_IOC;
612 } else if (rem) 653 } else if (rem)
613 exceptions |= FPSCR_IXC; 654 exceptions |= FPSCR_IXC;
614 } else { 655 } else {
615 d = 0; 656 d = 0;
616 if (vsm.exponent | vsm.significand) { 657 if (vsm.exponent | vsm.significand) {
617 exceptions |= FPSCR_IXC; 658 exceptions |= FPSCR_IXC;
618 if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) 659 if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
619 d = 1; 660 d = 1;
620 else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { 661 else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) {
621 d = 0; 662 d = 0;
622 exceptions |= FPSCR_IOC; 663 exceptions |= FPSCR_IOC;
623 } 664 }
624 } 665 }
625 } 666 }
626 667
627 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); 668 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
628 669
629 vfp_put_float(state, d, sd); 670 vfp_put_float(state, d, sd);
630 671
631 return exceptions; 672 return exceptions;
632} 673}
633 674
634static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 675static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
635{ 676{
636 return vfp_single_ftoui(state, sd, unused, m, FPSCR_ROUND_TOZERO); 677 return vfp_single_ftoui(state, sd, unused, m, FPSCR_ROUND_TOZERO);
637} 678}
638 679
639static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 680static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
640{ 681{
641 struct vfp_single vsm; 682 struct vfp_single vsm;
642 u32 d, exceptions = 0; 683 u32 d, exceptions = 0;
643 int rmode = fpscr & FPSCR_RMODE_MASK; 684 int rmode = fpscr & FPSCR_RMODE_MASK;
644 int tm; 685 int tm;
645 686
646 vfp_single_unpack(&vsm, m); 687 vfp_single_unpack(&vsm, m);
647 vfp_single_dump("VSM", &vsm); 688 vfp_single_dump("VSM", &vsm);
648 689
649 /* 690 /*
650 * Do we have a denormalised number? 691 * Do we have a denormalised number?
651 */ 692 */
652 tm = vfp_single_type(&vsm); 693 tm = vfp_single_type(&vsm);
653 if (vfp_single_type(&vsm) & VFP_DENORMAL) 694 if (vfp_single_type(&vsm) & VFP_DENORMAL)
654 exceptions |= FPSCR_IDC; 695 exceptions |= FPSCR_IDC;
655 696
656 if (tm & VFP_NAN) { 697 if (tm & VFP_NAN) {
657 d = 0; 698 d = 0;
658 exceptions |= FPSCR_IOC; 699 exceptions |= FPSCR_IOC;
659 } else if (vsm.exponent >= 127 + 32) { 700 } else if (vsm.exponent >= 127 + 32) {
660 /* 701 /*
661 * m >= 2^31-2^7: invalid 702 * m >= 2^31-2^7: invalid
662 */ 703 */
663 d = 0x7fffffff; 704 d = 0x7fffffff;
664 if (vsm.sign) 705 if (vsm.sign)
665 d = ~d; 706 d = ~d;
666 exceptions |= FPSCR_IOC; 707 exceptions |= FPSCR_IOC;
667 } else if (vsm.exponent >= 127 - 1) { 708 } else if (vsm.exponent >= 127 - 1) {
668 int shift = 127 + 31 - vsm.exponent; 709 int shift = 127 + 31 - vsm.exponent;
669 u32 rem, incr = 0; 710 u32 rem, incr = 0;
670 711
671 /* 2^0 <= m <= 2^31-2^7 */ 712 /* 2^0 <= m <= 2^31-2^7 */
672 d = (vsm.significand << 1) >> shift; 713 d = (vsm.significand << 1) >> shift;
673 rem = vsm.significand << (33 - shift); 714 rem = vsm.significand << (33 - shift);
674 715
675 if (rmode == FPSCR_ROUND_NEAREST) { 716 if (rmode == FPSCR_ROUND_NEAREST) {
676 incr = 0x80000000; 717 incr = 0x80000000;
677 if ((d & 1) == 0) 718 if ((d & 1) == 0)
678 incr -= 1; 719 incr -= 1;
679 } else if (rmode == FPSCR_ROUND_TOZERO) { 720 } else if (rmode == FPSCR_ROUND_TOZERO) {
680 incr = 0; 721 incr = 0;
681 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) { 722 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
682 incr = ~0; 723 incr = ~0;
683 } 724 }
684 725
685 if ((rem + incr) < rem && d < 0xffffffff) 726 if ((rem + incr) < rem && d < 0xffffffff)
686 d += 1; 727 d += 1;
687 if (d > 0x7fffffff + (vsm.sign != 0)) { 728 if (d > (0x7fffffffu + (vsm.sign != 0))) {
688 d = 0x7fffffff + (vsm.sign != 0); 729 d = (0x7fffffffu + (vsm.sign != 0));
689 exceptions |= FPSCR_IOC; 730 exceptions |= FPSCR_IOC;
690 } else if (rem) 731 } else if (rem)
691 exceptions |= FPSCR_IXC; 732 exceptions |= FPSCR_IXC;
692 733
693 if (vsm.sign) 734 if (vsm.sign)
694 d = -d; 735 d = 0-d;
695 } else { 736 } else {
696 d = 0; 737 d = 0;
697 if (vsm.exponent | vsm.significand) { 738 if (vsm.exponent | vsm.significand) {
698 exceptions |= FPSCR_IXC; 739 exceptions |= FPSCR_IXC;
699 if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) 740 if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
700 d = 1; 741 d = 1;
701 else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) 742 else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign)
702 d = -1; 743 d = -1;
703 } 744 }
704 } 745 }
705 746
706 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); 747 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
707 748
708 vfp_put_float(state, (s32)d, sd); 749 vfp_put_float(state, (s32)d, sd);
709 750
710 return exceptions; 751 return exceptions;
711} 752}
712 753
713static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 754static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr)
714{ 755{
715 return vfp_single_ftosi(state, sd, unused, m, FPSCR_ROUND_TOZERO); 756 return vfp_single_ftosi(state, sd, unused, m, FPSCR_ROUND_TOZERO);
716} 757}
717 758
718static struct op fops_ext[] = { 759static struct op fops_ext[] = {
@@ -752,200 +793,237 @@ static struct op fops_ext[] = {
752 793
753static u32 794static u32
754vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn, 795vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn,
755 struct vfp_single *vsm, u32 fpscr) 796 struct vfp_single *vsm, u32 fpscr)
756{ 797{
757 struct vfp_single *vsp; 798 struct vfp_single *vsp;
758 u32 exceptions = 0; 799 u32 exceptions = 0;
759 int tn, tm; 800 int tn, tm;
760 801
761 tn = vfp_single_type(vsn); 802 tn = vfp_single_type(vsn);
762 tm = vfp_single_type(vsm); 803 tm = vfp_single_type(vsm);
763 804
764 if (tn & tm & VFP_INFINITY) { 805 if (tn & tm & VFP_INFINITY) {
765 /* 806 /*
766 * Two infinities. Are they different signs? 807 * Two infinities. Are they different signs?
767 */ 808 */
768 if (vsn->sign ^ vsm->sign) { 809 if (vsn->sign ^ vsm->sign) {
769 /* 810 /*
770 * different signs -> invalid 811 * different signs -> invalid
771 */ 812 */
772 exceptions = FPSCR_IOC; 813 exceptions = FPSCR_IOC;
773 vsp = &vfp_single_default_qnan; 814 vsp = &vfp_single_default_qnan;
774 } else { 815 } else {
775 /* 816 /*
776 * same signs -> valid 817 * same signs -> valid
777 */ 818 */
778 vsp = vsn; 819 vsp = vsn;
779 } 820 }
780 } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) { 821 } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
781 /* 822 /*
782 * One infinity and one number -> infinity 823 * One infinity and one number -> infinity
783 */ 824 */
784 vsp = vsn; 825 vsp = vsn;
785 } else { 826 } else {
786 /* 827 /*
787 * 'n' is a NaN of some type 828 * 'n' is a NaN of some type
788 */ 829 */
789 return vfp_propagate_nan(vsd, vsn, vsm, fpscr); 830 return vfp_propagate_nan(vsd, vsn, vsm, fpscr);
790 } 831 }
791 *vsd = *vsp; 832 *vsd = *vsp;
792 return exceptions; 833 return exceptions;
793} 834}
794 835
795static u32 836static u32
796vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn, 837vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
797 struct vfp_single *vsm, u32 fpscr) 838 struct vfp_single *vsm, u32 fpscr)
798{ 839{
799 u32 exp_diff, m_sig; 840 u32 exp_diff, m_sig;
800 841
801 if (vsn->significand & 0x80000000 || 842 if (vsn->significand & 0x80000000 ||
802 vsm->significand & 0x80000000) { 843 vsm->significand & 0x80000000) {
803 pr_info("VFP: bad FP values\n"); 844 pr_info("VFP: bad FP values in %s\n", __func__);
804 vfp_single_dump("VSN", vsn); 845 vfp_single_dump("VSN", vsn);
805 vfp_single_dump("VSM", vsm); 846 vfp_single_dump("VSM", vsm);
806 } 847 }
807 848
808 /* 849 /*
809 * Ensure that 'n' is the largest magnitude number. Note that 850 * Ensure that 'n' is the largest magnitude number. Note that
810 * if 'n' and 'm' have equal exponents, we do not swap them. 851 * if 'n' and 'm' have equal exponents, we do not swap them.
811 * This ensures that NaN propagation works correctly. 852 * This ensures that NaN propagation works correctly.
812 */ 853 */
813 if (vsn->exponent < vsm->exponent) { 854 if (vsn->exponent < vsm->exponent) {
814 struct vfp_single *t = vsn; 855 struct vfp_single *t = vsn;
815 vsn = vsm; 856 vsn = vsm;
816 vsm = t; 857 vsm = t;
817 } 858 }
818 859
819 /* 860 /*
820 * Is 'n' an infinity or a NaN? Note that 'm' may be a number, 861 * Is 'n' an infinity or a NaN? Note that 'm' may be a number,
821 * infinity or a NaN here. 862 * infinity or a NaN here.
822 */ 863 */
823 if (vsn->exponent == 255) 864 if (vsn->exponent == 255)
824 return vfp_single_fadd_nonnumber(vsd, vsn, vsm, fpscr); 865 return vfp_single_fadd_nonnumber(vsd, vsn, vsm, fpscr);
825 866
826 /* 867 /*
827 * We have two proper numbers, where 'vsn' is the larger magnitude. 868 * We have two proper numbers, where 'vsn' is the larger magnitude.
828 * 869 *
829 * Copy 'n' to 'd' before doing the arithmetic. 870 * Copy 'n' to 'd' before doing the arithmetic.
830 */ 871 */
831 *vsd = *vsn; 872 *vsd = *vsn;
832 873
833 /* 874 /*
834 * Align both numbers. 875 * Align both numbers.
835 */ 876 */
836 exp_diff = vsn->exponent - vsm->exponent; 877 exp_diff = vsn->exponent - vsm->exponent;
837 m_sig = vfp_shiftright32jamming(vsm->significand, exp_diff); 878 m_sig = vfp_shiftright32jamming(vsm->significand, exp_diff);
838 879
839 /* 880 /*
840 * If the signs are different, we are really subtracting. 881 * If the signs are different, we are really subtracting.
841 */ 882 */
842 if (vsn->sign ^ vsm->sign) { 883 if (vsn->sign ^ vsm->sign) {
843 m_sig = vsn->significand - m_sig; 884 m_sig = vsn->significand - m_sig;
844 if ((s32)m_sig < 0) { 885 if ((s32)m_sig < 0) {
845 vsd->sign = vfp_sign_negate(vsd->sign); 886 vsd->sign = vfp_sign_negate(vsd->sign);
846 m_sig = -m_sig; 887 m_sig = 0-m_sig;
847 } else if (m_sig == 0) { 888 } else if (m_sig == 0) {
848 vsd->sign = (fpscr & FPSCR_RMODE_MASK) == 889 vsd->sign = (fpscr & FPSCR_RMODE_MASK) ==
849 FPSCR_ROUND_MINUSINF ? 0x8000 : 0; 890 FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
850 } 891 }
851 } else { 892 } else {
852 m_sig = vsn->significand + m_sig; 893 m_sig = vsn->significand + m_sig;
853 } 894 }
854 vsd->significand = m_sig; 895 vsd->significand = m_sig;
855 896
856 return 0; 897 return 0;
857} 898}
858 899
859static u32 900static u32
860vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr) 901vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr)
861{ 902{
862 vfp_single_dump("VSN", vsn); 903 vfp_single_dump("VSN", vsn);
863 vfp_single_dump("VSM", vsm); 904 vfp_single_dump("VSM", vsm);
864 905
865 /* 906 /*
866 * Ensure that 'n' is the largest magnitude number. Note that 907 * Ensure that 'n' is the largest magnitude number. Note that
867 * if 'n' and 'm' have equal exponents, we do not swap them. 908 * if 'n' and 'm' have equal exponents, we do not swap them.
868 * This ensures that NaN propagation works correctly. 909 * This ensures that NaN propagation works correctly.
869 */ 910 */
870 if (vsn->exponent < vsm->exponent) { 911 if (vsn->exponent < vsm->exponent) {
871 struct vfp_single *t = vsn; 912 struct vfp_single *t = vsn;
872 vsn = vsm; 913 vsn = vsm;
873 vsm = t; 914 vsm = t;
874 pr_debug("VFP: swapping M <-> N\n"); 915 pr_debug("VFP: swapping M <-> N\n");
875 } 916 }
876 917
877 vsd->sign = vsn->sign ^ vsm->sign; 918 vsd->sign = vsn->sign ^ vsm->sign;
878 919
879 /* 920 /*
880 * If 'n' is an infinity or NaN, handle it. 'm' may be anything. 921 * If 'n' is an infinity or NaN, handle it. 'm' may be anything.
881 */ 922 */
882 if (vsn->exponent == 255) { 923 if (vsn->exponent == 255) {
883 if (vsn->significand || (vsm->exponent == 255 && vsm->significand)) 924 if (vsn->significand || (vsm->exponent == 255 && vsm->significand))
884 return vfp_propagate_nan(vsd, vsn, vsm, fpscr); 925 return vfp_propagate_nan(vsd, vsn, vsm, fpscr);
885 if ((vsm->exponent | vsm->significand) == 0) { 926 if ((vsm->exponent | vsm->significand) == 0) {
886 *vsd = vfp_single_default_qnan; 927 *vsd = vfp_single_default_qnan;
887 return FPSCR_IOC; 928 return FPSCR_IOC;
888 } 929 }
889 vsd->exponent = vsn->exponent; 930 vsd->exponent = vsn->exponent;
890 vsd->significand = 0; 931 vsd->significand = 0;
891 return 0; 932 return 0;
892 } 933 }
893 934
894 /* 935 /*
895 * If 'm' is zero, the result is always zero. In this case, 936 * If 'm' is zero, the result is always zero. In this case,
896 * 'n' may be zero or a number, but it doesn't matter which. 937 * 'n' may be zero or a number, but it doesn't matter which.
897 */ 938 */
898 if ((vsm->exponent | vsm->significand) == 0) { 939 if ((vsm->exponent | vsm->significand) == 0) {
899 vsd->exponent = 0; 940 vsd->exponent = 0;
900 vsd->significand = 0; 941 vsd->significand = 0;
901 return 0; 942 return 0;
902 } 943 }
903 944
904 /* 945 /*
905 * We add 2 to the destination exponent for the same reason as 946 * We add 2 to the destination exponent for the same reason as
906 * the addition case - though this time we have +1 from each 947 * the addition case - though this time we have +1 from each
907 * input operand. 948 * input operand.
908 */ 949 */
909 vsd->exponent = vsn->exponent + vsm->exponent - 127 + 2; 950 vsd->exponent = vsn->exponent + vsm->exponent - 127 + 2;
910 vsd->significand = vfp_hi64to32jamming((u64)vsn->significand * vsm->significand); 951 vsd->significand = vfp_hi64to32jamming((u64)vsn->significand * vsm->significand);
911 952
912 vfp_single_dump("VSD", vsd); 953 vfp_single_dump("VSD", vsd);
913 return 0; 954 return 0;
914} 955}
915 956
916#define NEG_MULTIPLY (1 << 0) 957#define NEG_MULTIPLY (1 << 0)
917#define NEG_SUBTRACT (1 << 1) 958#define NEG_SUBTRACT (1 << 1)
918 959
919static u32 960static u32
920vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, const char *func) 961vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, char *func)
921{ 962{
922 struct vfp_single vsd, vsp, vsn, vsm; 963
923 u32 exceptions; 964 {
924 s32 v; 965 struct vfp_single vsd, vsp, vsn, vsm;
966 u32 exceptions;
967 s32 v;
968
969
970
971 v = vfp_get_float(state, sn);
972 pr_debug("VFP: s%u = %08x\n", sn, v);
973 vfp_single_unpack(&vsn, v);
974 if (vsn.exponent == 0 && vsn.significand)
975 vfp_single_normalise_denormal(&vsn);
976
977 vfp_single_unpack(&vsm, m);
978 if (vsm.exponent == 0 && vsm.significand)
979 vfp_single_normalise_denormal(&vsm);
980
981 exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr);
982
983 if (negate & NEG_MULTIPLY)
984 vsp.sign = vfp_sign_negate(vsp.sign);
985
986 v = vfp_get_float(state, sd);
987 pr_debug("VFP: s%u = %08x\n", sd, v);
988 vfp_single_unpack(&vsn, v);
989 if (negate & NEG_SUBTRACT)
990 vsn.sign = vfp_sign_negate(vsn.sign);
991
992 exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr);
993
994 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, func);
995 }
996
997 struct vfp_double vsd, vsp, vsn, vsm;
998 u32 exceptions;
999 s32 v;
1000 s64 vd;
1001 s64 md;
1002
1003 v = vfp_get_float(state, sn);
1004 vd = vfp_single_to_doubleintern(state, v, fpscr);
1005 vfp_double_unpack(&vsn, vd);
1006
1007 md = vfp_single_to_doubleintern(state, m, fpscr);
1008 vfp_double_unpack(&vsm, md);
1009
1010 exceptions = vfp_double_multiply(&vsp, &vsn, &vsm, fpscr);
1011 if (negate & NEG_MULTIPLY)
1012 vsp.sign = vfp_sign_negate(vsp.sign);
925 1013
926 v = vfp_get_float(state, sn); 1014 v = vfp_get_float(state, sd);
927 pr_debug("VFP: s%u = %08x\n", sn, v); 1015 vd = vfp_single_to_doubleintern(state, v, fpscr);
928 vfp_single_unpack(&vsn, v); 1016 vfp_double_unpack(&vsn, vd);
929 if (vsn.exponent == 0 && vsn.significand)
930 vfp_single_normalise_denormal(&vsn);
931 1017
932 vfp_single_unpack(&vsm, m); 1018 if (negate & NEG_SUBTRACT)
933 if (vsm.exponent == 0 && vsm.significand) 1019 vsn.sign = vfp_sign_negate(vsn.sign);
934 vfp_single_normalise_denormal(&vsm);
935 1020
936 exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr); 1021 exceptions |= vfp_double_add(&vsd, &vsn, &vsp, fpscr);
937 if (negate & NEG_MULTIPLY)
938 vsp.sign = vfp_sign_negate(vsp.sign);
939 1022
940 v = vfp_get_float(state, sd); 1023 s64 debug = vfp_double_pack(&vsd);
941 pr_debug("VFP: s%u = %08x\n", sd, v);
942 vfp_single_unpack(&vsn, v);
943 if (negate & NEG_SUBTRACT)
944 vsn.sign = vfp_sign_negate(vsn.sign);
945 1024
946 exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr); 1025 return vfp_double_fcvtsinterncutting(state, sd, &vsd, fpscr);
947 1026
948 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, func);
949} 1027}
950 1028
951/* 1029/*
@@ -957,8 +1035,8 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
957 */ 1035 */
958static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1036static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
959{ 1037{
960 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd); 1038 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
961 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac"); 1039 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac");
962} 1040}
963 1041
964/* 1042/*
@@ -966,8 +1044,8 @@ static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
966 */ 1044 */
967static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1045static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
968{ 1046{
969 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sd, sn); 1047 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sd, sn);
970 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac"); 1048 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac");
971} 1049}
972 1050
973/* 1051/*
@@ -975,8 +1053,8 @@ static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
975 */ 1053 */
976static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1054static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
977{ 1055{
978 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd); 1056 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
979 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc"); 1057 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc");
980} 1058}
981 1059
982/* 1060/*
@@ -984,8 +1062,8 @@ static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
984 */ 1062 */
985static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1063static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
986{ 1064{
987 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd); 1065 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
988 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); 1066 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
989} 1067}
990 1068
991/* 1069/*
@@ -993,22 +1071,22 @@ static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
993 */ 1071 */
994static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1072static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
995{ 1073{
996 struct vfp_single vsd, vsn, vsm; 1074 struct vfp_single vsd, vsn, vsm;
997 u32 exceptions; 1075 u32 exceptions;
998 s32 n = vfp_get_float(state, sn); 1076 s32 n = vfp_get_float(state, sn);
999 1077
1000 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, n); 1078 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, n);
1001 1079
1002 vfp_single_unpack(&vsn, n); 1080 vfp_single_unpack(&vsn, n);
1003 if (vsn.exponent == 0 && vsn.significand) 1081 if (vsn.exponent == 0 && vsn.significand)
1004 vfp_single_normalise_denormal(&vsn); 1082 vfp_single_normalise_denormal(&vsn);
1005 1083
1006 vfp_single_unpack(&vsm, m); 1084 vfp_single_unpack(&vsm, m);
1007 if (vsm.exponent == 0 && vsm.significand) 1085 if (vsm.exponent == 0 && vsm.significand)
1008 vfp_single_normalise_denormal(&vsm); 1086 vfp_single_normalise_denormal(&vsm);
1009 1087
1010 exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); 1088 exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr);
1011 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fmul"); 1089 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fmul");
1012} 1090}
1013 1091
1014/* 1092/*
@@ -1016,23 +1094,23 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1016 */ 1094 */
1017static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1095static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1018{ 1096{
1019 struct vfp_single vsd, vsn, vsm; 1097 struct vfp_single vsd, vsn, vsm;
1020 u32 exceptions; 1098 u32 exceptions;
1021 s32 n = vfp_get_float(state, sn); 1099 s32 n = vfp_get_float(state, sn);
1022 1100
1023 pr_debug("VFP: s%u = %08x\n", sn, n); 1101 pr_debug("VFP: s%u = %08x\n", sn, n);
1024 1102
1025 vfp_single_unpack(&vsn, n); 1103 vfp_single_unpack(&vsn, n);
1026 if (vsn.exponent == 0 && vsn.significand) 1104 if (vsn.exponent == 0 && vsn.significand)
1027 vfp_single_normalise_denormal(&vsn); 1105 vfp_single_normalise_denormal(&vsn);
1028 1106
1029 vfp_single_unpack(&vsm, m); 1107 vfp_single_unpack(&vsm, m);
1030 if (vsm.exponent == 0 && vsm.significand) 1108 if (vsm.exponent == 0 && vsm.significand)
1031 vfp_single_normalise_denormal(&vsm); 1109 vfp_single_normalise_denormal(&vsm);
1032 1110
1033 exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); 1111 exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr);
1034 vsd.sign = vfp_sign_negate(vsd.sign); 1112 vsd.sign = vfp_sign_negate(vsd.sign);
1035 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fnmul"); 1113 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fnmul");
1036} 1114}
1037 1115
1038/* 1116/*
@@ -1040,26 +1118,26 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
1040 */ 1118 */
1041static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1119static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1042{ 1120{
1043 struct vfp_single vsd, vsn, vsm; 1121 struct vfp_single vsd, vsn, vsm;
1044 u32 exceptions; 1122 u32 exceptions;
1045 s32 n = vfp_get_float(state, sn); 1123 s32 n = vfp_get_float(state, sn);
1046 1124
1047 pr_debug("VFP: s%u = %08x\n", sn, n); 1125 pr_debug("VFP: s%u = %08x\n", sn, n);
1048 1126
1049 /* 1127 /*
1050 * Unpack and normalise denormals. 1128 * Unpack and normalise denormals.
1051 */ 1129 */
1052 vfp_single_unpack(&vsn, n); 1130 vfp_single_unpack(&vsn, n);
1053 if (vsn.exponent == 0 && vsn.significand) 1131 if (vsn.exponent == 0 && vsn.significand)
1054 vfp_single_normalise_denormal(&vsn); 1132 vfp_single_normalise_denormal(&vsn);
1055 1133
1056 vfp_single_unpack(&vsm, m); 1134 vfp_single_unpack(&vsm, m);
1057 if (vsm.exponent == 0 && vsm.significand) 1135 if (vsm.exponent == 0 && vsm.significand)
1058 vfp_single_normalise_denormal(&vsm); 1136 vfp_single_normalise_denormal(&vsm);
1059 1137
1060 exceptions = vfp_single_add(&vsd, &vsn, &vsm, fpscr); 1138 exceptions = vfp_single_add(&vsd, &vsn, &vsm, fpscr);
1061 1139
1062 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fadd"); 1140 return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fadd");
1063} 1141}
1064 1142
1065/* 1143/*
@@ -1067,11 +1145,11 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1067 */ 1145 */
1068static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1146static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1069{ 1147{
1070 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd); 1148 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
1071 /* 1149 /*
1072 * Subtraction is addition with one sign inverted. 1150 * Subtraction is addition with one sign inverted.
1073 */ 1151 */
1074 return vfp_single_fadd(state, sd, sn, vfp_single_packed_negate(m), fpscr); 1152 return vfp_single_fadd(state, sd, sn, vfp_single_packed_negate(m), fpscr);
1075} 1153}
1076 1154
1077/* 1155/*
@@ -1079,107 +1157,107 @@ static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1079 */ 1157 */
1080static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1158static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1081{ 1159{
1082 struct vfp_single vsd, vsn, vsm; 1160 struct vfp_single vsd, vsn, vsm;
1083 u32 exceptions = 0; 1161 u32 exceptions = 0;
1084 s32 n = vfp_get_float(state, sn); 1162 s32 n = vfp_get_float(state, sn);
1085 int tm, tn; 1163 int tm, tn;
1086 1164
1087 pr_debug("VFP: s%u = %08x\n", sn, n); 1165 pr_debug("VFP: s%u = %08x\n", sn, n);
1088 1166
1089 vfp_single_unpack(&vsn, n); 1167 vfp_single_unpack(&vsn, n);
1090 vfp_single_unpack(&vsm, m); 1168 vfp_single_unpack(&vsm, m);
1091 1169
1092 vsd.sign = vsn.sign ^ vsm.sign; 1170 vsd.sign = vsn.sign ^ vsm.sign;
1093 1171
1094 tn = vfp_single_type(&vsn); 1172 tn = vfp_single_type(&vsn);
1095 tm = vfp_single_type(&vsm); 1173 tm = vfp_single_type(&vsm);
1096 1174
1097 /* 1175 /*
1098 * Is n a NAN? 1176 * Is n a NAN?
1099 */ 1177 */
1100 if (tn & VFP_NAN) 1178 if (tn & VFP_NAN)
1101 goto vsn_nan; 1179 goto vsn_nan;
1102 1180
1103 /* 1181 /*
1104 * Is m a NAN? 1182 * Is m a NAN?
1105 */ 1183 */
1106 if (tm & VFP_NAN) 1184 if (tm & VFP_NAN)
1107 goto vsm_nan; 1185 goto vsm_nan;
1108 1186
1109 /* 1187 /*
1110 * If n and m are infinity, the result is invalid 1188 * If n and m are infinity, the result is invalid
1111 * If n and m are zero, the result is invalid 1189 * If n and m are zero, the result is invalid
1112 */ 1190 */
1113 if (tm & tn & (VFP_INFINITY|VFP_ZERO)) 1191 if (tm & tn & (VFP_INFINITY|VFP_ZERO))
1114 goto invalid; 1192 goto invalid;
1115 1193
1116 /* 1194 /*
1117 * If n is infinity, the result is infinity 1195 * If n is infinity, the result is infinity
1118 */ 1196 */
1119 if (tn & VFP_INFINITY) 1197 if (tn & VFP_INFINITY)
1120 goto infinity; 1198 goto infinity;
1121 1199
1122 /* 1200 /*
1123 * If m is zero, raise div0 exception 1201 * If m is zero, raise div0 exception
1124 */ 1202 */
1125 if (tm & VFP_ZERO) 1203 if (tm & VFP_ZERO)
1126 goto divzero; 1204 goto divzero;
1127 1205
1128 /* 1206 /*
1129 * If m is infinity, or n is zero, the result is zero 1207 * If m is infinity, or n is zero, the result is zero
1130 */ 1208 */
1131 if (tm & VFP_INFINITY || tn & VFP_ZERO) 1209 if (tm & VFP_INFINITY || tn & VFP_ZERO)
1132 goto zero; 1210 goto zero;
1133 1211
1134 if (tn & VFP_DENORMAL) 1212 if (tn & VFP_DENORMAL)
1135 vfp_single_normalise_denormal(&vsn); 1213 vfp_single_normalise_denormal(&vsn);
1136 if (tm & VFP_DENORMAL) 1214 if (tm & VFP_DENORMAL)
1137 vfp_single_normalise_denormal(&vsm); 1215 vfp_single_normalise_denormal(&vsm);
1138 1216
1139 /* 1217 /*
1140 * Ok, we have two numbers, we can perform division. 1218 * Ok, we have two numbers, we can perform division.
1141 */ 1219 */
1142 vsd.exponent = vsn.exponent - vsm.exponent + 127 - 1; 1220 vsd.exponent = vsn.exponent - vsm.exponent + 127 - 1;
1143 vsm.significand <<= 1; 1221 vsm.significand <<= 1;
1144 if (vsm.significand <= (2 * vsn.significand)) { 1222 if (vsm.significand <= (2 * vsn.significand)) {
1145 vsn.significand >>= 1; 1223 vsn.significand >>= 1;
1146 vsd.exponent++; 1224 vsd.exponent++;
1147 } 1225 }
1148 { 1226 {
1149 u64 significand = (u64)vsn.significand << 32; 1227 u64 significand = (u64)vsn.significand << 32;
1150 do_div(significand, vsm.significand); 1228 do_div(significand, vsm.significand);
1151 vsd.significand = significand; 1229 vsd.significand = (u32)significand;
1152 } 1230 }
1153 if ((vsd.significand & 0x3f) == 0) 1231 if ((vsd.significand & 0x3f) == 0)
1154 vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32); 1232 vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32);
1155 1233
1156 return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fdiv"); 1234 return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fdiv");
1157 1235
1158 vsn_nan: 1236vsn_nan:
1159 exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); 1237 exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr);
1160 pack: 1238pack:
1161 vfp_put_float(state, vfp_single_pack(&vsd), sd); 1239 vfp_put_float(state, vfp_single_pack(&vsd), sd);
1162 return exceptions; 1240 return exceptions;
1163 1241
1164 vsm_nan: 1242vsm_nan:
1165 exceptions = vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr); 1243 exceptions = vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr);
1166 goto pack; 1244 goto pack;
1167 1245
1168 zero: 1246zero:
1169 vsd.exponent = 0; 1247 vsd.exponent = 0;
1170 vsd.significand = 0; 1248 vsd.significand = 0;
1171 goto pack; 1249 goto pack;
1172 1250
1173 divzero: 1251divzero:
1174 exceptions = FPSCR_DZC; 1252 exceptions = FPSCR_DZC;
1175 infinity: 1253infinity:
1176 vsd.exponent = 255; 1254 vsd.exponent = 255;
1177 vsd.significand = 0; 1255 vsd.significand = 0;
1178 goto pack; 1256 goto pack;
1179 1257
1180 invalid: 1258invalid:
1181 vfp_put_float(state, vfp_single_pack(&vfp_single_default_qnan), sd); 1259 vfp_put_float(state, vfp_single_pack(&vfp_single_default_qnan), sd);
1182 return FPSCR_IOC; 1260 return FPSCR_IOC;
1183} 1261}
1184 1262
1185static struct op fops[] = { 1263static struct op fops[] = {
@@ -1199,80 +1277,80 @@ static struct op fops[] = {
1199 1277
1200u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) 1278u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1201{ 1279{
1202 u32 op = inst & FOP_MASK; 1280 u32 op = inst & FOP_MASK;
1203 u32 exceptions = 0; 1281 u32 exceptions = 0;
1204 unsigned int dest; 1282 unsigned int dest;
1205 unsigned int sn = vfp_get_sn(inst); 1283 unsigned int sn = vfp_get_sn(inst);
1206 unsigned int sm = vfp_get_sm(inst); 1284 unsigned int sm = vfp_get_sm(inst);
1207 unsigned int vecitr, veclen, vecstride; 1285 unsigned int vecitr, veclen, vecstride;
1208 struct op *fop; 1286 struct op *fop;
1209 pr_debug("In %s\n", __FUNCTION__); 1287 pr_debug("In %s\n", __FUNCTION__);
1210 1288
1211 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); 1289 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
1212 1290
1213 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)]; 1291 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
1214 1292
1215 /* 1293 /*
1216 * fcvtsd takes a dN register number as destination, not sN. 1294 * fcvtsd takes a dN register number as destination, not sN.
1217 * Technically, if bit 0 of dd is set, this is an invalid 1295 * Technically, if bit 0 of dd is set, this is an invalid
1218 * instruction. However, we ignore this for efficiency. 1296 * instruction. However, we ignore this for efficiency.
1219 * It also only operates on scalars. 1297 * It also only operates on scalars.
1220 */ 1298 */
1221 if (fop->flags & OP_DD) 1299 if (fop->flags & OP_DD)
1222 dest = vfp_get_dd(inst); 1300 dest = vfp_get_dd(inst);
1223 else 1301 else
1224 dest = vfp_get_sd(inst); 1302 dest = vfp_get_sd(inst);
1225 1303
1226 /* 1304 /*
1227 * If destination bank is zero, vector length is always '1'. 1305 * If destination bank is zero, vector length is always '1'.
1228 * ARM DDI0100F C5.1.3, C5.3.2. 1306 * ARM DDI0100F C5.1.3, C5.3.2.
1229 */ 1307 */
1230 if ((fop->flags & OP_SCALAR) || FREG_BANK(dest) == 0) 1308 if ((fop->flags & OP_SCALAR) || FREG_BANK(dest) == 0)
1231 veclen = 0; 1309 veclen = 0;
1232 else 1310 else
1233 veclen = fpscr & FPSCR_LENGTH_MASK; 1311 veclen = fpscr & FPSCR_LENGTH_MASK;
1234 1312
1235 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, 1313 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
1236 (veclen >> FPSCR_LENGTH_BIT) + 1); 1314 (veclen >> FPSCR_LENGTH_BIT) + 1);
1237 1315
1238 if (!fop->fn) { 1316 if (!fop->fn) {
1239 printf("VFP: could not find single op %d, inst=0x%x@0x%x\n", FEXT_TO_IDX(inst), inst, state->Reg[15]); 1317 printf("VFP: could not find single op %d, inst=0x%x@0x%x\n", FEXT_TO_IDX(inst), inst, state->Reg[15]);
1240 exit(-1); 1318 exit(-1);
1241 goto invalid; 1319 goto invalid;
1242 } 1320 }
1243 1321
1244 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { 1322 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
1245 s32 m = vfp_get_float(state, sm); 1323 s32 m = vfp_get_float(state, sm);
1246 u32 except; 1324 u32 except;
1247 char type; 1325 char type;
1248 1326
1249 type = fop->flags & OP_DD ? 'd' : 's'; 1327 type = fop->flags & OP_DD ? 'd' : 's';
1250 if (op == FOP_EXT) 1328 if (op == FOP_EXT)
1251 pr_debug("VFP: itr%d (%c%u) = op[%u] (s%u=%08x)\n", 1329 pr_debug("VFP: itr%d (%c%u) = op[%u] (s%u=%08x)\n",
1252 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, 1330 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
1253 sm, m); 1331 sm, m);
1254 else 1332 else
1255 pr_debug("VFP: itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)\n", 1333 pr_debug("VFP: itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)\n",
1256 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, 1334 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
1257 FOP_TO_IDX(op), sm, m); 1335 FOP_TO_IDX(op), sm, m);
1258 1336
1259 except = fop->fn(state, dest, sn, m, fpscr); 1337 except = fop->fn(state, dest, sn, m, fpscr);
1260 pr_debug("VFP: itr%d: exceptions=%08x\n", 1338 pr_debug("VFP: itr%d: exceptions=%08x\n",
1261 vecitr >> FPSCR_LENGTH_BIT, except); 1339 vecitr >> FPSCR_LENGTH_BIT, except);
1262 1340
1263 exceptions |= except; 1341 exceptions |= except;
1264 1342
1265 /* 1343 /*
1266 * CHECK: It appears to be undefined whether we stop when 1344 * CHECK: It appears to be undefined whether we stop when
1267 * we encounter an exception. We continue. 1345 * we encounter an exception. We continue.
1268 */ 1346 */
1269 dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7); 1347 dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
1270 sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7); 1348 sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
1271 if (FREG_BANK(sm) != 0) 1349 if (FREG_BANK(sm) != 0)
1272 sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7); 1350 sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7);
1273 } 1351 }
1274 return exceptions; 1352 return exceptions;
1275 1353
1276 invalid: 1354invalid:
1277 return (u32)-1; 1355 return (u32)-1;
1278} 1356}
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 01d4f0afa..25c78d33c 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -5,12 +5,14 @@
5#include "common/common_types.h" 5#include "common/common_types.h"
6 6
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hw/hw.h" 8
9#include "core/settings.h"
9#include "core/arm/disassembler/arm_disasm.h" 10#include "core/arm/disassembler/arm_disasm.h"
10#include "core/arm/interpreter/arm_interpreter.h" 11#include "core/arm/interpreter/arm_interpreter.h"
11 12#include "core/arm/dyncom/arm_dyncom.h"
12#include "core/hle/hle.h" 13#include "core/hle/hle.h"
13#include "core/hle/kernel/thread.h" 14#include "core/hle/kernel/thread.h"
15#include "core/hw/hw.h"
14 16
15namespace Core { 17namespace Core {
16 18
@@ -48,9 +50,18 @@ int Init() {
48 NOTICE_LOG(MASTER_LOG, "initialized OK"); 50 NOTICE_LOG(MASTER_LOG, "initialized OK");
49 51
50 g_disasm = new ARM_Disasm(); 52 g_disasm = new ARM_Disasm();
51 g_app_core = new ARM_Interpreter();
52 g_sys_core = new ARM_Interpreter(); 53 g_sys_core = new ARM_Interpreter();
53 54
55 switch (Settings::values.cpu_core) {
56 case CPU_FastInterpreter:
57 g_app_core = new ARM_DynCom();
58 break;
59 case CPU_Interpreter:
60 default:
61 g_app_core = new ARM_Interpreter();
62 break;
63 }
64
54 g_last_ticks = Core::g_app_core->GetTicks(); 65 g_last_ticks = Core::g_app_core->GetTicks();
55 66
56 return 0; 67 return 0;
diff --git a/src/core/core.h b/src/core/core.h
index 87da252b8..850bb0ab4 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -11,6 +11,11 @@
11 11
12namespace Core { 12namespace Core {
13 13
14enum CPUCore {
15 CPU_Interpreter,
16 CPU_FastInterpreter
17};
18
14extern ARM_Interface* g_app_core; ///< ARM11 application core 19extern ARM_Interface* g_app_core; ///< ARM11 application core
15extern ARM_Interface* g_sys_core; ///< ARM11 system (OS) core 20extern ARM_Interface* g_sys_core; ///< ARM11 system (OS) core
16 21
@@ -21,13 +26,13 @@ void Start();
21 26
22/** 27/**
23 * Run the core CPU loop 28 * Run the core CPU loop
24 * This function loops for 100 instructions in the CPU before trying to update hardware. This is a 29 * This function runs the core for the specified number of CPU instructions before trying to update
25 * little bit faster than SingleStep, and should be pretty much equivalent. The number of 30 * hardware. This is much faster than SingleStep (and should be equivalent), as the CPU is not
26 * instructions chosen is fairly arbitrary, however a large number will more drastically affect the 31 * required to do a full dispatch with each instruction. NOTE: the number of instructions requested
27 * frequency of GSP interrupts and likely break things. The point of this is to just loop in the CPU 32 * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is
28 * for more than 1 instruction to reduce overhead and make it a little bit faster... 33 * requested (e.g. on a thread switch).
29 */ 34 */
30void RunLoop(int tight_loop=100); 35void RunLoop(int tight_loop=1000);
31 36
32/// Step the CPU one instruction 37/// Step the CPU one instruction
33void SingleStep(); 38void SingleStep();
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h
index 560db6dea..38145eed8 100644
--- a/src/core/file_sys/archive.h
+++ b/src/core/file_sys/archive.h
@@ -7,11 +7,13 @@
7#include <memory> 7#include <memory>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/string_util.h"
10#include "common/bit_field.h" 11#include "common/bit_field.h"
11 12
12#include "core/file_sys/file.h" 13#include "core/file_sys/file.h"
13#include "core/file_sys/directory.h" 14#include "core/file_sys/directory.h"
14 15
16#include "core/mem_map.h"
15#include "core/hle/kernel/kernel.h" 17#include "core/hle/kernel/kernel.h"
16 18
17//////////////////////////////////////////////////////////////////////////////////////////////////// 19////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -19,6 +21,15 @@
19 21
20namespace FileSys { 22namespace FileSys {
21 23
24// Path string type
25enum LowPathType : u32 {
26 Invalid = 0,
27 Empty = 1,
28 Binary = 2,
29 Char = 3,
30 Wchar = 4
31};
32
22union Mode { 33union Mode {
23 u32 hex; 34 u32 hex;
24 BitField<0, 1, u32> read_flag; 35 BitField<0, 1, u32> read_flag;
@@ -26,6 +37,94 @@ union Mode {
26 BitField<2, 1, u32> create_flag; 37 BitField<2, 1, u32> create_flag;
27}; 38};
28 39
40class Path {
41public:
42
43 Path():
44 type(Invalid)
45 {
46 }
47
48 Path(LowPathType type, u32 size, u32 pointer):
49 type(type)
50 {
51 switch (type) {
52 case Binary:
53 {
54 u8* data = Memory::GetPointer(pointer);
55 binary = std::vector<u8>(data, data + size);
56 break;
57 }
58 case Char:
59 {
60 const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer));
61 string = std::string(data, size - 1); // Data is always null-terminated.
62 break;
63 }
64 case Wchar:
65 {
66 const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer));
67 u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated.
68 break;
69 }
70 }
71 }
72
73 LowPathType GetType() const {
74 return type;
75 }
76
77 const std::string AsString() const {
78 switch (GetType()) {
79 case Char:
80 return string;
81 case Wchar:
82 return Common::UTF16ToUTF8(u16str);
83 case Empty:
84 return {};
85 default:
86 ERROR_LOG(KERNEL, "LowPathType cannot be converted to string!");
87 return {};
88 }
89 }
90
91 const std::u16string AsU16Str() const {
92 switch (GetType()) {
93 case Char:
94 return Common::UTF8ToUTF16(string);
95 case Wchar:
96 return u16str;
97 case Empty:
98 return {};
99 default:
100 ERROR_LOG(KERNEL, "LowPathType cannot be converted to u16string!");
101 return {};
102 }
103 }
104
105 const std::vector<u8> AsBinary() const {
106 switch (GetType()) {
107 case Binary:
108 return binary;
109 case Char:
110 return std::vector<u8>(string.begin(), string.end());
111 case Wchar:
112 return std::vector<u8>(u16str.begin(), u16str.end());
113 case Empty:
114 return {};
115 default:
116 ERROR_LOG(KERNEL, "LowPathType cannot be converted to binary!");
117 return {};
118 }
119 }
120
121private:
122 LowPathType type;
123 std::vector<u8> binary;
124 std::string string;
125 std::u16string u16str;
126};
127
29class Archive : NonCopyable { 128class Archive : NonCopyable {
30public: 129public:
31 /// Supported archive types 130 /// Supported archive types
@@ -57,6 +156,13 @@ public:
57 virtual std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const = 0; 156 virtual std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const = 0;
58 157
59 /** 158 /**
159 * Create a directory specified by its path
160 * @param path Path relative to the archive
161 * @return Whether the directory could be created
162 */
163 virtual bool CreateDirectory(const std::string& path) const = 0;
164
165 /**
60 * Open a directory specified by its path 166 * Open a directory specified by its path
61 * @param path Path relative to the archive 167 * @param path Path relative to the archive
62 * @return Opened directory, or nullptr 168 * @return Opened directory, or nullptr
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index 9bab3471f..cc759faa8 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -34,6 +34,16 @@ std::unique_ptr<File> Archive_RomFS::OpenFile(const std::string& path, const Mod
34} 34}
35 35
36/** 36/**
37 * Create a directory specified by its path
38 * @param path Path relative to the archive
39 * @return Whether the directory could be created
40 */
41bool Archive_RomFS::CreateDirectory(const std::string& path) const {
42 ERROR_LOG(FILESYS, "Attempted to create a directory in ROMFS.");
43 return false;
44};
45
46/**
37 * Open a directory specified by its path 47 * Open a directory specified by its path
38 * @param path Path relative to the archive 48 * @param path Path relative to the archive
39 * @return Opened directory, or nullptr 49 * @return Opened directory, or nullptr
@@ -50,7 +60,7 @@ std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const std::string& path)
50 * @return Number of bytes read 60 * @return Number of bytes read
51 */ 61 */
52size_t Archive_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { 62size_t Archive_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const {
53 DEBUG_LOG(FILESYS, "called offset=%d, length=%d", offset, length); 63 DEBUG_LOG(FILESYS, "called offset=%llu, length=%d", offset, length);
54 memcpy(buffer, &raw_data[(u32)offset], length); 64 memcpy(buffer, &raw_data[(u32)offset], length);
55 return length; 65 return length;
56} 66}
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index fcdefa95f..ae2344e82 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -37,6 +37,13 @@ public:
37 std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; 37 std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override;
38 38
39 /** 39 /**
40 * Create a directory specified by its path
41 * @param path Path relative to the archive
42 * @return Whether the directory could be created
43 */
44 bool CreateDirectory(const std::string& path) const override;
45
46 /**
40 * Open a directory specified by its path 47 * Open a directory specified by its path
41 * @param path Path relative to the archive 48 * @param path Path relative to the archive
42 * @return Opened directory, or nullptr 49 * @return Opened directory, or nullptr
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 0b647f7d0..66931e93e 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -58,6 +58,15 @@ std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const Mode
58} 58}
59 59
60/** 60/**
61 * Create a directory specified by its path
62 * @param path Path relative to the archive
63 * @return Whether the directory could be created
64 */
65bool Archive_SDMC::CreateDirectory(const std::string& path) const {
66 return FileUtil::CreateDir(GetMountPoint() + path);
67}
68
69/**
61 * Open a directory specified by its path 70 * Open a directory specified by its path
62 * @param path Path relative to the archive 71 * @param path Path relative to the archive
63 * @return Opened directory, or nullptr 72 * @return Opened directory, or nullptr
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index f68648e6f..0e059b635 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -41,6 +41,13 @@ public:
41 std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; 41 std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override;
42 42
43 /** 43 /**
44 * Create a directory specified by its path
45 * @param path Path relative to the archive
46 * @return Whether the directory could be created
47 */
48 bool CreateDirectory(const std::string& path) const override;
49
50 /**
44 * Open a directory specified by its path 51 * Open a directory specified by its path
45 * @param path Path relative to the archive 52 * @param path Path relative to the archive
46 * @return Opened directory, or nullptr 53 * @return Opened directory, or nullptr
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp
index 36951564d..fd558def9 100644
--- a/src/core/file_sys/directory_sdmc.cpp
+++ b/src/core/file_sys/directory_sdmc.cpp
@@ -42,7 +42,7 @@ u32 Directory_SDMC::Read(const u32 count, Entry* entries) {
42 const std::string& filename = file.virtualName; 42 const std::string& filename = file.virtualName;
43 Entry& entry = entries[entries_read]; 43 Entry& entry = entries[entries_read];
44 44
45 WARN_LOG(FILESYS, "File %s: size=%d dir=%d", filename.c_str(), file.size, file.isDirectory); 45 WARN_LOG(FILESYS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory);
46 46
47 // TODO(Link Mauve): use a proper conversion to UTF-16. 47 // TODO(Link Mauve): use a proper conversion to UTF-16.
48 for (int j = 0; j < FILENAME_LENGTH; ++j) { 48 for (int j = 0; j < FILENAME_LENGTH; ++j) {
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 174d4cd6e..2b21657da 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -17,11 +17,11 @@ namespace Kernel {
17 17
18class AddressArbiter : public Object { 18class AddressArbiter : public Object {
19public: 19public:
20 std::string GetTypeName() const { return "Arbiter"; } 20 std::string GetTypeName() const override { return "Arbiter"; }
21 std::string GetName() const { return name; } 21 std::string GetName() const override { return name; }
22 22
23 static Kernel::HandleType GetStaticHandleType() { return HandleType::AddressArbiter; } 23 static Kernel::HandleType GetStaticHandleType() { return HandleType::AddressArbiter; }
24 Kernel::HandleType GetHandleType() const { return HandleType::AddressArbiter; } 24 Kernel::HandleType GetHandleType() const override { return HandleType::AddressArbiter; }
25 25
26 std::string name; ///< Name of address arbiter object (optional) 26 std::string name; ///< Name of address arbiter object (optional)
27 27
@@ -30,7 +30,7 @@ public:
30 * @param wait Boolean wait set if current thread should wait as a result of sync operation 30 * @param wait Boolean wait set if current thread should wait as a result of sync operation
31 * @return Result of operation, 0 on success, otherwise error code 31 * @return Result of operation, 0 on success, otherwise error code
32 */ 32 */
33 Result WaitSynchronization(bool* wait) { 33 Result WaitSynchronization(bool* wait) override {
34 // TODO(bunnei): ImplementMe 34 // TODO(bunnei): ImplementMe
35 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 35 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
36 return 0; 36 return 0;
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
index 86aba7489..764082d71 100644
--- a/src/core/hle/kernel/archive.cpp
+++ b/src/core/hle/kernel/archive.cpp
@@ -42,11 +42,11 @@ enum class DirectoryCommand : u32 {
42 42
43class Archive : public Object { 43class Archive : public Object {
44public: 44public:
45 std::string GetTypeName() const { return "Archive"; } 45 std::string GetTypeName() const override { return "Archive"; }
46 std::string GetName() const { return name; } 46 std::string GetName() const override { return name; }
47 47
48 static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; } 48 static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; }
49 Kernel::HandleType GetHandleType() const { return HandleType::Archive; } 49 Kernel::HandleType GetHandleType() const override { return HandleType::Archive; }
50 50
51 std::string name; ///< Name of archive (optional) 51 std::string name; ///< Name of archive (optional)
52 FileSys::Archive* backend; ///< Archive backend interface 52 FileSys::Archive* backend; ///< Archive backend interface
@@ -56,7 +56,7 @@ public:
56 * @param wait Boolean wait set if current thread should wait as a result of sync operation 56 * @param wait Boolean wait set if current thread should wait as a result of sync operation
57 * @return Result of operation, 0 on success, otherwise error code 57 * @return Result of operation, 0 on success, otherwise error code
58 */ 58 */
59 Result SyncRequest(bool* wait) { 59 Result SyncRequest(bool* wait) override {
60 u32* cmd_buff = Service::GetCommandBuffer(); 60 u32* cmd_buff = Service::GetCommandBuffer();
61 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 61 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
62 62
@@ -119,7 +119,7 @@ public:
119 * @param wait Boolean wait set if current thread should wait as a result of sync operation 119 * @param wait Boolean wait set if current thread should wait as a result of sync operation
120 * @return Result of operation, 0 on success, otherwise error code 120 * @return Result of operation, 0 on success, otherwise error code
121 */ 121 */
122 Result WaitSynchronization(bool* wait) { 122 Result WaitSynchronization(bool* wait) override {
123 // TODO(bunnei): ImplementMe 123 // TODO(bunnei): ImplementMe
124 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 124 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
125 return 0; 125 return 0;
@@ -128,11 +128,11 @@ public:
128 128
129class File : public Object { 129class File : public Object {
130public: 130public:
131 std::string GetTypeName() const { return "File"; } 131 std::string GetTypeName() const override { return "File"; }
132 std::string GetName() const { return path; } 132 std::string GetName() const override { return path; }
133 133
134 static Kernel::HandleType GetStaticHandleType() { return HandleType::File; } 134 static Kernel::HandleType GetStaticHandleType() { return HandleType::File; }
135 Kernel::HandleType GetHandleType() const { return HandleType::File; } 135 Kernel::HandleType GetHandleType() const override { return HandleType::File; }
136 136
137 std::string path; ///< Path of the file 137 std::string path; ///< Path of the file
138 std::unique_ptr<FileSys::File> backend; ///< File backend interface 138 std::unique_ptr<FileSys::File> backend; ///< File backend interface
@@ -142,7 +142,7 @@ public:
142 * @param wait Boolean wait set if current thread should wait as a result of sync operation 142 * @param wait Boolean wait set if current thread should wait as a result of sync operation
143 * @return Result of operation, 0 on success, otherwise error code 143 * @return Result of operation, 0 on success, otherwise error code
144 */ 144 */
145 Result SyncRequest(bool* wait) { 145 Result SyncRequest(bool* wait) override {
146 u32* cmd_buff = Service::GetCommandBuffer(); 146 u32* cmd_buff = Service::GetCommandBuffer();
147 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 147 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
148 switch (cmd) { 148 switch (cmd) {
@@ -153,7 +153,7 @@ public:
153 u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; 153 u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32;
154 u32 length = cmd_buff[3]; 154 u32 length = cmd_buff[3];
155 u32 address = cmd_buff[5]; 155 u32 address = cmd_buff[5];
156 DEBUG_LOG(KERNEL, "Read %s %s: offset=0x%x length=%d address=0x%x", 156 DEBUG_LOG(KERNEL, "Read %s %s: offset=0x%llx length=%d address=0x%x",
157 GetTypeName().c_str(), GetName().c_str(), offset, length, address); 157 GetTypeName().c_str(), GetName().c_str(), offset, length, address);
158 cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); 158 cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address));
159 break; 159 break;
@@ -166,7 +166,7 @@ public:
166 u32 length = cmd_buff[3]; 166 u32 length = cmd_buff[3];
167 u32 flush = cmd_buff[4]; 167 u32 flush = cmd_buff[4];
168 u32 address = cmd_buff[6]; 168 u32 address = cmd_buff[6];
169 DEBUG_LOG(KERNEL, "Write %s %s: offset=0x%x length=%d address=0x%x, flush=0x%x", 169 DEBUG_LOG(KERNEL, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
170 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); 170 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
171 cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); 171 cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address));
172 break; 172 break;
@@ -184,7 +184,7 @@ public:
184 case FileCommand::SetSize: 184 case FileCommand::SetSize:
185 { 185 {
186 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); 186 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
187 DEBUG_LOG(KERNEL, "SetSize %s %s size=%d", GetTypeName().c_str(), GetName().c_str(), size); 187 DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(), size);
188 backend->SetSize(size); 188 backend->SetSize(size);
189 break; 189 break;
190 } 190 }
@@ -211,7 +211,7 @@ public:
211 * @param wait Boolean wait set if current thread should wait as a result of sync operation 211 * @param wait Boolean wait set if current thread should wait as a result of sync operation
212 * @return Result of operation, 0 on success, otherwise error code 212 * @return Result of operation, 0 on success, otherwise error code
213 */ 213 */
214 Result WaitSynchronization(bool* wait) { 214 Result WaitSynchronization(bool* wait) override {
215 // TODO(bunnei): ImplementMe 215 // TODO(bunnei): ImplementMe
216 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 216 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
217 return 0; 217 return 0;
@@ -220,11 +220,11 @@ public:
220 220
221class Directory : public Object { 221class Directory : public Object {
222public: 222public:
223 std::string GetTypeName() const { return "Directory"; } 223 std::string GetTypeName() const override { return "Directory"; }
224 std::string GetName() const { return path; } 224 std::string GetName() const override { return path; }
225 225
226 static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; } 226 static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; }
227 Kernel::HandleType GetHandleType() const { return HandleType::Directory; } 227 Kernel::HandleType GetHandleType() const override { return HandleType::Directory; }
228 228
229 std::string path; ///< Path of the directory 229 std::string path; ///< Path of the directory
230 std::unique_ptr<FileSys::Directory> backend; ///< File backend interface 230 std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
@@ -234,7 +234,7 @@ public:
234 * @param wait Boolean wait set if current thread should wait as a result of sync operation 234 * @param wait Boolean wait set if current thread should wait as a result of sync operation
235 * @return Result of operation, 0 on success, otherwise error code 235 * @return Result of operation, 0 on success, otherwise error code
236 */ 236 */
237 Result SyncRequest(bool* wait) { 237 Result SyncRequest(bool* wait) override {
238 u32* cmd_buff = Service::GetCommandBuffer(); 238 u32* cmd_buff = Service::GetCommandBuffer();
239 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 239 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
240 switch (cmd) { 240 switch (cmd) {
@@ -274,7 +274,7 @@ public:
274 * @param wait Boolean wait set if current thread should wait as a result of sync operation 274 * @param wait Boolean wait set if current thread should wait as a result of sync operation
275 * @return Result of operation, 0 on success, otherwise error code 275 * @return Result of operation, 0 on success, otherwise error code
276 */ 276 */
277 Result WaitSynchronization(bool* wait) { 277 Result WaitSynchronization(bool* wait) override {
278 // TODO(bunnei): ImplementMe 278 // TODO(bunnei): ImplementMe
279 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 279 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
280 return 0; 280 return 0;
@@ -381,6 +381,21 @@ Handle OpenFileFromArchive(Handle archive_handle, const std::string& path, const
381} 381}
382 382
383/** 383/**
384 * Create a Directory from an Archive
385 * @param archive_handle Handle to an open Archive object
386 * @param path Path to the Directory inside of the Archive
387 * @return Opened Directory object
388 */
389Result CreateDirectoryFromArchive(Handle archive_handle, const std::string& path) {
390 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
391 if (archive == nullptr)
392 return -1;
393 if (archive->backend->CreateDirectory(path))
394 return 0;
395 return -1;
396}
397
398/**
384 * Open a Directory from an Archive 399 * Open a Directory from an Archive
385 * @param archive_handle Handle to an open Archive object 400 * @param archive_handle Handle to an open Archive object
386 * @param path Path to the Directory inside of the Archive 401 * @param path Path to the Directory inside of the Archive
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h
index 593861f8e..0230996b6 100644
--- a/src/core/hle/kernel/archive.h
+++ b/src/core/hle/kernel/archive.h
@@ -43,7 +43,15 @@ Handle CreateArchive(FileSys::Archive* backend, const std::string& name);
43 * @param mode Mode under which to open the File 43 * @param mode Mode under which to open the File
44 * @return Opened File object 44 * @return Opened File object
45 */ 45 */
46Handle OpenFileFromArchive(Handle handle, const std::string& name, const FileSys::Mode mode); 46Handle OpenFileFromArchive(Handle archive_handle, const std::string& name, const FileSys::Mode mode);
47
48/**
49 * Create a Directory from an Archive
50 * @param archive_handle Handle to an open Archive object
51 * @param path Path to the Directory inside of the Archive
52 * @return Whether creation of directory succeeded
53 */
54Result CreateDirectoryFromArchive(Handle archive_handle, const std::string& name);
47 55
48/** 56/**
49 * Open a Directory from an Archive 57 * Open a Directory from an Archive
@@ -51,7 +59,7 @@ Handle OpenFileFromArchive(Handle handle, const std::string& name, const FileSys
51 * @param path Path to the Directory inside of the Archive 59 * @param path Path to the Directory inside of the Archive
52 * @return Opened Directory object 60 * @return Opened Directory object
53 */ 61 */
54Handle OpenDirectoryFromArchive(Handle handle, const std::string& name); 62Handle OpenDirectoryFromArchive(Handle archive_handle, const std::string& name);
55 63
56/// Initialize archives 64/// Initialize archives
57void ArchiveInit(); 65void ArchiveInit();
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 64f6a9649..45ed79be8 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -16,11 +16,11 @@ namespace Kernel {
16 16
17class Event : public Object { 17class Event : public Object {
18public: 18public:
19 std::string GetTypeName() const { return "Event"; } 19 std::string GetTypeName() const override { return "Event"; }
20 std::string GetName() const { return name; } 20 std::string GetName() const override { return name; }
21 21
22 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } 22 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; }
23 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } 23 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Event; }
24 24
25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization 25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
26 ResetType reset_type; ///< Current ResetType 26 ResetType reset_type; ///< Current ResetType
@@ -35,7 +35,7 @@ public:
35 * @param wait Boolean wait set if current thread should wait as a result of sync operation 35 * @param wait Boolean wait set if current thread should wait as a result of sync operation
36 * @return Result of operation, 0 on success, otherwise error code 36 * @return Result of operation, 0 on success, otherwise error code
37 */ 37 */
38 Result WaitSynchronization(bool* wait) { 38 Result WaitSynchronization(bool* wait) override {
39 *wait = locked; 39 *wait = locked;
40 if (locked) { 40 if (locked) {
41 Handle thread = GetCurrentThreadHandle(); 41 Handle thread = GetCurrentThreadHandle();
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 5d7d65dd9..fcfd061ac 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -15,11 +15,11 @@ namespace Kernel {
15 15
16class Mutex : public Object { 16class Mutex : public Object {
17public: 17public:
18 std::string GetTypeName() const { return "Mutex"; } 18 std::string GetTypeName() const override { return "Mutex"; }
19 std::string GetName() const { return name; } 19 std::string GetName() const override { return name; }
20 20
21 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } 21 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; }
22 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; } 22 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Mutex; }
23 23
24 bool initial_locked; ///< Initial lock state when mutex was created 24 bool initial_locked; ///< Initial lock state when mutex was created
25 bool locked; ///< Current locked state 25 bool locked; ///< Current locked state
@@ -32,7 +32,7 @@ public:
32 * @param wait Boolean wait set if current thread should wait as a result of sync operation 32 * @param wait Boolean wait set if current thread should wait as a result of sync operation
33 * @return Result of operation, 0 on success, otherwise error code 33 * @return Result of operation, 0 on success, otherwise error code
34 */ 34 */
35 Result SyncRequest(bool* wait) { 35 Result SyncRequest(bool* wait) override {
36 // TODO(bunnei): ImplementMe 36 // TODO(bunnei): ImplementMe
37 locked = true; 37 locked = true;
38 return 0; 38 return 0;
@@ -43,7 +43,7 @@ public:
43 * @param wait Boolean wait set if current thread should wait as a result of sync operation 43 * @param wait Boolean wait set if current thread should wait as a result of sync operation
44 * @return Result of operation, 0 on success, otherwise error code 44 * @return Result of operation, 0 on success, otherwise error code
45 */ 45 */
46 Result WaitSynchronization(bool* wait) { 46 Result WaitSynchronization(bool* wait) override {
47 // TODO(bunnei): ImplementMe 47 // TODO(bunnei): ImplementMe
48 *wait = locked; 48 *wait = locked;
49 49
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 2a6a483a1..f538c6550 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -11,17 +11,17 @@ namespace Kernel {
11 11
12class SharedMemory : public Object { 12class SharedMemory : public Object {
13public: 13public:
14 std::string GetTypeName() const { return "SharedMemory"; } 14 std::string GetTypeName() const override { return "SharedMemory"; }
15 15
16 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; } 16 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; }
17 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::SharedMemory; } 17 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; }
18 18
19 /** 19 /**
20 * Wait for kernel object to synchronize 20 * Wait for kernel object to synchronize
21 * @param wait Boolean wait set if current thread should wait as a result of sync operation 21 * @param wait Boolean wait set if current thread should wait as a result of sync operation
22 * @return Result of operation, 0 on success, otherwise error code 22 * @return Result of operation, 0 on success, otherwise error code
23 */ 23 */
24 Result WaitSynchronization(bool* wait) { 24 Result WaitSynchronization(bool* wait) override {
25 // TODO(bunnei): ImplementMe 25 // TODO(bunnei): ImplementMe
26 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 26 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
27 return 0; 27 return 0;
@@ -72,7 +72,7 @@ Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
72 72
73 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { 73 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
74 ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", 74 ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
75 handle); 75 handle, address);
76 return -1; 76 return -1;
77 } 77 }
78 SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle); 78 SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 33c0b2a47..e15590c49 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -21,11 +21,11 @@ namespace Kernel {
21class Thread : public Kernel::Object { 21class Thread : public Kernel::Object {
22public: 22public:
23 23
24 std::string GetName() const { return name; } 24 std::string GetName() const override { return name; }
25 std::string GetTypeName() const { return "Thread"; } 25 std::string GetTypeName() const override { return "Thread"; }
26 26
27 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; } 27 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; }
28 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Thread; } 28 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Thread; }
29 29
30 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } 30 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; }
31 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } 31 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; }
@@ -38,7 +38,7 @@ public:
38 * @param wait Boolean wait set if current thread should wait as a result of sync operation 38 * @param wait Boolean wait set if current thread should wait as a result of sync operation
39 * @return Result of operation, 0 on success, otherwise error code 39 * @return Result of operation, 0 on success, otherwise error code
40 */ 40 */
41 Result WaitSynchronization(bool* wait) { 41 Result WaitSynchronization(bool* wait) override {
42 if (status != THREADSTATUS_DORMANT) { 42 if (status != THREADSTATUS_DORMANT) {
43 Handle thread = GetCurrentThreadHandle(); 43 Handle thread = GetCurrentThreadHandle();
44 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { 44 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
new file mode 100644
index 000000000..b39603bdf
--- /dev/null
+++ b/src/core/hle/service/ac_u.cpp
@@ -0,0 +1,44 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/ac_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace AC_U
11
12namespace AC_U {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010000, nullptr, "CreateDefaultConfig"},
16 {0x00040006, nullptr, "ConnectAsync"},
17 {0x00050002, nullptr, "GetConnectResult"},
18 {0x00080004, nullptr, "CloseAsync"},
19 {0x00090002, nullptr, "GetCloseResult"},
20 {0x000A0000, nullptr, "GetLastErrorCode"},
21 {0x000D0000, nullptr, "GetWifiStatus"},
22 {0x000E0042, nullptr, "GetCurrentAPInfo"},
23 {0x00100042, nullptr, "GetCurrentNZoneInfo"},
24 {0x00110042, nullptr, "GetNZoneApNumService"},
25 {0x00240042, nullptr, "AddDenyApType "},
26 {0x00270002, nullptr, "GetInfraPriority "},
27 {0x002D0082, nullptr, "SetRequestEulaVersion"},
28 {0x00300004, nullptr, "RegisterDisconnectEvent"},
29 {0x003C0042, nullptr, "GetAPSSIDList"},
30 {0x003E0042, nullptr, "IsConnected "},
31 {0x00400042, nullptr, "SetClientVersion"},
32};
33
34////////////////////////////////////////////////////////////////////////////////////////////////////
35// Interface class
36
37Interface::Interface() {
38 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
39}
40
41Interface::~Interface() {
42}
43
44} // namespace
diff --git a/src/core/hle/service/ac_u.h b/src/core/hle/service/ac_u.h
new file mode 100644
index 000000000..3c5958d27
--- /dev/null
+++ b/src/core/hle/service/ac_u.h
@@ -0,0 +1,29 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace AC_U
11
12// socket service "ac:u"
13
14namespace AC_U {
15
16class Interface : public Service::Interface {
17public:
18 Interface();
19 ~Interface();
20 /**
21 * Gets the string port name used by CTROS for the service
22 * @return Port name of service
23 */
24 std::string GetPortName() const {
25 return "ac:u";
26 }
27};
28
29} // namespace
diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt_u.cpp
index 3753f1107..4f41ec5f4 100644
--- a/src/core/hle/service/apt.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -8,13 +8,15 @@
8#include "core/hle/hle.h" 8#include "core/hle/hle.h"
9#include "core/hle/kernel/event.h" 9#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/mutex.h" 10#include "core/hle/kernel/mutex.h"
11#include "core/hle/service/apt.h" 11#include "apt_u.h"
12 12
13//////////////////////////////////////////////////////////////////////////////////////////////////// 13////////////////////////////////////////////////////////////////////////////////////////////////////
14// Namespace APT_U 14// Namespace APT_U
15 15
16namespace APT_U { 16namespace APT_U {
17 17
18static Handle lock_handle = 0;
19
18/// Signals used by APT functions 20/// Signals used by APT functions
19enum class SignalType : u32 { 21enum class SignalType : u32 {
20 None = 0x0, 22 None = 0x0,
@@ -32,15 +34,32 @@ void Initialize(Service::Interface* self) {
32 Kernel::SetEventLocked(cmd_buff[3], true); 34 Kernel::SetEventLocked(cmd_buff[3], true);
33 Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event 35 Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event
34 36
37 _assert_msg_(KERNEL, (0 != lock_handle), "Cannot initialize without lock");
38 Kernel::ReleaseMutex(lock_handle);
39
35 cmd_buff[1] = 0; // No error 40 cmd_buff[1] = 0; // No error
41
36 DEBUG_LOG(KERNEL, "called"); 42 DEBUG_LOG(KERNEL, "called");
37} 43}
38 44
39void GetLockHandle(Service::Interface* self) { 45void GetLockHandle(Service::Interface* self) {
40 u32* cmd_buff = Service::GetCommandBuffer(); 46 u32* cmd_buff = Service::GetCommandBuffer();
41 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field 47 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
48
49 if (0 == lock_handle) {
50 // TODO(bunnei): Verify if this is created here or at application boot?
51 lock_handle = Kernel::CreateMutex(false, "APT_U:Lock");
52 Kernel::ReleaseMutex(lock_handle);
53 }
42 cmd_buff[1] = 0; // No error 54 cmd_buff[1] = 0; // No error
43 cmd_buff[5] = Kernel::CreateMutex(false, "APT_U:Lock"); 55
56 // Not sure what these parameters are used for, but retail apps check that they are 0 after
57 // GetLockHandle has been called.
58 cmd_buff[2] = 0;
59 cmd_buff[3] = 0;
60 cmd_buff[4] = 0;
61
62 cmd_buff[5] = lock_handle;
44 DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]); 63 DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]);
45} 64}
46 65
@@ -59,6 +78,25 @@ void InquireNotification(Service::Interface* self) {
59 WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X", app_id); 78 WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X", app_id);
60} 79}
61 80
81/**
82 * APT_U::ReceiveParameter service function. This returns the current parameter data from NS state,
83 * from the source process which set the parameters. Once finished, NS will clear a flag in the NS
84 * state so that this command will return an error if this command is used again if parameters were
85 * not set again. This is called when the second Initialize event is triggered. It returns a signal
86 * type indicating why it was triggered.
87 * Inputs:
88 * 1 : AppID
89 * 2 : Parameter buffer size, max size is 0x1000
90 * Outputs:
91 * 1 : Result of function, 0 on success, otherwise error code
92 * 2 : Unknown, for now assume AppID of the process which sent these parameters
93 * 3 : Unknown, for now assume Signal type
94 * 4 : Actual parameter buffer size, this is <= to the the input size
95 * 5 : Value
96 * 6 : Handle from the source process which set the parameters, likely used for shared memory
97 * 7 : Size
98 * 8 : Output parameter buffer ptr
99 */
62void ReceiveParameter(Service::Interface* self) { 100void ReceiveParameter(Service::Interface* self) {
63 u32* cmd_buff = Service::GetCommandBuffer(); 101 u32* cmd_buff = Service::GetCommandBuffer();
64 u32 app_id = cmd_buff[1]; 102 u32 app_id = cmd_buff[1];
@@ -66,7 +104,7 @@ void ReceiveParameter(Service::Interface* self) {
66 cmd_buff[1] = 0; // No error 104 cmd_buff[1] = 0; // No error
67 cmd_buff[2] = 0; 105 cmd_buff[2] = 0;
68 cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type 106 cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type
69 cmd_buff[4] = 0x10; 107 cmd_buff[4] = 0x10; // Parameter buffer size (16)
70 cmd_buff[5] = 0; 108 cmd_buff[5] = 0;
71 cmd_buff[6] = 0; 109 cmd_buff[6] = 0;
72 cmd_buff[7] = 0; 110 cmd_buff[7] = 0;
@@ -74,35 +112,66 @@ void ReceiveParameter(Service::Interface* self) {
74} 112}
75 113
76/** 114/**
77* APT_U::GlanceParameter service function 115 * APT_U::GlanceParameter service function. This is exactly the same as APT_U::ReceiveParameter
78* Inputs: 116 * (except for the word value prior to the output handle), except this will not clear the flag
79* 1 : AppID 117 * (except when responseword[3]==8 || responseword[3]==9) in NS state.
80* 2 : Parameter buffer size, max size is 0x1000 118 * Inputs:
81* Outputs: 119 * 1 : AppID
82* 1 : Result of function, 0 on success, otherwise error code 120 * 2 : Parameter buffer size, max size is 0x1000
83* 2 : Unknown, for now assume AppID of the process which sent these parameters 121 * Outputs:
84* 3 : Unknown, for now assume Signal type 122 * 1 : Result of function, 0 on success, otherwise error code
85* 4 : Actual parameter buffer size, this is <= to the the input size 123 * 2 : Unknown, for now assume AppID of the process which sent these parameters
86* 5 : Value 124 * 3 : Unknown, for now assume Signal type
87* 6 : Handle from the source process which set the parameters, likely used for shared memory 125 * 4 : Actual parameter buffer size, this is <= to the the input size
88* 7 : Size 126 * 5 : Value
89* 8 : Output parameter buffer ptr 127 * 6 : Handle from the source process which set the parameters, likely used for shared memory
90*/ 128 * 7 : Size
129 * 8 : Output parameter buffer ptr
130 */
91void GlanceParameter(Service::Interface* self) { 131void GlanceParameter(Service::Interface* self) {
92 u32* cmd_buff = Service::GetCommandBuffer(); 132 u32* cmd_buff = Service::GetCommandBuffer();
93 u32 app_id = cmd_buff[1]; 133 u32 app_id = cmd_buff[1];
94 u32 buffer_size = cmd_buff[2]; 134 u32 buffer_size = cmd_buff[2];
135
95 cmd_buff[1] = 0; // No error 136 cmd_buff[1] = 0; // No error
96 cmd_buff[2] = 0; 137 cmd_buff[2] = 0;
97 cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type 138 cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type
98 cmd_buff[4] = 0; 139 cmd_buff[4] = 0x10; // Parameter buffer size (16)
99 cmd_buff[5] = 0; 140 cmd_buff[5] = 0;
100 cmd_buff[6] = 0; 141 cmd_buff[6] = 0;
101 cmd_buff[7] = 0; 142 cmd_buff[7] = 0;
102 cmd_buff[8] = 0; 143
103 WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); 144 WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
104} 145}
105 146
147/**
148 * APT_U::AppletUtility service function
149 * Inputs:
150 * 1 : Unknown, but clearly used for something
151 * 2 : Buffer 1 size (purpose is unknown)
152 * 3 : Buffer 2 size (purpose is unknown)
153 * 5 : Buffer 1 address (purpose is unknown)
154 * 65 : Buffer 2 address (purpose is unknown)
155 * Outputs:
156 * 1 : Result of function, 0 on success, otherwise error code
157 */
158void AppletUtility(Service::Interface* self) {
159 u32* cmd_buff = Service::GetCommandBuffer();
160
161 // These are from 3dbrew - I'm not really sure what they're used for.
162 u32 unk = cmd_buff[1];
163 u32 buffer1_size = cmd_buff[2];
164 u32 buffer2_size = cmd_buff[3];
165 u32 buffer1_addr = cmd_buff[5];
166 u32 buffer2_addr = cmd_buff[65];
167
168 cmd_buff[1] = 0; // No error
169
170 WARN_LOG(KERNEL, "(STUBBED) called unk=0x%08X, buffer1_size=0x%08x, buffer2_size=0x%08x, "
171 "buffer1_addr=0x%08x, buffer2_addr=0x%08x", unk, buffer1_size, buffer2_size,
172 buffer1_addr, buffer2_addr);
173}
174
106const Interface::FunctionInfo FunctionTable[] = { 175const Interface::FunctionInfo FunctionTable[] = {
107 {0x00010040, GetLockHandle, "GetLockHandle"}, 176 {0x00010040, GetLockHandle, "GetLockHandle"},
108 {0x00020080, Initialize, "Initialize"}, 177 {0x00020080, Initialize, "Initialize"},
@@ -178,7 +247,7 @@ const Interface::FunctionInfo FunctionTable[] = {
178 {0x00480100, nullptr, "GetProgramInfo"}, 247 {0x00480100, nullptr, "GetProgramInfo"},
179 {0x00490180, nullptr, "Reboot"}, 248 {0x00490180, nullptr, "Reboot"},
180 {0x004A0040, nullptr, "GetCaptureInfo"}, 249 {0x004A0040, nullptr, "GetCaptureInfo"},
181 {0x004B00C2, nullptr, "AppletUtility"}, 250 {0x004B00C2, AppletUtility, "AppletUtility"},
182 {0x004C0000, nullptr, "SetFatalErrDispMode"}, 251 {0x004C0000, nullptr, "SetFatalErrDispMode"},
183 {0x004D0080, nullptr, "GetAppletProgramInfo"}, 252 {0x004D0080, nullptr, "GetAppletProgramInfo"},
184 {0x004E0000, nullptr, "HardwareResetAsync"}, 253 {0x004E0000, nullptr, "HardwareResetAsync"},
@@ -191,6 +260,8 @@ const Interface::FunctionInfo FunctionTable[] = {
191 260
192Interface::Interface() { 261Interface::Interface() {
193 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 262 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
263
264 lock_handle = 0;
194} 265}
195 266
196Interface::~Interface() { 267Interface::~Interface() {
diff --git a/src/core/hle/service/apt.h b/src/core/hle/service/apt_u.h
index 4c7dd07e7..5af39e085 100644
--- a/src/core/hle/service/apt.h
+++ b/src/core/hle/service/apt_u.h
@@ -29,7 +29,7 @@ public:
29 * Gets the string port name used by CTROS for the service 29 * Gets the string port name used by CTROS for the service
30 * @return Port name of service 30 * @return Port name of service
31 */ 31 */
32 std::string GetPortName() const { 32 std::string GetPortName() const override {
33 return "APT:U"; 33 return "APT:U";
34 } 34 }
35}; 35};
diff --git a/src/core/hle/service/cfg_u.cpp b/src/core/hle/service/cfg_u.cpp
new file mode 100644
index 000000000..822b0e2b8
--- /dev/null
+++ b/src/core/hle/service/cfg_u.cpp
@@ -0,0 +1,36 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/cfg_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace CFG_U
11
12namespace CFG_U {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010082, nullptr, "GetConfigInfoBlk2"},
16 {0x00020000, nullptr, "SecureInfoGetRegion"},
17 {0x00030000, nullptr, "GenHashConsoleUnique"},
18 {0x00040000, nullptr, "GetRegionCanadaUSA"},
19 {0x00050000, nullptr, "GetSystemModel"},
20 {0x00060000, nullptr, "GetModelNintendo2DS"},
21 {0x00070040, nullptr, "unknown"},
22 {0x00080080, nullptr, "unknown"},
23 {0x00090080, nullptr, "GetCountryCodeString"},
24 {0x000A0040, nullptr, "GetCountryCodeID"},
25};
26////////////////////////////////////////////////////////////////////////////////////////////////////
27// Interface class
28
29Interface::Interface() {
30 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
31}
32
33Interface::~Interface() {
34}
35
36} // namespace
diff --git a/src/core/hle/service/cfg_u.h b/src/core/hle/service/cfg_u.h
new file mode 100644
index 000000000..7525bd7c6
--- /dev/null
+++ b/src/core/hle/service/cfg_u.h
@@ -0,0 +1,27 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace CFG_U
11
12namespace CFG_U {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17 ~Interface();
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const {
23 return "cfg:u";
24 }
25};
26
27} // namespace
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
new file mode 100644
index 000000000..9e84ac938
--- /dev/null
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -0,0 +1,52 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/dsp_dsp.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace DSP_DSP
11
12namespace DSP_DSP {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010040, nullptr, "RecvData"},
16 {0x00020040, nullptr, "RecvDataIsReady"},
17 {0x00030080, nullptr, "SendData"},
18 {0x00040040, nullptr, "SendDataIsEmpty"},
19 {0x00070040, nullptr, "WriteReg0x10"},
20 {0x00080000, nullptr, "GetSemaphore"},
21 {0x00090040, nullptr, "ClearSemaphore"},
22 {0x000B0000, nullptr, "CheckSemaphoreRequest"},
23 {0x000C0040, nullptr, "ConvertProcessAddressFromDspDram"},
24 {0x000D0082, nullptr, "WriteProcessPipe"},
25 {0x001000C0, nullptr, "ReadPipeIfPossible"},
26 {0x001100C2, nullptr, "LoadComponent"},
27 {0x00120000, nullptr, "UnloadComponent"},
28 {0x00130082, nullptr, "FlushDataCache"},
29 {0x00140082, nullptr, "InvalidateDCache "},
30 {0x00150082, nullptr, "RegisterInterruptEvents"},
31 {0x00160000, nullptr, "GetSemaphoreEventHandle"},
32 {0x00170040, nullptr, "SetSemaphoreMask"},
33 {0x00180040, nullptr, "GetPhysicalAddress"},
34 {0x00190040, nullptr, "GetVirtualAddress" },
35 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
36 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
37 {0x001C0082, nullptr, "SetIirFilterEQ"},
38 {0x001F0000, nullptr, "GetHeadphoneStatus"},
39 {0x00210000, nullptr, "GetIsDspOccupied"},
40};
41
42////////////////////////////////////////////////////////////////////////////////////////////////////
43// Interface class
44
45Interface::Interface() {
46 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
47}
48
49Interface::~Interface() {
50}
51
52} // namespace
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h
new file mode 100644
index 000000000..c439ed266
--- /dev/null
+++ b/src/core/hle/service/dsp_dsp.h
@@ -0,0 +1,27 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace DSP_DSP
11
12namespace DSP_DSP {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17 ~Interface();
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const {
23 return "dsp:DSP";
24 }
25};
26
27} // namespace
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
new file mode 100644
index 000000000..917b2f8ca
--- /dev/null
+++ b/src/core/hle/service/err_f.cpp
@@ -0,0 +1,27 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/err_f.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace ERR_F
11
12namespace ERR_F {
13
14 const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010800, nullptr, "ThrowFatalError"}
16 };
17 ////////////////////////////////////////////////////////////////////////////////////////////////////
18 // Interface class
19
20 Interface::Interface() {
21 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
22 }
23
24 Interface::~Interface() {
25 }
26
27} // namespace
diff --git a/src/core/hle/service/err_f.h b/src/core/hle/service/err_f.h
new file mode 100644
index 000000000..5da663267
--- /dev/null
+++ b/src/core/hle/service/err_f.h
@@ -0,0 +1,27 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace ERR_F
11
12namespace ERR_F {
13
14 class Interface : public Service::Interface {
15 public:
16 Interface();
17 ~Interface();
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const {
23 return "err:f";
24 }
25 };
26
27} // namespace
diff --git a/src/core/hle/service/frd_u.cpp b/src/core/hle/service/frd_u.cpp
new file mode 100644
index 000000000..58023e536
--- /dev/null
+++ b/src/core/hle/service/frd_u.cpp
@@ -0,0 +1,35 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/frd_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace FRD_U
11
12namespace FRD_U {
13
14 const Interface::FunctionInfo FunctionTable[] = {
15 {0x00050000, nullptr, "GetFriendKey"},
16 {0x00080000, nullptr, "GetMyPresence"},
17 {0x00100040, nullptr, "GetPassword"},
18 {0x00190042, nullptr, "GetFriendFavoriteGame"},
19 {0x001A00C4, nullptr, "GetFriendInfo"},
20 {0x001B0080, nullptr, "IsOnFriendList"},
21 {0x001C0042, nullptr, "DecodeLocalFriendCode"},
22 {0x001D0002, nullptr, "SetCurrentlyPlayingText"},
23 {0x00320042, nullptr, "SetClientSdkVersion"}
24 };
25 ////////////////////////////////////////////////////////////////////////////////////////////////////
26 // Interface class
27
28 Interface::Interface() {
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
30 }
31
32 Interface::~Interface() {
33 }
34
35} // namespace
diff --git a/src/core/hle/service/frd_u.h b/src/core/hle/service/frd_u.h
new file mode 100644
index 000000000..9df8a815a
--- /dev/null
+++ b/src/core/hle/service/frd_u.h
@@ -0,0 +1,27 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace FRD_U
11
12namespace FRD_U {
13
14 class Interface : public Service::Interface {
15 public:
16 Interface();
17 ~Interface();
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const {
23 return "frd:u";
24 }
25 };
26
27} // namespace
diff --git a/src/core/hle/service/fs.cpp b/src/core/hle/service/fs_user.cpp
index 662c4f247..9dc83291d 100644
--- a/src/core/hle/service/fs.cpp
+++ b/src/core/hle/service/fs_user.cpp
@@ -4,7 +4,9 @@
4 4
5#include "common/common.h" 5#include "common/common.h"
6 6
7#include "core/hle/service/fs.h" 7#include "fs_user.h"
8#include "common/string_util.h"
9#include "core/settings.h"
8#include "core/hle/kernel/archive.h" 10#include "core/hle/kernel/archive.h"
9 11
10//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -12,20 +14,6 @@
12 14
13namespace FS_User { 15namespace FS_User {
14 16
15// Command to access archive file
16enum class LowPathType : u32 {
17 Invalid = 0,
18 Empty = 1,
19 Binary = 2,
20 Char = 3,
21 Wchar = 4
22};
23
24std::string GetStringFromCmdBuff(const u32 pointer, const u32 size) {
25 auto data = reinterpret_cast<const char*>(Memory::GetPointer(pointer));
26 return std::string(data, size - 1);
27}
28
29// We currently return 0 for success and -1 for failure in cmd_buff[1]. -1 was chosen because it 17// We currently return 0 for success and -1 for failure in cmd_buff[1]. -1 was chosen because it
30// puts all the sections of the http://3dbrew.org/wiki/Error_codes to something non-zero, to make 18// puts all the sections of the http://3dbrew.org/wiki/Error_codes to something non-zero, to make
31// sure we don't mislead the application into thinking something worked. 19// sure we don't mislead the application into thinking something worked.
@@ -43,32 +31,36 @@ void Initialize(Service::Interface* self) {
43void OpenFile(Service::Interface* self) { 31void OpenFile(Service::Interface* self) {
44 u32* cmd_buff = Service::GetCommandBuffer(); 32 u32* cmd_buff = Service::GetCommandBuffer();
45 33
46 u32 transaction = cmd_buff[1];
47 // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to 34 // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
48 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. 35 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
49 Handle archive_handle = static_cast<Handle>(cmd_buff[3]); 36 Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
50 LowPathType type = static_cast<LowPathType>(cmd_buff[4]); 37 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
51 u32 size = cmd_buff[5]; 38 u32 filename_size = cmd_buff[5];
52 FileSys::Mode mode; mode.hex = cmd_buff[6]; 39 FileSys::Mode mode; mode.hex = cmd_buff[6];
53 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. 40 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes.
54 u32 pointer = cmd_buff[9]; 41 u32 filename_ptr = cmd_buff[9];
55 42
56 if (type != LowPathType::Char) { 43 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
57 ERROR_LOG(KERNEL, "file LowPath type other than char is currently unsupported"); 44 std::string file_string;
58 cmd_buff[1] = -1; 45 switch (file_path.GetType()) {
46 case FileSys::Char:
47 case FileSys::Wchar:
48 file_string = file_path.AsString();
49 break;
50 default:
51 WARN_LOG(KERNEL, "file LowPath type is currently unsupported; returning archive handle instead");
59 return; 52 return;
60 } 53 }
61 54
62 std::string file_name = GetStringFromCmdBuff(pointer, size); 55 DEBUG_LOG(KERNEL, "type=%d size=%d mode=%d attrs=%d data=%s",
63 56 filename_type, filename_size, mode, attributes, file_string.c_str());
64 DEBUG_LOG(KERNEL, "type=%d size=%d mode=%d attrs=%d data=%s", type, size, mode, attributes, file_name.c_str());
65 57
66 Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_name, mode); 58 Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_string, mode);
67 if (handle) { 59 if (handle) {
68 cmd_buff[1] = 0; 60 cmd_buff[1] = 0;
69 cmd_buff[3] = handle; 61 cmd_buff[3] = handle;
70 } else { 62 } else {
71 ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_name.c_str()); 63 ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_string.c_str());
72 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. 64 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
73 cmd_buff[1] = -1; 65 cmd_buff[1] = -1;
74 } 66 }
@@ -79,31 +71,25 @@ void OpenFile(Service::Interface* self) {
79void OpenFileDirectly(Service::Interface* self) { 71void OpenFileDirectly(Service::Interface* self) {
80 u32* cmd_buff = Service::GetCommandBuffer(); 72 u32* cmd_buff = Service::GetCommandBuffer();
81 73
82 u32 transaction = cmd_buff[1]; 74 auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]);
83 auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); 75 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
84 LowPathType archive_type = static_cast<LowPathType>(cmd_buff[3]); 76 u32 archivename_size = cmd_buff[4];
85 u32 archive_size = cmd_buff[4]; 77 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]);
86 LowPathType file_type = static_cast<LowPathType>(cmd_buff[5]); 78 u32 filename_size = cmd_buff[6];
87 u32 size = cmd_buff[6];
88 FileSys::Mode mode; mode.hex = cmd_buff[7]; 79 FileSys::Mode mode; mode.hex = cmd_buff[7];
89 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. 80 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes.
90 u32 archive_pointer = cmd_buff[10]; 81 u32 archivename_ptr = cmd_buff[10];
91 u32 pointer = cmd_buff[12]; 82 u32 filename_ptr = cmd_buff[12];
92 83
93 if (archive_type != LowPathType::Empty) { 84 DEBUG_LOG(KERNEL, "archive_type=%d archive_size=%d file_type=%d file_size=%d file_mode=%d file_attrs=%d",
85 archivename_type, archivename_size, filename_type, filename_size, mode, attributes);
86
87 if (archivename_type != FileSys::Empty) {
94 ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); 88 ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported");
95 cmd_buff[1] = -1; 89 cmd_buff[1] = -1;
96 return; 90 return;
97 } 91 }
98 92
99 std::string archive_name = GetStringFromCmdBuff(archive_pointer, archive_size);
100 std::string file_name = GetStringFromCmdBuff(pointer, size);
101
102 DEBUG_LOG(KERNEL, "archive_type=%d archive_size=%d archive_data=%s"
103 "file_type=%d file_size=%d file_mode=%d file_attrs=%d file_data=%s",
104 archive_type, archive_size, archive_name.c_str(),
105 file_type, size, mode, attributes, file_name.c_str());
106
107 // TODO(Link Mauve): check if we should even get a handle for the archive, and don't leak it. 93 // TODO(Link Mauve): check if we should even get a handle for the archive, and don't leak it.
108 Handle archive_handle = Kernel::OpenArchive(archive_id); 94 Handle archive_handle = Kernel::OpenArchive(archive_id);
109 if (archive_handle) { 95 if (archive_handle) {
@@ -111,23 +97,30 @@ void OpenFileDirectly(Service::Interface* self) {
111 // cmd_buff[2] isn't used according to 3dmoo's implementation. 97 // cmd_buff[2] isn't used according to 3dmoo's implementation.
112 cmd_buff[3] = archive_handle; 98 cmd_buff[3] = archive_handle;
113 } else { 99 } else {
114 ERROR_LOG(KERNEL, "failed to get a handle for archive %s", archive_name.c_str()); 100 ERROR_LOG(KERNEL, "failed to get a handle for archive");
115 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. 101 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
116 cmd_buff[1] = -1; 102 cmd_buff[1] = -1;
117 return; 103 return;
118 } 104 }
119 105
120 if (file_type != LowPathType::Char) { 106 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
121 WARN_LOG(KERNEL, "file LowPath type other than char is currently unsupported; returning archive handle instead"); 107 std::string file_string;
108 switch (file_path.GetType()) {
109 case FileSys::Char:
110 case FileSys::Wchar:
111 file_string = file_path.AsString();
112 break;
113 default:
114 WARN_LOG(KERNEL, "file LowPath type is currently unsupported; returning archive handle instead");
122 return; 115 return;
123 } 116 }
124 117
125 Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_name, mode); 118 Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_string, mode);
126 if (handle) { 119 if (handle) {
127 cmd_buff[1] = 0; 120 cmd_buff[1] = 0;
128 cmd_buff[3] = handle; 121 cmd_buff[3] = handle;
129 } else { 122 } else {
130 ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_name.c_str()); 123 ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_string.c_str());
131 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. 124 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
132 cmd_buff[1] = -1; 125 cmd_buff[1] = -1;
133 } 126 }
@@ -135,32 +128,76 @@ void OpenFileDirectly(Service::Interface* self) {
135 DEBUG_LOG(KERNEL, "called"); 128 DEBUG_LOG(KERNEL, "called");
136} 129}
137 130
131/*
132 * FS_User::CreateDirectory service function
133 * Inputs:
134 * 2 : Archive handle lower word
135 * 3 : Archive handle upper word
136 * 4 : Directory path string type
137 * 5 : Directory path string size
138 * 8 : Directory path string data
139 * Outputs:
140 * 1 : Result of function, 0 on success, otherwise error code
141 */
142void CreateDirectory(Service::Interface* self) {
143 u32* cmd_buff = Service::GetCommandBuffer();
144
145 // TODO: cmd_buff[2], aka archive handle lower word, isn't used according to
146 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
147 Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
148 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
149 u32 dirname_size = cmd_buff[5];
150 u32 dirname_ptr = cmd_buff[8];
151
152 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
153 std::string dir_string;
154 switch (dir_path.GetType()) {
155 case FileSys::Char:
156 case FileSys::Wchar:
157 dir_string = dir_path.AsString();
158 break;
159 default:
160 cmd_buff[1] = -1;
161 return;
162 }
163
164 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_string.c_str());
165
166 cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_string);
167
168 DEBUG_LOG(KERNEL, "called");
169}
170
138void OpenDirectory(Service::Interface* self) { 171void OpenDirectory(Service::Interface* self) {
139 u32* cmd_buff = Service::GetCommandBuffer(); 172 u32* cmd_buff = Service::GetCommandBuffer();
140 173
141 // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to 174 // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
142 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. 175 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
143 Handle archive_handle = static_cast<Handle>(cmd_buff[2]); 176 Handle archive_handle = static_cast<Handle>(cmd_buff[2]);
144 LowPathType type = static_cast<LowPathType>(cmd_buff[3]); 177 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
145 u32 size = cmd_buff[4]; 178 u32 dirname_size = cmd_buff[4];
146 u32 pointer = cmd_buff[6]; 179 u32 dirname_ptr = cmd_buff[6];
147 180
148 if (type != LowPathType::Char) { 181 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
149 ERROR_LOG(KERNEL, "directory LowPath type other than char is currently unsupported"); 182 std::string dir_string;
183 switch (dir_path.GetType()) {
184 case FileSys::Char:
185 case FileSys::Wchar:
186 dir_string = dir_path.AsString();
187 break;
188 default:
150 cmd_buff[1] = -1; 189 cmd_buff[1] = -1;
151 return; 190 return;
152 } 191 }
153 192
154 std::string dir_name = GetStringFromCmdBuff(pointer, size); 193 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_string.c_str());
155 194
156 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", type, size, dir_name.c_str()); 195 Handle handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_string);
157
158 Handle handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_name);
159 if (handle) { 196 if (handle) {
160 cmd_buff[1] = 0; 197 cmd_buff[1] = 0;
161 cmd_buff[3] = handle; 198 cmd_buff[3] = handle;
162 } else { 199 } else {
163 ERROR_LOG(KERNEL, "failed to get a handle for directory %s", dir_name.c_str()); 200 ERROR_LOG(KERNEL, "failed to get a handle for directory %s", dir_string.c_str());
164 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. 201 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
165 cmd_buff[1] = -1; 202 cmd_buff[1] = -1;
166 } 203 }
@@ -171,28 +208,26 @@ void OpenDirectory(Service::Interface* self) {
171void OpenArchive(Service::Interface* self) { 208void OpenArchive(Service::Interface* self) {
172 u32* cmd_buff = Service::GetCommandBuffer(); 209 u32* cmd_buff = Service::GetCommandBuffer();
173 210
174 auto arch_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); 211 auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]);
175 LowPathType type = static_cast<LowPathType>(cmd_buff[2]); 212 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
176 u32 size = cmd_buff[3]; 213 u32 archivename_size = cmd_buff[3];
177 u32 pointer = cmd_buff[5]; 214 u32 archivename_ptr = cmd_buff[5];
215
216 DEBUG_LOG(KERNEL, "type=%d size=%d", archivename_type, archivename_size);
178 217
179 if (type != LowPathType::Empty) { 218 if (archivename_type != FileSys::Empty) {
180 ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); 219 ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported");
181 cmd_buff[1] = -1; 220 cmd_buff[1] = -1;
182 return; 221 return;
183 } 222 }
184 223
185 std::string archive_name = GetStringFromCmdBuff(pointer, size); 224 Handle handle = Kernel::OpenArchive(archive_id);
186
187 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", type, size, archive_name.c_str());
188
189 Handle handle = Kernel::OpenArchive(arch_id);
190 if (handle) { 225 if (handle) {
191 cmd_buff[1] = 0; 226 cmd_buff[1] = 0;
192 // cmd_buff[2] isn't used according to 3dmoo's implementation. 227 // cmd_buff[2] isn't used according to 3dmoo's implementation.
193 cmd_buff[3] = handle; 228 cmd_buff[3] = handle;
194 } else { 229 } else {
195 ERROR_LOG(KERNEL, "failed to get a handle for archive %s", archive_name.c_str()); 230 ERROR_LOG(KERNEL, "failed to get a handle for archive");
196 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. 231 // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
197 cmd_buff[1] = -1; 232 cmd_buff[1] = -1;
198 } 233 }
@@ -200,6 +235,21 @@ void OpenArchive(Service::Interface* self) {
200 DEBUG_LOG(KERNEL, "called"); 235 DEBUG_LOG(KERNEL, "called");
201} 236}
202 237
238/*
239* FS_User::IsSdmcDetected service function
240* Outputs:
241* 1 : Result of function, 0 on success, otherwise error code
242* 2 : Whether the Sdmc could be detected
243*/
244void IsSdmcDetected(Service::Interface* self) {
245 u32* cmd_buff = Service::GetCommandBuffer();
246
247 cmd_buff[1] = 0;
248 cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0;
249
250 DEBUG_LOG(KERNEL, "called");
251}
252
203const Interface::FunctionInfo FunctionTable[] = { 253const Interface::FunctionInfo FunctionTable[] = {
204 {0x000100C6, nullptr, "Dummy1"}, 254 {0x000100C6, nullptr, "Dummy1"},
205 {0x040100C4, nullptr, "Control"}, 255 {0x040100C4, nullptr, "Control"},
@@ -211,7 +261,7 @@ const Interface::FunctionInfo FunctionTable[] = {
211 {0x08060142, nullptr, "DeleteDirectory"}, 261 {0x08060142, nullptr, "DeleteDirectory"},
212 {0x08070142, nullptr, "DeleteDirectoryRecursively"}, 262 {0x08070142, nullptr, "DeleteDirectoryRecursively"},
213 {0x08080202, nullptr, "CreateFile"}, 263 {0x08080202, nullptr, "CreateFile"},
214 {0x08090182, nullptr, "CreateDirectory"}, 264 {0x08090182, CreateDirectory, "CreateDirectory"},
215 {0x080A0244, nullptr, "RenameDirectory"}, 265 {0x080A0244, nullptr, "RenameDirectory"},
216 {0x080B0102, OpenDirectory, "OpenDirectory"}, 266 {0x080B0102, OpenDirectory, "OpenDirectory"},
217 {0x080C00C2, OpenArchive, "OpenArchive"}, 267 {0x080C00C2, OpenArchive, "OpenArchive"},
@@ -225,7 +275,7 @@ const Interface::FunctionInfo FunctionTable[] = {
225 {0x08140000, nullptr, "GetSdmcArchiveResource"}, 275 {0x08140000, nullptr, "GetSdmcArchiveResource"},
226 {0x08150000, nullptr, "GetNandArchiveResource"}, 276 {0x08150000, nullptr, "GetNandArchiveResource"},
227 {0x08160000, nullptr, "GetSdmcFatfsErro"}, 277 {0x08160000, nullptr, "GetSdmcFatfsErro"},
228 {0x08170000, nullptr, "IsSdmcDetected"}, 278 {0x08170000, IsSdmcDetected, "IsSdmcDetected"},
229 {0x08180000, nullptr, "IsSdmcWritable"}, 279 {0x08180000, nullptr, "IsSdmcWritable"},
230 {0x08190042, nullptr, "GetSdmcCid"}, 280 {0x08190042, nullptr, "GetSdmcCid"},
231 {0x081A0042, nullptr, "GetNandCid"}, 281 {0x081A0042, nullptr, "GetNandCid"},
diff --git a/src/core/hle/service/fs.h b/src/core/hle/service/fs_user.h
index 36f3697d3..005382540 100644
--- a/src/core/hle/service/fs.h
+++ b/src/core/hle/service/fs_user.h
@@ -23,7 +23,7 @@ public:
23 * Gets the string port name used by CTROS for the service 23 * Gets the string port name used by CTROS for the service
24 * @return Port name of service 24 * @return Port name of service
25 */ 25 */
26 std::string GetPortName() const { 26 std::string GetPortName() const override {
27 return "fs:USER"; 27 return "fs:USER";
28 } 28 }
29}; 29};
diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp_gpu.cpp
index 614d9584d..6119e6300 100644
--- a/src/core/hle/service/gsp.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -9,7 +9,7 @@
9#include "core/mem_map.h" 9#include "core/mem_map.h"
10#include "core/hle/kernel/event.h" 10#include "core/hle/kernel/event.h"
11#include "core/hle/kernel/shared_memory.h" 11#include "core/hle/kernel/shared_memory.h"
12#include "core/hle/service/gsp.h" 12#include "gsp_gpu.h"
13#include "core/hw/gpu.h" 13#include "core/hw/gpu.h"
14 14
15#include "video_core/gpu_debugger.h" 15#include "video_core/gpu_debugger.h"
diff --git a/src/core/hle/service/gsp.h b/src/core/hle/service/gsp_gpu.h
index a09d59dbb..177ce8da6 100644
--- a/src/core/hle/service/gsp.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -167,7 +167,7 @@ public:
167 * Gets the string port name used by CTROS for the service 167 * Gets the string port name used by CTROS for the service
168 * @return Port name of service 168 * @return Port name of service
169 */ 169 */
170 std::string GetPortName() const { 170 std::string GetPortName() const override {
171 return "gsp::Gpu"; 171 return "gsp::Gpu";
172 } 172 }
173 173
diff --git a/src/core/hle/service/hid.cpp b/src/core/hle/service/hid_user.cpp
index b6ec1b8ff..0eb32ba4a 100644
--- a/src/core/hle/service/hid.cpp
+++ b/src/core/hle/service/hid_user.cpp
@@ -7,7 +7,7 @@
7#include "core/hle/hle.h" 7#include "core/hle/hle.h"
8#include "core/hle/kernel/event.h" 8#include "core/hle/kernel/event.h"
9#include "core/hle/kernel/shared_memory.h" 9#include "core/hle/kernel/shared_memory.h"
10#include "core/hle/service/hid.h" 10#include "hid_user.h"
11 11
12//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
13// Namespace HID_User 13// Namespace HID_User
@@ -78,6 +78,10 @@ void PadButtonRelease(PadState pad_state) {
78void PadUpdateComplete() { 78void PadUpdateComplete() {
79 PadData* pad_data = GetPadData(); 79 PadData* pad_data = GetPadData();
80 80
81 if (pad_data == nullptr) {
82 return;
83 }
84
81 // Update PadData struct 85 // Update PadData struct
82 pad_data->current_state.hex = next_state.hex; 86 pad_data->current_state.hex = next_state.hex;
83 pad_data->index = next_index; 87 pad_data->index = next_index;
diff --git a/src/core/hle/service/hid.h b/src/core/hle/service/hid_user.h
index a077e25cd..9f6c4d5ed 100644
--- a/src/core/hle/service/hid.h
+++ b/src/core/hle/service/hid_user.h
@@ -111,7 +111,7 @@ public:
111 * Gets the string port name used by CTROS for the service 111 * Gets the string port name used by CTROS for the service
112 * @return Port name of service 112 * @return Port name of service
113 */ 113 */
114 std::string GetPortName() const { 114 std::string GetPortName() const override {
115 return "hid:USER"; 115 return "hid:USER";
116 } 116 }
117 117
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
new file mode 100644
index 000000000..58051f133
--- /dev/null
+++ b/src/core/hle/service/mic_u.cpp
@@ -0,0 +1,43 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/mic_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace MIC_U
11
12namespace MIC_U {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010042, nullptr, "MapSharedMem"},
16 {0x00020000, nullptr, "UnmapSharedMem"},
17 {0x00030140, nullptr, "Initialize"},
18 {0x00040040, nullptr, "AdjustSampling"},
19 {0x00050000, nullptr, "StopSampling"},
20 {0x00060000, nullptr, "IsSampling"},
21 {0x00070000, nullptr, "GetEventHandle"},
22 {0x00080040, nullptr, "SetControl"},
23 {0x00090000, nullptr, "GetControl"},
24 {0x000A0040, nullptr, "SetBias"},
25 {0x000B0000, nullptr, "GetBias"},
26 {0x000C0042, nullptr, "size"},
27 {0x000D0040, nullptr, "SetClamp"},
28 {0x000E0000, nullptr, "GetClamp"},
29 {0x000F0040, nullptr, "unknown_input1"},
30 {0x00100040, nullptr, "unknown_input2"},
31};
32
33////////////////////////////////////////////////////////////////////////////////////////////////////
34// Interface class
35
36Interface::Interface() {
37 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
38}
39
40Interface::~Interface() {
41}
42
43} // namespace
diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h
new file mode 100644
index 000000000..72ba048ef
--- /dev/null
+++ b/src/core/hle/service/mic_u.h
@@ -0,0 +1,29 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace MIC_U
11
12// mic service
13
14namespace MIC_U {
15
16class Interface : public Service::Interface {
17public:
18 Interface();
19 ~Interface();
20 /**
21 * Gets the string port name used by CTROS for the service
22 * @return Port name of service
23 */
24 std::string GetPortName() const {
25 return "mic:u";
26 }
27};
28
29} // namespace
diff --git a/src/core/hle/service/ndm.cpp b/src/core/hle/service/ndm_u.cpp
index f6af0a153..37c0661bf 100644
--- a/src/core/hle/service/ndm.cpp
+++ b/src/core/hle/service/ndm_u.cpp
@@ -3,7 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/hle.h" 5#include "core/hle/hle.h"
6#include "core/hle/service/ndm.h" 6#include "ndm_u.h"
7 7
8//////////////////////////////////////////////////////////////////////////////////////////////////// 8////////////////////////////////////////////////////////////////////////////////////////////////////
9// Namespace NDM_U 9// Namespace NDM_U
diff --git a/src/core/hle/service/ndm.h b/src/core/hle/service/ndm_u.h
index d5ec28f5b..2ca9fcf22 100644
--- a/src/core/hle/service/ndm.h
+++ b/src/core/hle/service/ndm_u.h
@@ -24,7 +24,7 @@ public:
24 * Gets the string port name used by CTROS for the service 24 * Gets the string port name used by CTROS for the service
25 * @return Port name of service 25 * @return Port name of service
26 */ 26 */
27 std::string GetPortName() const { 27 std::string GetPortName() const override {
28 return "ndm:u"; 28 return "ndm:u";
29 } 29 }
30 30
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
new file mode 100644
index 000000000..14df86d85
--- /dev/null
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -0,0 +1,35 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/nwm_uds.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace NWM_UDS
11
12namespace NWM_UDS {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00030000, nullptr, "Shutdown"},
16 {0x000F0404, nullptr, "RecvBeaconBroadcastData"},
17 {0x00100042, nullptr, "SetBeaconAdditionalData"},
18 {0x001400C0, nullptr, "RecvBroadcastDataFrame"},
19 {0x001B0302, nullptr, "Initialize"},
20 {0x001D0044, nullptr, "BeginHostingNetwork"},
21 {0x001E0084, nullptr, "ConnectToNetwork"},
22 {0x001F0006, nullptr, "DecryptBeaconData"},
23};
24
25////////////////////////////////////////////////////////////////////////////////////////////////////
26// Interface class
27
28Interface::Interface() {
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
30}
31
32Interface::~Interface() {
33}
34
35} // namespace
diff --git a/src/core/hle/service/nwm_uds.h b/src/core/hle/service/nwm_uds.h
new file mode 100644
index 000000000..a956ca812
--- /dev/null
+++ b/src/core/hle/service/nwm_uds.h
@@ -0,0 +1,29 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace NWM_UDS
11
12// local-WLAN service
13
14namespace NWM_UDS {
15
16class Interface : public Service::Interface {
17public:
18 Interface();
19 ~Interface();
20 /**
21 * Gets the string port name used by CTROS for the service
22 * @return Port name of service
23 */
24 std::string GetPortName() const {
25 return "nwm:UDS";
26 }
27};
28
29} // namespace
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp
new file mode 100644
index 000000000..f6a14d509
--- /dev/null
+++ b/src/core/hle/service/ptm_u.cpp
@@ -0,0 +1,42 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/ptm_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace PTM_U
11
12namespace PTM_U {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010002, nullptr, "RegisterAlarmClient"},
16 {0x00020080, nullptr, "SetRtcAlarm"},
17 {0x00030000, nullptr, "GetRtcAlarm"},
18 {0x00040000, nullptr, "CancelRtcAlarm"},
19 {0x00050000, nullptr, "GetAdapterState"},
20 {0x00060000, nullptr, "GetShellState "},
21 {0x00070000, nullptr, "GetBatteryLevel"},
22 {0x00080000, nullptr, "GetBatteryChargeState"},
23 {0x00090000, nullptr, "GetPedometerState"},
24 {0x000A0042, nullptr, "GetStepHistoryEntry"},
25 {0x000B00C2, nullptr, "GetStepHistory "},
26 {0x000C0000, nullptr, "GetTotalStepCount "},
27 {0x000D0040, nullptr, "SetPedometerRecordingMode"},
28 {0x000E0000, nullptr, "GetPedometerRecordingMode"},
29 {0x000F0084, nullptr, "GetStepHistoryAll"},
30};
31
32////////////////////////////////////////////////////////////////////////////////////////////////////
33// Interface class
34
35Interface::Interface() {
36 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
37}
38
39Interface::~Interface() {
40}
41
42} // namespace
diff --git a/src/core/hle/service/ptm_u.h b/src/core/hle/service/ptm_u.h
new file mode 100644
index 000000000..82749fa39
--- /dev/null
+++ b/src/core/hle/service/ptm_u.h
@@ -0,0 +1,29 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace PTM_U
11
12// ptm service
13
14namespace PTM_U {
15
16class Interface : public Service::Interface {
17public:
18 Interface();
19 ~Interface();
20 /**
21 * Gets the string port name used by CTROS for the service
22 * @return Port name of service
23 */
24 std::string GetPortName() const {
25 return "ptm:u";
26 }
27};
28
29} // namespace
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 9eb1726aa..bb0f80e98 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -6,12 +6,22 @@
6#include "common/string_util.h" 6#include "common/string_util.h"
7 7
8#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
9#include "core/hle/service/apt.h" 9#include "core/hle/service/ac_u.h"
10#include "core/hle/service/fs.h" 10#include "core/hle/service/apt_u.h"
11#include "core/hle/service/gsp.h" 11#include "core/hle/service/cfg_u.h"
12#include "core/hle/service/hid.h" 12#include "core/hle/service/dsp_dsp.h"
13#include "core/hle/service/ndm.h" 13#include "core/hle/service/err_f.h"
14#include "core/hle/service/fs_user.h"
15#include "core/hle/service/frd_u.h"
16#include "core/hle/service/gsp_gpu.h"
17#include "core/hle/service/hid_user.h"
18#include "core/hle/service/mic_u.h"
19#include "core/hle/service/ndm_u.h"
20#include "core/hle/service/nwm_uds.h"
21#include "core/hle/service/ptm_u.h"
22#include "core/hle/service/soc_u.h"
14#include "core/hle/service/srv.h" 23#include "core/hle/service/srv.h"
24#include "core/hle/service/ssl_c.h"
15 25
16namespace Service { 26namespace Service {
17 27
@@ -66,11 +76,21 @@ void Init() {
66 g_manager = new Manager; 76 g_manager = new Manager;
67 77
68 g_manager->AddService(new SRV::Interface); 78 g_manager->AddService(new SRV::Interface);
79 g_manager->AddService(new AC_U::Interface);
69 g_manager->AddService(new APT_U::Interface); 80 g_manager->AddService(new APT_U::Interface);
81 g_manager->AddService(new CFG_U::Interface);
82 g_manager->AddService(new DSP_DSP::Interface);
83 g_manager->AddService(new ERR_F::Interface);
84 g_manager->AddService(new FRD_U::Interface);
70 g_manager->AddService(new FS_User::Interface); 85 g_manager->AddService(new FS_User::Interface);
71 g_manager->AddService(new GSP_GPU::Interface); 86 g_manager->AddService(new GSP_GPU::Interface);
72 g_manager->AddService(new HID_User::Interface); 87 g_manager->AddService(new HID_User::Interface);
88 g_manager->AddService(new MIC_U::Interface);
73 g_manager->AddService(new NDM_U::Interface); 89 g_manager->AddService(new NDM_U::Interface);
90 g_manager->AddService(new NWM_UDS::Interface);
91 g_manager->AddService(new PTM_U::Interface);
92 g_manager->AddService(new SOC_U::Interface);
93 g_manager->AddService(new SSL_C::Interface);
74 94
75 NOTICE_LOG(HLE, "initialized OK"); 95 NOTICE_LOG(HLE, "initialized OK");
76} 96}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index c0e803bda..2f5a866c9 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -39,11 +39,11 @@ class Interface : public Kernel::Object {
39 friend class Manager; 39 friend class Manager;
40public: 40public:
41 41
42 std::string GetName() const { return GetPortName(); } 42 std::string GetName() const override { return GetPortName(); }
43 std::string GetTypeName() const { return GetPortName(); } 43 std::string GetTypeName() const override { return GetPortName(); }
44 44
45 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; } 45 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; }
46 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Service; } 46 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Service; }
47 47
48 typedef void (*Function)(Interface*); 48 typedef void (*Function)(Interface*);
49 49
@@ -80,7 +80,7 @@ public:
80 * @param wait Boolean wait set if current thread should wait as a result of sync operation 80 * @param wait Boolean wait set if current thread should wait as a result of sync operation
81 * @return Result of operation, 0 on success, otherwise error code 81 * @return Result of operation, 0 on success, otherwise error code
82 */ 82 */
83 Result SyncRequest(bool* wait) { 83 Result SyncRequest(bool* wait) override {
84 u32* cmd_buff = GetCommandBuffer(); 84 u32* cmd_buff = GetCommandBuffer();
85 auto itr = m_functions.find(cmd_buff[0]); 85 auto itr = m_functions.find(cmd_buff[0]);
86 86
@@ -113,7 +113,7 @@ public:
113 * @param wait Boolean wait set if current thread should wait as a result of sync operation 113 * @param wait Boolean wait set if current thread should wait as a result of sync operation
114 * @return Result of operation, 0 on success, otherwise error code 114 * @return Result of operation, 0 on success, otherwise error code
115 */ 115 */
116 Result WaitSynchronization(bool* wait) { 116 Result WaitSynchronization(bool* wait) override {
117 // TODO(bunnei): ImplementMe 117 // TODO(bunnei): ImplementMe
118 ERROR_LOG(OSHLE, "unimplemented function"); 118 ERROR_LOG(OSHLE, "unimplemented function");
119 return 0; 119 return 0;
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
new file mode 100644
index 000000000..2f8910468
--- /dev/null
+++ b/src/core/hle/service/soc_u.cpp
@@ -0,0 +1,58 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/soc_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace SOC_U
11
12namespace SOC_U {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010044, nullptr, "InitializeSockets"},
16 {0x000200C2, nullptr, "socket"},
17 {0x00030082, nullptr, "listen"},
18 {0x00040082, nullptr, "accept"},
19 {0x00050084, nullptr, "bind"},
20 {0x00060084, nullptr, "connect"},
21 {0x00070104, nullptr, "recvfrom_other"},
22 {0x00080102, nullptr, "recvfrom"},
23 {0x00090106, nullptr, "sendto_other"},
24 {0x000A0106, nullptr, "sendto"},
25 {0x000B0042, nullptr, "close"},
26 {0x000C0082, nullptr, "shutdown"},
27 {0x000D0082, nullptr, "gethostbyname"},
28 {0x000E00C2, nullptr, "gethostbyaddr"},
29 {0x000F0106, nullptr, "unknown_resolve_ip"},
30 {0x00110102, nullptr, "getsockopt"},
31 {0x00120104, nullptr, "setsockopt"},
32 {0x001300C2, nullptr, "fcntl"},
33 {0x00140084, nullptr, "poll"},
34 {0x00150042, nullptr, "sockatmark"},
35 {0x00160000, nullptr, "gethostid"},
36 {0x00170082, nullptr, "getsockname"},
37 {0x00180082, nullptr, "getpeername"},
38 {0x00190000, nullptr, "ShutdownSockets"},
39 {0x001A00C0, nullptr, "GetNetworkOpt"},
40 {0x001B0040, nullptr, "ICMPSocket"},
41 {0x001C0104, nullptr, "ICMPPing"},
42 {0x001D0040, nullptr, "ICMPCancel"},
43 {0x001E0040, nullptr, "ICMPClose"},
44 {0x001F0040, nullptr, "GetResolverInfo"},
45 {0x00210002, nullptr, "CloseSockets"},
46};
47
48////////////////////////////////////////////////////////////////////////////////////////////////////
49// Interface class
50
51Interface::Interface() {
52 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
53}
54
55Interface::~Interface() {
56}
57
58} // namespace
diff --git a/src/core/hle/service/soc_u.h b/src/core/hle/service/soc_u.h
new file mode 100644
index 000000000..e27a2b1fe
--- /dev/null
+++ b/src/core/hle/service/soc_u.h
@@ -0,0 +1,27 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace SOC_U
11
12namespace SOC_U {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17 ~Interface();
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const {
23 return "soc:U";
24 }
25};
26
27} // namespace
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index eb2c73f93..6c02a43d9 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -57,6 +57,8 @@ const Interface::FunctionInfo FunctionTable[] = {
57 {0x00030100, nullptr, "RegisterService"}, 57 {0x00030100, nullptr, "RegisterService"},
58 {0x000400C0, nullptr, "UnregisterService"}, 58 {0x000400C0, nullptr, "UnregisterService"},
59 {0x00050100, GetServiceHandle, "GetServiceHandle"}, 59 {0x00050100, GetServiceHandle, "GetServiceHandle"},
60 {0x000B0000, nullptr, "ReceiveNotification"},
61 {0x000C0080, nullptr, "PublishToSubscriber"}
60}; 62};
61 63
62//////////////////////////////////////////////////////////////////////////////////////////////////// 64////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h
index 9451472de..6d5fe5048 100644
--- a/src/core/hle/service/srv.h
+++ b/src/core/hle/service/srv.h
@@ -22,7 +22,7 @@ public:
22 * Gets the string name used by CTROS for the service 22 * Gets the string name used by CTROS for the service
23 * @return Port name of service 23 * @return Port name of service
24 */ 24 */
25 std::string GetPortName() const { 25 std::string GetPortName() const override {
26 return "srv:"; 26 return "srv:";
27 } 27 }
28 28
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
new file mode 100644
index 000000000..4aa660ecc
--- /dev/null
+++ b/src/core/hle/service/ssl_c.cpp
@@ -0,0 +1,31 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/ssl_c.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace SSL_C
11
12namespace SSL_C {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x000200C2, nullptr, "CreateContext"},
16 {0x00050082, nullptr, "AddTrustedRootCA"},
17 {0x00150082, nullptr, "Read"},
18 {0x00170082, nullptr, "Write"},
19};
20
21////////////////////////////////////////////////////////////////////////////////////////////////////
22// Interface class
23
24Interface::Interface() {
25 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
26}
27
28Interface::~Interface() {
29}
30
31} // namespace
diff --git a/src/core/hle/service/ssl_c.h b/src/core/hle/service/ssl_c.h
new file mode 100644
index 000000000..7b4e7fd8a
--- /dev/null
+++ b/src/core/hle/service/ssl_c.h
@@ -0,0 +1,27 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace SSL_C
11
12namespace SSL_C {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17 ~Interface();
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const {
23 return "ssl:C";
24 }
25};
26
27} // namespace
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 490e05cde..1eda36c53 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -115,7 +115,7 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
115 115
116 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); 116 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
117 117
118 DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%d", handle, object->GetTypeName().c_str(), 118 DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(),
119 object->GetName().c_str(), nano_seconds); 119 object->GetName().c_str(), nano_seconds);
120 120
121 _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); 121 _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!");
@@ -138,7 +138,7 @@ Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wa
138 bool unlock_all = true; 138 bool unlock_all = true;
139 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated 139 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
140 140
141 DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%d", 141 DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld",
142 handle_count, (wait_all ? "true" : "false"), nano_seconds); 142 handle_count, (wait_all ? "true" : "false"), nano_seconds);
143 143
144 // Iterate through each handle, synchronize kernel object 144 // Iterate through each handle, synchronize kernel object
@@ -324,7 +324,7 @@ Result ClearEvent(Handle evt) {
324 324
325/// Sleep the current thread 325/// Sleep the current thread
326void SleepThread(s64 nanoseconds) { 326void SleepThread(s64 nanoseconds) {
327 DEBUG_LOG(SVC, "called nanoseconds=%d", nanoseconds); 327 DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds);
328} 328}
329 329
330/// This returns the total CPU ticks elapsed since the CPU was powered-on 330/// This returns the total CPU ticks elapsed since the CPU was powered-on
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 33a0e0fe7..3ad801c63 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -4,11 +4,12 @@
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
6 6
7#include "core/settings.h"
7#include "core/core.h" 8#include "core/core.h"
8#include "core/mem_map.h" 9#include "core/mem_map.h"
9 10
10#include "core/hle/hle.h" 11#include "core/hle/hle.h"
11#include "core/hle/service/gsp.h" 12#include "core/hle/service/gsp_gpu.h"
12 13
13#include "core/hw/gpu.h" 14#include "core/hw/gpu.h"
14 15
@@ -24,6 +25,9 @@ u32 g_cur_line = 0; ///< Current vertical screen line
24u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line 25u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line
25u64 g_last_frame_ticks = 0; ///< CPU tick count from last frame 26u64 g_last_frame_ticks = 0; ///< CPU tick count from last frame
26 27
28static u32 kFrameCycles = 0; ///< 268MHz / 60 frames per second
29static u32 kFrameTicks = 0; ///< Approximate number of instructions/frame
30
27template <typename T> 31template <typename T>
28inline void Read(T &var, const u32 raw_addr) { 32inline void Read(T &var, const u32 raw_addr) {
29 u32 addr = raw_addr - 0x1EF00000; 33 u32 addr = raw_addr - 0x1EF00000;
@@ -31,7 +35,7 @@ inline void Read(T &var, const u32 raw_addr) {
31 35
32 // Reads other than u32 are untested, so I'd rather have them abort than silently fail 36 // Reads other than u32 are untested, so I'd rather have them abort than silently fail
33 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { 37 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) {
34 ERROR_LOG(GPU, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr); 38 ERROR_LOG(GPU, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr);
35 return; 39 return;
36 } 40 }
37 41
@@ -45,7 +49,7 @@ inline void Write(u32 addr, const T data) {
45 49
46 // Writes other than u32 are untested, so I'd rather have them abort than silently fail 50 // Writes other than u32 are untested, so I'd rather have them abort than silently fail
47 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { 51 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) {
48 ERROR_LOG(GPU, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); 52 ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
49 return; 53 return;
50 } 54 }
51 55
@@ -214,6 +218,9 @@ void Update() {
214 218
215/// Initialize hardware 219/// Initialize hardware
216void Init() { 220void Init() {
221 kFrameCycles = 268123480 / Settings::values.gpu_refresh_rate;
222 kFrameTicks = kFrameCycles / 3;
223
217 g_cur_line = 0; 224 g_cur_line = 0;
218 g_last_frame_ticks = g_last_line_ticks = Core::g_app_core->GetTicks(); 225 g_last_frame_ticks = g_last_line_ticks = Core::g_app_core->GetTicks();
219 226
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index 92097d182..3fa7b9ccf 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -11,9 +11,6 @@
11 11
12namespace GPU { 12namespace GPU {
13 13
14static const u32 kFrameCycles = 268123480 / 60; ///< 268MHz / 60 frames per second
15static const u32 kFrameTicks = kFrameCycles / 3; ///< Approximate number of instructions/frame
16
17// Returns index corresponding to the Regs member labeled by field_name 14// Returns index corresponding to the Regs member labeled by field_name
18// TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions 15// TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions
19// when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])). 16// when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])).
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index efd94f147..33f75c50a 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -50,7 +50,7 @@ inline void Read(T &var, const u32 addr) {
50 break; 50 break;
51 51
52 default: 52 default:
53 ERROR_LOG(HW, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr); 53 ERROR_LOG(HW, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr);
54 } 54 }
55} 55}
56 56
@@ -68,7 +68,7 @@ inline void Write(u32 addr, const T data) {
68 break; 68 break;
69 69
70 default: 70 default:
71 ERROR_LOG(HW, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); 71 ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
72 } 72 }
73} 73}
74 74
diff --git a/src/core/hw/ndma.cpp b/src/core/hw/ndma.cpp
index 158241fd6..e29a773f1 100644
--- a/src/core/hw/ndma.cpp
+++ b/src/core/hw/ndma.cpp
@@ -10,12 +10,12 @@ namespace NDMA {
10 10
11template <typename T> 11template <typename T>
12inline void Read(T &var, const u32 addr) { 12inline void Read(T &var, const u32 addr) {
13 ERROR_LOG(NDMA, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr); 13 ERROR_LOG(NDMA, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr);
14} 14}
15 15
16template <typename T> 16template <typename T>
17inline void Write(u32 addr, const T data) { 17inline void Write(u32 addr, const T data) {
18 ERROR_LOG(NDMA, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); 18 ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
19} 19}
20 20
21// Explicitly instantiate template functions because we aren't defining this in the header: 21// Explicitly instantiate template functions because we aren't defining this in the header:
diff --git a/src/core/settings.h b/src/core/settings.h
index 77b2f02fc..7e7a66b89 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -7,6 +7,7 @@
7namespace Settings { 7namespace Settings {
8 8
9struct Values { 9struct Values {
10 // Controls
10 int pad_a_key; 11 int pad_a_key;
11 int pad_b_key; 12 int pad_b_key;
12 int pad_x_key; 13 int pad_x_key;
@@ -25,6 +26,11 @@ struct Values {
25 int pad_sleft_key; 26 int pad_sleft_key;
26 int pad_sright_key; 27 int pad_sright_key;
27 28
29 // Core
30 int cpu_core;
31 int gpu_refresh_rate;
32
33 // Data Storage
28 bool use_virtual_sd; 34 bool use_virtual_sd;
29 35
30 bool enable_log; 36 bool enable_log;
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp
index 2cf166afd..fbe4047ce 100644
--- a/src/video_core/clipper.cpp
+++ b/src/video_core/clipper.cpp
@@ -158,11 +158,11 @@ void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
158 InitScreenCoordinates(vtx2); 158 InitScreenCoordinates(vtx2);
159 159
160 DEBUG_LOG(GPU, 160 DEBUG_LOG(GPU,
161 "Triangle %u/%u (%u buffer vertices) at position (%.3f, %.3f, %.3f, %.3f), " 161 "Triangle %lu/%lu (%lu buffer vertices) at position (%.3f, %.3f, %.3f, %.3f), "
162 "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and " 162 "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and "
163 "screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)", 163 "screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)",
164 i,output_list.size(), buffer_vertices.size(), 164 i,output_list.size(), buffer_vertices.size(),
165 vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(),output_list.size(), 165 vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(),
166 vtx1.pos.x.ToFloat32(), vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(), 166 vtx1.pos.x.ToFloat32(), vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(),
167 vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), vtx2.pos.w.ToFloat32(), 167 vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), vtx2.pos.w.ToFloat32(),
168 vtx0.screenpos.x.ToFloat32(), vtx0.screenpos.y.ToFloat32(), vtx0.screenpos.z.ToFloat32(), 168 vtx0.screenpos.x.ToFloat32(), vtx0.screenpos.y.ToFloat32(), vtx0.screenpos.z.ToFloat32(),
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index a9510fa2e..1ec727698 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -102,7 +102,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
102 (vertex_attribute_formats[i] == 2) ? *(s16*)srcdata : 102 (vertex_attribute_formats[i] == 2) ? *(s16*)srcdata :
103 *(float*)srcdata; 103 *(float*)srcdata;
104 input.attr[i][comp] = float24::FromFloat32(srcval); 104 input.attr[i][comp] = float24::FromFloat32(srcval);
105 DEBUG_LOG(GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08x + 0x%04x: %f", 105 DEBUG_LOG(GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f",
106 comp, i, vertex, index, 106 comp, i, vertex, index,
107 attribute_config.GetBaseAddress(), 107 attribute_config.GetBaseAddress(),
108 vertex_attribute_sources[i] - base_address, 108 vertex_attribute_sources[i] - base_address,
diff --git a/src/video_core/gpu_debugger.h b/src/video_core/gpu_debugger.h
index 5a81fcfcb..1242eb58f 100644
--- a/src/video_core/gpu_debugger.h
+++ b/src/video_core/gpu_debugger.h
@@ -10,7 +10,7 @@
10 10
11#include "common/log.h" 11#include "common/log.h"
12 12
13#include "core/hle/service/gsp.h" 13#include "core/hle/service/gsp_gpu.h"
14 14
15#include "command_processor.h" 15#include "command_processor.h"
16#include "pica.h" 16#include "pica.h"
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 82ef4b14b..eed201a95 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -21,19 +21,19 @@ public:
21 ~RendererOpenGL() override; 21 ~RendererOpenGL() override;
22 22
23 /// Swap buffers (render frame) 23 /// Swap buffers (render frame)
24 void SwapBuffers(); 24 void SwapBuffers() override;
25 25
26 /** 26 /**
27 * Set the emulator window to use for renderer 27 * Set the emulator window to use for renderer
28 * @param window EmuWindow handle to emulator window to use for rendering 28 * @param window EmuWindow handle to emulator window to use for rendering
29 */ 29 */
30 void SetWindow(EmuWindow* window); 30 void SetWindow(EmuWindow* window) override;
31 31
32 /// Initialize the renderer 32 /// Initialize the renderer
33 void Init(); 33 void Init() override;
34 34
35 /// Shutdown the renderer 35 /// Shutdown the renderer
36 void ShutDown(); 36 void ShutDown() override;
37 37
38private: 38private:
39 /// Structure used for storing information about the textures for each 3DS screen 39 /// Structure used for storing information about the textures for each 3DS screen