summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra/config.cpp1
-rw-r--r--src/citra/default_ini.h1
-rw-r--r--src/citra_qt/config.cpp2
-rw-r--r--src/citra_qt/debugger/disassembler.cpp9
-rw-r--r--src/citra_qt/debugger/disassembler.h9
-rw-r--r--src/citra_qt/debugger/disassembler.ui117
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.cpp4
-rw-r--r--src/citra_qt/util/spinbox.cpp2
-rw-r--r--src/common/logging/log.h2
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/arm/arm_interface.h9
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp19
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h57
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp107
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp14
-rw-r--r--src/core/arm/interpreter/arm_interpreter.cpp114
-rw-r--r--src/core/arm/interpreter/arm_interpreter.h96
-rw-r--r--src/core/arm/interpreter/armcopro.cpp257
-rw-r--r--src/core/arm/interpreter/armemu.cpp5648
-rw-r--r--src/core/arm/interpreter/arminit.cpp179
-rw-r--r--src/core/arm/interpreter/armsupp.cpp881
-rw-r--r--src/core/arm/interpreter/armvirt.cpp165
-rw-r--r--src/core/arm/interpreter/thumbemu.cpp513
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h4
-rw-r--r--src/core/arm/skyeye_common/armdefs.h344
-rw-r--r--src/core/arm/skyeye_common/armemu.h556
-rw-r--r--src/core/arm/skyeye_common/vfp/asm_vfp.h141
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp241
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h112
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h705
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp202
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp1733
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp57
-rw-r--r--src/core/core.cpp14
-rw-r--r--src/core/core.h6
-rw-r--r--src/core/file_sys/archive_backend.h39
-rw-r--r--src/core/file_sys/archive_extsavedata.cpp15
-rw-r--r--src/core/file_sys/archive_extsavedata.h21
-rw-r--r--src/core/file_sys/archive_romfs.cpp17
-rw-r--r--src/core/file_sys/archive_romfs.h11
-rw-r--r--src/core/file_sys/archive_savedata.cpp23
-rw-r--r--src/core/file_sys/archive_savedata.h17
-rw-r--r--src/core/file_sys/archive_savedatacheck.cpp28
-rw-r--r--src/core/file_sys/archive_savedatacheck.h8
-rw-r--r--src/core/file_sys/archive_sdmc.cpp17
-rw-r--r--src/core/file_sys/archive_sdmc.h10
-rw-r--r--src/core/file_sys/disk_archive.cpp26
-rw-r--r--src/core/file_sys/disk_archive.h25
-rw-r--r--src/core/file_sys/ivfc_archive.cpp22
-rw-r--r--src/core/file_sys/ivfc_archive.h13
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp13
-rw-r--r--src/core/hle/kernel/address_arbiter.h5
-rw-r--r--src/core/hle/kernel/event.cpp9
-rw-r--r--src/core/hle/kernel/event.h5
-rw-r--r--src/core/hle/kernel/kernel.cpp24
-rw-r--r--src/core/hle/kernel/kernel.h21
-rw-r--r--src/core/hle/kernel/mutex.cpp64
-rw-r--r--src/core/hle/kernel/mutex.h10
-rw-r--r--src/core/hle/kernel/semaphore.cpp5
-rw-r--r--src/core/hle/kernel/semaphore.h3
-rw-r--r--src/core/hle/kernel/session.cpp13
-rw-r--r--src/core/hle/kernel/session.h4
-rw-r--r--src/core/hle/kernel/shared_memory.cpp23
-rw-r--r--src/core/hle/kernel/shared_memory.h7
-rw-r--r--src/core/hle/kernel/thread.cpp407
-rw-r--r--src/core/hle/kernel/thread.h142
-rw-r--r--src/core/hle/kernel/timer.cpp28
-rw-r--r--src/core/hle/kernel/timer.h8
-rw-r--r--src/core/hle/result.h6
-rw-r--r--src/core/hle/service/ac_u.cpp2
-rw-r--r--src/core/hle/service/act_u.cpp2
-rw-r--r--src/core/hle/service/am_app.cpp2
-rw-r--r--src/core/hle/service/am_net.cpp2
-rw-r--r--src/core/hle/service/am_sys.cpp2
-rw-r--r--src/core/hle/service/apt_a.cpp2
-rw-r--r--src/core/hle/service/apt_s.cpp2
-rw-r--r--src/core/hle/service/apt_u.cpp10
-rw-r--r--src/core/hle/service/boss_p.cpp2
-rw-r--r--src/core/hle/service/boss_u.cpp2
-rw-r--r--src/core/hle/service/cam_u.cpp2
-rw-r--r--src/core/hle/service/cecd_s.cpp2
-rw-r--r--src/core/hle/service/cecd_u.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg_s.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp2
-rw-r--r--src/core/hle/service/csnd_snd.cpp2
-rw-r--r--src/core/hle/service/dsp_dsp.cpp5
-rw-r--r--src/core/hle/service/err_f.cpp2
-rw-r--r--src/core/hle/service/frd_a.cpp2
-rw-r--r--src/core/hle/service/frd_u.cpp2
-rw-r--r--src/core/hle/service/fs/archive.cpp209
-rw-r--r--src/core/hle/service/fs/archive.h55
-rw-r--r--src/core/hle/service/fs/fs_user.cpp33
-rw-r--r--src/core/hle/service/gsp_gpu.cpp4
-rw-r--r--src/core/hle/service/gsp_lcd.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp14
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp2
-rw-r--r--src/core/hle/service/hid/hid_user.cpp2
-rw-r--r--src/core/hle/service/http_c.cpp2
-rw-r--r--src/core/hle/service/ir_rst.cpp2
-rw-r--r--src/core/hle/service/ir_u.cpp2
-rw-r--r--src/core/hle/service/ldr_ro.cpp2
-rw-r--r--src/core/hle/service/mic_u.cpp2
-rw-r--r--src/core/hle/service/ndm_u.cpp2
-rw-r--r--src/core/hle/service/news_s.cpp2
-rw-r--r--src/core/hle/service/news_u.cpp2
-rw-r--r--src/core/hle/service/nim_aoc.cpp2
-rw-r--r--src/core/hle/service/ns_s.cpp2
-rw-r--r--src/core/hle/service/nwm_uds.cpp2
-rw-r--r--src/core/hle/service/pm_app.cpp2
-rw-r--r--src/core/hle/service/ptm_play.cpp2
-rw-r--r--src/core/hle/service/ptm_sysm.cpp2
-rw-r--r--src/core/hle/service/ptm_u.cpp37
-rw-r--r--src/core/hle/service/service.cpp130
-rw-r--r--src/core/hle/service/service.h73
-rw-r--r--src/core/hle/service/soc_u.cpp2
-rw-r--r--src/core/hle/service/srv.cpp10
-rw-r--r--src/core/hle/service/ssl_c.cpp2
-rw-r--r--src/core/hle/service/y2r_u.cpp2
-rw-r--r--src/core/hle/svc.cpp80
-rw-r--r--src/core/hw/gpu.cpp2
-rw-r--r--src/core/loader/elf.cpp4
-rw-r--r--src/core/loader/loader.cpp2
-rw-r--r--src/core/loader/loader.h2
-rw-r--r--src/core/settings.h1
-rw-r--r--src/video_core/math.h51
-rw-r--r--src/video_core/pica.h63
-rw-r--r--src/video_core/rasterizer.cpp192
128 files changed, 2013 insertions, 12458 deletions
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 50ed468d7..f5b4069c7 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -57,7 +57,6 @@ void Config::ReadValues() {
57 Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); 57 Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT);
58 58
59 // Core 59 // Core
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", 30); 60 Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 30);
62 Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0); 61 Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0);
63 62
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 005f3de23..be4b289bd 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -27,7 +27,6 @@ pad_sleft =
27pad_sright = 27pad_sright =
28 28
29[Core] 29[Core]
30cpu_core = ## 0: Interpreter (default), 1: OldInterpreter (may work better, soon to be deprecated)
31gpu_refresh_rate = ## 30 (default) 30gpu_refresh_rate = ## 30 (default)
32frame_skip = ## 0: No frameskip (default), 1 : 2x frameskip, 2 : 4x frameskip, etc. 31frame_skip = ## 0: No frameskip (default), 1 : 2x frameskip, 2 : 4x frameskip, etc.
33 32
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index b0ff5a37e..76aeaedd0 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -43,7 +43,6 @@ void Config::ReadValues() {
43 qt_config->endGroup(); 43 qt_config->endGroup();
44 44
45 qt_config->beginGroup("Core"); 45 qt_config->beginGroup("Core");
46 Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt();
47 Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 30).toInt(); 46 Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 30).toInt();
48 Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt(); 47 Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt();
49 qt_config->endGroup(); 48 qt_config->endGroup();
@@ -83,7 +82,6 @@ void Config::SaveValues() {
83 qt_config->endGroup(); 82 qt_config->endGroup();
84 83
85 qt_config->beginGroup("Core"); 84 qt_config->beginGroup("Core");
86 qt_config->setValue("cpu_core", Settings::values.cpu_core);
87 qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate); 85 qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate);
88 qt_config->setValue("frame_skip", Settings::values.frame_skip); 86 qt_config->setValue("frame_skip", Settings::values.frame_skip);
89 qt_config->endGroup(); 87 qt_config->endGroup();
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index c61ace925..54d21dc90 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -17,16 +17,9 @@
17#include "core/arm/skyeye_common/armdefs.h" 17#include "core/arm/skyeye_common/armdefs.h"
18#include "core/arm/disassembler/arm_disasm.h" 18#include "core/arm/disassembler/arm_disasm.h"
19 19
20DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractItemModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) {
21 20
22} 21DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) {
23
24QModelIndex DisassemblerModel::index(int row, int column, const QModelIndex& parent) const {
25 return createIndex(row, column);
26}
27 22
28QModelIndex DisassemblerModel::parent(const QModelIndex& child) const {
29 return QModelIndex();
30} 23}
31 24
32int DisassemblerModel::columnCount(const QModelIndex& parent) const { 25int DisassemblerModel::columnCount(const QModelIndex& parent) const {
diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h
index 0deccc240..5e19d7c51 100644
--- a/src/citra_qt/debugger/disassembler.h
+++ b/src/citra_qt/debugger/disassembler.h
@@ -2,8 +2,11 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QAbstractItemModel> 5#pragma once
6
7#include <QAbstractListModel>
6#include <QDockWidget> 8#include <QDockWidget>
9
7#include "ui_disassembler.h" 10#include "ui_disassembler.h"
8 11
9#include "common/common.h" 12#include "common/common.h"
@@ -12,15 +15,13 @@
12class QAction; 15class QAction;
13class EmuThread; 16class EmuThread;
14 17
15class DisassemblerModel : public QAbstractItemModel 18class DisassemblerModel : public QAbstractListModel
16{ 19{
17 Q_OBJECT 20 Q_OBJECT
18 21
19public: 22public:
20 DisassemblerModel(QObject* parent); 23 DisassemblerModel(QObject* parent);
21 24
22 QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
23 QModelIndex parent(const QModelIndex& child) const override;
24 int columnCount(const QModelIndex& parent = QModelIndex()) const override; 25 int columnCount(const QModelIndex& parent = QModelIndex()) const override;
25 int rowCount(const QModelIndex& parent = QModelIndex()) const override; 26 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
26 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; 27 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
diff --git a/src/citra_qt/debugger/disassembler.ui b/src/citra_qt/debugger/disassembler.ui
index bd0752aa4..5ca6dc5d2 100644
--- a/src/citra_qt/debugger/disassembler.ui
+++ b/src/citra_qt/debugger/disassembler.ui
@@ -13,63 +13,66 @@
13 <property name="windowTitle"> 13 <property name="windowTitle">
14 <string>Disassembly</string> 14 <string>Disassembly</string>
15 </property> 15 </property>
16 <widget class="QWidget" name="dockWidgetContents"> 16 <widget class="QWidget" name="dockWidgetContents">
17 <layout class="QVBoxLayout" name="verticalLayout"> 17 <layout class="QVBoxLayout" name="verticalLayout">
18 <item> 18 <item>
19 <layout class="QHBoxLayout" name="horizontalLayout"> 19 <layout class="QHBoxLayout" name="horizontalLayout">
20 <item> 20 <item>
21 <widget class="QPushButton" name="button_step"> 21 <widget class="QPushButton" name="button_step">
22 <property name="text"> 22 <property name="text">
23 <string>Step</string> 23 <string>Step</string>
24 </property> 24 </property>
25 </widget> 25 </widget>
26 </item> 26 </item>
27 <item> 27 <item>
28 <widget class="QPushButton" name="button_pause"> 28 <widget class="QPushButton" name="button_pause">
29 <property name="text"> 29 <property name="text">
30 <string>Pause</string> 30 <string>Pause</string>
31 </property> 31 </property>
32 </widget> 32 </widget>
33 </item> 33 </item>
34 <item> 34 <item>
35 <widget class="QPushButton" name="button_continue"> 35 <widget class="QPushButton" name="button_continue">
36 <property name="text"> 36 <property name="text">
37 <string>Continue</string> 37 <string>Continue</string>
38 </property> 38 </property>
39 </widget> 39 </widget>
40 </item> 40 </item>
41 <item> 41 <item>
42 <widget class="QPushButton" name="pushButton"> 42 <widget class="QPushButton" name="pushButton">
43 <property name="text"> 43 <property name="text">
44 <string>Step Into</string> 44 <string>Step Into</string>
45 </property> 45 </property>
46 </widget> 46 </widget>
47 </item> 47 </item>
48 <item> 48 <item>
49 <widget class="QPushButton" name="button_breakpoint"> 49 <widget class="QPushButton" name="button_breakpoint">
50 <property name="text"> 50 <property name="text">
51 <string>Set Breakpoint</string> 51 <string>Set Breakpoint</string>
52 </property> 52 </property>
53 </widget> 53 </widget>
54 </item> 54 </item>
55 </layout> 55 </layout>
56 </item> 56 </item>
57 <item> 57 <item>
58 <widget class="QTreeView" name="treeView"> 58 <widget class="QTreeView" name="treeView">
59 <property name="alternatingRowColors"> 59 <property name="alternatingRowColors">
60 <bool>true</bool> 60 <bool>true</bool>
61 </property> 61 </property>
62 <property name="indentation"> 62 <property name="indentation">
63 <number>20</number> 63 <number>20</number>
64 </property> 64 </property>
65 <property name="rootIsDecorated"> 65 <property name="rootIsDecorated">
66 <bool>false</bool> 66 <bool>false</bool>
67 </property> 67 </property>
68 <attribute name="headerVisible"> 68 <property name="uniformRowHeights">
69 <bool>false</bool> 69 <bool>true</bool>
70 </attribute> 70 </property>
71 </widget> 71 <attribute name="headerVisible">
72 </item> 72 <bool>false</bool>
73 </attribute>
74 </widget>
75 </item>
73 </layout> 76 </layout>
74 </widget> 77 </widget>
75 </widget> 78 </widget>
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index a9423d6c7..43c59738f 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -170,8 +170,8 @@ void GraphicsFramebufferWidget::OnFramebufferWidthChanged(int new_value)
170 170
171void GraphicsFramebufferWidget::OnFramebufferHeightChanged(int new_value) 171void GraphicsFramebufferWidget::OnFramebufferHeightChanged(int new_value)
172{ 172{
173 if (framebuffer_height != new_value) { 173 if (framebuffer_height != static_cast<unsigned>(new_value)) {
174 framebuffer_height = new_value; 174 framebuffer_height = static_cast<unsigned>(new_value);
175 175
176 framebuffer_source_list->setCurrentIndex(static_cast<int>(Source::Custom)); 176 framebuffer_source_list->setCurrentIndex(static_cast<int>(Source::Custom));
177 emit Update(); 177 emit Update();
diff --git a/src/citra_qt/util/spinbox.cpp b/src/citra_qt/util/spinbox.cpp
index 54f628e4c..1e3767c18 100644
--- a/src/citra_qt/util/spinbox.cpp
+++ b/src/citra_qt/util/spinbox.cpp
@@ -36,7 +36,7 @@
36 36
37#include "spinbox.h" 37#include "spinbox.h"
38 38
39CSpinBox::CSpinBox(QWidget* parent) : QAbstractSpinBox(parent), base(10), min_value(-100), max_value(100), value(0), num_digits(0) 39CSpinBox::CSpinBox(QWidget* parent) : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0)
40{ 40{
41 // TODO: Might be nice to not immediately call the slot. 41 // TODO: Might be nice to not immediately call the slot.
42 // Think of an address that is being replaced by a different one, in which case a lot 42 // Think of an address that is being replaced by a different one, in which case a lot
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index af931a7e8..6c5ca3968 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -32,7 +32,7 @@ typedef u8 ClassType;
32/** 32/**
33 * Specifies the sub-system that generated the log message. 33 * Specifies the sub-system that generated the log message.
34 * 34 *
35 * @note If you add a new entry here, also add a corresponding one to `ALL_LOG_CLASSES` in log.cpp. 35 * @note If you add a new entry here, also add a corresponding one to `ALL_LOG_CLASSES` in backend.cpp.
36 */ 36 */
37enum class Class : ClassType { 37enum class Class : ClassType {
38 Log, ///< Messages about the log system itself 38 Log, ///< Messages about the log system itself
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 2168d9959..0ab0e440c 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -6,13 +6,9 @@ set(SRCS
6 arm/dyncom/arm_dyncom_interpreter.cpp 6 arm/dyncom/arm_dyncom_interpreter.cpp
7 arm/dyncom/arm_dyncom_run.cpp 7 arm/dyncom/arm_dyncom_run.cpp
8 arm/dyncom/arm_dyncom_thumb.cpp 8 arm/dyncom/arm_dyncom_thumb.cpp
9 arm/interpreter/arm_interpreter.cpp
10 arm/interpreter/armcopro.cpp 9 arm/interpreter/armcopro.cpp
11 arm/interpreter/armemu.cpp
12 arm/interpreter/arminit.cpp 10 arm/interpreter/arminit.cpp
13 arm/interpreter/armsupp.cpp 11 arm/interpreter/armsupp.cpp
14 arm/interpreter/armvirt.cpp
15 arm/interpreter/thumbemu.cpp
16 arm/skyeye_common/vfp/vfp.cpp 12 arm/skyeye_common/vfp/vfp.cpp
17 arm/skyeye_common/vfp/vfpdouble.cpp 13 arm/skyeye_common/vfp/vfpdouble.cpp
18 arm/skyeye_common/vfp/vfpinstr.cpp 14 arm/skyeye_common/vfp/vfpinstr.cpp
@@ -30,6 +26,7 @@ set(SRCS
30 hle/kernel/kernel.cpp 26 hle/kernel/kernel.cpp
31 hle/kernel/mutex.cpp 27 hle/kernel/mutex.cpp
32 hle/kernel/semaphore.cpp 28 hle/kernel/semaphore.cpp
29 hle/kernel/session.cpp
33 hle/kernel/shared_memory.cpp 30 hle/kernel/shared_memory.cpp
34 hle/kernel/timer.cpp 31 hle/kernel/timer.cpp
35 hle/kernel/thread.cpp 32 hle/kernel/thread.cpp
@@ -108,7 +105,6 @@ set(HEADERS
108 arm/dyncom/arm_dyncom_interpreter.h 105 arm/dyncom/arm_dyncom_interpreter.h
109 arm/dyncom/arm_dyncom_run.h 106 arm/dyncom/arm_dyncom_run.h
110 arm/dyncom/arm_dyncom_thumb.h 107 arm/dyncom/arm_dyncom_thumb.h
111 arm/interpreter/arm_interpreter.h
112 arm/skyeye_common/arm_regformat.h 108 arm/skyeye_common/arm_regformat.h
113 arm/skyeye_common/armdefs.h 109 arm/skyeye_common/armdefs.h
114 arm/skyeye_common/armemu.h 110 arm/skyeye_common/armemu.h
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index e612f7439..ef37ee055 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -86,6 +86,15 @@ public:
86 virtual void AddTicks(u64 ticks) = 0; 86 virtual void AddTicks(u64 ticks) = 0;
87 87
88 /** 88 /**
89 * Initializes a CPU context for use on this CPU
90 * @param context Thread context to reset
91 * @param stack_top Pointer to the top of the stack
92 * @param entry_point Entry point for execution
93 * @param arg User argument for thread
94 */
95 virtual void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) = 0;
96
97 /**
89 * Saves the current CPU context 98 * Saves the current CPU context
90 * @param ctx Thread context to save 99 * @param ctx Thread context to save
91 */ 100 */
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 01ffbcc87..68fddc94f 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -36,9 +36,8 @@ ARM_DynCom::ARM_DynCom() {
36 state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext 36 state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
37 state->Emulate = 3; 37 state->Emulate = 3;
38 38
39 state->pc = state->Reg[15] = 0x00000000; 39 state->Reg[15] = 0x00000000;
40 state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack 40 state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
41 state->servaddr = 0xFFFF0000;
42 state->NirqSig = HIGH; 41 state->NirqSig = HIGH;
43 42
44 VFPInit(state.get()); // Initialize the VFP 43 VFPInit(state.get()); // Initialize the VFP
@@ -50,7 +49,7 @@ ARM_DynCom::~ARM_DynCom() {
50} 49}
51 50
52void ARM_DynCom::SetPC(u32 pc) { 51void ARM_DynCom::SetPC(u32 pc) {
53 state->pc = state->Reg[15] = pc; 52 state->Reg[15] = pc;
54} 53}
55 54
56u32 ARM_DynCom::GetPC() const { 55u32 ARM_DynCom::GetPC() const {
@@ -94,6 +93,16 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
94 AddTicks(ticks_executed); 93 AddTicks(ticks_executed);
95} 94}
96 95
96void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) {
97 memset(&context, 0, sizeof(Core::ThreadContext));
98
99 context.cpu_registers[0] = arg;
100 context.pc = entry_point;
101 context.sp = stack_top;
102 context.cpsr = 0x1F; // Usermode
103 context.mode = 8; // Instructs dyncom CPU core to start execution as if it's "resuming" a thread.
104}
105
97void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { 106void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
98 memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); 107 memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
99 memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); 108 memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
@@ -106,7 +115,6 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
106 ctx.fpscr = state->VFP[1]; 115 ctx.fpscr = state->VFP[1];
107 ctx.fpexc = state->VFP[2]; 116 ctx.fpexc = state->VFP[2];
108 117
109 ctx.reg_15 = state->Reg[15];
110 ctx.mode = state->NextInstr; 118 ctx.mode = state->NextInstr;
111} 119}
112 120
@@ -116,13 +124,12 @@ void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
116 124
117 state->Reg[13] = ctx.sp; 125 state->Reg[13] = ctx.sp;
118 state->Reg[14] = ctx.lr; 126 state->Reg[14] = ctx.lr;
119 state->pc = ctx.pc; 127 state->Reg[15] = ctx.pc;
120 state->Cpsr = ctx.cpsr; 128 state->Cpsr = ctx.cpsr;
121 129
122 state->VFP[1] = ctx.fpscr; 130 state->VFP[1] = ctx.fpscr;
123 state->VFP[2] = ctx.fpexc; 131 state->VFP[2] = ctx.fpexc;
124 132
125 state->Reg[15] = ctx.reg_15;
126 state->NextInstr = ctx.mode; 133 state->NextInstr = ctx.mode;
127} 134}
128 135
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index f16fb070c..9e2dda843 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -13,79 +13,24 @@
13 13
14class ARM_DynCom final : virtual public ARM_Interface { 14class ARM_DynCom final : virtual public ARM_Interface {
15public: 15public:
16
17 ARM_DynCom(); 16 ARM_DynCom();
18 ~ARM_DynCom(); 17 ~ARM_DynCom();
19 18
20 /**
21 * Set the Program Counter to an address
22 * @param pc Address to set PC to
23 */
24 void SetPC(u32 pc) override; 19 void SetPC(u32 pc) override;
25
26 /*
27 * Get the current Program Counter
28 * @return Returns current PC
29 */
30 u32 GetPC() const override; 20 u32 GetPC() const override;
31
32 /**
33 * Get an ARM register
34 * @param index Register index (0-15)
35 * @return Returns the value in the register
36 */
37 u32 GetReg(int index) const override; 21 u32 GetReg(int index) const override;
38
39 /**
40 * Set an ARM register
41 * @param index Register index (0-15)
42 * @param value Value to set register to
43 */
44 void SetReg(int index, u32 value) override; 22 void SetReg(int index, u32 value) override;
45
46 /**
47 * Get the current CPSR register
48 * @return Returns the value of the CPSR register
49 */
50 u32 GetCPSR() const override; 23 u32 GetCPSR() const override;
51
52 /**
53 * Set the current CPSR register
54 * @param cpsr Value to set CPSR to
55 */
56 void SetCPSR(u32 cpsr) override; 24 void SetCPSR(u32 cpsr) override;
57 25
58 /**
59 * Returns the number of clock ticks since the last reset
60 * @return Returns number of clock ticks
61 */
62 u64 GetTicks() const override; 26 u64 GetTicks() const override;
63
64 /**
65 * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
66 * @param ticks Number of ticks to advance the CPU core
67 */
68 void AddTicks(u64 ticks) override; 27 void AddTicks(u64 ticks) override;
69 28
70 /** 29 void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg);
71 * Saves the current CPU context
72 * @param ctx Thread context to save
73 */
74 void SaveContext(Core::ThreadContext& ctx) override; 30 void SaveContext(Core::ThreadContext& ctx) override;
75
76 /**
77 * Loads a CPU context
78 * @param ctx Thread context to load
79 */
80 void LoadContext(const Core::ThreadContext& ctx) override; 31 void LoadContext(const Core::ThreadContext& ctx) override;
81 32
82 /// Prepare core for thread reschedule (if needed to correctly handle state)
83 void PrepareReschedule() override; 33 void PrepareReschedule() override;
84
85 /**
86 * Executes the given number of instructions
87 * @param num_instructions Number of instructions to executes
88 */
89 void ExecuteInstructions(int num_instructions) override; 34 void ExecuteInstructions(int num_instructions) override;
90 35
91private: 36private:
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 4e569fd9a..c91943f24 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -34,10 +34,6 @@ enum {
34 THUMB = (1 << 7) 34 THUMB = (1 << 7)
35}; 35};
36 36
37#undef BITS
38#undef BIT
39#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
40#define BIT(s, n) ((s >> (n)) & 1)
41#define RM BITS(sht_oper, 0, 3) 37#define RM BITS(sht_oper, 0, 3)
42#define RS BITS(sht_oper, 8, 11) 38#define RS BITS(sht_oper, 8, 11)
43 39
@@ -48,10 +44,6 @@ enum {
48#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32) 44#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
49#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32) 45#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
50 46
51#define rotr(x,n) ( (x >> n) | ((x & ((1 << (n + 1)) - 1)) << (32 - n)) )
52
53extern void switch_mode(arm_core_t *core, uint32_t mode);
54
55typedef arm_core_t arm_processor; 47typedef arm_core_t arm_processor;
56typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper); 48typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper);
57 49
@@ -231,45 +223,6 @@ unsigned int DPO(RotateRightByRegister)(arm_processor *cpu, unsigned int sht_ope
231 return shifter_operand; 223 return shifter_operand;
232} 224}
233 225
234typedef struct _MiscImmeData {
235 unsigned int U;
236 unsigned int Rn;
237 unsigned int offset_8;
238} MiscLSData;
239
240typedef struct _MiscRegData {
241 unsigned int U;
242 unsigned int Rn;
243 unsigned int Rm;
244} MiscRegData;
245
246typedef struct _MiscImmePreIdx {
247 unsigned int offset_8;
248 unsigned int U;
249 unsigned int Rn;
250} MiscImmePreIdx;
251
252typedef struct _MiscRegPreIdx {
253 unsigned int U;
254 unsigned int Rn;
255 unsigned int Rm;
256} MiscRegPreIdx;
257
258typedef struct _MiscImmePstIdx {
259 unsigned int offset_8;
260 unsigned int U;
261 unsigned int Rn;
262} MIscImmePstIdx;
263
264typedef struct _MiscRegPstIdx {
265 unsigned int Rn;
266 unsigned int Rm;
267 unsigned int U;
268} MiscRegPstIdx;
269
270typedef struct _LSWordorUnsignedByte {
271} LDnST;
272
273typedef void (*get_addr_fp_t)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int rw); 226typedef void (*get_addr_fp_t)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int rw);
274 227
275typedef struct _ldst_inst { 228typedef struct _ldst_inst {
@@ -279,8 +232,9 @@ typedef struct _ldst_inst {
279#define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0) 232#define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0)
280 233
281int CondPassed(arm_processor *cpu, unsigned int cond); 234int CondPassed(arm_processor *cpu, unsigned int cond);
282#define LnSWoUB(s) glue(LnSWoUB, s) 235
283#define MLnS(s) glue(MLnS, s) 236#define LnSWoUB(s) glue(LnSWoUB, s)
237#define MLnS(s) glue(MLnS, s)
284#define LdnStM(s) glue(LdnStM, s) 238#define LdnStM(s) glue(LdnStM, s)
285 239
286#define W_BIT BIT(inst, 21) 240#define W_BIT BIT(inst, 21)
@@ -3557,7 +3511,6 @@ static tdstate decode_thumb_instr(arm_processor *cpu, uint32_t inst, addr_t addr
3557 case 26: 3511 case 26:
3558 case 27: 3512 case 27:
3559 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ 3513 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){
3560 u32 cond = (tinstr & 0x0F00) >> 8;
3561 inst_index = table_length - 4; 3514 inst_index = table_length - 4;
3562 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); 3515 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3563 } else { 3516 } else {
@@ -3697,6 +3650,9 @@ static bool InAPrivilegedMode(arm_core_t *core) {
3697} 3650}
3698 3651
3699unsigned InterpreterMainLoop(ARMul_State* state) { 3652unsigned InterpreterMainLoop(ARMul_State* state) {
3653 #undef RM
3654 #undef RS
3655
3700 #define CRn inst_cream->crn 3656 #define CRn inst_cream->crn
3701 #define OPCODE_2 inst_cream->opcode_2 3657 #define OPCODE_2 inst_cream->opcode_2
3702 #define CRm inst_cream->crm 3658 #define CRm inst_cream->crm
@@ -4769,20 +4725,20 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4769 if (inst_cream->cp_num == 15) { 4725 if (inst_cream->cp_num == 15) {
4770 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) { 4726 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) {
4771 CP15_REG(CP15_MAIN_ID) = RD; 4727 CP15_REG(CP15_MAIN_ID) = RD;
4728 } else if(CRn == 1 && CRm == 0 && OPCODE_2 == 0) {
4729 CP15_REG(CP15_CONTROL) = RD;
4772 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { 4730 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) {
4773 CP15_REG(CP15_AUXILIARY_CONTROL) = RD; 4731 CP15_REG(CP15_AUXILIARY_CONTROL) = RD;
4774 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { 4732 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) {
4775 CP15_REG(CP15_COPROCESSOR_ACCESS_CONTROL) = RD; 4733 CP15_REG(CP15_COPROCESSOR_ACCESS_CONTROL) = RD;
4776 } else if(CRn == 1 && CRm == 0 && OPCODE_2 == 0) {
4777 CP15_REG(CP15_CONTROL) = RD;
4778 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) {
4779 CP15_REG(CP15_DOMAIN_ACCESS_CONTROL) = RD;
4780 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { 4734 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) {
4781 CP15_REG(CP15_TRANSLATION_BASE_TABLE_0) = RD; 4735 CP15_REG(CP15_TRANSLATION_BASE_TABLE_0) = RD;
4782 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) { 4736 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) {
4783 CP15_REG(CP15_TRANSLATION_BASE_TABLE_1) = RD; 4737 CP15_REG(CP15_TRANSLATION_BASE_TABLE_1) = RD;
4784 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) { 4738 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) {
4785 CP15_REG(CP15_TRANSLATION_BASE_CONTROL) = RD; 4739 CP15_REG(CP15_TRANSLATION_BASE_CONTROL) = RD;
4740 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) {
4741 CP15_REG(CP15_DOMAIN_ACCESS_CONTROL) = RD;
4786 } else if(CRn == MMU_CACHE_OPS){ 4742 } else if(CRn == MMU_CACHE_OPS){
4787 //LOG_WARNING(Core_ARM11, "cache operations have not implemented."); 4743 //LOG_WARNING(Core_ARM11, "cache operations have not implemented.");
4788 } else if(CRn == MMU_TLB_OPS){ 4744 } else if(CRn == MMU_TLB_OPS){
@@ -4837,12 +4793,18 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4837 break; 4793 break;
4838 } 4794 }
4839 } else if(CRn == MMU_PID) { 4795 } else if(CRn == MMU_PID) {
4840 if(OPCODE_2 == 0) 4796 if(OPCODE_2 == 0) {
4841 CP15_REG(CP15_PID) = RD; 4797 CP15_REG(CP15_PID) = RD;
4842 else if(OPCODE_2 == 1) 4798 } else if(OPCODE_2 == 1) {
4843 CP15_REG(CP15_CONTEXT_ID) = RD; 4799 CP15_REG(CP15_CONTEXT_ID) = RD;
4844 else if(OPCODE_2 == 3) { 4800 } else if (OPCODE_2 == 2) {
4845 CP15_REG(CP15_THREAD_URO) = RD; 4801 CP15_REG(CP15_THREAD_UPRW) = RD;
4802 } else if(OPCODE_2 == 3) {
4803 if (InAPrivilegedMode(cpu))
4804 CP15_REG(CP15_THREAD_URO) = RD;
4805 } else if (OPCODE_2 == 4) {
4806 if (InAPrivilegedMode(cpu))
4807 CP15_REG(CP15_THREAD_PRW) = RD;
4846 } else { 4808 } else {
4847 LOG_ERROR(Core_ARM11, "mmu_mcr wrote UNKNOWN - reg %d", CRn); 4809 LOG_ERROR(Core_ARM11, "mmu_mcr wrote UNKNOWN - reg %d", CRn);
4848 } 4810 }
@@ -4930,31 +4892,40 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4930 if (inst_cream->cp_num == 15) { 4892 if (inst_cream->cp_num == 15) {
4931 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) { 4893 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) {
4932 RD = cpu->CP15[CP15(CP15_MAIN_ID)]; 4894 RD = cpu->CP15[CP15(CP15_MAIN_ID)];
4895 } else if (CRn == 0 && CRm == 0 && OPCODE_2 == 1) {
4896 RD = cpu->CP15[CP15(CP15_CACHE_TYPE)];
4933 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) { 4897 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) {
4934 RD = cpu->CP15[CP15(CP15_CONTROL)]; 4898 RD = cpu->CP15[CP15(CP15_CONTROL)];
4935 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { 4899 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) {
4936 RD = cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)]; 4900 RD = cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)];
4937 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { 4901 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) {
4938 RD = cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)]; 4902 RD = cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)];
4939 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) {
4940 RD = cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)];
4941 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { 4903 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) {
4942 RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)]; 4904 RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)];
4905 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) {
4906 RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_1)];
4907 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) {
4908 RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_CONTROL)];
4909 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) {
4910 RD = cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)];
4943 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 0) { 4911 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 0) {
4944 RD = cpu->CP15[CP15(CP15_FAULT_STATUS)]; 4912 RD = cpu->CP15[CP15(CP15_FAULT_STATUS)];
4945 } else if (CRn == 6 && CRm == 0 && OPCODE_2 == 0) {
4946 RD = cpu->CP15[CP15(CP15_FAULT_ADDRESS)];
4947 } else if (CRn == 0 && CRm == 0 && OPCODE_2 == 1) {
4948 RD = cpu->CP15[CP15(CP15_CACHE_TYPE)];
4949 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 1) { 4913 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 1) {
4950 RD = cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)]; 4914 RD = cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)];
4915 } else if (CRn == 6 && CRm == 0 && OPCODE_2 == 0) {
4916 RD = cpu->CP15[CP15(CP15_FAULT_ADDRESS)];
4951 } else if (CRn == 13) { 4917 } else if (CRn == 13) {
4952 if(OPCODE_2 == 0) 4918 if(OPCODE_2 == 0) {
4953 RD = CP15_REG(CP15_PID); 4919 RD = CP15_REG(CP15_PID);
4954 else if(OPCODE_2 == 1) 4920 } else if(OPCODE_2 == 1) {
4955 RD = CP15_REG(CP15_CONTEXT_ID); 4921 RD = CP15_REG(CP15_CONTEXT_ID);
4956 else if(OPCODE_2 == 3) { 4922 } else if (OPCODE_2 == 2) {
4923 RD = CP15_REG(CP15_THREAD_UPRW);
4924 } else if(OPCODE_2 == 3) {
4957 RD = Memory::KERNEL_MEMORY_VADDR; 4925 RD = Memory::KERNEL_MEMORY_VADDR;
4926 } else if (OPCODE_2 == 4) {
4927 if (InAPrivilegedMode(cpu))
4928 RD = CP15_REG(CP15_THREAD_PRW);
4958 } else { 4929 } else {
4959 LOG_ERROR(Core_ARM11, "mmu_mrr wrote UNKNOWN - reg %d", CRn); 4930 LOG_ERROR(Core_ARM11, "mmu_mrr wrote UNKNOWN - reg %d", CRn);
4960 } 4931 }
@@ -5003,7 +4974,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5003 } 4974 }
5004 uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) 4975 uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
5005 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); 4976 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
5006 uint32_t mask; 4977 uint32_t mask = 0;
5007 if (!inst_cream->R) { 4978 if (!inst_cream->R) {
5008 if (InAPrivilegedMode(cpu)) { 4979 if (InAPrivilegedMode(cpu)) {
5009 if ((operand & StateMask) != 0) { 4980 if ((operand & StateMask) != 0) {
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index de70ca8ae..d5a698365 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -48,7 +48,7 @@ tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t
48 48
49 case 3: // ADD/SUB 49 case 3: // ADD/SUB
50 { 50 {
51 ARMword subset[4] = { 51 static const ARMword subset[4] = {
52 0xE0900000, // ADDS Rd,Rs,Rn 52 0xE0900000, // ADDS Rd,Rs,Rn
53 0xE0500000, // SUBS Rd,Rs,Rn 53 0xE0500000, // SUBS Rd,Rs,Rn
54 0xE2900000, // ADDS Rd,Rs,#imm3 54 0xE2900000, // ADDS Rd,Rs,#imm3
@@ -67,7 +67,7 @@ tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t
67 case 6: // ADD 67 case 6: // ADD
68 case 7: // SUB 68 case 7: // SUB
69 { 69 {
70 ARMword subset[4] = { 70 static const ARMword subset[4] = {
71 0xE3B00000, // MOVS Rd,#imm8 71 0xE3B00000, // MOVS Rd,#imm8
72 0xE3500000, // CMP Rd,#imm8 72 0xE3500000, // CMP Rd,#imm8
73 0xE2900000, // ADDS Rd,Rd,#imm8 73 0xE2900000, // ADDS Rd,Rd,#imm8
@@ -95,7 +95,7 @@ tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t
95 t_mul 95 t_mul
96 }; 96 };
97 97
98 struct { 98 static const struct {
99 ARMword opcode; 99 ARMword opcode;
100 otype type; 100 otype type;
101 } subset[16] = { 101 } subset[16] = {
@@ -205,7 +205,7 @@ tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t
205 // merged into a single subset, saving on the following boolean: 205 // merged into a single subset, saving on the following boolean:
206 206
207 if ((tinstr & (1 << 9)) == 0) { 207 if ((tinstr & (1 << 9)) == 0) {
208 ARMword subset[4] = { 208 static const ARMword subset[4] = {
209 0xE7800000, // STR Rd,[Rb,Ro] 209 0xE7800000, // STR Rd,[Rb,Ro]
210 0xE7C00000, // STRB Rd,[Rb,Ro] 210 0xE7C00000, // STRB Rd,[Rb,Ro]
211 0xE7900000, // LDR Rd,[Rb,Ro] 211 0xE7900000, // LDR Rd,[Rb,Ro]
@@ -218,7 +218,7 @@ tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t
218 |((tinstr & 0x01C0) >> 6); // Ro 218 |((tinstr & 0x01C0) >> 6); // Ro
219 219
220 } else { 220 } else {
221 ARMword subset[4] = { 221 static const ARMword subset[4] = {
222 0xE18000B0, // STRH Rd,[Rb,Ro] 222 0xE18000B0, // STRH Rd,[Rb,Ro]
223 0xE19000D0, // LDRSB Rd,[Rb,Ro] 223 0xE19000D0, // LDRSB Rd,[Rb,Ro]
224 0xE19000B0, // LDRH Rd,[Rb,Ro] 224 0xE19000B0, // LDRH Rd,[Rb,Ro]
@@ -236,7 +236,7 @@ tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t
236 case 14: // STRB Rd,[Rb,#imm5] 236 case 14: // STRB Rd,[Rb,#imm5]
237 case 15: // LDRB Rd,[Rb,#imm5] 237 case 15: // LDRB Rd,[Rb,#imm5]
238 { 238 {
239 ARMword subset[4] = { 239 static const ARMword subset[4] = {
240 0xE5800000, // STR Rd,[Rb,#imm5] 240 0xE5800000, // STR Rd,[Rb,#imm5]
241 0xE5900000, // LDR Rd,[Rb,#imm5] 241 0xE5900000, // LDR Rd,[Rb,#imm5]
242 0xE5C00000, // STRB Rd,[Rb,#imm5] 242 0xE5C00000, // STRB Rd,[Rb,#imm5]
@@ -300,7 +300,7 @@ tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t
300 } else if ((tinstr & 0x0F00) == 0x0e00) 300 } else if ((tinstr & 0x0F00) == 0x0e00)
301 *ainstr = 0xEF000000 | SWI_Breakpoint; 301 *ainstr = 0xEF000000 | SWI_Breakpoint;
302 else { 302 else {
303 ARMword subset[4] = { 303 static const ARMword subset[4] = {
304 0xE92D0000, // STMDB sp!,{rlist} 304 0xE92D0000, // STMDB sp!,{rlist}
305 0xE92D4000, // STMDB sp!,{rlist,lr} 305 0xE92D4000, // STMDB sp!,{rlist,lr}
306 0xE8BD0000, // LDMIA sp!,{rlist} 306 0xE8BD0000, // LDMIA sp!,{rlist}
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
deleted file mode 100644
index c76d371a2..000000000
--- a/src/core/arm/interpreter/arm_interpreter.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/arm/interpreter/arm_interpreter.h"
6
7#include "core/core.h"
8
9const static cpu_config_t arm11_cpu_info = {
10 "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
11};
12
13ARM_Interpreter::ARM_Interpreter() {
14 state = new ARMul_State;
15
16 ARMul_EmulateInit();
17 memset(state, 0, sizeof(ARMul_State));
18
19 ARMul_NewState(state);
20
21 state->abort_model = 0;
22 state->cpu = (cpu_config_t*)&arm11_cpu_info;
23 state->bigendSig = LOW;
24
25 ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
26 state->lateabtSig = LOW;
27
28 // Reset the core to initial state
29 ARMul_CoProInit(state);
30 ARMul_Reset(state);
31 state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
32 state->Emulate = 3;
33
34 state->pc = state->Reg[15] = 0x00000000;
35 state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
36 state->servaddr = 0xFFFF0000;
37}
38
39ARM_Interpreter::~ARM_Interpreter() {
40 delete state;
41}
42
43void ARM_Interpreter::SetPC(u32 pc) {
44 state->pc = state->Reg[15] = pc;
45}
46
47u32 ARM_Interpreter::GetPC() const {
48 return state->pc;
49}
50
51u32 ARM_Interpreter::GetReg(int index) const {
52 return state->Reg[index];
53}
54
55void ARM_Interpreter::SetReg(int index, u32 value) {
56 state->Reg[index] = value;
57}
58
59u32 ARM_Interpreter::GetCPSR() const {
60 return state->Cpsr;
61}
62
63void ARM_Interpreter::SetCPSR(u32 cpsr) {
64 state->Cpsr = cpsr;
65}
66
67u64 ARM_Interpreter::GetTicks() const {
68 return state->NumInstrs;
69}
70
71void ARM_Interpreter::AddTicks(u64 ticks) {
72 state->NumInstrs += ticks;
73}
74
75void ARM_Interpreter::ExecuteInstructions(int num_instructions) {
76 state->NumInstrsToExecute = num_instructions - 1;
77 ARMul_Emulate32(state);
78}
79
80void ARM_Interpreter::SaveContext(Core::ThreadContext& ctx) {
81 memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
82 memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
83
84 ctx.sp = state->Reg[13];
85 ctx.lr = state->Reg[14];
86 ctx.pc = state->pc;
87 ctx.cpsr = state->Cpsr;
88
89 ctx.fpscr = state->VFP[1];
90 ctx.fpexc = state->VFP[2];
91
92 ctx.reg_15 = state->Reg[15];
93 ctx.mode = state->NextInstr;
94}
95
96void ARM_Interpreter::LoadContext(const Core::ThreadContext& ctx) {
97 memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
98 memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
99
100 state->Reg[13] = ctx.sp;
101 state->Reg[14] = ctx.lr;
102 state->pc = ctx.pc;
103 state->Cpsr = ctx.cpsr;
104
105 state->VFP[1] = ctx.fpscr;
106 state->VFP[2] = ctx.fpexc;
107
108 state->Reg[15] = ctx.reg_15;
109 state->NextInstr = ctx.mode;
110}
111
112void ARM_Interpreter::PrepareReschedule() {
113 state->NumInstrsToExecute = 0;
114}
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
deleted file mode 100644
index e5ecc69c2..000000000
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ /dev/null
@@ -1,96 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common.h"
8
9#include "core/arm/arm_interface.h"
10#include "core/arm/skyeye_common/armdefs.h"
11#include "core/arm/skyeye_common/armemu.h"
12
13class ARM_Interpreter final : virtual public ARM_Interface {
14public:
15
16 ARM_Interpreter();
17 ~ARM_Interpreter();
18
19 /**
20 * Set the Program Counter to an address
21 * @param pc Address to set PC to
22 */
23 void SetPC(u32 pc) override;
24
25 /*
26 * Get the current Program Counter
27 * @return Returns current PC
28 */
29 u32 GetPC() const override;
30
31 /**
32 * Get an ARM register
33 * @param index Register index (0-15)
34 * @return Returns the value in the register
35 */
36 u32 GetReg(int index) const override;
37
38 /**
39 * Set an ARM register
40 * @param index Register index (0-15)
41 * @param value Value to set register to
42 */
43 void SetReg(int index, u32 value) override;
44
45 /**
46 * Get the current CPSR register
47 * @return Returns the value of the CPSR register
48 */
49 u32 GetCPSR() const override;
50
51 /**
52 * Set the current CPSR register
53 * @param cpsr Value to set CPSR to
54 */
55 void SetCPSR(u32 cpsr) override;
56
57 /**
58 * Returns the number of clock ticks since the last reset
59 * @return Returns number of clock ticks
60 */
61 u64 GetTicks() const override;
62
63 /**
64 * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
65 * @param ticks Number of ticks to advance the CPU core
66 */
67 void AddTicks(u64 ticks) override;
68
69 /**
70 * Saves the current CPU context
71 * @param ctx Thread context to save
72 */
73 void SaveContext(Core::ThreadContext& ctx) override;
74
75 /**
76 * Loads a CPU context
77 * @param ctx Thread context to load
78 */
79 void LoadContext(const Core::ThreadContext& ctx) override;
80
81 /// Prepare core for thread reschedule (if needed to correctly handle state)
82 void PrepareReschedule() override;
83
84protected:
85
86 /**
87 * Executes the given number of instructions
88 * @param num_instructions Number of instructions to executes
89 */
90 void ExecuteInstructions(int num_instructions) override;
91
92private:
93
94 ARMul_State* state;
95
96};
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp
index b4ddc3d96..4ae0c52e4 100644
--- a/src/core/arm/interpreter/armcopro.cpp
+++ b/src/core/arm/interpreter/armcopro.cpp
@@ -19,213 +19,45 @@
19#include "core/arm/skyeye_common/armemu.h" 19#include "core/arm/skyeye_common/armemu.h"
20#include "core/arm/skyeye_common/vfp/vfp.h" 20#include "core/arm/skyeye_common/vfp/vfp.h"
21 21
22//chy 2005-07-08 22// Dummy Co-processors.
23//#include "ansidecl.h"
24//chy -------
25//#include "iwmmxt.h"
26 23
27/* Dummy Co-processors. */ 24static unsigned int NoCoPro3R(ARMul_State* state, unsigned int a, ARMword b)
28
29static unsigned
30NoCoPro3R(ARMul_State * state,
31unsigned a, ARMword b)
32{ 25{
33 return ARMul_CANT; 26 return ARMul_CANT;
34} 27}
35 28
36static unsigned 29static unsigned int NoCoPro4R(ARMul_State* state, unsigned int a, ARMword b, ARMword c)
37NoCoPro4R(ARMul_State * state,
38unsigned a,
39ARMword b, ARMword c)
40{ 30{
41 return ARMul_CANT; 31 return ARMul_CANT;
42} 32}
43 33
44static unsigned 34static unsigned int NoCoPro4W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c)
45NoCoPro4W(ARMul_State * state,
46unsigned a,
47ARMword b, ARMword * c)
48{ 35{
49 return ARMul_CANT; 36 return ARMul_CANT;
50} 37}
51 38
52static unsigned 39static unsigned int NoCoPro5R(ARMul_State* state, unsigned int a, ARMword b, ARMword c, ARMword d)
53NoCoPro5R(ARMul_State * state,
54unsigned a,
55ARMword b,
56ARMword c, ARMword d)
57{ 40{
58 return ARMul_CANT; 41 return ARMul_CANT;
59} 42}
60 43
61static unsigned 44static unsigned int NoCoPro5W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c, ARMword* d)
62NoCoPro5W(ARMul_State * state,
63unsigned a,
64ARMword b,
65ARMword * c, ARMword * d)
66{ 45{
67 return ARMul_CANT; 46 return ARMul_CANT;
68} 47}
69 48
70/* The XScale Co-processors. */ 49// Install co-processor instruction handlers in this routine.
71 50void ARMul_CoProInit(ARMul_State* state)
72/* Coprocessor 15: System Control. */
73static void write_cp14_reg(unsigned, ARMword);
74static ARMword read_cp14_reg(unsigned);
75
76/* Check an access to a register. */
77
78static unsigned
79check_cp15_access(ARMul_State * state,
80unsigned reg,
81unsigned CRm, unsigned opcode_1, unsigned opcode_2)
82{
83 /* Do not allow access to these register in USER mode. */
84 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
85 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
86 return ARMul_CANT;
87
88 /* Opcode_1should be zero. */
89 if (opcode_1 != 0)
90 return ARMul_CANT;
91
92 /* Different register have different access requirements. */
93 switch (reg) {
94 case 0:
95 case 1:
96 /* CRm must be 0. Opcode_2 can be anything. */
97 if (CRm != 0)
98 return ARMul_CANT;
99 break;
100 case 2:
101 case 3:
102 /* CRm must be 0. Opcode_2 must be zero. */
103 if ((CRm != 0) || (opcode_2 != 0))
104 return ARMul_CANT;
105 break;
106 case 4:
107 /* Access not allowed. */
108 return ARMul_CANT;
109 case 5:
110 case 6:
111 /* Opcode_2 must be zero. CRm must be 0. */
112 if ((CRm != 0) || (opcode_2 != 0))
113 return ARMul_CANT;
114 break;
115 case 7:
116 /* Permissable combinations:
117 Opcode_2 CRm
118 0 5
119 0 6
120 0 7
121 1 5
122 1 6
123 1 10
124 4 10
125 5 2
126 6 5 */
127 switch (opcode_2) {
128 default:
129 return ARMul_CANT;
130 case 6:
131 if (CRm != 5)
132 return ARMul_CANT;
133 break;
134 case 5:
135 if (CRm != 2)
136 return ARMul_CANT;
137 break;
138 case 4:
139 if (CRm != 10)
140 return ARMul_CANT;
141 break;
142 case 1:
143 if ((CRm != 5) && (CRm != 6) && (CRm != 10))
144 return ARMul_CANT;
145 break;
146 case 0:
147 if ((CRm < 5) || (CRm > 7))
148 return ARMul_CANT;
149 break;
150 }
151 break;
152
153 case 8:
154 /* Permissable combinations:
155 Opcode_2 CRm
156 0 5
157 0 6
158 0 7
159 1 5
160 1 6 */
161 if (opcode_2 > 1)
162 return ARMul_CANT;
163 if ((CRm < 5) || (CRm > 7))
164 return ARMul_CANT;
165 if (opcode_2 == 1 && CRm == 7)
166 return ARMul_CANT;
167 break;
168 case 9:
169 /* Opcode_2 must be zero or one. CRm must be 1 or 2. */
170 if (((CRm != 0) && (CRm != 1))
171 || ((opcode_2 != 1) && (opcode_2 != 2)))
172 return ARMul_CANT;
173 break;
174 case 10:
175 /* Opcode_2 must be zero or one. CRm must be 4 or 8. */
176 if (((CRm != 0) && (CRm != 1))
177 || ((opcode_2 != 4) && (opcode_2 != 8)))
178 return ARMul_CANT;
179 break;
180 case 11:
181 /* Access not allowed. */
182 return ARMul_CANT;
183 case 12:
184 /* Access not allowed. */
185 return ARMul_CANT;
186 case 13:
187 /* Opcode_2 must be zero. CRm must be 0. */
188 if ((CRm != 0) || (opcode_2 != 0))
189 return ARMul_CANT;
190 break;
191 case 14:
192 /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */
193 if (opcode_2 != 0)
194 return ARMul_CANT;
195
196 if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8)
197 && (CRm != 9))
198 return ARMul_CANT;
199 break;
200 case 15:
201 /* Opcode_2 must be zero. CRm must be 1. */
202 if ((CRm != 1) || (opcode_2 != 0))
203 return ARMul_CANT;
204 break;
205 default:
206 /* Should never happen. */
207 return ARMul_CANT;
208 }
209
210 return ARMul_DONE;
211}
212
213/* Install co-processor instruction handlers in this routine. */
214
215unsigned
216ARMul_CoProInit(ARMul_State * state)
217{ 51{
218 unsigned int i; 52 // Initialise tham all first.
219 53 for (unsigned int i = 0; i < 16; i++)
220 /* Initialise tham all first. */
221 for (i = 0; i < 16; i++)
222 ARMul_CoProDetach(state, i); 54 ARMul_CoProDetach(state, i);
223 55
224 /* Install CoPro Instruction handlers here. 56 // Install CoPro Instruction handlers here.
225 The format is: 57 // The format is:
226 ARMul_CoProAttach (state, CP Number, Init routine, Exit routine 58 // ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
227 LDC routine, STC routine, MRC routine, MCR routine, 59 // LDC routine, STC routine, MRC routine, MCR routine,
228 CDP routine, Read Reg routine, Write Reg routine). */ 60 // CDP routine, Read Reg routine, Write Reg routine).
229 if (state->is_v6) { 61 if (state->is_v6) {
230 ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC, 62 ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
231 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); 63 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
@@ -235,57 +67,43 @@ ARMul_CoProInit(ARMul_State * state)
235 /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, 67 /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
236 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/ 68 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
237 } 69 }
238 //chy 2003-09-03 do it in future!!!!????
239#if 0
240 if (state->is_iWMMXt) {
241 ARMul_CoProAttach(state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
242 NULL, NULL, IwmmxtCDP, NULL, NULL);
243 70
244 ARMul_CoProAttach(state, 1, NULL, NULL, NULL, NULL, 71 // No handlers below here.
245 IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL,
246 NULL);
247 }
248#endif
249 /* No handlers below here. */
250 72
251 /* Call all the initialisation routines. */ 73 // Call all the initialisation routines.
252 for (i = 0; i < 16; i++) 74 for (unsigned int i = 0; i < 16; i++) {
253 if (state->CPInit[i]) 75 if (state->CPInit[i])
254 (state->CPInit[i]) (state); 76 (state->CPInit[i]) (state);
255 77 }
256 return TRUE;
257} 78}
258 79
259/* Install co-processor finalisation routines in this routine. */ 80// Install co-processor finalisation routines in this routine.
260 81void ARMul_CoProExit(ARMul_State * state)
261void
262ARMul_CoProExit(ARMul_State * state)
263{ 82{
264 register unsigned i; 83 for (unsigned int i = 0; i < 16; i++)
265
266 for (i = 0; i < 16; i++)
267 if (state->CPExit[i]) 84 if (state->CPExit[i])
268 (state->CPExit[i]) (state); 85 (state->CPExit[i]) (state);
269 86
270 for (i = 0; i < 16; i++) /* Detach all handlers. */ 87 // Detach all handlers.
88 for (unsigned int i = 0; i < 16; i++)
271 ARMul_CoProDetach(state, i); 89 ARMul_CoProDetach(state, i);
272} 90}
273 91
274/* Routines to hook Co-processors into ARMulator. */ 92// Routines to hook Co-processors into ARMulator.
275 93
276void 94void
277ARMul_CoProAttach(ARMul_State * state, 95ARMul_CoProAttach(ARMul_State* state,
278unsigned number, 96unsigned number,
279ARMul_CPInits * init, 97ARMul_CPInits* init,
280ARMul_CPExits * exit, 98ARMul_CPExits* exit,
281ARMul_LDCs * ldc, 99ARMul_LDCs* ldc,
282ARMul_STCs * stc, 100ARMul_STCs* stc,
283ARMul_MRCs * mrc, 101ARMul_MRCs* mrc,
284ARMul_MCRs * mcr, 102ARMul_MCRs* mcr,
285ARMul_MRRCs * mrrc, 103ARMul_MRRCs* mrrc,
286ARMul_MCRRs * mcrr, 104ARMul_MCRRs* mcrr,
287ARMul_CDPs * cdp, 105ARMul_CDPs* cdp,
288ARMul_CPReads * read, ARMul_CPWrites * write) 106ARMul_CPReads* read, ARMul_CPWrites* write)
289{ 107{
290 if (init != NULL) 108 if (init != NULL)
291 state->CPInit[number] = init; 109 state->CPInit[number] = init;
@@ -311,8 +129,7 @@ ARMul_CPReads * read, ARMul_CPWrites * write)
311 state->CPWrite[number] = write; 129 state->CPWrite[number] = write;
312} 130}
313 131
314void 132void ARMul_CoProDetach(ARMul_State* state, unsigned number)
315ARMul_CoProDetach(ARMul_State * state, unsigned number)
316{ 133{
317 ARMul_CoProAttach(state, number, NULL, NULL, 134 ARMul_CoProAttach(state, number, NULL, NULL,
318 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, 135 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
deleted file mode 100644
index 7114313d6..000000000
--- a/src/core/arm/interpreter/armemu.cpp
+++ /dev/null
@@ -1,5648 +0,0 @@
1/* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3 Modifications to add arch. v4 support by <jsmith@cygnus.com>.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19#include "core/arm/skyeye_common/arm_regformat.h"
20#include "core/arm/skyeye_common/armdefs.h"
21#include "core/arm/skyeye_common/armemu.h"
22#include "core/hle/hle.h"
23
24static ARMword GetDPRegRHS (ARMul_State *, ARMword);
25static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
26static void WriteR15 (ARMul_State *, ARMword);
27static void WriteSR15 (ARMul_State *, ARMword);
28static void WriteR15Branch (ARMul_State *, ARMword);
29static ARMword GetLSRegRHS (ARMul_State *, ARMword);
30static ARMword GetLS7RHS (ARMul_State *, ARMword);
31static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
32static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
33static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
34static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
35static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
36static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
37static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
38static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
39static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
40static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
41static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
42static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
43static void Handle_Load_Double (ARMul_State *, ARMword);
44static void Handle_Store_Double (ARMul_State *, ARMword);
45
46static int handle_v6_insn (ARMul_State * state, ARMword instr);
47
48#define LUNSIGNED (0) /* unsigned operation */
49#define LSIGNED (1) /* signed operation */
50#define LDEFAULT (0) /* default : do nothing */
51#define LSCC (1) /* set condition codes on result */
52
53/* Short-hand macros for LDR/STR. */
54
55/* Store post decrement writeback. */
56#define SHDOWNWB() \
57 lhs = LHS ; \
58 if (StoreHalfWord (state, instr, lhs)) \
59 LSBase = lhs - GetLS7RHS (state, instr);
60
61/* Store post increment writeback. */
62#define SHUPWB() \
63 lhs = LHS ; \
64 if (StoreHalfWord (state, instr, lhs)) \
65 LSBase = lhs + GetLS7RHS (state, instr);
66
67/* Store pre decrement. */
68#define SHPREDOWN() \
69 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
70
71/* Store pre decrement writeback. */
72#define SHPREDOWNWB() \
73 temp = LHS - GetLS7RHS (state, instr); \
74 if (StoreHalfWord (state, instr, temp)) \
75 LSBase = temp;
76
77/* Store pre increment. */
78#define SHPREUP() \
79 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
80
81/* Store pre increment writeback. */
82#define SHPREUPWB() \
83 temp = LHS + GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
85 LSBase = temp;
86
87/* Load post decrement writeback. */
88#define LHPOSTDOWN() \
89{ \
90 int done = 1; \
91 lhs = LHS; \
92 temp = lhs - GetLS7RHS (state, instr); \
93 \
94 switch (BITS (5, 6)) \
95 { \
96 case 1: /* H */ \
97 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
98 LSBase = temp; \
99 break; \
100 case 2: /* SB */ \
101 if (LoadByte (state, instr, lhs, LSIGNED)) \
102 LSBase = temp; \
103 break; \
104 case 3: /* SH */ \
105 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
106 LSBase = temp; \
107 break; \
108 case 0: /* SWP handled elsewhere. */ \
109 default: \
110 done = 0; \
111 break; \
112 } \
113 if (done) \
114 break; \
115}
116
117/* Load post increment writeback. */
118#define LHPOSTUP() \
119{ \
120 int done = 1; \
121 lhs = LHS; \
122 temp = lhs + GetLS7RHS (state, instr); \
123 \
124 switch (BITS (5, 6)) \
125 { \
126 case 1: /* H */ \
127 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
128 LSBase = temp; \
129 break; \
130 case 2: /* SB */ \
131 if (LoadByte (state, instr, lhs, LSIGNED)) \
132 LSBase = temp; \
133 break; \
134 case 3: /* SH */ \
135 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
136 LSBase = temp; \
137 break; \
138 case 0: /* SWP handled elsewhere. */ \
139 default: \
140 done = 0; \
141 break; \
142 } \
143 if (done) \
144 break; \
145}
146
147/* Load pre decrement. */
148#define LHPREDOWN() \
149{ \
150 int done = 1; \
151 \
152 temp = LHS - GetLS7RHS (state, instr); \
153 switch (BITS (5, 6)) \
154 { \
155 case 1: /* H */ \
156 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
157 break; \
158 case 2: /* SB */ \
159 (void) LoadByte (state, instr, temp, LSIGNED); \
160 break; \
161 case 3: /* SH */ \
162 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
163 break; \
164 case 0: \
165 /* SWP handled elsewhere. */ \
166 default: \
167 done = 0; \
168 break; \
169 } \
170 if (done) \
171 break; \
172}
173
174/* Load pre decrement writeback. */
175#define LHPREDOWNWB() \
176{ \
177 int done = 1; \
178 \
179 temp = LHS - GetLS7RHS (state, instr); \
180 switch (BITS (5, 6)) \
181 { \
182 case 1: /* H */ \
183 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
184 LSBase = temp; \
185 break; \
186 case 2: /* SB */ \
187 if (LoadByte (state, instr, temp, LSIGNED)) \
188 LSBase = temp; \
189 break; \
190 case 3: /* SH */ \
191 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
192 LSBase = temp; \
193 break; \
194 case 0: \
195 /* SWP handled elsewhere. */ \
196 default: \
197 done = 0; \
198 break; \
199 } \
200 if (done) \
201 break; \
202}
203
204/* Load pre increment. */
205#define LHPREUP() \
206{ \
207 int done = 1; \
208 \
209 temp = LHS + GetLS7RHS (state, instr); \
210 switch (BITS (5, 6)) \
211 { \
212 case 1: /* H */ \
213 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
214 break; \
215 case 2: /* SB */ \
216 (void) LoadByte (state, instr, temp, LSIGNED); \
217 break; \
218 case 3: /* SH */ \
219 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
220 break; \
221 case 0: \
222 /* SWP handled elsewhere. */ \
223 default: \
224 done = 0; \
225 break; \
226 } \
227 if (done) \
228 break; \
229}
230
231/* Load pre increment writeback. */
232#define LHPREUPWB() \
233{ \
234 int done = 1; \
235 \
236 temp = LHS + GetLS7RHS (state, instr); \
237 switch (BITS (5, 6)) \
238 { \
239 case 1: /* H */ \
240 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
241 LSBase = temp; \
242 break; \
243 case 2: /* SB */ \
244 if (LoadByte (state, instr, temp, LSIGNED)) \
245 LSBase = temp; \
246 break; \
247 case 3: /* SH */ \
248 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
249 LSBase = temp; \
250 break; \
251 case 0: \
252 /* SWP handled elsewhere. */ \
253 default: \
254 done = 0; \
255 break; \
256 } \
257 if (done) \
258 break; \
259}
260
261/* EMULATION of ARM6. */
262
263int ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr);
264#ifdef MODE32
265//chy 2006-04-12, for ICE debug
266int ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr)
267{
268 return 0;
269}
270
271ARMword ARMul_Debug(ARMul_State * state, ARMword pc, ARMword instr)
272{
273 return 0;
274}
275
276ARMword ARMul_Emulate32(ARMul_State* state)
277#else
278ARMword ARMul_Emulate26(ARMul_State* state)
279#endif
280{
281 /* The PC pipeline value depends on whether ARM
282 or Thumb instructions are being
283 d. */
284 ARMword isize;
285 ARMword instr; /* The current instruction. */
286 ARMword dest = 0; /* Almost the DestBus. */
287 ARMword temp; /* Ubiquitous third hand. */
288 ARMword pc = 0; /* The address of the current instruction. */
289 ARMword lhs; /* Almost the ABus and BBus. */
290 ARMword rhs;
291 ARMword decoded = 0; /* Instruction pipeline. */
292 ARMword loaded = 0;
293 ARMword decoded_addr=0;
294 ARMword loaded_addr=0;
295 ARMword have_bp=0;
296
297 /* Execute the next instruction. */
298 if (state->NextInstr < PRIMEPIPE) {
299 decoded = state->decoded;
300 loaded = state->loaded;
301 pc = state->pc;
302 //chy 2006-04-12, for ICE debug
303 decoded_addr=state->decoded_addr;
304 loaded_addr=state->loaded_addr;
305 }
306
307 do {
308 //print_func_name(state->pc);
309 /* Just keep going. */
310 isize = INSN_SIZE;
311
312 switch (state->NextInstr) {
313 case SEQ:
314 /* Advance the pipeline, and an S cycle. */
315 state->Reg[15] += isize;
316 pc += isize;
317 instr = decoded;
318 //chy 2006-04-12, for ICE debug
319 have_bp = ARMul_ICE_debug(state,instr,decoded_addr);
320 decoded = loaded;
321 decoded_addr=loaded_addr;
322 //loaded = ARMul_LoadInstrS (state, pc + (isize * 2),
323 // isize);
324 loaded_addr=pc + (isize * 2);
325 if (have_bp) goto TEST_EMULATE;
326 break;
327
328 case NONSEQ:
329 /* Advance the pipeline, and an N cycle. */
330 state->Reg[15] += isize;
331 pc += isize;
332 instr = decoded;
333 //chy 2006-04-12, for ICE debug
334 have_bp=ARMul_ICE_debug(state,instr,decoded_addr);
335 decoded = loaded;
336 decoded_addr=loaded_addr;
337 //loaded = ARMul_LoadInstrN (state, pc + (isize * 2),
338 // isize);
339 loaded_addr=pc + (isize * 2);
340 NORMALCYCLE;
341 if (have_bp) goto TEST_EMULATE;
342 break;
343
344 case PCINCEDSEQ:
345 /* Program counter advanced, and an S cycle. */
346 pc += isize;
347 instr = decoded;
348 //chy 2006-04-12, for ICE debug
349 have_bp=ARMul_ICE_debug(state,instr,decoded_addr);
350 decoded = loaded;
351 decoded_addr=loaded_addr;
352 //loaded = ARMul_LoadInstrS (state, pc + (isize * 2),
353 // isize);
354 loaded_addr=pc + (isize * 2);
355 NORMALCYCLE;
356 if (have_bp) goto TEST_EMULATE;
357 break;
358
359 case PCINCEDNONSEQ:
360 /* Program counter advanced, and an N cycle. */
361 pc += isize;
362 instr = decoded;
363 //chy 2006-04-12, for ICE debug
364 have_bp=ARMul_ICE_debug(state,instr,decoded_addr);
365 decoded = loaded;
366 decoded_addr=loaded_addr;
367 //loaded = ARMul_LoadInstrN (state, pc + (isize * 2),
368 // isize);
369 loaded_addr=pc + (isize * 2);
370 NORMALCYCLE;
371 if (have_bp) goto TEST_EMULATE;
372 break;
373
374 case RESUME:
375 /* The program counter has been changed. */
376 pc = state->Reg[15];
377#ifndef MODE32
378 pc = pc & R15PCBITS;
379#endif
380 state->Reg[15] = pc + (isize * 2);
381 state->Aborted = 0;
382 //chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU>
383 state->AbortAddr = 1;
384
385 instr = ARMul_LoadInstrN (state, pc, isize);
386 //instr = ARMul_ReLoadInstr (state, pc, isize);
387 //chy 2006-04-12, for ICE debug
388 have_bp=ARMul_ICE_debug(state,instr,pc);
389 //decoded =
390 // ARMul_ReLoadInstr (state, pc + isize, isize);
391 decoded_addr=pc+isize;
392 //loaded = ARMul_ReLoadInstr (state, pc + isize * 2,
393 // isize);
394 loaded_addr=pc + isize * 2;
395 NORMALCYCLE;
396 if (have_bp) goto TEST_EMULATE;
397 break;
398
399 default:
400 /* The program counter has been changed. */
401 pc = state->Reg[15];
402#ifndef MODE32
403 pc = pc & R15PCBITS;
404#endif
405 state->Reg[15] = pc + (isize * 2);
406 state->Aborted = 0;
407 //chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU>
408 state->AbortAddr = 1;
409
410 instr = ARMul_LoadInstrN (state, pc, isize);
411
412 //chy 2006-04-12, for ICE debug
413 have_bp=ARMul_ICE_debug(state,instr,pc);
414
415 decoded_addr=pc+isize;
416
417 loaded_addr=pc + isize * 2;
418 NORMALCYCLE;
419 if (have_bp) goto TEST_EMULATE;
420 break;
421 }
422
423 instr = ARMul_LoadInstrN (state, pc, isize);
424 state->last_instr = state->CurrInstr;
425 state->CurrInstr = instr;
426 ARMul_Debug(state, pc, instr);
427
428 /* Any exceptions ? */
429 if (state->NresetSig == LOW) {
430 ARMul_Abort (state, ARMul_ResetV);
431 break;
432 } else if (!state->NfiqSig && !FFLAG) {
433 ARMul_Abort (state, ARMul_FIQV);
434 break;
435 } else if (!state->NirqSig && !IFLAG) {
436 ARMul_Abort (state, ARMul_IRQV);
437 break;
438 }
439
440 if (state->Emulate < ONCE) {
441 state->NextInstr = RESUME;
442 break;
443 }
444
445 state->NumInstrs++;
446
447#ifdef MODET
448 /* Provide Thumb instruction decoding. If the processor is in Thumb
449 mode, then we can simply decode the Thumb instruction, and map it
450 to the corresponding ARM instruction (by directly loading the
451 instr variable, and letting the normal ARM simulator
452 execute). There are some caveats to ensure that the correct
453 pipelined PC value is used when executing Thumb code, and also for
454 dealing with the BL instruction. */
455 if (TFLAG) {
456 ARMword armOp = 0;
457 /* Check if in Thumb mode. */
458 switch (ARMul_ThumbDecode(state, pc, instr, &armOp)) {
459 case t_undefined:
460 /* This is a Thumb instruction. */
461 ARMul_UndefInstr (state, instr);
462 goto donext;
463
464 case t_branch:
465 /* Already processed. */
466 //pc = state->Reg[15] - 2;
467 //state->pc = state->Reg[15] - 2; //ichfly why do I need that
468 goto donext;
469
470 case t_decoded:
471 /* ARM instruction available. */
472 //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp);
473
474 if (armOp == 0xDEADC0DE) {
475 LOG_ERROR(Core_ARM11, "Failed to decode thumb opcode %04X at %08X", instr, pc);
476 }
477
478 instr = armOp;
479
480 /* So continue instruction decoding. */
481 break;
482 default:
483 break;
484 }
485 }
486#endif
487 /* Check the condition codes. */
488 if ((temp = TOPBITS (28)) == AL) {
489 /* Vile deed in the need for speed. */
490 goto mainswitch;
491 }
492
493 /* Check the condition code. */
494 switch ((int) TOPBITS (28)) {
495 case AL:
496 temp = TRUE;
497 break;
498 case NV:
499
500 /* shenoubang add for armv7 instr dmb 2012-3-11 */
501 if (state->is_v7) {
502 if ((instr & 0x0fffff00) == 0x057ff000) {
503 switch((instr >> 4) & 0xf) {
504 case 4: /* dsb */
505 case 5: /* dmb */
506 case 6: /* isb */
507 // TODO: do no implemented thes instr
508 goto donext;
509 }
510 }
511 }
512 /* dyf add for armv6 instruct CPS 2010.9.17 */
513 if (state->is_v6) {
514 /* clrex do nothing here temporary */
515 if (instr == 0xf57ff01f) {
516 //printf("clrex \n");
517 /* shenoubang 2012-3-14 refer the dyncom_interpreter */
518 state->exclusive_tag_array[0] = 0xFFFFFFFF;
519 state->exclusive_access_state = 0;
520 goto donext;
521 }
522
523 if (BITS(20, 27) == 0x10) {
524 if (BIT(19)) {
525 if (BIT(8)) {
526 if (BIT(18))
527 state->Cpsr |= 1<<8;
528 else
529 state->Cpsr &= ~(1<<8);
530 }
531 if (BIT(7)) {
532 if (BIT(18))
533 state->Cpsr |= 1<<7;
534 else
535 state->Cpsr &= ~(1<<7);
536 ASSIGNINT (state->Cpsr & INTBITS);
537 }
538 if (BIT(6)) {
539 if (BIT(18))
540 state->Cpsr |= 1<<6;
541 else
542 state->Cpsr &= ~(1<<6);
543 ASSIGNINT (state->Cpsr & INTBITS);
544 }
545 }
546 if (BIT(17)) {
547 state->Cpsr |= BITS(0, 4);
548 printf("skyeye test state->Mode\n");
549 if (state->Mode != (state->Cpsr & MODEBITS)) {
550 state->Mode = ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
551 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
552 }
553 }
554 goto donext;
555 }
556 }
557 if (state->is_v5) {
558 if (BITS (25, 27) == 5) { /* BLX(1) */
559 ARMword dest;
560
561 state->Reg[14] = pc + 4;
562
563 /* Force entry into Thumb mode. */
564 dest = pc + 8 + 1;
565 if (BIT (23))
566 dest += (NEGBRANCH +
567 (BIT (24) << 1));
568 else
569 dest += POSBRANCH +
570 (BIT (24) << 1);
571
572 WriteR15Branch (state, dest);
573 goto donext;
574 } else if ((instr & 0xFC70F000) == 0xF450F000) {
575 /* The PLD instruction. Ignored. */
576 goto donext;
577 } else if (((instr & 0xfe500f00) == 0xfc100100)
578 || ((instr & 0xfe500f00) ==
579 0xfc000100)) {
580 /* wldrw and wstrw are unconditional. */
581 goto mainswitch;
582 } else {
583 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
584 ARMul_UndefInstr (state, instr);
585 }
586 }
587 temp = FALSE;
588 break;
589 case EQ:
590 temp = ZFLAG;
591 break;
592 case NE:
593 temp = !ZFLAG;
594 break;
595 case VS:
596 temp = VFLAG;
597 break;
598 case VC:
599 temp = !VFLAG;
600 break;
601 case MI:
602 temp = NFLAG;
603 break;
604 case PL:
605 temp = !NFLAG;
606 break;
607 case CS:
608 temp = CFLAG;
609 break;
610 case CC:
611 temp = !CFLAG;
612 break;
613 case HI:
614 temp = (CFLAG && !ZFLAG);
615 break;
616 case LS:
617 temp = (!CFLAG || ZFLAG);
618 break;
619 case GE:
620 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
621 break;
622 case LT:
623 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
624 break;
625 case GT:
626 temp = ((!NFLAG && !VFLAG && !ZFLAG)
627 || (NFLAG && VFLAG && !ZFLAG));
628 break;
629 case LE:
630 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG))
631 || ZFLAG;
632 break;
633 } /* cc check */
634
635//chy 2003-08-24 now #if 0 .... #endif process cp14, cp15.reg14, I disable it...
636
637 /* Actual execution of instructions begins here. */
638 /* If the condition codes don't match, stop here. */
639 if (temp) {
640mainswitch:
641
642 /* shenoubang sbfx and ubfx instr 2012-3-16 */
643 if (state->is_v6) {
644 unsigned int m, lsb, width, Rd, Rn, data;
645 Rd = Rn = lsb = width = data = m = 0;
646
647 //printf("helloworld\n");
648 if ((((int) BITS (21, 27)) == 0x3f) && (((int) BITS (4, 6)) == 0x5)) {
649 m = (unsigned)BITS(7, 11);
650 width = (unsigned)BITS(16, 20);
651 Rd = (unsigned)BITS(12, 15);
652 Rn = (unsigned)BITS(0, 3);
653 if ((Rd == 15) || (Rn == 15)) {
654 ARMul_UndefInstr (state, instr);
655 } else if ((m + width) < 32) {
656 data = state->Reg[Rn];
657 state->Reg[Rd] ^= state->Reg[Rd];
658 state->Reg[Rd] = ((ARMword)(data << (31 -(m + width))) >> ((31 - (m + width)) + (m)));
659 //SKYEYE_LOG_IN_CLR(RED, "UBFX: In %s, line = %d, Reg_src[%d] = 0x%x, Reg_d[%d] = 0x%x, m = %d, width = %d, Rd = %d, Rn = %d\n",
660 // __FUNCTION__, __LINE__, Rn, data, Rd, state->Reg[Rd], m, width + 1, Rd, Rn);
661 goto donext;
662 }
663 } // ubfx instr
664 else if ((((int) BITS (21, 27)) == 0x3d) && (((int) BITS (4, 6)) == 0x5)) {
665 int tmp = 0;
666 Rd = BITS(12, 15);
667 Rn = BITS(0, 3);
668 lsb = BITS(7, 11);
669 width = BITS(16, 20);
670 if ((Rd == 15) || (Rn == 15)) {
671 ARMul_UndefInstr (state, instr);
672 } else if ((lsb + width) < 32) {
673 state->Reg[Rd] ^= state->Reg[Rd];
674 data = state->Reg[Rn];
675 tmp = (data << (32 - (lsb + width + 1)));
676 state->Reg[Rd] = (tmp >> (32 - (lsb + width + 1)));
677 //SKYEYE_LOG_IN_CLR(RED, "sbfx: In %s, line = %d, pc = 0x%x, instr = 0x%x,Rd = 0x%x, Rn = 0x%x, lsb = %d, width = %d, Rs[%d] = 0x%x, Rd[%d] = 0x%x\n",
678 // __func__, __LINE__, pc, instr, Rd, Rn, lsb, width + 1, Rn, state->Reg[Rn], Rd, state->Reg[Rd]);
679 goto donext;
680 }
681 } // sbfx instr
682 else if ((((int)BITS(21, 27)) == 0x3e) && ((int)BITS(4, 6) == 0x1)) {
683 //(ARMword)(instr<<(31-(n))) >> ((31-(n))+(m))
684 unsigned msb ,tmp_rn, tmp_rd, dst;
685 tmp_rd = tmp_rn = dst = 0;
686 Rd = BITS(12, 15);
687 Rn = BITS(0, 3);
688 lsb = BITS(7, 11);
689 msb = BITS(16, 20); //-V519
690 if (Rd == 15) {
691 ARMul_UndefInstr (state, instr);
692 } else if (Rn == 15) {
693 data = state->Reg[Rd];
694 tmp_rd = ((ARMword)(data << (31 - lsb)) >> (31 - lsb));
695 dst = ((data >> msb) << (msb - lsb));
696 dst = (dst << lsb) | tmp_rd;
697 goto donext;
698 } // bfc instr
699 else if (((msb >= lsb) && (msb < 32))) {
700 data = state->Reg[Rn];
701 tmp_rn = ((ARMword)(data << (31 - (msb - lsb))) >> (31 - (msb - lsb)));
702 data = state->Reg[Rd];
703 tmp_rd = ((ARMword)(data << (31 - lsb)) >> (31 - lsb));
704 dst = ((data >> msb) << (msb - lsb)) | tmp_rn;
705 dst = (dst << lsb) | tmp_rd;
706 goto donext;
707 } // bfi instr
708 }
709 }
710
711 switch ((int) BITS (20, 27)) {
712 /* Data Processing Register RHS Instructions. */
713
714 case 0x00: /* AND reg and MUL */
715#ifdef MODET
716 if (BITS (4, 11) == 0xB) {
717 /* STRH register offset, no write-back, down, post indexed. */
718 SHDOWNWB ();
719 break;
720 }
721 if (BITS (4, 7) == 0xD) {
722 Handle_Load_Double (state, instr);
723 break;
724 }
725 if (BITS (4, 7) == 0xF) {
726 Handle_Store_Double (state, instr);
727 break;
728 }
729#endif
730 if (BITS (4, 7) == 9) {
731 /* MUL */
732 rhs = state->Reg[MULRHSReg];
733 //if (MULLHSReg == MULDESTReg) {
734 if(0) { /* For armv6, the restriction is removed */
735 UNDEF_MULDestEQOp1;
736 state->Reg[MULDESTReg] = 0;
737 } else if (MULDESTReg != 15)
738 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
739 else
740 UNDEF_MULPCDest;
741
742 for (dest = 0, temp = 0; dest < 32;
743 dest++)
744 if (rhs & (1L << dest))
745 temp = dest;
746
747 /* Mult takes this many/2 I cycles. */
748 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
749 } else {
750 /* AND reg. */
751 rhs = DPRegRHS;
752 dest = LHS & rhs;
753 WRITEDEST (dest);
754 }
755 break;
756
757 case 0x01: /* ANDS reg and MULS */
758#ifdef MODET
759 if ((BITS (4, 11) & 0xF9) == 0x9)
760 /* LDR register offset, no write-back, down, post indexed. */
761 LHPOSTDOWN ();
762 /* Fall through to rest of decoding. */
763#endif
764 if (BITS (4, 7) == 9) {
765 /* MULS */
766 rhs = state->Reg[MULRHSReg];
767
768 //if (MULLHSReg == MULDESTReg) {
769 if(0) {
770 printf("Something in %d line\n", __LINE__);
771 UNDEF_WARNING;
772 UNDEF_MULDestEQOp1;
773 state->Reg[MULDESTReg] = 0;
774 CLEARN;
775 SETZ;
776 } else if (MULDESTReg != 15) {
777 dest = state->Reg[MULLHSReg] * rhs;
778 ARMul_NegZero (state, dest);
779 state->Reg[MULDESTReg] = dest;
780 } else
781 UNDEF_MULPCDest;
782
783 for (dest = 0, temp = 0; dest < 32;
784 dest++)
785 if (rhs & (1L << dest))
786 temp = dest;
787
788 /* Mult takes this many/2 I cycles. */
789 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
790 } else {
791 /* ANDS reg. */
792 rhs = DPSRegRHS;
793 dest = LHS & rhs;
794 WRITESDEST (dest);
795 }
796 break;
797
798 case 0x02: /* EOR reg and MLA */
799#ifdef MODET
800 if (BITS (4, 11) == 0xB) {
801 /* STRH register offset, write-back, down, post indexed. */
802 SHDOWNWB ();
803 break;
804 }
805#endif
806 if (BITS (4, 7) == 9) { /* MLA */
807 rhs = state->Reg[MULRHSReg];
808#if 0
809 if (MULLHSReg == MULDESTReg) {
810 UNDEF_MULDestEQOp1;
811 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
812 } else if (MULDESTReg != 15) {
813#endif
814 if (MULDESTReg != 15) {
815 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
816 } else
817 UNDEF_MULPCDest;
818
819 for (dest = 0, temp = 0; dest < 32;
820 dest++)
821 if (rhs & (1L << dest))
822 temp = dest;
823
824 /* Mult takes this many/2 I cycles. */
825 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
826 } else {
827 rhs = DPRegRHS;
828 dest = LHS ^ rhs;
829 WRITEDEST (dest);
830 }
831 break;
832
833 case 0x03: /* EORS reg and MLAS */
834#ifdef MODET
835 if ((BITS (4, 11) & 0xF9) == 0x9)
836 /* LDR register offset, write-back, down, post-indexed. */
837 LHPOSTDOWN ();
838 /* Fall through to rest of the decoding. */
839#endif
840 if (BITS (4, 7) == 9) {
841 /* MLAS */
842 rhs = state->Reg[MULRHSReg];
843 //if (MULLHSReg == MULDESTReg) {
844 if (0) {
845 UNDEF_MULDestEQOp1;
846 dest = state->Reg[MULACCReg];
847 ARMul_NegZero (state, dest);
848 state->Reg[MULDESTReg] = dest;
849 } else if (MULDESTReg != 15) {
850 dest = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
851 ARMul_NegZero (state, dest);
852 state->Reg[MULDESTReg] = dest;
853 } else
854 UNDEF_MULPCDest;
855
856 for (dest = 0, temp = 0; dest < 32;
857 dest++)
858 if (rhs & (1L << dest))
859 temp = dest;
860
861 /* Mult takes this many/2 I cycles. */
862 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
863 } else {
864 /* EORS Reg. */
865 rhs = DPSRegRHS;
866 dest = LHS ^ rhs;
867 WRITESDEST (dest);
868 }
869 break;
870
871 case 0x04: /* SUB reg */
872 // Signifies UMAAL
873 if (state->is_v6 && BITS(4, 7) == 0x09) {
874 if (handle_v6_insn(state, instr))
875 break;
876 }
877
878#ifdef MODET
879 if (BITS (4, 7) == 0xB) {
880 /* STRH immediate offset, no write-back, down, post indexed. */
881 SHDOWNWB ();
882 break;
883 }
884 if (BITS (4, 7) == 0xD) {
885 Handle_Load_Double (state, instr);
886 break;
887 }
888 if (BITS (4, 7) == 0xF) {
889 Handle_Store_Double (state, instr);
890 break;
891 }
892#endif
893 rhs = DPRegRHS;
894 dest = LHS - rhs;
895 WRITEDEST (dest);
896 break;
897
898 case 0x05: /* SUBS reg */
899#ifdef MODET
900 if ((BITS (4, 7) & 0x9) == 0x9)
901 /* LDR immediate offset, no write-back, down, post indexed. */
902 LHPOSTDOWN ();
903 /* Fall through to the rest of the instruction decoding. */
904#endif
905 lhs = LHS;
906 rhs = DPRegRHS;
907 dest = lhs - rhs;
908
909 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
910 ARMul_SubCarry (state, lhs, rhs, dest);
911 ARMul_SubOverflow (state, lhs, rhs, dest);
912 } else {
913 CLEARC;
914 CLEARV;
915 }
916 WRITESDEST (dest);
917 break;
918
919 case 0x06: /* RSB reg */
920#ifdef MODET
921 if (BITS (4, 7) == 0xB) {
922 /* STRH immediate offset, write-back, down, post indexed. */
923 SHDOWNWB ();
924 break;
925 }
926#endif
927 rhs = DPRegRHS;
928 dest = rhs - LHS;
929 WRITEDEST (dest);
930 break;
931
932 case 0x07: /* RSBS reg */
933#ifdef MODET
934 if ((BITS (4, 7) & 0x9) == 0x9)
935 /* LDR immediate offset, write-back, down, post indexed. */
936 LHPOSTDOWN ();
937 /* Fall through to remainder of instruction decoding. */
938#endif
939 lhs = LHS;
940 rhs = DPRegRHS;
941 dest = rhs - lhs;
942
943 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
944 ARMul_SubCarry (state, rhs, lhs, dest);
945 ARMul_SubOverflow (state, rhs, lhs, dest);
946 } else {
947 CLEARC;
948 CLEARV;
949 }
950 WRITESDEST (dest);
951 break;
952
953 case 0x08: /* ADD reg */
954#ifdef MODET
955 if (BITS (4, 11) == 0xB) {
956 /* STRH register offset, no write-back, up, post indexed. */
957 SHUPWB ();
958 break;
959 }
960 if (BITS (4, 7) == 0xD) {
961 Handle_Load_Double (state, instr);
962 break;
963 }
964 if (BITS (4, 7) == 0xF) {
965 Handle_Store_Double (state, instr);
966 break;
967 }
968#endif
969#ifdef MODET
970 if (BITS (4, 7) == 0x9) {
971 /* MULL */
972 /* 32x32 = 64 */
973 ARMul_Icycles (state, Multiply64 (state, instr, LUNSIGNED, LDEFAULT), 0L);
974 break;
975 }
976#endif
977 rhs = DPRegRHS;
978 dest = LHS + rhs;
979 WRITEDEST (dest);
980 break;
981
982 case 0x09: /* ADDS reg */
983#ifdef MODET
984 if ((BITS (4, 11) & 0xF9) == 0x9)
985 /* LDR register offset, no write-back, up, post indexed. */
986 LHPOSTUP ();
987 /* Fall through to remaining instruction decoding. */
988#endif
989#ifdef MODET
990 if (BITS (4, 7) == 0x9) {
991 /* MULL */
992 /* 32x32=64 */
993 ARMul_Icycles (state, Multiply64 (state, instr, LUNSIGNED, LSCC), 0L);
994 break;
995 }
996#endif
997 lhs = LHS;
998 rhs = DPRegRHS;
999 dest = lhs + rhs;
1000 ASSIGNZ (dest == 0);
1001 if ((lhs | rhs) >> 30) {
1002 /* Possible C,V,N to set. */
1003 ASSIGNN (NEG (dest));
1004 ARMul_AddCarry (state, lhs, rhs, dest);
1005 ARMul_AddOverflow (state, lhs, rhs, dest);
1006 } else {
1007 CLEARN;
1008 CLEARC;
1009 CLEARV;
1010 }
1011 WRITESDEST (dest);
1012 break;
1013
1014 case 0x0a: /* ADC reg */
1015#ifdef MODET
1016 if (BITS (4, 11) == 0xB) {
1017 /* STRH register offset, write-back, up, post-indexed. */
1018 SHUPWB ();
1019 break;
1020 }
1021 if (BITS (4, 7) == 0x9) {
1022 /* MULL */
1023 /* 32x32=64 */
1024 ARMul_Icycles (state, MultiplyAdd64 (state, instr, LUNSIGNED, LDEFAULT), 0L);
1025 break;
1026 }
1027#endif
1028 rhs = DPRegRHS;
1029 dest = LHS + rhs + CFLAG;
1030 WRITEDEST (dest);
1031 break;
1032
1033 case 0x0b: /* ADCS reg */
1034#ifdef MODET
1035 if ((BITS (4, 11) & 0xF9) == 0x9)
1036 /* LDR register offset, write-back, up, post indexed. */
1037 LHPOSTUP ();
1038 /* Fall through to remaining instruction decoding. */
1039 if (BITS (4, 7) == 0x9) {
1040 /* MULL */
1041 /* 32x32=64 */
1042 ARMul_Icycles (state, MultiplyAdd64 (state, instr, LUNSIGNED, LSCC), 0L);
1043 break;
1044 }
1045#endif
1046 lhs = LHS;
1047 rhs = DPRegRHS;
1048 dest = lhs + rhs + CFLAG;
1049 ASSIGNZ (dest == 0);
1050 if ((lhs | rhs) >> 30) {
1051 /* Possible C,V,N to set. */
1052 ASSIGNN (NEG (dest));
1053 ARMul_AddCarry (state, lhs, rhs, dest);
1054 ARMul_AddOverflow (state, lhs, rhs, dest);
1055 } else {
1056 CLEARN;
1057 CLEARC;
1058 CLEARV;
1059 }
1060 WRITESDEST (dest);
1061 break;
1062
1063 case 0x0c: /* SBC reg */
1064#ifdef MODET
1065 if (BITS (4, 7) == 0xB) {
1066 /* STRH immediate offset, no write-back, up post indexed. */
1067 SHUPWB ();
1068 break;
1069 }
1070 if (BITS (4, 7) == 0xD) {
1071 Handle_Load_Double (state, instr);
1072 break;
1073 }
1074 if (BITS (4, 7) == 0xF) {
1075 Handle_Store_Double (state, instr);
1076 break;
1077 }
1078 if (BITS (4, 7) == 0x9) {
1079 /* MULL */
1080 /* 32x32=64 */
1081 ARMul_Icycles (state, Multiply64 (state, instr, LSIGNED, LDEFAULT), 0L);
1082 break;
1083 }
1084#endif
1085 rhs = DPRegRHS;
1086 dest = LHS - rhs - !CFLAG;
1087 WRITEDEST (dest);
1088 break;
1089
1090 case 0x0d: /* SBCS reg */
1091#ifdef MODET
1092 if ((BITS (4, 7) & 0x9) == 0x9)
1093 /* LDR immediate offset, no write-back, up, post indexed. */
1094 LHPOSTUP ();
1095
1096 if (BITS (4, 7) == 0x9) {
1097 /* MULL */
1098 /* 32x32=64 */
1099 ARMul_Icycles (state, Multiply64 (state, instr, LSIGNED, LSCC), 0L);
1100 break;
1101 }
1102#endif
1103 lhs = LHS;
1104 rhs = DPRegRHS;
1105 dest = lhs - rhs - !CFLAG;
1106 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1107 ARMul_SubCarry (state, lhs, rhs, dest);
1108 ARMul_SubOverflow (state, lhs, rhs, dest);
1109 } else {
1110 CLEARC;
1111 CLEARV;
1112 }
1113 WRITESDEST (dest);
1114 break;
1115
1116 case 0x0e: /* RSC reg */
1117#ifdef MODET
1118 if (BITS (4, 7) == 0xB) {
1119 /* STRH immediate offset, write-back, up, post indexed. */
1120 SHUPWB ();
1121 break;
1122 }
1123
1124 if (BITS (4, 7) == 0x9) {
1125 /* MULL */
1126 /* 32x32=64 */
1127 ARMul_Icycles (state, MultiplyAdd64 (state, instr, LSIGNED, LDEFAULT), 0L);
1128 break;
1129 }
1130#endif
1131 rhs = DPRegRHS;
1132 dest = rhs - LHS - !CFLAG;
1133 WRITEDEST (dest);
1134 break;
1135
1136 case 0x0f: /* RSCS reg */
1137#ifdef MODET
1138 if ((BITS (4, 7) & 0x9) == 0x9)
1139 /* LDR immediate offset, write-back, up, post indexed. */
1140 LHPOSTUP ();
1141 /* Fall through to remaining instruction decoding. */
1142
1143 if (BITS (4, 7) == 0x9) {
1144 /* MULL */
1145 /* 32x32=64 */
1146 ARMul_Icycles (state, MultiplyAdd64 (state, instr, LSIGNED, LSCC), 0L);
1147 break;
1148 }
1149#endif
1150 lhs = LHS;
1151 rhs = DPRegRHS;
1152 dest = rhs - lhs - !CFLAG;
1153
1154 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
1155 ARMul_SubCarry (state, rhs, lhs, dest);
1156 ARMul_SubOverflow (state, rhs, lhs, dest);
1157 } else {
1158 CLEARC;
1159 CLEARV;
1160 }
1161 WRITESDEST (dest);
1162 break;
1163
1164 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1165 if (state->is_v5e) {
1166 if (BIT (4) == 0 && BIT (7) == 1) {
1167 /* ElSegundo SMLAxy insn. */
1168 ARMword op1 = state->Reg[BITS (0, 3)];
1169 ARMword op2 = state->Reg[BITS (8, 11)];
1170 ARMword Rn = state->Reg[BITS (12, 15)];
1171
1172 if (BIT (5))
1173 op1 >>= 16;
1174 if (BIT (6))
1175 op2 >>= 16;
1176 op1 &= 0xFFFF;
1177 op2 &= 0xFFFF;
1178 if (op1 & 0x8000)
1179 op1 -= 65536;
1180 if (op2 & 0x8000)
1181 op2 -= 65536;
1182 op1 *= op2;
1183 //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn);
1184 if (AddOverflow(op1, Rn, op1 + Rn))
1185 SETQ;
1186 state->Reg[BITS (16, 19)] = op1 + Rn;
1187 break;
1188 }
1189
1190 if (BITS (4, 11) == 5) {
1191 /* ElSegundo QADD insn. */
1192 ARMword op1 = state->Reg[BITS (0, 3)];
1193 ARMword op2 = state->Reg[BITS (16, 19)];
1194 ARMword result = op1 + op2;
1195 if (AddOverflow(op1, op2, result)) {
1196 result = POS (result) ? 0x80000000 : 0x7fffffff;
1197 SETQ;
1198 }
1199 state->Reg[BITS (12, 15)] = result;
1200 break;
1201 }
1202 }
1203#ifdef MODET
1204 if (BITS (4, 11) == 0xB) {
1205 /* STRH register offset, no write-back, down, pre indexed. */
1206 SHPREDOWN ();
1207 break;
1208 }
1209 if (BITS (4, 7) == 0xD) {
1210 Handle_Load_Double (state, instr);
1211 break;
1212 }
1213 if (BITS (4, 7) == 0xF) {
1214 Handle_Store_Double (state, instr);
1215 break;
1216 }
1217#endif
1218 if (BITS (4, 11) == 9) {
1219 /* SWP */
1220 UNDEF_SWPPC;
1221 temp = LHS;
1222 BUSUSEDINCPCS;
1223#ifndef MODE32
1224 if (VECTORACCESS (temp) || ADDREXCEPT (temp)) {
1225 INTERNALABORT (temp);
1226 (void) ARMul_LoadWordN (state, temp);
1227 (void) ARMul_LoadWordN (state, temp);
1228 } else
1229#endif
1230 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
1231 if (temp & 3)
1232 DEST = ARMul_Align (state, temp, dest);
1233 else
1234 DEST = dest;
1235 if (state->abortSig || state->Aborted)
1236 TAKEABORT;
1237 } else if ((BITS (0, 11) == 0) && (LHSReg == 15)) { /* MRS CPSR */
1238 UNDEF_MRSPC;
1239 DEST = ARMul_GetCPSR(state);
1240 } else {
1241 UNDEF_Test;
1242 }
1243 break;
1244
1245 case 0x11: /* TSTP reg */
1246#ifdef MODET
1247 if ((BITS (4, 11) & 0xF9) == 0x9)
1248 /* LDR register offset, no write-back, down, pre indexed. */
1249 LHPREDOWN ();
1250 /* Continue with remaining instruction decode. */
1251#endif
1252 if (DESTReg == 15) {
1253 /* TSTP reg */
1254#ifdef MODE32
1255 //chy 2006-02-15 if in user mode, can not set cpsr 0:23
1256 //from p165 of ARMARM book
1257 state->Cpsr = GETSPSR (state->Bank);
1258 ARMul_CPSRAltered (state);
1259#else
1260 rhs = DPRegRHS;
1261 temp = LHS & rhs;
1262 SETR15PSR (temp);
1263#endif
1264 } else {
1265 /* TST reg */
1266 rhs = DPSRegRHS;
1267 dest = LHS & rhs;
1268 ARMul_NegZero (state, dest);
1269 }
1270 break;
1271
1272 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1273
1274 if (state->is_v5) {
1275 if (BITS (4, 7) == 3) {
1276 /* BLX(2) */
1277 ARMword temp;
1278
1279 if (TFLAG)
1280 temp = (pc + 2) | 1;
1281 else
1282 temp = pc + 4;
1283
1284 WriteR15Branch (state, state->Reg[RHSReg]);
1285 state->Reg[14] = temp;
1286 break;
1287 }
1288 }
1289
1290 if (state->is_v5e) {
1291 if (BIT (4) == 0 && BIT (7) == 1 && (BIT (5) == 0 || BITS (12, 15) == 0)) {
1292 /* ElSegundo SMLAWy/SMULWy insn. */
1293 unsigned long long op1 = state->Reg[BITS (0, 3)];
1294 unsigned long long op2 = state->Reg[BITS (8, 11)];
1295 unsigned long long result;
1296
1297 if (BIT (6))
1298 op2 >>= 16;
1299 if (op1 & 0x80000000)
1300 op1 -= 1ULL << 32;
1301 op2 &= 0xFFFF;
1302 if (op2 & 0x8000)
1303 op2 -= 65536;
1304 result = (op1 * op2) >> 16;
1305
1306 if (BIT (5) == 0) {
1307 ARMword Rn = state->Reg[BITS(12, 15)];
1308
1309 if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn)))
1310 SETQ;
1311 result += Rn;
1312 }
1313 state->Reg[BITS (16, 19)] = (ARMword)result;
1314 break;
1315 }
1316
1317 if (BITS (4, 11) == 5) {
1318 /* ElSegundo QSUB insn. */
1319 ARMword op1 = state->Reg[BITS (0, 3)];
1320 ARMword op2 = state->Reg[BITS (16, 19)];
1321 ARMword result = op1 - op2;
1322
1323 if (SubOverflow
1324 (op1, op2, result)) {
1325 result = POS (result) ? 0x80000000 : 0x7fffffff;
1326 SETQ;
1327 }
1328
1329 state->Reg[BITS (12, 15)] = result;
1330 break;
1331 }
1332 }
1333#ifdef MODET
1334 if (BITS (4, 11) == 0xB) {
1335 /* STRH register offset, write-back, down, pre indexed. */
1336 SHPREDOWNWB ();
1337 break;
1338 }
1339 if (BITS (4, 27) == 0x12FFF1) {
1340 /* BX */
1341 WriteR15Branch (state, state->Reg[RHSReg]);
1342 break;
1343 }
1344 if (BITS (4, 7) == 0xD) {
1345 Handle_Load_Double (state, instr);
1346 break;
1347 }
1348 if (BITS (4, 7) == 0xF) {
1349 Handle_Store_Double (state, instr);
1350 break;
1351 }
1352#endif
1353 if (state->is_v5) {
1354 if (BITS (4, 7) == 0x7) {
1355 //ARMword value;
1356 //extern int SWI_vector_installed;
1357
1358 /* Hardware is allowed to optionally override this
1359 instruction and treat it as a breakpoint. Since
1360 this is a simulator not hardware, we take the position
1361 that if a SWI vector was not installed, then an Abort
1362 vector was probably not installed either, and so
1363 normally this instruction would be ignored, even if an
1364 Abort is generated. This is a bad thing, since GDB
1365 uses this instruction for its breakpoints (at least in
1366 Thumb mode it does). So intercept the instruction here
1367 and generate a breakpoint SWI instead. */
1368 /* Force the next instruction to be refetched. */
1369 state->NextInstr = RESUME;
1370 break;
1371 }
1372 }
1373 if (DESTReg == 15) {
1374 /* MSR reg to CPSR. */
1375 UNDEF_MSRPC;
1376 temp = DPRegRHS;
1377#ifdef MODET
1378 /* Don't allow TBIT to be set by MSR. */
1379 temp &= ~TBIT;
1380#endif
1381 ARMul_FixCPSR (state, instr, temp);
1382 } else
1383 UNDEF_Test;
1384
1385 break;
1386
1387 case 0x13: /* TEQP reg */
1388#ifdef MODET
1389 if ((BITS (4, 11) & 0xF9) == 0x9)
1390 /* LDR register offset, write-back, down, pre indexed. */
1391 LHPREDOWNWB ();
1392 /* Continue with remaining instruction decode. */
1393#endif
1394 if (DESTReg == 15) {
1395 /* TEQP reg */
1396#ifdef MODE32
1397 state->Cpsr = GETSPSR (state->Bank);
1398 ARMul_CPSRAltered (state);
1399#else
1400 rhs = DPRegRHS;
1401 temp = LHS ^ rhs;
1402 SETR15PSR (temp);
1403#endif
1404 } else {
1405 /* TEQ Reg. */
1406 rhs = DPSRegRHS;
1407 dest = LHS ^ rhs;
1408 ARMul_NegZero (state, dest);
1409 }
1410 break;
1411
1412 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1413 if (state->is_v5e) {
1414 if (BIT (4) == 0 && BIT (7) == 1) {
1415 /* ElSegundo SMLALxy insn. */
1416 unsigned long long op1 = state->Reg[BITS (0, 3)];
1417 unsigned long long op2 = state->Reg[BITS (8, 11)];
1418 unsigned long long dest;
1419 //unsigned long long result;
1420
1421 if (BIT (5))
1422 op1 >>= 16;
1423 if (BIT (6))
1424 op2 >>= 16;
1425 op1 &= 0xFFFF;
1426 if (op1 & 0x8000)
1427 op1 -= 65536;
1428 op2 &= 0xFFFF;
1429 if (op2 & 0x8000)
1430 op2 -= 65536;
1431
1432 dest = (unsigned long long) state->Reg[BITS (16, 19)] << 32;
1433 dest |= state->Reg[BITS (12, 15)];
1434 dest += op1 * op2;
1435 state->Reg[BITS(12, 15)] = (ARMword)dest;
1436 state->Reg[BITS(16, 19)] = (ARMword)(dest >> 32);
1437 break;
1438 }
1439
1440 if (BITS (4, 11) == 5) {
1441 /* ElSegundo QDADD insn. */
1442 ARMword op1 = state->Reg[BITS (0, 3)];
1443 ARMword op2 = state->Reg[BITS (16, 19)];
1444 ARMword op2d = op2 + op2;
1445 ARMword result;
1446
1447 if (AddOverflow
1448 (op2, op2, op2d)) {
1449 SETQ;
1450 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1451 }
1452
1453 result = op1 + op2d;
1454 if (AddOverflow(op1, op2d, result)) {
1455 SETQ;
1456 result = POS (result) ? 0x80000000 : 0x7fffffff;
1457 }
1458
1459 state->Reg[BITS (12, 15)] = result;
1460 break;
1461 }
1462 }
1463#ifdef MODET
1464 if (BITS (4, 7) == 0xB) {
1465 /* STRH immediate offset, no write-back, down, pre indexed. */
1466 SHPREDOWN ();
1467 break;
1468 }
1469 if (BITS (4, 7) == 0xD) {
1470 Handle_Load_Double (state, instr);
1471 break;
1472 }
1473 if (BITS (4, 7) == 0xF) {
1474 Handle_Store_Double (state, instr);
1475 break;
1476 }
1477#endif
1478 if (BITS (4, 11) == 9) {
1479 /* SWP */
1480 UNDEF_SWPPC;
1481 temp = LHS;
1482 BUSUSEDINCPCS;
1483#ifndef MODE32
1484 if (VECTORACCESS (temp) || ADDREXCEPT (temp)) {
1485 INTERNALABORT (temp);
1486 (void) ARMul_LoadByte (state, temp);
1487 (void) ARMul_LoadByte (state, temp);
1488 } else
1489#endif
1490 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
1491 if (state->abortSig || state->Aborted)
1492 TAKEABORT;
1493 } else if ((BITS (0, 11) == 0)
1494 && (LHSReg == 15)) {
1495 /* MRS SPSR */
1496 UNDEF_MRSPC;
1497 DEST = GETSPSR (state->Bank);
1498 } else
1499 UNDEF_Test;
1500
1501 break;
1502
1503 case 0x15: /* CMPP reg. */
1504#ifdef MODET
1505 if ((BITS (4, 7) & 0x9) == 0x9)
1506 /* LDR immediate offset, no write-back, down, pre indexed. */
1507 LHPREDOWN ();
1508 /* Continue with remaining instruction decode. */
1509#endif
1510 if (DESTReg == 15) {
1511 /* CMPP reg. */
1512#ifdef MODE32
1513 state->Cpsr = GETSPSR (state->Bank);
1514 ARMul_CPSRAltered (state);
1515#else
1516 rhs = DPRegRHS;
1517 temp = LHS - rhs;
1518 SETR15PSR (temp);
1519#endif
1520 } else {
1521 /* CMP reg. */
1522 lhs = LHS;
1523 rhs = DPRegRHS;
1524 dest = lhs - rhs;
1525 ARMul_NegZero (state, dest);
1526 if ((lhs >= rhs)
1527 || ((rhs | lhs) >> 31)) {
1528 ARMul_SubCarry (state, lhs, rhs, dest);
1529 ARMul_SubOverflow (state, lhs, rhs, dest);
1530 } else {
1531 CLEARC;
1532 CLEARV;
1533 }
1534 }
1535 break;
1536
1537 case 0x16: /* CMN reg and MSR reg to SPSR */
1538 if (state->is_v5e) {
1539 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0) {
1540 /* ElSegundo SMULxy insn. */
1541 ARMword op1 = state->Reg[BITS (0, 3)];
1542 ARMword op2 = state->Reg[BITS (8, 11)];
1543 ARMword Rn = state->Reg[BITS (12, 15)];
1544
1545 if (BIT (5))
1546 op1 >>= 16;
1547 if (BIT (6))
1548 op2 >>= 16;
1549 op1 &= 0xFFFF;
1550 op2 &= 0xFFFF;
1551 if (op1 & 0x8000)
1552 op1 -= 65536;
1553 if (op2 & 0x8000)
1554 op2 -= 65536;
1555
1556 state->Reg[BITS (16, 19)] = op1 * op2;
1557 break;
1558 }
1559
1560 if (BITS (4, 11) == 5) {
1561 /* ElSegundo QDSUB insn. */
1562 ARMword op1 = state->Reg[BITS (0, 3)];
1563 ARMword op2 = state->Reg[BITS (16, 19)];
1564 ARMword op2d = op2 + op2;
1565 ARMword result;
1566
1567 if (AddOverflow(op2, op2, op2d)) {
1568 SETQ;
1569 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1570 }
1571
1572 result = op1 - op2d;
1573 if (SubOverflow(op1, op2d, result)) {
1574 SETQ;
1575 result = POS (result) ? 0x80000000 : 0x7fffffff;
1576 }
1577
1578 state->Reg[BITS (12, 15)] = result;
1579 break;
1580 }
1581 }
1582
1583 if (state->is_v5) {
1584 if (BITS (4, 11) == 0xF1
1585 && BITS (16, 19) == 0xF) {
1586 /* ARM5 CLZ insn. */
1587 ARMword op1 = state->Reg[BITS (0, 3)];
1588 int result = 32;
1589
1590 if (op1)
1591 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
1592 result++;
1593 state->Reg[BITS (12, 15)] = result;
1594 break;
1595 }
1596 }
1597
1598#ifdef MODET
1599 if (BITS (4, 7) == 0xB) {
1600 /* STRH immediate offset, write-back, down, pre indexed. */
1601 SHPREDOWNWB ();
1602 break;
1603 }
1604 if (BITS (4, 7) == 0xD) {
1605 Handle_Load_Double (state, instr);
1606 break;
1607 }
1608 if (BITS (4, 7) == 0xF) {
1609 Handle_Store_Double (state, instr);
1610 break;
1611 }
1612#endif
1613 if (DESTReg == 15) {
1614 /* MSR */
1615 UNDEF_MSRPC;
1616 /*ARMul_FixSPSR (state, instr,
1617 DPRegRHS);*/
1618 } else {
1619 UNDEF_Test;
1620 }
1621 break;
1622
1623 case 0x17: /* CMNP reg */
1624#ifdef MODET
1625 if ((BITS (4, 7) & 0x9) == 0x9)
1626 /* LDR immediate offset, write-back, down, pre indexed. */
1627 LHPREDOWNWB ();
1628 /* Continue with remaining instruction decoding. */
1629#endif
1630 if (DESTReg == 15) {
1631#ifdef MODE32
1632 state->Cpsr = GETSPSR (state->Bank);
1633 ARMul_CPSRAltered (state);
1634#else
1635 rhs = DPRegRHS;
1636 temp = LHS + rhs;
1637 SETR15PSR (temp);
1638#endif
1639 break;
1640 } else {
1641 /* CMN reg. */
1642 lhs = LHS;
1643 rhs = DPRegRHS;
1644 dest = lhs + rhs;
1645 ASSIGNZ (dest == 0);
1646 if ((lhs | rhs) >> 30) {
1647 /* Possible C,V,N to set. */
1648 ASSIGNN (NEG (dest));
1649 ARMul_AddCarry (state, lhs, rhs, dest);
1650 ARMul_AddOverflow (state, lhs, rhs, dest);
1651 } else {
1652 CLEARN;
1653 CLEARC;
1654 CLEARV;
1655 }
1656 }
1657 break;
1658
1659 case 0x18: /* ORR reg */
1660#ifdef MODET
1661 /* dyf add armv6 instr strex 2010.9.17 */
1662 if (state->is_v6) {
1663 if (BITS (4, 7) == 0x9)
1664 if (handle_v6_insn (state, instr))
1665 break;
1666 }
1667
1668 if (BITS (4, 11) == 0xB) {
1669 /* STRH register offset, no write-back, up, pre indexed. */
1670 SHPREUP ();
1671 break;
1672 }
1673 if (BITS (4, 7) == 0xD) {
1674 Handle_Load_Double (state, instr);
1675 break;
1676 }
1677 if (BITS (4, 7) == 0xF) {
1678 Handle_Store_Double (state, instr);
1679 break;
1680 }
1681#endif
1682 rhs = DPRegRHS;
1683 dest = LHS | rhs;
1684 WRITEDEST (dest);
1685 break;
1686
1687 case 0x19: /* ORRS reg */
1688#ifdef MODET
1689 /* dyf add armv6 instr ldrex */
1690 if (state->is_v6) {
1691 if (BITS (4, 7) == 0x9) {
1692 if (handle_v6_insn (state, instr))
1693 break;
1694 }
1695 }
1696 if ((BITS (4, 11) & 0xF9) == 0x9)
1697 /* LDR register offset, no write-back, up, pre indexed. */
1698 LHPREUP ();
1699 /* Continue with remaining instruction decoding. */
1700#endif
1701 rhs = DPSRegRHS;
1702 dest = LHS | rhs;
1703 WRITESDEST (dest);
1704 break;
1705
1706 case 0x1a: /* MOV reg */
1707#ifdef MODET
1708 if (BITS (4, 11) == 0xB) {
1709 /* STRH register offset, write-back, up, pre indexed. */
1710 SHPREUPWB ();
1711 break;
1712 }
1713 if (BITS (4, 7) == 0xD) {
1714 Handle_Load_Double (state, instr);
1715 break;
1716 }
1717 if (BITS (4, 7) == 0xF) {
1718 Handle_Store_Double (state, instr);
1719 break;
1720 }
1721 if (BITS(4, 11) == 0xF9) { //strexd
1722 u32 l = LHSReg;
1723
1724 bool enter = false;
1725
1726 if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr)&&
1727 state->currentexvald == (u32)ARMul_ReadWord(state, state->currentexaddr + 4))
1728 enter = true;
1729
1730 //todo bug this and STREXD and LDREXD http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360e/CHDGJGGC.html
1731
1732 if (enter) {
1733 ARMul_StoreWordN(state, LHS, state->Reg[RHSReg]);
1734 ARMul_StoreWordN(state,LHS + 4 , state->Reg[RHSReg + 1]);
1735 state->Reg[DESTReg] = 0;
1736 } else {
1737 state->Reg[DESTReg] = 1;
1738 }
1739
1740 break;
1741 }
1742#endif
1743 dest = DPRegRHS;
1744 WRITEDEST (dest);
1745 break;
1746
1747 case 0x1B: /* MOVS reg */
1748#ifdef MODET
1749 /* ldrexd ichfly */
1750 if (BITS(0, 11) == 0xF9F) { //strexd
1751 lhs = LHS;
1752
1753 state->currentexaddr = lhs;
1754 state->currentexval = (u32)ARMul_ReadWord(state, lhs);
1755 state->currentexvald = (u32)ARMul_ReadWord(state, lhs + 4);
1756
1757 state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs);
1758 state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs + 4);
1759 break;
1760 }
1761
1762 if ((BITS (4, 11) & 0xF9) == 0x9)
1763 /* LDR register offset, write-back, up, pre indexed. */
1764 LHPREUPWB ();
1765 /* Continue with remaining instruction decoding. */
1766
1767#endif
1768 dest = DPSRegRHS;
1769 WRITESDEST (dest);
1770 break;
1771
1772 case 0x1c: /* BIC reg */
1773#ifdef MODET
1774 /* dyf add for STREXB */
1775 if (state->is_v6) {
1776 if (BITS (4, 7) == 0x9) {
1777 if (handle_v6_insn (state, instr))
1778 break;
1779 }
1780 }
1781 if (BITS (4, 7) == 0xB) {
1782 /* STRH immediate offset, no write-back, up, pre indexed. */
1783 SHPREUP ();
1784 break;
1785 }
1786 if (BITS (4, 7) == 0xD) {
1787 Handle_Load_Double (state, instr);
1788 break;
1789 } else if (BITS (4, 7) == 0xF) {
1790 Handle_Store_Double (state, instr);
1791 break;
1792 }
1793#endif
1794 rhs = DPRegRHS;
1795 dest = LHS & ~rhs;
1796 WRITEDEST (dest);
1797 break;
1798
1799 case 0x1d: /* BICS reg */
1800#ifdef MODET
1801 /* ladsh P=1 U=1 W=0 L=1 S=1 H=1 */
1802 if (BITS(4, 7) == 0xF) {
1803 temp = LHS + GetLS7RHS (state, instr);
1804 LoadHalfWord (state, instr, temp, LSIGNED);
1805 break;
1806 }
1807 if (BITS (4, 7) == 0xb) {
1808 /* LDRH immediate offset, no write-back, up, pre indexed. */
1809 temp = LHS + GetLS7RHS (state, instr);
1810 LoadHalfWord (state, instr, temp, LUNSIGNED);
1811 break;
1812 }
1813 if (BITS (4, 7) == 0xd) {
1814 // alex-ykl fix: 2011-07-20 missing ldrsb instruction
1815 temp = LHS + GetLS7RHS (state, instr);
1816 LoadByte (state, instr, temp, LSIGNED);
1817 break;
1818 }
1819
1820 /* Continue with instruction decoding. */
1821 /*if ((BITS (4, 7) & 0x9) == 0x9) */
1822 if ((BITS (4, 7)) == 0x9) {
1823 /* ldrexb */
1824 if (state->is_v6) {
1825 if (handle_v6_insn (state, instr))
1826 break;
1827 }
1828 /* LDR immediate offset, no write-back, up, pre indexed. */
1829 LHPREUP ();
1830 }
1831
1832#endif
1833 rhs = DPSRegRHS;
1834 dest = LHS & ~rhs;
1835 WRITESDEST (dest);
1836 break;
1837
1838 case 0x1e: /* MVN reg */
1839#ifdef MODET
1840 if ((instr & 0x00000FF0) == 0x00000F90) { //if ((instr & 0x0FF00FF0) == 0x01e00f90) { //todo make that better ichfly
1841 /* strexh ichfly */
1842 u32 l = LHSReg;
1843 u32 r = RHSReg;
1844 lhs = LHS;
1845
1846 bool enter = false;
1847
1848 if (state->currentexval == (u32)ARMul_LoadHalfWord(state, state->currentexaddr))enter = true;
1849
1850 //StoreWord(state, lhs, RHS)
1851 if (state->Aborted) {
1852 TAKEABORT;
1853 }
1854 if (enter) {
1855 ARMul_StoreHalfWord(state, lhs, RHS);
1856 state->Reg[DESTReg] = 0;
1857 } else {
1858 state->Reg[DESTReg] = 1;
1859 }
1860 break;
1861 }
1862 if (BITS (4, 7) == 0xB) {
1863 /* STRH immediate offset, write-back, up, pre indexed. */
1864 SHPREUPWB ();
1865 break;
1866 }
1867 if (BITS (4, 7) == 0xD) {
1868 Handle_Load_Double (state, instr);
1869 break;
1870 }
1871 if (BITS (4, 7) == 0xF) {
1872 Handle_Store_Double (state, instr);
1873 break;
1874 }
1875#endif
1876 dest = ~DPRegRHS;
1877 WRITEDEST (dest);
1878 break;
1879
1880 case 0x1f: /* MVNS reg */
1881#ifdef MODET
1882
1883 if ((instr & 0x00000FF0) == 0x00000F90) { //(instr & 0x0FF00FF0) == 0x01f00f90)//if ((instr & 0x0FF00FF0) == 0x01f00f90) {
1884 /* ldrexh ichfly */
1885 lhs = LHS;
1886
1887 state->currentexaddr = lhs;
1888 state->currentexval = (u32)ARMul_LoadHalfWord(state, lhs);
1889
1890 LoadHalfWord(state, instr, lhs,0);
1891 break;
1892 }
1893
1894 if ((BITS (4, 7) & 0x9) == 0x9)
1895 /* LDR immediate offset, write-back, up, pre indexed. */
1896 LHPREUPWB ();
1897 /* Continue instruction decoding. */
1898#endif
1899 dest = ~DPSRegRHS;
1900 WRITESDEST (dest);
1901 break;
1902
1903 /* Data Processing Immediate RHS Instructions. */
1904
1905 case 0x20: /* AND immed */
1906 dest = LHS & DPImmRHS;
1907 WRITEDEST (dest);
1908 break;
1909
1910 case 0x21: /* ANDS immed */
1911 DPSImmRHS;
1912 dest = LHS & rhs;
1913 WRITESDEST (dest);
1914 break;
1915
1916 case 0x22: /* EOR immed */
1917 dest = LHS ^ DPImmRHS;
1918 WRITEDEST (dest);
1919 break;
1920
1921 case 0x23: /* EORS immed */
1922 DPSImmRHS;
1923 dest = LHS ^ rhs;
1924 WRITESDEST (dest);
1925 break;
1926
1927 case 0x24: /* SUB immed */
1928 dest = LHS - DPImmRHS;
1929 WRITEDEST (dest);
1930 break;
1931
1932 case 0x25: /* SUBS immed */
1933 lhs = LHS;
1934 rhs = DPImmRHS;
1935 dest = lhs - rhs;
1936
1937 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1938 ARMul_SubCarry (state, lhs, rhs, dest);
1939 ARMul_SubOverflow (state, lhs, rhs, dest);
1940 } else {
1941 CLEARC;
1942 CLEARV;
1943 }
1944 WRITESDEST (dest);
1945 break;
1946
1947 case 0x26: /* RSB immed */
1948 dest = DPImmRHS - LHS;
1949 WRITEDEST (dest);
1950 break;
1951
1952 case 0x27: /* RSBS immed */
1953 lhs = LHS;
1954 rhs = DPImmRHS;
1955 dest = rhs - lhs;
1956
1957 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
1958 ARMul_SubCarry (state, rhs, lhs, dest);
1959 ARMul_SubOverflow (state, rhs, lhs, dest);
1960 } else {
1961 CLEARC;
1962 CLEARV;
1963 }
1964 WRITESDEST (dest);
1965 break;
1966
1967 case 0x28: /* ADD immed */
1968 dest = LHS + DPImmRHS;
1969 WRITEDEST (dest);
1970 break;
1971
1972 case 0x29: /* ADDS immed */
1973 lhs = LHS;
1974 rhs = DPImmRHS;
1975 dest = lhs + rhs;
1976 ASSIGNZ (dest == 0);
1977
1978 if ((lhs | rhs) >> 30) {
1979 /* Possible C,V,N to set. */
1980 ASSIGNN (NEG (dest));
1981 ARMul_AddCarry (state, lhs, rhs, dest);
1982 ARMul_AddOverflow (state, lhs, rhs, dest);
1983 } else {
1984 CLEARN;
1985 CLEARC;
1986 CLEARV;
1987 }
1988 WRITESDEST (dest);
1989 break;
1990
1991 case 0x2a: /* ADC immed */
1992 dest = LHS + DPImmRHS + CFLAG;
1993 WRITEDEST (dest);
1994 break;
1995
1996 case 0x2b: /* ADCS immed */
1997 lhs = LHS;
1998 rhs = DPImmRHS;
1999 dest = lhs + rhs + CFLAG;
2000 ASSIGNZ (dest == 0);
2001 if ((lhs | rhs) >> 30) {
2002 /* Possible C,V,N to set. */
2003 ASSIGNN (NEG (dest));
2004 ARMul_AddCarry (state, lhs, rhs, dest);
2005 ARMul_AddOverflow (state, lhs, rhs, dest);
2006 } else {
2007 CLEARN;
2008 CLEARC;
2009 CLEARV;
2010 }
2011 WRITESDEST (dest);
2012 break;
2013
2014 case 0x2c: /* SBC immed */
2015 dest = LHS - DPImmRHS - !CFLAG;
2016 WRITEDEST (dest);
2017 break;
2018
2019 case 0x2d: /* SBCS immed */
2020 lhs = LHS;
2021 rhs = DPImmRHS;
2022 dest = lhs - rhs - !CFLAG;
2023 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
2024 ARMul_SubCarry (state, lhs, rhs, dest);
2025 ARMul_SubOverflow (state, lhs, rhs, dest);
2026 } else {
2027 CLEARC;
2028 CLEARV;
2029 }
2030 WRITESDEST (dest);
2031 break;
2032
2033 case 0x2e: /* RSC immed */
2034 dest = DPImmRHS - LHS - !CFLAG;
2035 WRITEDEST (dest);
2036 break;
2037
2038 case 0x2f: /* RSCS immed */
2039 lhs = LHS;
2040 rhs = DPImmRHS;
2041 dest = rhs - lhs - !CFLAG;
2042 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
2043 ARMul_SubCarry (state, rhs, lhs, dest);
2044 ARMul_SubOverflow (state, rhs, lhs, dest);
2045 } else {
2046 CLEARC;
2047 CLEARV;
2048 }
2049 WRITESDEST (dest);
2050 break;
2051
2052 case 0x30: /* TST immed */
2053 /* shenoubang 2012-3-14*/
2054 if (state->is_v6) { /* movw, ARMV6, ARMv7 */
2055 dest ^= dest;
2056 dest = BITS(16, 19);
2057 dest = ((dest<<12) | BITS(0, 11));
2058 WRITEDEST(dest);
2059 break;
2060 } else {
2061 UNDEF_Test;
2062 break;
2063 }
2064
2065 case 0x31: /* TSTP immed */
2066 if (DESTReg == 15) {
2067 /* TSTP immed. */
2068#ifdef MODE32
2069 state->Cpsr = GETSPSR (state->Bank);
2070 ARMul_CPSRAltered (state);
2071#else
2072 temp = LHS & DPImmRHS;
2073 SETR15PSR (temp);
2074#endif
2075 } else {
2076 /* TST immed. */
2077 DPSImmRHS;
2078 dest = LHS & rhs;
2079 ARMul_NegZero (state, dest);
2080 }
2081 break;
2082
2083 case 0x32: /* TEQ immed and MSR immed to CPSR */
2084 if (DESTReg == 15)
2085 /* MSR immed to CPSR. */
2086 ARMul_FixCPSR (state, instr,
2087 DPImmRHS);
2088 else
2089 UNDEF_Test;
2090 break;
2091
2092 case 0x33: /* TEQP immed */
2093 if (DESTReg == 15) {
2094 /* TEQP immed. */
2095#ifdef MODE32
2096 state->Cpsr = GETSPSR (state->Bank);
2097 ARMul_CPSRAltered (state);
2098#else
2099 temp = LHS ^ DPImmRHS;
2100 SETR15PSR (temp);
2101#endif
2102 } else {
2103 DPSImmRHS; /* TEQ immed */
2104 dest = LHS ^ rhs;
2105 ARMul_NegZero (state, dest);
2106 }
2107 break;
2108
2109 case 0x34: /* CMP immed */
2110 UNDEF_Test;
2111 break;
2112
2113 case 0x35: /* CMPP immed */
2114 if (DESTReg == 15) {
2115 /* CMPP immed. */
2116#ifdef MODE32
2117 state->Cpsr = GETSPSR (state->Bank);
2118 ARMul_CPSRAltered (state);
2119#else
2120 temp = LHS - DPImmRHS;
2121 SETR15PSR (temp);
2122#endif
2123 break;
2124 } else {
2125 /* CMP immed. */
2126 lhs = LHS;
2127 rhs = DPImmRHS;
2128 dest = lhs - rhs;
2129 ARMul_NegZero (state, dest);
2130
2131 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
2132 ARMul_SubCarry (state, lhs, rhs, dest);
2133 ARMul_SubOverflow (state, lhs, rhs, dest);
2134 } else {
2135 CLEARC;
2136 CLEARV;
2137 }
2138 }
2139 break;
2140
2141 case 0x36: /* CMN immed and MSR immed to SPSR */
2142 //if (DESTReg == 15)
2143 /*ARMul0_FixSPSR (state, instr,
2144 DPImmRHS);*/
2145 //else
2146 UNDEF_Test;
2147 break;
2148
2149 case 0x37: /* CMNP immed. */
2150 if (DESTReg == 15) {
2151 /* CMNP immed. */
2152#ifdef MODE32
2153 state->Cpsr = GETSPSR (state->Bank);
2154 ARMul_CPSRAltered (state);
2155#else
2156 temp = LHS + DPImmRHS;
2157 SETR15PSR (temp);
2158#endif
2159 break;
2160 } else {
2161 /* CMN immed. */
2162 lhs = LHS;
2163 rhs = DPImmRHS;
2164 dest = lhs + rhs;
2165 ASSIGNZ (dest == 0);
2166 if ((lhs | rhs) >> 30) {
2167 /* Possible C,V,N to set. */
2168 ASSIGNN (NEG (dest));
2169 ARMul_AddCarry (state, lhs, rhs, dest);
2170 ARMul_AddOverflow (state, lhs, rhs, dest);
2171 } else {
2172 CLEARN;
2173 CLEARC;
2174 CLEARV;
2175 }
2176 }
2177 break;
2178
2179 case 0x38: /* ORR immed. */
2180 dest = LHS | DPImmRHS;
2181 WRITEDEST (dest);
2182 break;
2183
2184 case 0x39: /* ORRS immed. */
2185 DPSImmRHS;
2186 dest = LHS | rhs;
2187 WRITESDEST (dest);
2188 break;
2189
2190 case 0x3a: /* MOV immed. */
2191 dest = DPImmRHS;
2192 WRITEDEST (dest);
2193 break;
2194
2195 case 0x3b: /* MOVS immed. */
2196 DPSImmRHS;
2197 WRITESDEST (rhs);
2198 break;
2199
2200 case 0x3c: /* BIC immed. */
2201 dest = LHS & ~DPImmRHS;
2202 WRITEDEST (dest);
2203 break;
2204
2205 case 0x3d: /* BICS immed. */
2206 DPSImmRHS;
2207 dest = LHS & ~rhs;
2208 WRITESDEST (dest);
2209 break;
2210
2211 case 0x3e: /* MVN immed. */
2212 dest = ~DPImmRHS;
2213 WRITEDEST (dest);
2214 break;
2215
2216 case 0x3f: /* MVNS immed. */
2217 DPSImmRHS;
2218 WRITESDEST (~rhs);
2219 break;
2220
2221 /* Single Data Transfer Immediate RHS Instructions. */
2222
2223 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2224 lhs = LHS;
2225 if (StoreWord (state, instr, lhs))
2226 LSBase = lhs - LSImmRHS;
2227 break;
2228
2229 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2230 lhs = LHS;
2231 if (LoadWord (state, instr, lhs))
2232 LSBase = lhs - LSImmRHS;
2233 break;
2234
2235 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2236 UNDEF_LSRBaseEQDestWb;
2237 UNDEF_LSRPCBaseWb;
2238 lhs = LHS;
2239 temp = lhs - LSImmRHS;
2240 state->NtransSig = LOW;
2241 if (StoreWord (state, instr, lhs))
2242 LSBase = temp;
2243 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2244 break;
2245
2246 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2247 UNDEF_LSRBaseEQDestWb;
2248 UNDEF_LSRPCBaseWb;
2249 lhs = LHS;
2250 state->NtransSig = LOW;
2251 if (LoadWord (state, instr, lhs))
2252 LSBase = lhs - LSImmRHS;
2253 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2254 break;
2255
2256 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2257 lhs = LHS;
2258 if (StoreByte (state, instr, lhs))
2259 LSBase = lhs - LSImmRHS;
2260 break;
2261
2262 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2263 lhs = LHS;
2264 if (LoadByte (state, instr, lhs, LUNSIGNED))
2265 LSBase = lhs - LSImmRHS;
2266 break;
2267
2268 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2269 UNDEF_LSRBaseEQDestWb;
2270 UNDEF_LSRPCBaseWb;
2271 lhs = LHS;
2272 state->NtransSig = LOW;
2273 if (StoreByte (state, instr, lhs))
2274 LSBase = lhs - LSImmRHS;
2275 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2276 break;
2277
2278 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2279 UNDEF_LSRBaseEQDestWb;
2280 UNDEF_LSRPCBaseWb;
2281 lhs = LHS;
2282 state->NtransSig = LOW;
2283 if (LoadByte (state, instr, lhs, LUNSIGNED))
2284 LSBase = lhs - LSImmRHS;
2285 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2286 break;
2287
2288 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2289 lhs = LHS;
2290 if (StoreWord (state, instr, lhs))
2291 LSBase = lhs + LSImmRHS;
2292 break;
2293
2294 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2295 lhs = LHS;
2296 if (LoadWord (state, instr, lhs))
2297 LSBase = lhs + LSImmRHS;
2298 break;
2299
2300 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2301 UNDEF_LSRBaseEQDestWb;
2302 UNDEF_LSRPCBaseWb;
2303 lhs = LHS;
2304 state->NtransSig = LOW;
2305 if (StoreWord (state, instr, lhs))
2306 LSBase = lhs + LSImmRHS;
2307 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2308 break;
2309
2310 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2311 UNDEF_LSRBaseEQDestWb;
2312 UNDEF_LSRPCBaseWb;
2313 lhs = LHS;
2314 state->NtransSig = LOW;
2315 if (LoadWord (state, instr, lhs))
2316 LSBase = lhs + LSImmRHS;
2317 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2318 break;
2319
2320 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2321 lhs = LHS;
2322 if (StoreByte (state, instr, lhs))
2323 LSBase = lhs + LSImmRHS;
2324 break;
2325
2326 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2327 lhs = LHS;
2328 if (LoadByte (state, instr, lhs, LUNSIGNED))
2329 LSBase = lhs + LSImmRHS;
2330 break;
2331
2332 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2333 UNDEF_LSRBaseEQDestWb;
2334 UNDEF_LSRPCBaseWb;
2335 lhs = LHS;
2336 state->NtransSig = LOW;
2337 if (StoreByte (state, instr, lhs))
2338 LSBase = lhs + LSImmRHS;
2339 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2340 break;
2341
2342 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2343 UNDEF_LSRBaseEQDestWb;
2344 UNDEF_LSRPCBaseWb;
2345 lhs = LHS;
2346 state->NtransSig = LOW;
2347 if (LoadByte (state, instr, lhs, LUNSIGNED))
2348 LSBase = lhs + LSImmRHS;
2349 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2350 break;
2351
2352 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2353 (void) StoreWord (state, instr, LHS - LSImmRHS);
2354 break;
2355
2356 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2357 (void) LoadWord (state, instr, LHS - LSImmRHS);
2358 break;
2359
2360 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2361 UNDEF_LSRBaseEQDestWb;
2362 UNDEF_LSRPCBaseWb;
2363 temp = LHS - LSImmRHS;
2364 if (StoreWord (state, instr, temp))
2365 LSBase = temp;
2366 break;
2367
2368 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2369 UNDEF_LSRBaseEQDestWb;
2370 UNDEF_LSRPCBaseWb;
2371 temp = LHS - LSImmRHS;
2372 if (LoadWord (state, instr, temp))
2373 LSBase = temp;
2374 break;
2375
2376 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2377 (void) StoreByte (state, instr, LHS - LSImmRHS);
2378 break;
2379
2380 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2381 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2382 break;
2383
2384 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2385 UNDEF_LSRBaseEQDestWb;
2386 UNDEF_LSRPCBaseWb;
2387 temp = LHS - LSImmRHS;
2388 if (StoreByte (state, instr, temp))
2389 LSBase = temp;
2390 break;
2391
2392 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2393 UNDEF_LSRBaseEQDestWb;
2394 UNDEF_LSRPCBaseWb;
2395 temp = LHS - LSImmRHS;
2396 if (LoadByte (state, instr, temp, LUNSIGNED))
2397 LSBase = temp;
2398 break;
2399
2400 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2401 (void) StoreWord (state, instr, LHS + LSImmRHS);
2402 break;
2403
2404 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2405 (void) LoadWord (state, instr, LHS + LSImmRHS);
2406 break;
2407
2408 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2409 UNDEF_LSRBaseEQDestWb;
2410 UNDEF_LSRPCBaseWb;
2411 temp = LHS + LSImmRHS;
2412 if (StoreWord (state, instr, temp))
2413 LSBase = temp;
2414 break;
2415
2416 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2417 UNDEF_LSRBaseEQDestWb;
2418 UNDEF_LSRPCBaseWb;
2419 temp = LHS + LSImmRHS;
2420 if (LoadWord (state, instr, temp))
2421 LSBase = temp;
2422 break;
2423
2424 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2425 (void) StoreByte (state, instr, LHS + LSImmRHS);
2426 break;
2427
2428 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2429 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2430 break;
2431
2432 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2433 UNDEF_LSRBaseEQDestWb;
2434 UNDEF_LSRPCBaseWb;
2435 temp = LHS + LSImmRHS;
2436 if (StoreByte (state, instr, temp))
2437 LSBase = temp;
2438 break;
2439
2440 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2441 UNDEF_LSRBaseEQDestWb;
2442 UNDEF_LSRPCBaseWb;
2443 temp = LHS + LSImmRHS;
2444 if (LoadByte (state, instr, temp, LUNSIGNED))
2445 LSBase = temp;
2446 break;
2447
2448 /* Single Data Transfer Register RHS Instructions. */
2449
2450 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2451 if (BIT (4)) {
2452 ARMul_UndefInstr (state, instr);
2453 break;
2454 }
2455 UNDEF_LSRBaseEQOffWb;
2456 UNDEF_LSRBaseEQDestWb;
2457 UNDEF_LSRPCBaseWb;
2458 UNDEF_LSRPCOffWb;
2459 lhs = LHS;
2460 if (StoreWord (state, instr, lhs))
2461 LSBase = lhs - LSRegRHS;
2462 break;
2463
2464 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2465 if (BIT (4)) {
2466#ifdef MODE32
2467 if (state->is_v6 && handle_v6_insn (state, instr))
2468 break;
2469#endif
2470 ARMul_UndefInstr (state, instr);
2471 break;
2472 }
2473 UNDEF_LSRBaseEQOffWb;
2474 UNDEF_LSRBaseEQDestWb;
2475 UNDEF_LSRPCBaseWb;
2476 UNDEF_LSRPCOffWb;
2477 lhs = LHS;
2478 temp = lhs - LSRegRHS;
2479 if (LoadWord (state, instr, lhs))
2480 LSBase = temp;
2481 break;
2482
2483 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2484 if (BIT (4)) {
2485#ifdef MODE32
2486 if (state->is_v6 && handle_v6_insn (state, instr))
2487 break;
2488#endif
2489 ARMul_UndefInstr (state, instr);
2490 break;
2491 }
2492 UNDEF_LSRBaseEQOffWb;
2493 UNDEF_LSRBaseEQDestWb;
2494 UNDEF_LSRPCBaseWb;
2495 UNDEF_LSRPCOffWb;
2496 lhs = LHS;
2497 state->NtransSig = LOW;
2498 if (StoreWord (state, instr, lhs))
2499 LSBase = lhs - LSRegRHS;
2500 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2501 break;
2502
2503 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2504 if (BIT (4)) {
2505#ifdef MODE32
2506 if (state->is_v6 && handle_v6_insn (state, instr))
2507 break;
2508#endif
2509 ARMul_UndefInstr (state, instr);
2510 break;
2511 }
2512 UNDEF_LSRBaseEQOffWb;
2513 UNDEF_LSRBaseEQDestWb;
2514 UNDEF_LSRPCBaseWb;
2515 UNDEF_LSRPCOffWb;
2516 lhs = LHS;
2517 temp = lhs - LSRegRHS;
2518 state->NtransSig = LOW;
2519 if (LoadWord (state, instr, lhs))
2520 LSBase = temp;
2521 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2522 break;
2523
2524 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2525 if (BIT (4)) {
2526 ARMul_UndefInstr (state, instr);
2527 break;
2528 }
2529 UNDEF_LSRBaseEQOffWb;
2530 UNDEF_LSRBaseEQDestWb;
2531 UNDEF_LSRPCBaseWb;
2532 UNDEF_LSRPCOffWb;
2533 lhs = LHS;
2534 if (StoreByte (state, instr, lhs))
2535 LSBase = lhs - LSRegRHS;
2536 break;
2537
2538 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2539 if (BIT (4)) {
2540#ifdef MODE32
2541 if (state->is_v6 && handle_v6_insn (state, instr))
2542 break;
2543#endif
2544 ARMul_UndefInstr (state, instr);
2545 break;
2546 }
2547 UNDEF_LSRBaseEQOffWb;
2548 UNDEF_LSRBaseEQDestWb;
2549 UNDEF_LSRPCBaseWb;
2550 UNDEF_LSRPCOffWb;
2551 lhs = LHS;
2552 temp = lhs - LSRegRHS;
2553 if (LoadByte (state, instr, lhs, LUNSIGNED))
2554 LSBase = temp;
2555 break;
2556
2557 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2558 if (BIT (4)) {
2559#ifdef MODE32
2560 if (state->is_v6 && handle_v6_insn (state, instr))
2561 break;
2562#endif
2563 ARMul_UndefInstr (state, instr);
2564 break;
2565 }
2566 UNDEF_LSRBaseEQOffWb;
2567 UNDEF_LSRBaseEQDestWb;
2568 UNDEF_LSRPCBaseWb;
2569 UNDEF_LSRPCOffWb;
2570 lhs = LHS;
2571 state->NtransSig = LOW;
2572 if (StoreByte (state, instr, lhs))
2573 LSBase = lhs - LSRegRHS;
2574 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2575 break;
2576
2577 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2578 if (BIT (4)) {
2579#ifdef MODE32
2580 if (state->is_v6
2581 && handle_v6_insn (state, instr))
2582 break;
2583#endif
2584
2585 ARMul_UndefInstr (state, instr);
2586 break;
2587 }
2588 UNDEF_LSRBaseEQOffWb;
2589 UNDEF_LSRBaseEQDestWb;
2590 UNDEF_LSRPCBaseWb;
2591 UNDEF_LSRPCOffWb;
2592 lhs = LHS;
2593 temp = lhs - LSRegRHS;
2594 state->NtransSig = LOW;
2595 if (LoadByte (state, instr, lhs, LUNSIGNED))
2596 LSBase = temp;
2597 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2598 break;
2599
2600 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2601 if ((instr & 0x70) == 0x10) { //pkhbt
2602 u8 idest = BITS(12, 15);
2603 u8 rfis = BITS(16, 19);
2604 u8 rlast = BITS(0, 3);
2605 u8 ishi = BITS(7,11);
2606 state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000);
2607 break;
2608 } else if ((instr & 0x70) == 0x50) { //pkhtb
2609 u8 rd_idx = BITS(12, 15);
2610 u8 rn_idx = BITS(16, 19);
2611 u8 rm_idx = BITS(0, 3);
2612 u8 imm5 = BITS(7, 11) ? BITS(7, 11) : 31;
2613 state->Reg[rd_idx] = ((static_cast<s32>(state->Reg[rm_idx]) >> imm5) & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000);
2614 break;
2615 } else if (BIT (4)) {
2616#ifdef MODE32
2617 if (state->is_v6
2618 && handle_v6_insn (state, instr))
2619 break;
2620#endif
2621
2622 ARMul_UndefInstr (state, instr);
2623 break;
2624 }
2625 UNDEF_LSRBaseEQOffWb;
2626 UNDEF_LSRBaseEQDestWb;
2627 UNDEF_LSRPCBaseWb;
2628 UNDEF_LSRPCOffWb;
2629 lhs = LHS;
2630 if (StoreWord (state, instr, lhs))
2631 LSBase = lhs + LSRegRHS;
2632 break;
2633
2634 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2635 if (BIT (4)) {
2636 ARMul_UndefInstr (state, instr);
2637 break;
2638 }
2639 UNDEF_LSRBaseEQOffWb;
2640 UNDEF_LSRBaseEQDestWb;
2641 UNDEF_LSRPCBaseWb;
2642 UNDEF_LSRPCOffWb;
2643 lhs = LHS;
2644 temp = lhs + LSRegRHS;
2645 if (LoadWord (state, instr, lhs))
2646 LSBase = temp;
2647 break;
2648
2649 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2650 if (BIT (4)) {
2651#ifdef MODE32
2652 if (state->is_v6
2653 && handle_v6_insn (state, instr))
2654 break;
2655#endif
2656
2657 ARMul_UndefInstr (state, instr);
2658 break;
2659 }
2660 UNDEF_LSRBaseEQOffWb;
2661 UNDEF_LSRBaseEQDestWb;
2662 UNDEF_LSRPCBaseWb;
2663 UNDEF_LSRPCOffWb;
2664 lhs = LHS;
2665 state->NtransSig = LOW;
2666 if (StoreWord (state, instr, lhs))
2667 LSBase = lhs + LSRegRHS;
2668 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2669 break;
2670
2671 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2672 if (BIT (4)) {
2673#ifdef MODE32
2674 if (state->is_v6
2675 && handle_v6_insn (state, instr))
2676 break;
2677#endif
2678
2679 ARMul_UndefInstr (state, instr);
2680 break;
2681 }
2682 UNDEF_LSRBaseEQOffWb;
2683 UNDEF_LSRBaseEQDestWb;
2684 UNDEF_LSRPCBaseWb;
2685 UNDEF_LSRPCOffWb;
2686 lhs = LHS;
2687 temp = lhs + LSRegRHS;
2688 state->NtransSig = LOW;
2689 if (LoadWord (state, instr, lhs))
2690 LSBase = temp;
2691 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2692 break;
2693
2694 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2695 if (BIT (4)) {
2696#ifdef MODE32
2697 if (state->is_v6
2698 && handle_v6_insn (state, instr))
2699 break;
2700#endif
2701
2702 ARMul_UndefInstr (state, instr);
2703 break;
2704 }
2705 UNDEF_LSRBaseEQOffWb;
2706 UNDEF_LSRBaseEQDestWb;
2707 UNDEF_LSRPCBaseWb;
2708 UNDEF_LSRPCOffWb;
2709 lhs = LHS;
2710 if (StoreByte (state, instr, lhs))
2711 LSBase = lhs + LSRegRHS;
2712 break;
2713
2714 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2715 if (BIT (4)) {
2716 ARMul_UndefInstr (state, instr);
2717 break;
2718 }
2719 UNDEF_LSRBaseEQOffWb;
2720 UNDEF_LSRBaseEQDestWb;
2721 UNDEF_LSRPCBaseWb;
2722 UNDEF_LSRPCOffWb;
2723 lhs = LHS;
2724 temp = lhs + LSRegRHS;
2725 if (LoadByte (state, instr, lhs, LUNSIGNED))
2726 LSBase = temp;
2727 break;
2728
2729 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
2730 if (BIT (4)) {
2731#ifdef MODE32
2732 if (state->is_v6
2733 && handle_v6_insn (state, instr))
2734 break;
2735#endif
2736
2737 ARMul_UndefInstr (state, instr);
2738 break;
2739 }
2740 UNDEF_LSRBaseEQOffWb;
2741 UNDEF_LSRBaseEQDestWb;
2742 UNDEF_LSRPCBaseWb;
2743 UNDEF_LSRPCOffWb;
2744 lhs = LHS;
2745 state->NtransSig = LOW;
2746 if (StoreByte (state, instr, lhs))
2747 LSBase = lhs + LSRegRHS;
2748 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2749 break;
2750
2751 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
2752 if (BIT (4)) {
2753#ifdef MODE32
2754 if (state->is_v6
2755 && handle_v6_insn (state, instr))
2756 break;
2757#endif
2758
2759 ARMul_UndefInstr (state, instr);
2760 break;
2761 }
2762 UNDEF_LSRBaseEQOffWb;
2763 UNDEF_LSRBaseEQDestWb;
2764 UNDEF_LSRPCBaseWb;
2765 UNDEF_LSRPCOffWb;
2766 lhs = LHS;
2767 temp = lhs + LSRegRHS;
2768 state->NtransSig = LOW;
2769 if (LoadByte (state, instr, lhs, LUNSIGNED))
2770 LSBase = temp;
2771 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2772 break;
2773
2774 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
2775 if (BIT (4)) {
2776#ifdef MODE32
2777 if (state->is_v6 && handle_v6_insn (state, instr))
2778 break;
2779#endif
2780 ARMul_UndefInstr (state, instr);
2781 break;
2782 }
2783 (void) StoreWord (state, instr, LHS - LSRegRHS);
2784 break;
2785
2786 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
2787 if (BIT (4)) {
2788 ARMul_UndefInstr (state, instr);
2789 break;
2790 }
2791 (void) LoadWord (state, instr, LHS - LSRegRHS);
2792 break;
2793
2794 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
2795 if (BIT (4)) {
2796 ARMul_UndefInstr (state, instr);
2797 break;
2798 }
2799 UNDEF_LSRBaseEQOffWb;
2800 UNDEF_LSRBaseEQDestWb;
2801 UNDEF_LSRPCBaseWb;
2802 UNDEF_LSRPCOffWb;
2803 temp = LHS - LSRegRHS;
2804 if (StoreWord (state, instr, temp))
2805 LSBase = temp;
2806 break;
2807
2808 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
2809 if (BIT (4)) {
2810 ARMul_UndefInstr (state, instr);
2811 break;
2812 }
2813 UNDEF_LSRBaseEQOffWb;
2814 UNDEF_LSRBaseEQDestWb;
2815 UNDEF_LSRPCBaseWb;
2816 UNDEF_LSRPCOffWb;
2817 temp = LHS - LSRegRHS;
2818 if (LoadWord (state, instr, temp))
2819 LSBase = temp;
2820 break;
2821
2822 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
2823 if (BIT (4)) {
2824#ifdef MODE32
2825 if (state->is_v6 && handle_v6_insn (state, instr))
2826 break;
2827#endif
2828 ARMul_UndefInstr (state, instr);
2829 break;
2830 }
2831 (void) StoreByte (state, instr, LHS - LSRegRHS);
2832 break;
2833
2834 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
2835 if (BIT (4)) {
2836#ifdef MODE32
2837 if (state->is_v6 && handle_v6_insn (state, instr))
2838 break;
2839#endif
2840 ARMul_UndefInstr (state, instr);
2841 break;
2842 }
2843 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
2844 break;
2845
2846 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
2847 if (BIT (4)) {
2848 ARMul_UndefInstr (state, instr);
2849 break;
2850 }
2851 UNDEF_LSRBaseEQOffWb;
2852 UNDEF_LSRBaseEQDestWb;
2853 UNDEF_LSRPCBaseWb;
2854 UNDEF_LSRPCOffWb;
2855 temp = LHS - LSRegRHS;
2856 if (StoreByte (state, instr, temp))
2857 LSBase = temp;
2858 break;
2859
2860 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
2861 if (BIT (4)) {
2862 ARMul_UndefInstr (state, instr);
2863 break;
2864 }
2865 UNDEF_LSRBaseEQOffWb;
2866 UNDEF_LSRBaseEQDestWb;
2867 UNDEF_LSRPCBaseWb;
2868 UNDEF_LSRPCOffWb;
2869 temp = LHS - LSRegRHS;
2870 if (LoadByte (state, instr, temp, LUNSIGNED))
2871 LSBase = temp;
2872 break;
2873
2874 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
2875 if (BIT (4)) {
2876#ifdef MODE32
2877 if (state->is_v6 && handle_v6_insn (state, instr))
2878 break;
2879#endif
2880
2881 ARMul_UndefInstr (state, instr);
2882 break;
2883 }
2884 (void) StoreWord (state, instr, LHS + LSRegRHS);
2885 break;
2886
2887 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
2888 if (BIT (4)) {
2889 ARMul_UndefInstr (state, instr);
2890 break;
2891 }
2892 (void) LoadWord (state, instr, LHS + LSRegRHS);
2893 break;
2894
2895 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
2896 if (BIT (4)) {
2897#ifdef MODE32
2898 if (state->is_v6 && handle_v6_insn (state, instr))
2899 break;
2900#endif
2901
2902 ARMul_UndefInstr (state, instr);
2903 break;
2904 }
2905 UNDEF_LSRBaseEQOffWb;
2906 UNDEF_LSRBaseEQDestWb;
2907 UNDEF_LSRPCBaseWb;
2908 UNDEF_LSRPCOffWb;
2909 temp = LHS + LSRegRHS;
2910 if (StoreWord (state, instr, temp))
2911 LSBase = temp;
2912 break;
2913
2914 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
2915 if (BIT (4)) {
2916 ARMul_UndefInstr (state, instr);
2917 break;
2918 }
2919 UNDEF_LSRBaseEQOffWb;
2920 UNDEF_LSRBaseEQDestWb;
2921 UNDEF_LSRPCBaseWb;
2922 UNDEF_LSRPCOffWb;
2923 temp = LHS + LSRegRHS;
2924 if (LoadWord (state, instr, temp))
2925 LSBase = temp;
2926 break;
2927
2928 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
2929 if (BIT (4)) {
2930#ifdef MODE32
2931 if (state->is_v6 && handle_v6_insn (state, instr))
2932 break;
2933#endif
2934
2935 ARMul_UndefInstr (state, instr);
2936 break;
2937 }
2938 (void) StoreByte (state, instr, LHS + LSRegRHS);
2939 break;
2940
2941 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
2942 if (BIT (4)) {
2943 ARMul_UndefInstr (state, instr);
2944 break;
2945 }
2946 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
2947 break;
2948
2949 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
2950 if (BIT (4)) {
2951 ARMul_UndefInstr (state, instr);
2952 break;
2953 }
2954 UNDEF_LSRBaseEQOffWb;
2955 UNDEF_LSRBaseEQDestWb;
2956 UNDEF_LSRPCBaseWb;
2957 UNDEF_LSRPCOffWb;
2958 temp = LHS + LSRegRHS;
2959 if (StoreByte (state, instr, temp))
2960 LSBase = temp;
2961 break;
2962
2963 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
2964 if (BIT (4)) {
2965 LOG_DEBUG(Core_ARM11, "got unhandled special breakpoint");
2966 return 1;
2967 }
2968 UNDEF_LSRBaseEQOffWb;
2969 UNDEF_LSRBaseEQDestWb;
2970 UNDEF_LSRPCBaseWb;
2971 UNDEF_LSRPCOffWb;
2972 temp = LHS + LSRegRHS;
2973 if (LoadByte (state, instr, temp, LUNSIGNED))
2974 LSBase = temp;
2975 break;
2976
2977 /* Multiple Data Transfer Instructions. */
2978
2979 case 0x80: /* Store, No WriteBack, Post Dec. */
2980 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2981 break;
2982
2983 case 0x81: /* Load, No WriteBack, Post Dec. */
2984 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2985 break;
2986
2987 case 0x82: /* Store, WriteBack, Post Dec. */
2988 temp = LSBase - LSMNumRegs;
2989 STOREMULT (instr, temp + 4L, temp);
2990 break;
2991
2992 case 0x83: /* Load, WriteBack, Post Dec. */
2993 temp = LSBase - LSMNumRegs;
2994 LOADMULT (instr, temp + 4L, temp);
2995 break;
2996
2997 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
2998 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2999 break;
3000
3001 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3002 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3003 break;
3004
3005 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3006 temp = LSBase - LSMNumRegs;
3007 STORESMULT (instr, temp + 4L, temp);
3008 break;
3009
3010 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3011 temp = LSBase - LSMNumRegs;
3012 LOADSMULT (instr, temp + 4L, temp);
3013 break;
3014
3015 case 0x88: /* Store, No WriteBack, Post Inc. */
3016 STOREMULT (instr, LSBase, 0L);
3017 break;
3018
3019 case 0x89: /* Load, No WriteBack, Post Inc. */
3020 LOADMULT (instr, LSBase, 0L);
3021 break;
3022
3023 case 0x8a: /* Store, WriteBack, Post Inc. */
3024 temp = LSBase;
3025 STOREMULT (instr, temp, temp + LSMNumRegs);
3026 break;
3027
3028 case 0x8b: /* Load, WriteBack, Post Inc. */
3029 temp = LSBase;
3030 LOADMULT (instr, temp, temp + LSMNumRegs);
3031 break;
3032
3033 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3034 STORESMULT (instr, LSBase, 0L);
3035 break;
3036
3037 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3038 LOADSMULT (instr, LSBase, 0L);
3039 break;
3040
3041 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3042 temp = LSBase;
3043 STORESMULT (instr, temp, temp + LSMNumRegs);
3044 break;
3045
3046 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3047 temp = LSBase;
3048 LOADSMULT (instr, temp, temp + LSMNumRegs);
3049 break;
3050
3051 case 0x90: /* Store, No WriteBack, Pre Dec. */
3052 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
3053 break;
3054
3055 case 0x91: /* Load, No WriteBack, Pre Dec. */
3056 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
3057 break;
3058
3059 case 0x92: /* Store, WriteBack, Pre Dec. */
3060 temp = LSBase - LSMNumRegs;
3061 STOREMULT (instr, temp, temp);
3062 break;
3063
3064 case 0x93: /* Load, WriteBack, Pre Dec. */
3065 temp = LSBase - LSMNumRegs;
3066 LOADMULT (instr, temp, temp);
3067 break;
3068
3069 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3070 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
3071 break;
3072
3073 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3074 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
3075 break;
3076
3077 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3078 temp = LSBase - LSMNumRegs;
3079 STORESMULT (instr, temp, temp);
3080 break;
3081
3082 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3083 temp = LSBase - LSMNumRegs;
3084 LOADSMULT (instr, temp, temp);
3085 break;
3086
3087 case 0x98: /* Store, No WriteBack, Pre Inc. */
3088 STOREMULT (instr, LSBase + 4L, 0L);
3089 break;
3090
3091 case 0x99: /* Load, No WriteBack, Pre Inc. */
3092 LOADMULT (instr, LSBase + 4L, 0L);
3093 break;
3094
3095 case 0x9a: /* Store, WriteBack, Pre Inc. */
3096 temp = LSBase;
3097 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3098 break;
3099
3100 case 0x9b: /* Load, WriteBack, Pre Inc. */
3101 temp = LSBase;
3102 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3103 break;
3104
3105 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3106 STORESMULT (instr, LSBase + 4L, 0L);
3107 break;
3108
3109 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3110 LOADSMULT (instr, LSBase + 4L, 0L);
3111 break;
3112
3113 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3114 temp = LSBase;
3115 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3116 break;
3117
3118 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3119 temp = LSBase;
3120 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3121 break;
3122
3123 /* Branch forward. */
3124 case 0xa0:
3125 case 0xa1:
3126 case 0xa2:
3127 case 0xa3:
3128 case 0xa4:
3129 case 0xa5:
3130 case 0xa6:
3131 case 0xa7:
3132 state->Reg[15] = pc + 8 + POSBRANCH;
3133 FLUSHPIPE;
3134 break;
3135
3136 /* Branch backward. */
3137 case 0xa8:
3138 case 0xa9:
3139 case 0xaa:
3140 case 0xab:
3141 case 0xac:
3142 case 0xad:
3143 case 0xae:
3144 case 0xaf:
3145 state->Reg[15] = pc + 8 + NEGBRANCH;
3146 FLUSHPIPE;
3147 break;
3148
3149 /* Branch and Link forward. */
3150 case 0xb0:
3151 case 0xb1:
3152 case 0xb2:
3153 case 0xb3:
3154 case 0xb4:
3155 case 0xb5:
3156 case 0xb6:
3157 case 0xb7:
3158
3159 /* Put PC into Link. */
3160#ifdef MODE32
3161 state->Reg[14] = pc + 4;
3162#else
3163 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3164#endif
3165 state->Reg[15] = pc + 8 + POSBRANCH;
3166 FLUSHPIPE;
3167 break;
3168
3169 /* Branch and Link backward. */
3170 case 0xb8:
3171 case 0xb9:
3172 case 0xba:
3173 case 0xbb:
3174 case 0xbc:
3175 case 0xbd:
3176 case 0xbe:
3177 case 0xbf:
3178 /* Put PC into Link. */
3179#ifdef MODE32
3180 state->Reg[14] = pc + 4;
3181#else
3182 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3183#endif
3184 state->Reg[15] = pc + 8 + NEGBRANCH;
3185 FLUSHPIPE;
3186 break;
3187
3188 /* Co-Processor Data Transfers. */
3189 case 0xc4:
3190 if ((instr & 0x0FF00FF0) == 0xC400B10) { //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0
3191 state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)];
3192 state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)];
3193 break;
3194 } else if (state->is_v5) {
3195 /* Reading from R15 is UNPREDICTABLE. */
3196 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3197 ARMul_UndefInstr (state, instr);
3198 /* Is access to coprocessor 0 allowed ? */
3199 else if (!CP_ACCESS_ALLOWED(state, CPNum))
3200 ARMul_UndefInstr (state, instr);
3201 else {
3202 /* MCRR, ARMv5TE and up */
3203 ARMul_MCRR (state, instr, DEST, state->Reg[LHSReg]);
3204 break;
3205 }
3206 }
3207 /* Drop through. */
3208
3209 case 0xc0: /* Store , No WriteBack , Post Dec. */
3210 ARMul_STC (state, instr, LHS);
3211 break;
3212
3213 case 0xc5:
3214 if ((instr & 0x00000FF0) == 0xB10) { //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0
3215 state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1];
3216 state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1];
3217 break;
3218 } else if (state->is_v5) {
3219 /* Writes to R15 are UNPREDICATABLE. */
3220 if (DESTReg == 15 || LHSReg == 15)
3221 ARMul_UndefInstr (state, instr);
3222 /* Is access to the coprocessor allowed ? */
3223 else if (!CP_ACCESS_ALLOWED(state, CPNum)) {
3224 ARMul_UndefInstr(state, instr);
3225 } else {
3226 /* MRRC, ARMv5TE and up */
3227 ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg]));
3228 break;
3229 }
3230 }
3231 /* Drop through. */
3232
3233 case 0xc1: /* Load , No WriteBack , Post Dec. */
3234 ARMul_LDC (state, instr, LHS);
3235 break;
3236
3237 case 0xc2:
3238 case 0xc6: /* Store , WriteBack , Post Dec. */
3239 lhs = LHS;
3240 state->Base = lhs - LSCOff;
3241 ARMul_STC (state, instr, lhs);
3242 break;
3243
3244 case 0xc3:
3245 case 0xc7: /* Load , WriteBack , Post Dec. */
3246 lhs = LHS;
3247 state->Base = lhs - LSCOff;
3248 ARMul_LDC (state, instr, lhs);
3249 break;
3250
3251 case 0xc8:
3252 case 0xcc: /* Store , No WriteBack , Post Inc. */
3253 ARMul_STC (state, instr, LHS);
3254 break;
3255
3256 case 0xc9:
3257 case 0xcd: /* Load , No WriteBack , Post Inc. */
3258 ARMul_LDC (state, instr, LHS);
3259 break;
3260
3261 case 0xca:
3262 case 0xce: /* Store , WriteBack , Post Inc. */
3263 lhs = LHS;
3264 state->Base = lhs + LSCOff;
3265 ARMul_STC (state, instr, LHS);
3266 break;
3267
3268 case 0xcb:
3269 case 0xcf: /* Load , WriteBack , Post Inc. */
3270 lhs = LHS;
3271 state->Base = lhs + LSCOff;
3272 ARMul_LDC (state, instr, LHS);
3273 break;
3274
3275 case 0xd0:
3276 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3277 ARMul_STC (state, instr, LHS - LSCOff);
3278 break;
3279
3280 case 0xd1:
3281 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3282 ARMul_LDC (state, instr, LHS - LSCOff);
3283 break;
3284
3285 case 0xd2:
3286 case 0xd6: /* Store , WriteBack , Pre Dec. */
3287 lhs = LHS - LSCOff;
3288 state->Base = lhs;
3289 ARMul_STC (state, instr, lhs);
3290 break;
3291
3292 case 0xd3:
3293 case 0xd7: /* Load , WriteBack , Pre Dec. */
3294 lhs = LHS - LSCOff;
3295 state->Base = lhs;
3296 ARMul_LDC (state, instr, lhs);
3297 break;
3298
3299 case 0xd8:
3300 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3301 ARMul_STC (state, instr, LHS + LSCOff);
3302 break;
3303
3304 case 0xd9:
3305 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3306 ARMul_LDC (state, instr, LHS + LSCOff);
3307 break;
3308
3309 case 0xda:
3310 case 0xde: /* Store , WriteBack , Pre Inc. */
3311 lhs = LHS + LSCOff;
3312 state->Base = lhs;
3313 ARMul_STC (state, instr, lhs);
3314 break;
3315
3316 case 0xdb:
3317 case 0xdf: /* Load , WriteBack , Pre Inc. */
3318 lhs = LHS + LSCOff;
3319 state->Base = lhs;
3320 ARMul_LDC (state, instr, lhs);
3321 break;
3322
3323 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3324
3325 case 0xe2:
3326 /*if (!CP_ACCESS_ALLOWED (state, CPNum)) {
3327 ARMul_UndefInstr (state, instr);
3328 break;
3329 }*/
3330
3331 case 0xe0:
3332 case 0xe4:
3333 case 0xe6:
3334 case 0xe8:
3335 case 0xea:
3336 case 0xec:
3337 case 0xee:
3338 if (BIT (4)) {
3339 /* MCR. */
3340 if (DESTReg == 15) {
3341 UNDEF_MCRPC;
3342#ifdef MODE32
3343 ARMul_MCR (state, instr, state->Reg[15] + isize);
3344#else
3345 ARMul_MCR (state, instr, ECC | ER15INT | EMODE | ((state->Reg[15] + isize) & R15PCBITS));
3346#endif
3347 } else
3348 ARMul_MCR (state, instr, DEST);
3349 } else
3350 /* CDP Part 1. */
3351 ARMul_CDP (state, instr);
3352 break;
3353
3354 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3355 case 0xe1:
3356 case 0xe3:
3357 case 0xe5:
3358 case 0xe7:
3359 case 0xe9:
3360 case 0xeb:
3361 case 0xed:
3362 case 0xef:
3363 if (BIT (4)) {
3364 /* MRC */
3365 temp = ARMul_MRC (state, instr);
3366 if (DESTReg == 15) {
3367 ASSIGNN ((temp & NBIT) != 0);
3368 ASSIGNZ ((temp & ZBIT) != 0);
3369 ASSIGNC ((temp & CBIT) != 0);
3370 ASSIGNV ((temp & VBIT) != 0);
3371 } else
3372 DEST = temp;
3373 } else
3374 /* CDP Part 2. */
3375 ARMul_CDP (state, instr);
3376 break;
3377
3378 /* SWI instruction. */
3379 case 0xf0:
3380 case 0xf1:
3381 case 0xf2:
3382 case 0xf3:
3383 case 0xf4:
3384 case 0xf5:
3385 case 0xf6:
3386 case 0xf7:
3387 case 0xf8:
3388 case 0xf9:
3389 case 0xfa:
3390 case 0xfb:
3391 case 0xfc:
3392 case 0xfd:
3393 case 0xfe:
3394 case 0xff:
3395 //svc_Execute(state, BITS(0, 23));
3396 HLE::CallSVC(instr);
3397
3398 break;
3399 }
3400 }
3401
3402#ifdef MODET
3403donext:
3404#endif
3405 state->pc = pc;
3406
3407 /* jump out every time */
3408 //state->EndCondition = 0;
3409 //state->Emulate = STOP;
3410//chy 2006-04-12 for ICE debug
3411TEST_EMULATE:
3412 if (state->Emulate == ONCE)
3413 state->Emulate = STOP;
3414 else if (state->Emulate != RUN)
3415 break;
3416 }
3417
3418 while (state->NumInstrsToExecute);
3419exit:
3420 state->decoded = decoded;
3421 state->loaded = loaded;
3422 state->pc = pc;
3423 //chy 2006-04-12, for ICE debug
3424 state->decoded_addr=decoded_addr;
3425 state->loaded_addr=loaded_addr;
3426
3427 return pc;
3428 }
3429
3430 static volatile void (*gen_func) (void);
3431
3432 static volatile uint32_t tmp_st;
3433 static volatile uint32_t save_st;
3434 static volatile uint32_t save_T0;
3435 static volatile uint32_t save_T1;
3436 static volatile uint32_t save_T2;
3437
3438 /* This routine evaluates most Data Processing register RHS's with the S
3439 bit clear. It is intended to be called from the macro DPRegRHS, which
3440 filters the common case of an unshifted register with in line code. */
3441
3442 static ARMword
3443 GetDPRegRHS (ARMul_State * state, ARMword instr) {
3444 ARMword shamt, base;
3445
3446 base = RHSReg;
3447 if (BIT (4)) {
3448 /* Shift amount in a register. */
3449 UNDEF_Shift;
3450 INCPC;
3451#ifndef MODE32
3452 if (base == 15)
3453 base = ECC | ER15INT | R15PC | EMODE;
3454 else
3455#endif
3456 base = state->Reg[base];
3457 ARMul_Icycles (state, 1, 0L);
3458 shamt = state->Reg[BITS (8, 11)] & 0xff;
3459 switch ((int) BITS (5, 6)) {
3460 case LSL:
3461 if (shamt == 0)
3462 return (base);
3463 else if (shamt >= 32)
3464 return (0);
3465 else
3466 return (base << shamt);
3467 case LSR:
3468 if (shamt == 0)
3469 return (base);
3470 else if (shamt >= 32)
3471 return (0);
3472 else
3473 return (base >> shamt);
3474 case ASR:
3475 if (shamt == 0)
3476 return (base);
3477 else if (shamt >= 32)
3478 return ((ARMword) ((int) base >> 31L));
3479 else
3480 return ((ARMword)
3481 (( int) base >> (int) shamt));
3482 case ROR:
3483 shamt &= 0x1f;
3484 if (shamt == 0)
3485 return (base);
3486 else
3487 return ((base << (32 - shamt)) |
3488 (base >> shamt));
3489 }
3490 } else {
3491 /* Shift amount is a constant. */
3492#ifndef MODE32
3493 if (base == 15)
3494 base = ECC | ER15INT | R15PC | EMODE;
3495 else
3496#endif
3497 base = state->Reg[base];
3498 shamt = BITS (7, 11);
3499 switch ((int) BITS (5, 6)) {
3500 case LSL:
3501 return (base << shamt);
3502 case LSR:
3503 if (shamt == 0)
3504 return (0);
3505 else
3506 return (base >> shamt);
3507 case ASR:
3508 if (shamt == 0)
3509 return ((ARMword) (( int) base >> 31L));
3510 else
3511 return ((ARMword)
3512 (( int) base >> (int) shamt));
3513 case ROR:
3514 if (shamt == 0)
3515 /* It's an RRX. */
3516 return ((base >> 1) | (CFLAG << 31));
3517 else
3518 return ((base << (32 - shamt)) |
3519 (base >> shamt));
3520 }
3521 }
3522
3523 return 0;
3524 }
3525
3526 /* This routine evaluates most Logical Data Processing register RHS's
3527 with the S bit set. It is intended to be called from the macro
3528 DPSRegRHS, which filters the common case of an unshifted register
3529 with in line code. */
3530
3531 static ARMword
3532 GetDPSRegRHS (ARMul_State * state, ARMword instr) {
3533 ARMword shamt, base;
3534
3535 base = RHSReg;
3536 if (BIT (4)) {
3537 /* Shift amount in a register. */
3538 UNDEF_Shift;
3539 INCPC;
3540#ifndef MODE32
3541 if (base == 15)
3542 base = ECC | ER15INT | R15PC | EMODE;
3543 else
3544#endif
3545 base = state->Reg[base];
3546 ARMul_Icycles (state, 1, 0L);
3547 shamt = state->Reg[BITS (8, 11)] & 0xff;
3548 switch ((int) BITS (5, 6)) {
3549 case LSL:
3550 if (shamt == 0)
3551 return (base);
3552 else if (shamt == 32) {
3553 ASSIGNC (base & 1);
3554 return (0);
3555 } else if (shamt > 32) {
3556 CLEARC;
3557 return (0);
3558 } else {
3559 ASSIGNC ((base >> (32 - shamt)) & 1);
3560 return (base << shamt);
3561 }
3562 case LSR:
3563 if (shamt == 0)
3564 return (base);
3565 else if (shamt == 32) {
3566 ASSIGNC (base >> 31);
3567 return (0);
3568 } else if (shamt > 32) {
3569 CLEARC;
3570 return (0);
3571 } else {
3572 ASSIGNC ((base >> (shamt - 1)) & 1);
3573 return (base >> shamt);
3574 }
3575 case ASR:
3576 if (shamt == 0)
3577 return (base);
3578 else if (shamt >= 32) {
3579 ASSIGNC (base >> 31L);
3580 return ((ARMword) (( int) base >> 31L));
3581 } else {
3582 ASSIGNC ((ARMword)
3583 (( int) base >>
3584 (int) (shamt - 1)) & 1);
3585 return ((ARMword)
3586 ((int) base >> (int) shamt));
3587 }
3588 case ROR:
3589 if (shamt == 0)
3590 return (base);
3591 shamt &= 0x1f;
3592 if (shamt == 0) {
3593 ASSIGNC (base >> 31);
3594 return (base);
3595 } else {
3596 ASSIGNC ((base >> (shamt - 1)) & 1);
3597 return ((base << (32 - shamt)) |
3598 (base >> shamt));
3599 }
3600 }
3601 } else {
3602 /* Shift amount is a constant. */
3603#ifndef MODE32
3604 if (base == 15)
3605 base = ECC | ER15INT | R15PC | EMODE;
3606 else
3607#endif
3608 base = state->Reg[base];
3609 shamt = BITS (7, 11);
3610
3611 switch ((int) BITS (5, 6)) {
3612 case LSL:
3613 ASSIGNC ((base >> (32 - shamt)) & 1);
3614 return (base << shamt);
3615 case LSR:
3616 if (shamt == 0) {
3617 ASSIGNC (base >> 31);
3618 return (0);
3619 } else {
3620 ASSIGNC ((base >> (shamt - 1)) & 1);
3621 return (base >> shamt);
3622 }
3623 case ASR:
3624 if (shamt == 0) {
3625 ASSIGNC (base >> 31L);
3626 return ((ARMword) ((int) base >> 31L));
3627 } else {
3628 ASSIGNC ((ARMword)
3629 ((int) base >>
3630 (int) (shamt - 1)) & 1);
3631 return ((ARMword)
3632 (( int) base >> (int) shamt));
3633 }
3634 case ROR:
3635 if (shamt == 0) {
3636 /* It's an RRX. */
3637 shamt = CFLAG;
3638 ASSIGNC (base & 1);
3639 return ((base >> 1) | (shamt << 31));
3640 } else {
3641 ASSIGNC ((base >> (shamt - 1)) & 1);
3642 return ((base << (32 - shamt)) |
3643 (base >> shamt));
3644 }
3645 }
3646 }
3647
3648 return 0;
3649 }
3650
3651 /* This routine handles writes to register 15 when the S bit is not set. */
3652
3653 static void
3654 WriteR15 (ARMul_State * state, ARMword src) {
3655 /* The ARM documentation states that the two least significant bits
3656 are discarded when setting PC, except in the cases handled by
3657 WriteR15Branch() below. It's probably an oversight: in THUMB
3658 mode, the second least significant bit should probably not be
3659 discarded. */
3660#ifdef MODET
3661 if (TFLAG)
3662 src &= 0xfffffffe;
3663 else
3664#endif
3665 src &= 0xfffffffc;
3666
3667#ifdef MODE32
3668 state->Reg[15] = src & PCBITS;
3669#else
3670 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
3671 ARMul_R15Altered (state);
3672#endif
3673
3674 FLUSHPIPE;
3675 }
3676
3677 /* This routine handles writes to register 15 when the S bit is set. */
3678
3679 static void
3680 WriteSR15 (ARMul_State * state, ARMword src) {
3681#ifdef MODE32
3682 if (state->Bank > 0) {
3683 state->Cpsr = state->Spsr[state->Bank];
3684 ARMul_CPSRAltered (state);
3685 }
3686#ifdef MODET
3687 if (TFLAG)
3688 src &= 0xfffffffe;
3689 else
3690#endif
3691 src &= 0xfffffffc;
3692 state->Reg[15] = src & PCBITS;
3693#else
3694#ifdef MODET
3695 if (TFLAG)
3696 /* ARMul_R15Altered would have to support it. */
3697 abort ();
3698 else
3699#endif
3700 src &= 0xfffffffc;
3701
3702 if (state->Bank == USERBANK)
3703 state->Reg[15] =
3704 (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3705 else
3706 state->Reg[15] = src;
3707
3708 ARMul_R15Altered (state);
3709#endif
3710 FLUSHPIPE;
3711 }
3712
3713 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3714 will switch to Thumb mode if the least significant bit is set. */
3715
3716 static void
3717 WriteR15Branch (ARMul_State * state, ARMword src) {
3718#ifdef MODET
3719 if (src & 1) {
3720 /* Thumb bit. */
3721 SETT;
3722 state->Reg[15] = src & 0xfffffffe;
3723 } else {
3724 CLEART;
3725 state->Reg[15] = src & 0xfffffffc;
3726 }
3727 state->Cpsr = ARMul_GetCPSR (state);
3728 FLUSHPIPE;
3729#else
3730 WriteR15 (state, src);
3731#endif
3732 }
3733
3734 /* This routine evaluates most Load and Store register RHS's. It is
3735 intended to be called from the macro LSRegRHS, which filters the
3736 common case of an unshifted register with in line code. */
3737
3738 static ARMword
3739 GetLSRegRHS (ARMul_State * state, ARMword instr) {
3740 ARMword shamt, base;
3741
3742 base = RHSReg;
3743#ifndef MODE32
3744 if (base == 15)
3745 /* Now forbidden, but ... */
3746 base = ECC | ER15INT | R15PC | EMODE;
3747 else
3748#endif
3749 base = state->Reg[base];
3750
3751 shamt = BITS (7, 11);
3752 switch ((int) BITS (5, 6)) {
3753 case LSL:
3754 return (base << shamt);
3755 case LSR:
3756 if (shamt == 0)
3757 return (0);
3758 else
3759 return (base >> shamt);
3760 case ASR:
3761 if (shamt == 0)
3762 return ((ARMword) (( int) base >> 31L));
3763 else
3764 return ((ARMword) (( int) base >> (int) shamt));
3765 case ROR:
3766 if (shamt == 0)
3767 /* It's an RRX. */
3768 return ((base >> 1) | (CFLAG << 31));
3769 else
3770 return ((base << (32 - shamt)) | (base >> shamt));
3771 default:
3772 break;
3773 }
3774 return 0;
3775 }
3776
3777 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
3778
3779 static ARMword
3780 GetLS7RHS (ARMul_State * state, ARMword instr) {
3781 if (BIT (22) == 0) {
3782 /* Register. */
3783#ifndef MODE32
3784 if (RHSReg == 15)
3785 /* Now forbidden, but ... */
3786 return ECC | ER15INT | R15PC | EMODE;
3787#endif
3788 return state->Reg[RHSReg];
3789 }
3790
3791 /* Immediate. */
3792 return BITS (0, 3) | (BITS (8, 11) << 4);
3793 }
3794
3795 static unsigned
3796 LoadWord (ARMul_State * state, ARMword instr, ARMword address) {
3797 ARMword dest;
3798
3799 BUSUSEDINCPCS;
3800#ifndef MODE32
3801 if (ADDREXCEPT (address))
3802 INTERNALABORT (address);
3803#endif
3804
3805 dest = ARMul_LoadWordN (state, address);
3806
3807 if (state->Aborted) {
3808 TAKEABORT;
3809 return state->lateabtSig;
3810 }
3811 if (address & 3)
3812 dest = ARMul_Align (state, address, dest);
3813 WRITEDESTB (dest);
3814 ARMul_Icycles (state, 1, 0L);
3815
3816 return (DESTReg != LHSReg);
3817 }
3818
3819#ifdef MODET
3820 /* This function does the work of loading a halfword. */
3821
3822 static unsigned
3823 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
3824 int signextend) {
3825 ARMword dest;
3826
3827 BUSUSEDINCPCS;
3828#ifndef MODE32
3829 if (ADDREXCEPT (address))
3830 INTERNALABORT (address);
3831#endif
3832 dest = ARMul_LoadHalfWord (state, address);
3833 if (state->Aborted) {
3834 TAKEABORT;
3835 return state->lateabtSig;
3836 }
3837 UNDEF_LSRBPC;
3838 if (signextend)
3839 if (dest & 1 << (16 - 1))
3840 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
3841
3842 WRITEDEST (dest);
3843 ARMul_Icycles (state, 1, 0L);
3844
3845 return (DESTReg != LHSReg);
3846 }
3847
3848#endif /* MODET */
3849
3850 /* This function does the work of loading a byte for a LDRB instruction. */
3851
3852 static unsigned
3853 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) {
3854 ARMword dest;
3855
3856 BUSUSEDINCPCS;
3857#ifndef MODE32
3858 if (ADDREXCEPT (address))
3859 INTERNALABORT (address);
3860#endif
3861 dest = ARMul_LoadByte (state, address);
3862 if (state->Aborted) {
3863 TAKEABORT;
3864 return state->lateabtSig;
3865 }
3866 UNDEF_LSRBPC;
3867 if (signextend)
3868 if (dest & 1 << (8 - 1))
3869 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
3870
3871 WRITEDEST (dest);
3872 ARMul_Icycles (state, 1, 0L);
3873
3874 return (DESTReg != LHSReg);
3875 }
3876
3877 /* This function does the work of loading two words for a LDRD instruction. */
3878
3879 static void
3880 Handle_Load_Double (ARMul_State * state, ARMword instr) {
3881 ARMword dest_reg;
3882 ARMword addr_reg;
3883 ARMword write_back = BIT (21);
3884 ARMword immediate = BIT (22);
3885 ARMword add_to_base = BIT (23);
3886 ARMword pre_indexed = BIT (24);
3887 ARMword offset;
3888 ARMword addr;
3889 ARMword sum;
3890 ARMword base;
3891 ARMword value1;
3892 ARMword value2;
3893
3894 BUSUSEDINCPCS;
3895
3896 /* If the writeback bit is set, the pre-index bit must be clear. */
3897 if (write_back && !pre_indexed) {
3898 ARMul_UndefInstr (state, instr);
3899 return;
3900 }
3901
3902 /* Extract the base address register. */
3903 addr_reg = LHSReg;
3904
3905 /* Extract the destination register and check it. */
3906 dest_reg = DESTReg;
3907
3908 /* Destination register must be even. */
3909 if ((dest_reg & 1)
3910 /* Destination register cannot be LR. */
3911 || (dest_reg == 14)) {
3912 ARMul_UndefInstr (state, instr);
3913 return;
3914 }
3915
3916 /* Compute the base address. */
3917 base = state->Reg[addr_reg];
3918
3919 /* Compute the offset. */
3920 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->
3921 Reg[RHSReg];
3922
3923 /* Compute the sum of the two. */
3924 if (add_to_base)
3925 sum = base + offset;
3926 else
3927 sum = base - offset;
3928
3929 /* If this is a pre-indexed mode use the sum. */
3930 if (pre_indexed)
3931 addr = sum;
3932 else
3933 addr = base;
3934
3935 /* The address must be aligned on a 8 byte boundary. */
3936 /*if (addr & 0x7) {
3937 #ifdef ABORTS
3938 ARMul_DATAABORT (addr);
3939 #else
3940 ARMul_UndefInstr (state, instr);
3941 #endif
3942 return;
3943 }*/
3944 /* Lets just forcibly align it for now */
3945 //addr = (addr + 7) & ~7;
3946
3947 /* For pre indexed or post indexed addressing modes,
3948 check that the destination registers do not overlap
3949 the address registers. */
3950 if ((!pre_indexed || write_back)
3951 && (addr_reg == dest_reg || addr_reg == dest_reg + 1)) {
3952 ARMul_UndefInstr (state, instr);
3953 return;
3954 }
3955
3956 /* Load the words. */
3957 value1 = ARMul_LoadWordN (state, addr);
3958 value2 = ARMul_LoadWordN (state, addr + 4);
3959
3960 /* Check for data aborts. */
3961 if (state->Aborted) {
3962 TAKEABORT;
3963 return;
3964 }
3965
3966 ARMul_Icycles (state, 2, 0L);
3967
3968 /* Store the values. */
3969 state->Reg[dest_reg] = value1;
3970 state->Reg[dest_reg + 1] = value2;
3971
3972 /* Do the post addressing and writeback. */
3973 if (!pre_indexed)
3974 addr = sum;
3975
3976 if (!pre_indexed || write_back)
3977 state->Reg[addr_reg] = addr;
3978 }
3979
3980 /* This function does the work of storing two words for a STRD instruction. */
3981
3982 static void
3983 Handle_Store_Double (ARMul_State * state, ARMword instr) {
3984 ARMword src_reg;
3985 ARMword addr_reg;
3986 ARMword write_back = BIT (21);
3987 ARMword immediate = BIT (22);
3988 ARMword add_to_base = BIT (23);
3989 ARMword pre_indexed = BIT (24);
3990 ARMword offset;
3991 ARMword addr;
3992 ARMword sum;
3993 ARMword base;
3994
3995 BUSUSEDINCPCS;
3996
3997 /* If the writeback bit is set, the pre-index bit must be clear. */
3998 if (write_back && !pre_indexed) {
3999 ARMul_UndefInstr (state, instr);
4000 return;
4001 }
4002
4003 /* Extract the base address register. */
4004 addr_reg = LHSReg;
4005
4006 /* Base register cannot be PC. */
4007 if (addr_reg == 15) {
4008 ARMul_UndefInstr (state, instr);
4009 return;
4010 }
4011
4012 /* Extract the source register. */
4013 src_reg = DESTReg;
4014
4015 /* Source register must be even. */
4016 if (src_reg & 1) {
4017 ARMul_UndefInstr (state, instr);
4018 return;
4019 }
4020
4021 /* Compute the base address. */
4022 base = state->Reg[addr_reg];
4023
4024 /* Compute the offset. */
4025 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->
4026 Reg[RHSReg];
4027
4028 /* Compute the sum of the two. */
4029 if (add_to_base)
4030 sum = base + offset;
4031 else
4032 sum = base - offset;
4033
4034 /* If this is a pre-indexed mode use the sum. */
4035 if (pre_indexed)
4036 addr = sum;
4037 else
4038 addr = base;
4039
4040 /* The address must be aligned on a 8 byte boundary. */
4041 /*if (addr & 0x7) {
4042 #ifdef ABORTS
4043 ARMul_DATAABORT (addr);
4044 #else
4045 ARMul_UndefInstr (state, instr);
4046 #endif
4047 return;
4048 }*/
4049 /* Lets just forcibly align it for now */
4050 //addr = (addr + 7) & ~7;
4051
4052 /* For pre indexed or post indexed addressing modes,
4053 check that the destination registers do not overlap
4054 the address registers. */
4055 if ((!pre_indexed || write_back)
4056 && (addr_reg == src_reg || addr_reg == src_reg + 1)) {
4057 ARMul_UndefInstr (state, instr);
4058 return;
4059 }
4060
4061 /* Load the words. */
4062 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4063 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4064
4065 if (state->Aborted) {
4066 TAKEABORT;
4067 return;
4068 }
4069
4070 /* Do the post addressing and writeback. */
4071 if (!pre_indexed)
4072 addr = sum;
4073
4074 if (!pre_indexed || write_back)
4075 state->Reg[addr_reg] = addr;
4076 }
4077
4078 /* This function does the work of storing a word from a STR instruction. */
4079
4080 static unsigned
4081 StoreWord (ARMul_State * state, ARMword instr, ARMword address) {
4082 BUSUSEDINCPCN;
4083#ifndef MODE32
4084 if (DESTReg == 15)
4085 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4086#endif
4087#ifdef MODE32
4088 ARMul_StoreWordN (state, address, DEST);
4089#else
4090 if (VECTORACCESS (address) || ADDREXCEPT (address)) {
4091 INTERNALABORT (address);
4092 (void) ARMul_LoadWordN (state, address);
4093 } else
4094 ARMul_StoreWordN (state, address, DEST);
4095#endif
4096 if (state->Aborted) {
4097 TAKEABORT;
4098 return state->lateabtSig;
4099 }
4100
4101 return TRUE;
4102 }
4103
4104#ifdef MODET
4105 /* This function does the work of storing a byte for a STRH instruction. */
4106
4107 static unsigned
4108 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) {
4109 BUSUSEDINCPCN;
4110
4111#ifndef MODE32
4112 if (DESTReg == 15)
4113 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4114#endif
4115
4116#ifdef MODE32
4117 ARMul_StoreHalfWord (state, address, DEST);
4118#else
4119 if (VECTORACCESS (address) || ADDREXCEPT (address)) {
4120 INTERNALABORT (address);
4121 (void) ARMul_LoadHalfWord (state, address);
4122 } else
4123 ARMul_StoreHalfWord (state, address, DEST);
4124#endif
4125
4126 if (state->Aborted) {
4127 TAKEABORT;
4128 return state->lateabtSig;
4129 }
4130 return TRUE;
4131 }
4132
4133#endif /* MODET */
4134
4135 /* This function does the work of storing a byte for a STRB instruction. */
4136
4137 static unsigned
4138 StoreByte (ARMul_State * state, ARMword instr, ARMword address) {
4139 BUSUSEDINCPCN;
4140#ifndef MODE32
4141 if (DESTReg == 15)
4142 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4143#endif
4144#ifdef MODE32
4145 ARMul_StoreByte (state, address, DEST);
4146#else
4147 if (VECTORACCESS (address) || ADDREXCEPT (address)) {
4148 INTERNALABORT (address);
4149 (void) ARMul_LoadByte (state, address);
4150 } else
4151 ARMul_StoreByte (state, address, DEST);
4152#endif
4153 if (state->Aborted) {
4154 TAKEABORT;
4155 return state->lateabtSig;
4156 }
4157 //UNDEF_LSRBPC;
4158 return TRUE;
4159 }
4160
4161 /* This function does the work of loading the registers listed in an LDM
4162 instruction, when the S bit is clear. The code here is always increment
4163 after, it's up to the caller to get the input address correct and to
4164 handle base register modification. */
4165
4166 static void
4167 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) {
4168 ARMword dest, temp;
4169
4170 //UNDEF_LSMNoRegs;
4171 //UNDEF_LSMPCBase;
4172 //UNDEF_LSMBaseInListWb;
4173 BUSUSEDINCPCS;
4174#ifndef MODE32
4175 if (ADDREXCEPT (address))
4176 INTERNALABORT (address);
4177#endif
4178 /*chy 2004-05-23 may write twice
4179 if (BIT (21) && LHSReg != 15)
4180 LSBase = WBBase;
4181 */
4182 /* N cycle first. */
4183 for (temp = 0; !BIT (temp); temp++);
4184
4185 dest = ARMul_LoadWordN (state, address);
4186
4187 if (!state->abortSig && !state->Aborted)
4188 state->Reg[temp++] = dest;
4189 else if (!state->Aborted) {
4190 //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4191 state->Aborted = ARMul_DataAbortV;
4192 }
4193 /*chy 2004-05-23 chy goto end*/
4194 if (state->Aborted)
4195 goto L_ldm_makeabort;
4196 /* S cycles from here on. */
4197 for (; temp < 16; temp++)
4198 if (BIT (temp)) {
4199 /* Load this register. */
4200 address += 4;
4201 dest = ARMul_LoadWordS (state, address);
4202
4203 if (!state->abortSig && !state->Aborted)
4204 state->Reg[temp] = dest;
4205 else if (!state->Aborted) {
4206 /*XScale_set_fsr_far (state,
4207 ARMul_CP15_R5_ST_ALIGN,
4208 address);*/
4209 state->Aborted = ARMul_DataAbortV;
4210 }
4211 /*chy 2004-05-23 chy goto end */
4212 if (state->Aborted)
4213 goto L_ldm_makeabort;
4214 }
4215
4216 if (BIT (15) && !state->Aborted)
4217 /* PC is in the reg list. */
4218 WriteR15Branch (state, PC);
4219
4220 /* To write back the final register. */
4221 /* ARMul_Icycles (state, 1, 0L);*/
4222 /*chy 2004-05-23, see below
4223 if (state->Aborted)
4224 {
4225 if (BIT (21) && LHSReg != 15)
4226 LSBase = WBBase;
4227
4228 TAKEABORT;
4229 }
4230 */
4231 /*chy 2004-05-23 should compare the Abort Models*/
4232L_ldm_makeabort:
4233 /* To write back the final register. */
4234 ARMul_Icycles (state, 1, 0L);
4235
4236 /* chy 2005-11-24, bug found by benjl@cse.unsw.edu.au, etc */
4237 /*
4238 if (state->Aborted)
4239 {
4240 if (BIT (21) && LHSReg != 15)
4241 if (!(state->abortSig && state->Aborted && state->lateabtSig == LOW))
4242 LSBase = WBBase;
4243 TAKEABORT;
4244 }else if (BIT (21) && LHSReg != 15)
4245 LSBase = WBBase;
4246 */
4247 if (state->Aborted) {
4248 if (BIT (21) && LHSReg != 15) {
4249 if (!(state->abortSig)) {
4250 }
4251 }
4252 TAKEABORT;
4253 } else if (BIT (21) && LHSReg != 15) {
4254 LSBase = WBBase;
4255 }
4256 /* chy 2005-11-24, over */
4257 }
4258
4259 /* This function does the work of loading the registers listed in an LDM
4260 instruction, when the S bit is set. The code here is always increment
4261 after, it's up to the caller to get the input address correct and to
4262 handle base register modification. */
4263
4264 static void
4265 LoadSMult (ARMul_State * state,
4266 ARMword instr, ARMword address, ARMword WBBase) {
4267 ARMword dest, temp;
4268
4269 //UNDEF_LSMNoRegs;
4270 //UNDEF_LSMPCBase;
4271 //UNDEF_LSMBaseInListWb;
4272
4273 BUSUSEDINCPCS;
4274
4275#ifndef MODE32
4276 if (ADDREXCEPT (address))
4277 INTERNALABORT (address);
4278#endif
4279 /* chy 2004-05-23, may write twice
4280 if (BIT (21) && LHSReg != 15)
4281 LSBase = WBBase;
4282 */
4283 if (!BIT (15) && state->Bank != USERBANK) {
4284 /* Temporary reg bank switch. */
4285 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4286 UNDEF_LSMUserBankWb;
4287 }
4288
4289 /* N cycle first. */
4290 for (temp = 0; !BIT (temp); temp++);
4291
4292 dest = ARMul_LoadWordN (state, address);
4293
4294 if (!state->abortSig)
4295 state->Reg[temp++] = dest;
4296 else if (!state->Aborted) {
4297 //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4298 state->Aborted = ARMul_DataAbortV;
4299 }
4300
4301 /*chy 2004-05-23 chy goto end*/
4302 if (state->Aborted)
4303 goto L_ldm_s_makeabort;
4304 /* S cycles from here on. */
4305 for (; temp < 16; temp++)
4306 if (BIT (temp)) {
4307 /* Load this register. */
4308 address += 4;
4309 dest = ARMul_LoadWordS (state, address);
4310
4311 if (!state->abortSig && !state->Aborted)
4312 state->Reg[temp] = dest;
4313 else if (!state->Aborted) {
4314 /*XScale_set_fsr_far (state,
4315 ARMul_CP15_R5_ST_ALIGN,
4316 address);*/
4317 state->Aborted = ARMul_DataAbortV;
4318 }
4319 /*chy 2004-05-23 chy goto end */
4320 if (state->Aborted)
4321 goto L_ldm_s_makeabort;
4322 }
4323
4324 /*chy 2004-05-23 label of ldm_s_makeabort*/
4325L_ldm_s_makeabort:
4326 /*chy 2004-06-06 LSBase process should be here, not in the end of this function. Because ARMul_CPSRAltered maybe change R13(SP) R14(lr). If not, simulate INSTR ldmia sp!,[....pc]^ error.*/
4327 /*chy 2004-05-23 should compare the Abort Models*/
4328 if (state->Aborted) {
4329 if (BIT (21) && LHSReg != 15)
4330 if (!
4331 (state->abortSig && state->Aborted
4332 && state->lateabtSig == LOW))
4333 LSBase = WBBase;
4334 TAKEABORT;
4335 } else if (BIT (21) && LHSReg != 15)
4336 LSBase = WBBase;
4337
4338 if (BIT (15) && !state->Aborted) {
4339 /* PC is in the reg list. */
4340#ifdef MODE32
4341 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
4342 if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
4343 state->Cpsr = GETSPSR (state->Bank);
4344 ARMul_CPSRAltered (state);
4345 }
4346
4347 WriteR15 (state, PC);
4348#else
4349 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
4350 if (state->Mode == USER26MODE || state->Mode == USER32MODE ) {
4351 /* Protect bits in user mode. */
4352 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4353 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4354 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4355 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4356 } else
4357 ARMul_R15Altered (state);
4358
4359 FLUSHPIPE;
4360#endif
4361 }
4362
4363 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
4364 if (!BIT (15) && state->Mode != USER26MODE
4365 && state->Mode != USER32MODE )
4366 /* Restore the correct bank. */
4367 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4368
4369 /* To write back the final register. */
4370 ARMul_Icycles (state, 1, 0L);
4371 /* chy 2004-05-23, see below
4372 if (state->Aborted)
4373 {
4374 if (BIT (21) && LHSReg != 15)
4375 LSBase = WBBase;
4376
4377 TAKEABORT;
4378 }
4379 */
4380 }
4381
4382 /* This function does the work of storing the registers listed in an STM
4383 instruction, when the S bit is clear. The code here is always increment
4384 after, it's up to the caller to get the input address correct and to
4385 handle base register modification. */
4386
4387 static void
4388 StoreMult (ARMul_State * state,
4389 ARMword instr, ARMword address, ARMword WBBase) {
4390 ARMword temp;
4391
4392 UNDEF_LSMNoRegs;
4393 UNDEF_LSMPCBase;
4394 UNDEF_LSMBaseInListWb;
4395
4396 if (!TFLAG)
4397 /* N-cycle, increment the PC and update the NextInstr state. */
4398 BUSUSEDINCPCN;
4399
4400#ifndef MODE32
4401 if (VECTORACCESS (address) || ADDREXCEPT (address))
4402 INTERNALABORT (address);
4403
4404 if (BIT (15))
4405 PATCHR15;
4406#endif
4407
4408 /* N cycle first. */
4409 for (temp = 0; !BIT (temp); temp++);
4410
4411#ifdef MODE32
4412 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4413#else
4414 if (state->Aborted) {
4415 (void) ARMul_LoadWordN (state, address);
4416
4417 /* Fake the Stores as Loads. */
4418 for (; temp < 16; temp++)
4419 if (BIT (temp)) {
4420 /* Save this register. */
4421 address += 4;
4422 (void) ARMul_LoadWordS (state, address);
4423 }
4424
4425 if (BIT (21) && LHSReg != 15)
4426 LSBase = WBBase;
4427 TAKEABORT;
4428 return;
4429 } else
4430 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4431#endif
4432
4433 if (state->abortSig && !state->Aborted) {
4434 //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4435 state->Aborted = ARMul_DataAbortV;
4436 }
4437
4438//chy 2004-05-23, needn't store other when aborted
4439 if (state->Aborted)
4440 goto L_stm_takeabort;
4441
4442 /* S cycles from here on. */
4443 for (; temp < 16; temp++)
4444 if (BIT (temp)) {
4445 /* Save this register. */
4446 address += 4;
4447
4448 ARMul_StoreWordS (state, address, state->Reg[temp]);
4449
4450 if (state->abortSig && !state->Aborted) {
4451 /*XScale_set_fsr_far (state,
4452 ARMul_CP15_R5_ST_ALIGN,
4453 address);*/
4454 state->Aborted = ARMul_DataAbortV;
4455 }
4456 //chy 2004-05-23, needn't store other when aborted
4457 if (state->Aborted)
4458 goto L_stm_takeabort;
4459 }
4460
4461//chy 2004-05-23,should compare the Abort Models
4462L_stm_takeabort:
4463 if (BIT (21) && LHSReg != 15) {
4464 if (!
4465 (state->abortSig && state->Aborted
4466 && state->lateabtSig == LOW))
4467 LSBase = WBBase;
4468 }
4469 if (state->Aborted)
4470 TAKEABORT;
4471 }
4472
4473 /* This function does the work of storing the registers listed in an STM
4474 instruction when the S bit is set. The code here is always increment
4475 after, it's up to the caller to get the input address correct and to
4476 handle base register modification. */
4477
4478 static void
4479 StoreSMult (ARMul_State * state,
4480 ARMword instr, ARMword address, ARMword WBBase) {
4481 ARMword temp;
4482
4483 UNDEF_LSMNoRegs;
4484 UNDEF_LSMPCBase;
4485 UNDEF_LSMBaseInListWb;
4486
4487 BUSUSEDINCPCN;
4488
4489#ifndef MODE32
4490 if (VECTORACCESS (address) || ADDREXCEPT (address))
4491 INTERNALABORT (address);
4492
4493 if (BIT (15))
4494 PATCHR15;
4495#endif
4496
4497 if (state->Bank != USERBANK) {
4498 /* Force User Bank. */
4499 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4500 UNDEF_LSMUserBankWb;
4501 }
4502
4503 for (temp = 0; !BIT (temp); temp++); /* N cycle first. */
4504
4505#ifdef MODE32
4506 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4507#else
4508 if (state->Aborted) {
4509 (void) ARMul_LoadWordN (state, address);
4510
4511 for (; temp < 16; temp++)
4512 /* Fake the Stores as Loads. */
4513 if (BIT (temp)) {
4514 /* Save this register. */
4515 address += 4;
4516
4517 (void) ARMul_LoadWordS (state, address);
4518 }
4519
4520 if (BIT (21) && LHSReg != 15)
4521 LSBase = WBBase;
4522
4523 TAKEABORT;
4524 return;
4525 } else
4526 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4527#endif
4528
4529 if (state->abortSig && !state->Aborted) {
4530 //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4531 state->Aborted = ARMul_DataAbortV;
4532 }
4533
4534//chy 2004-05-23, needn't store other when aborted
4535 if (state->Aborted)
4536 goto L_stm_s_takeabort;
4537 /* S cycles from here on. */
4538 for (; temp < 16; temp++)
4539 if (BIT (temp)) {
4540 /* Save this register. */
4541 address += 4;
4542
4543 ARMul_StoreWordS (state, address, state->Reg[temp]);
4544
4545 if (state->abortSig && !state->Aborted) {
4546 /*XScale_set_fsr_far (state,
4547 ARMul_CP15_R5_ST_ALIGN,
4548 address);*/
4549 state->Aborted = ARMul_DataAbortV;
4550 }
4551 //chy 2004-05-23, needn't store other when aborted
4552 if (state->Aborted)
4553 goto L_stm_s_takeabort;
4554 }
4555
4556 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
4557 if (state->Mode != USER26MODE && state->Mode != USER32MODE )
4558 /* Restore the correct bank. */
4559 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4560
4561//chy 2004-05-23,should compare the Abort Models
4562L_stm_s_takeabort:
4563 if (BIT (21) && LHSReg != 15) {
4564 if (!
4565 (state->abortSig && state->Aborted
4566 && state->lateabtSig == LOW))
4567 LSBase = WBBase;
4568 }
4569
4570 if (state->Aborted)
4571 TAKEABORT;
4572 }
4573
4574 /* This function does the work of adding two 32bit values
4575 together, and calculating if a carry has occurred. */
4576
4577 static ARMword
4578 Add32 (ARMword a1, ARMword a2, int *carry) {
4579 ARMword result = (a1 + a2);
4580 unsigned int uresult = (unsigned int) result;
4581 unsigned int ua1 = (unsigned int) a1;
4582
4583 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4584 or (result > RdLo) then we have no carry. */
4585 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
4586 *carry = 1;
4587 else
4588 *carry = 0;
4589
4590 return result;
4591 }
4592
4593 /* This function does the work of multiplying
4594 two 32bit values to give a 64bit result. */
4595
4596 static unsigned
4597 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) {
4598 /* Operand register numbers. */
4599 int nRdHi, nRdLo, nRs, nRm;
4600 ARMword RdHi = 0, RdLo = 0, Rm;
4601 /* Cycle count. */
4602 int scount;
4603
4604 nRdHi = BITS (16, 19);
4605 nRdLo = BITS (12, 15);
4606 nRs = BITS (8, 11);
4607 nRm = BITS (0, 3);
4608
4609 /* Needed to calculate the cycle count. */
4610 Rm = state->Reg[nRm];
4611
4612 /* Check for illegal operand combinations first. */
4613 if (nRdHi != 15
4614 && nRdLo != 15
4615 && nRs != 15
4616 //&& nRm != 15 && nRdHi != nRdLo && nRdHi != nRm && nRdLo != nRm) {
4617 && nRm != 15 && nRdHi != nRdLo ) {
4618 /* Intermediate results. */
4619 ARMword lo, mid1, mid2, hi;
4620 int carry;
4621 ARMword Rs = state->Reg[nRs];
4622 int sign = 0;
4623
4624 if (msigned) {
4625 /* Compute sign of result and adjust operands if necessary. */
4626 sign = (Rm ^ Rs) & 0x80000000;
4627
4628 if (((signed int) Rm) < 0)
4629 Rm = -Rm;
4630
4631 if (((signed int) Rs) < 0)
4632 Rs = -Rs;
4633 }
4634
4635 /* We can split the 32x32 into four 16x16 operations. This
4636 ensures that we do not lose precision on 32bit only hosts. */
4637 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
4638 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4639 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
4640 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4641
4642 /* We now need to add all of these results together, taking
4643 care to propogate the carries from the additions. */
4644 RdLo = Add32 (lo, (mid1 << 16), &carry);
4645 RdHi = carry;
4646 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
4647 RdHi += (carry + ((mid1 >> 16) & 0xFFFF) +
4648 ((mid2 >> 16) & 0xFFFF) + hi);
4649
4650 if (sign) {
4651 /* Negate result if necessary. */
4652 RdLo = ~RdLo;
4653 RdHi = ~RdHi;
4654 if (RdLo == 0xFFFFFFFF) {
4655 RdLo = 0;
4656 RdHi += 1;
4657 } else
4658 RdLo += 1;
4659 }
4660
4661 state->Reg[nRdLo] = RdLo;
4662 state->Reg[nRdHi] = RdHi;
4663 } else {
4664 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS, instr=0x%x\n", instr);
4665 }
4666 if (scc)
4667 /* Ensure that both RdHi and RdLo are used to compute Z,
4668 but don't let RdLo's sign bit make it to N. */
4669 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4670
4671 /* The cycle count depends on whether the instruction is a signed or
4672 unsigned multiply, and what bits are clear in the multiplier. */
4673 if (msigned && (Rm & ((unsigned) 1 << 31)))
4674 /* Invert the bits to make the check against zero. */
4675 Rm = ~Rm;
4676
4677 if ((Rm & 0xFFFFFF00) == 0)
4678 scount = 1;
4679 else if ((Rm & 0xFFFF0000) == 0)
4680 scount = 2;
4681 else if ((Rm & 0xFF000000) == 0)
4682 scount = 3;
4683 else
4684 scount = 4;
4685
4686 return 2 + scount;
4687 }
4688
4689 /* This function does the work of multiplying two 32bit
4690 values and adding a 64bit value to give a 64bit result. */
4691
4692 static unsigned
4693 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) {
4694 unsigned scount;
4695 ARMword RdLo, RdHi;
4696 int nRdHi, nRdLo;
4697 int carry = 0;
4698
4699 nRdHi = BITS (16, 19);
4700 nRdLo = BITS (12, 15);
4701
4702 RdHi = state->Reg[nRdHi];
4703 RdLo = state->Reg[nRdLo];
4704
4705 scount = Multiply64 (state, instr, msigned, LDEFAULT);
4706
4707 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
4708 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
4709
4710 state->Reg[nRdLo] = RdLo;
4711 state->Reg[nRdHi] = RdHi;
4712
4713 if (scc)
4714 /* Ensure that both RdHi and RdLo are used to compute Z,
4715 but don't let RdLo's sign bit make it to N. */
4716 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4717
4718 /* Extra cycle for addition. */
4719 return scount + 1;
4720 }
4721
4722 /* Attempt to emulate an ARMv6 instruction.
4723 Returns non-zero upon success. */
4724
4725 static int handle_v6_insn(ARMul_State* state, ARMword instr) {
4726 switch (BITS(20, 27)) {
4727 case 0x03:
4728 printf ("Unhandled v6 insn: ldr\n");
4729 break;
4730 case 0x04: // UMAAL
4731 {
4732 const u8 rm_idx = BITS(8, 11);
4733 const u8 rn_idx = BITS(0, 3);
4734 const u8 rd_lo_idx = BITS(12, 15);
4735 const u8 rd_hi_idx = BITS(16, 19);
4736
4737 const u32 rm_val = state->Reg[rm_idx];
4738 const u32 rn_val = state->Reg[rn_idx];
4739 const u32 rd_lo_val = state->Reg[rd_lo_idx];
4740 const u32 rd_hi_val = state->Reg[rd_hi_idx];
4741
4742 const u64 result = (rn_val * rm_val) + rd_lo_val + rd_hi_val;
4743
4744 state->Reg[rd_lo_idx] = (result & 0xFFFFFFFF);
4745 state->Reg[rd_hi_idx] = ((result >> 32) & 0xFFFFFFFF);
4746 return 1;
4747 }
4748 break;
4749 case 0x06:
4750 printf ("Unhandled v6 insn: mls/str\n");
4751 break;
4752 case 0x16:
4753 printf ("Unhandled v6 insn: smi\n");
4754 break;
4755 case 0x18:
4756 if (BITS(4, 7) == 0x9) {
4757 /* strex */
4758 u32 l = LHSReg;
4759 u32 r = RHSReg;
4760 u32 lhs = LHS;
4761
4762 bool enter = false;
4763
4764 if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr))enter = true;
4765 //StoreWord(state, lhs, RHS)
4766 if (state->Aborted) {
4767 TAKEABORT;
4768 }
4769
4770 if (enter) {
4771 ARMul_StoreWordS(state, lhs, RHS);
4772 state->Reg[DESTReg] = 0;
4773 }
4774 else {
4775 state->Reg[DESTReg] = 1;
4776 }
4777
4778 return 1;
4779 }
4780 printf ("Unhandled v6 insn: strex\n");
4781 break;
4782 case 0x19:
4783 /* ldrex */
4784 if (BITS(4, 7) == 0x9) {
4785 u32 lhs = LHS;
4786
4787 state->currentexaddr = lhs;
4788 state->currentexval = ARMul_ReadWord(state, lhs);
4789
4790 LoadWord(state, instr, lhs);
4791 return 1;
4792 }
4793 printf ("Unhandled v6 insn: ldrex\n");
4794 break;
4795 case 0x1a:
4796 printf ("Unhandled v6 insn: strexd\n");
4797 break;
4798 case 0x1b:
4799 printf ("Unhandled v6 insn: ldrexd\n");
4800 break;
4801 case 0x1c:
4802 if (BITS(4, 7) == 0x9) {
4803 /* strexb */
4804 u32 lhs = LHS;
4805
4806 bool enter = false;
4807
4808 if (state->currentexval == (u32)ARMul_ReadByte(state, state->currentexaddr))enter = true;
4809
4810 BUSUSEDINCPCN;
4811 if (state->Aborted) {
4812 TAKEABORT;
4813 }
4814
4815 if (enter) {
4816 ARMul_StoreByte(state, lhs, RHS);
4817 state->Reg[DESTReg] = 0;
4818 }
4819 else {
4820 state->Reg[DESTReg] = 1;
4821 }
4822
4823 //printf("In %s, strexb not implemented\n", __FUNCTION__);
4824 UNDEF_LSRBPC;
4825 /* WRITESDEST (dest); */
4826 return 1;
4827 }
4828 printf ("Unhandled v6 insn: strexb\n");
4829 break;
4830 case 0x1d:
4831 if ((BITS(4, 7)) == 0x9) {
4832 /* ldrexb */
4833 u32 lhs = LHS;
4834 LoadByte(state, instr, lhs, LUNSIGNED);
4835
4836 state->currentexaddr = lhs;
4837 state->currentexval = (u32)ARMul_ReadByte(state, lhs);
4838
4839 //state->Reg[BITS(12, 15)] = ARMul_LoadByte(state, state->Reg[BITS(16, 19)]);
4840 //printf("ldrexb\n");
4841 //printf("instr is %x rm is %d\n", instr, BITS(16, 19));
4842 //exit(-1);
4843
4844 //printf("In %s, ldrexb not implemented\n", __FUNCTION__);
4845 return 1;
4846 }
4847 printf ("Unhandled v6 insn: ldrexb\n");
4848 break;
4849 case 0x1e:
4850 printf ("Unhandled v6 insn: strexh\n");
4851 break;
4852 case 0x1f:
4853 printf ("Unhandled v6 insn: ldrexh\n");
4854 break;
4855 case 0x30:
4856 printf ("Unhandled v6 insn: movw\n");
4857 break;
4858 case 0x32:
4859 printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n");
4860 break;
4861 case 0x34:
4862 printf ("Unhandled v6 insn: movt\n");
4863 break;
4864 case 0x3f:
4865 printf ("Unhandled v6 insn: rbit\n");
4866 break;
4867 case 0x61: // SADD16, SASX, SSAX, and SSUB16
4868 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
4869 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
4870 {
4871 const u8 rd_idx = BITS(12, 15);
4872 const u8 rm_idx = BITS(0, 3);
4873 const u8 rn_idx = BITS(16, 19);
4874 const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
4875 const s16 rn_hi = ((state->Reg[rn_idx] >> 16) & 0xFFFF);
4876 const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
4877 const s16 rm_hi = ((state->Reg[rm_idx] >> 16) & 0xFFFF);
4878
4879 s32 lo_result;
4880 s32 hi_result;
4881
4882 // SADD16
4883 if ((instr & 0xFF0) == 0xf10) {
4884 lo_result = (rn_lo + rm_lo);
4885 hi_result = (rn_hi + rm_hi);
4886 }
4887 // SASX
4888 else if ((instr & 0xFF0) == 0xf30) {
4889 lo_result = (rn_lo - rm_hi);
4890 hi_result = (rn_hi + rm_lo);
4891 }
4892 // SSAX
4893 else if ((instr & 0xFF0) == 0xf50) {
4894 lo_result = (rn_lo + rm_hi);
4895 hi_result = (rn_hi - rm_lo);
4896 }
4897 // SSUB16
4898 else {
4899 lo_result = (rn_lo - rm_lo);
4900 hi_result = (rn_hi - rm_hi);
4901 }
4902
4903 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
4904
4905 if (lo_result >= 0) {
4906 state->GEFlag |= (1 << 16);
4907 state->GEFlag |= (1 << 17);
4908 } else {
4909 state->GEFlag &= ~(1 << 16);
4910 state->GEFlag &= ~(1 << 17);
4911 }
4912
4913 if (hi_result >= 0) {
4914 state->GEFlag |= (1 << 18);
4915 state->GEFlag |= (1 << 19);
4916 } else {
4917 state->GEFlag &= ~(1 << 18);
4918 state->GEFlag &= ~(1 << 19);
4919 }
4920
4921 return 1;
4922 }
4923 // SADD8/SSUB8
4924 else if ((instr & 0xFF0) == 0xf90 || (instr & 0xFF0) == 0xff0)
4925 {
4926 const u8 rd_idx = BITS(12, 15);
4927 const u8 rm_idx = BITS(0, 3);
4928 const u8 rn_idx = BITS(16, 19);
4929 const u32 rm_val = state->Reg[rm_idx];
4930 const u32 rn_val = state->Reg[rn_idx];
4931
4932 s32 lo_val1, lo_val2;
4933 s32 hi_val1, hi_val2;
4934
4935 // SADD8
4936 if ((instr & 0xFF0) == 0xf90) {
4937 lo_val1 = (s32)(s8)(rn_val & 0xFF) + (s32)(s8)(rm_val & 0xFF);
4938 lo_val2 = (s32)(s8)((rn_val >> 8) & 0xFF) + (s32)(s8)((rm_val >> 8) & 0xFF);
4939 hi_val1 = (s32)(s8)((rn_val >> 16) & 0xFF) + (s32)(s8)((rm_val >> 16) & 0xFF);
4940 hi_val2 = (s32)(s8)((rn_val >> 24) & 0xFF) + (s32)(s8)((rm_val >> 24) & 0xFF);
4941 }
4942 // SSUB8
4943 else {
4944 lo_val1 = (s32)(s8)(rn_val & 0xFF) - (s32)(s8)(rm_val & 0xFF);
4945 lo_val2 = (s32)(s8)((rn_val >> 8) & 0xFF) - (s32)(s8)((rm_val >> 8) & 0xFF);
4946 hi_val1 = (s32)(s8)((rn_val >> 16) & 0xFF) - (s32)(s8)((rm_val >> 16) & 0xFF);
4947 hi_val2 = (s32)(s8)((rn_val >> 24) & 0xFF) - (s32)(s8)((rm_val >> 24) & 0xFF);
4948 }
4949
4950 if (lo_val1 >= 0)
4951 state->GEFlag |= (1 << 16);
4952 else
4953 state->GEFlag &= ~(1 << 16);
4954
4955 if (lo_val2 >= 0)
4956 state->GEFlag |= (1 << 17);
4957 else
4958 state->GEFlag &= ~(1 << 17);
4959
4960 if (hi_val1 >= 0)
4961 state->GEFlag |= (1 << 18);
4962 else
4963 state->GEFlag &= ~(1 << 18);
4964
4965 if (hi_val2 >= 0)
4966 state->GEFlag |= (1 << 19);
4967 else
4968 state->GEFlag &= ~(1 << 19);
4969
4970 state->Reg[rd_idx] = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24));
4971 return 1;
4972 }
4973 else {
4974 printf("Unhandled v6 insn: %08x", instr);
4975 }
4976 break;
4977 case 0x62: // QADD16, QASX, QSAX, QSUB16, QADD8, and QSUB8
4978 {
4979 const u8 op2 = BITS(5, 7);
4980
4981 const u8 rd_idx = BITS(12, 15);
4982 const u8 rn_idx = BITS(16, 19);
4983 const u8 rm_idx = BITS(0, 3);
4984 const u16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
4985 const u16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF);
4986 const u16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
4987 const u16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF);
4988
4989 u16 lo_result = 0;
4990 u16 hi_result = 0;
4991
4992 // QADD16
4993 if (op2 == 0x00) {
4994 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
4995 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
4996 }
4997 // QASX
4998 else if (op2 == 0x01) {
4999 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
5000 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
5001 }
5002 // QSAX
5003 else if (op2 == 0x02) {
5004 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
5005 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
5006 }
5007 // QSUB16
5008 else if (op2 == 0x03) {
5009 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
5010 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
5011 }
5012 // QADD8
5013 else if (op2 == 0x04) {
5014 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
5015 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
5016 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
5017 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
5018 }
5019 // QSUB8
5020 else if (op2 == 0x07) {
5021 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
5022 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
5023 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
5024 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
5025 }
5026
5027 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5028 return 1;
5029 }
5030 break;
5031 case 0x63:
5032 printf ("Unhandled v6 insn: shadd/shsub\n");
5033 break;
5034 case 0x65:
5035 {
5036 u32 rd = (instr >> 12) & 0xF;
5037 u32 rn = (instr >> 16) & 0xF;
5038 u32 rm = (instr >> 0) & 0xF;
5039 u32 from = state->Reg[rn];
5040 u32 to = state->Reg[rm];
5041
5042 if ((instr & 0xFF0) == 0xF10 || (instr & 0xFF0) == 0xF70) { // UADD16/USUB16
5043 u32 h1, h2;
5044 state->Cpsr &= 0xfff0ffff;
5045 if ((instr & 0x0F0) == 0x070) { // USUB16
5046 h1 = ((u16)from - (u16)to);
5047 h2 = ((u16)(from >> 16) - (u16)(to >> 16));
5048
5049 if (!(h1 & 0xffff0000))
5050 state->GEFlag |= (3 << 16);
5051 else
5052 state->GEFlag &= ~(3 << 16);
5053
5054 if (!(h2 & 0xffff0000))
5055 state->GEFlag |= (3 << 18);
5056 else
5057 state->GEFlag &= ~(3 << 18);
5058 }
5059 else { // UADD16
5060 h1 = ((u16)from + (u16)to);
5061 h2 = ((u16)(from >> 16) + (u16)(to >> 16));
5062
5063 if (h1 & 0xffff0000)
5064 state->GEFlag |= (3 << 16);
5065 else
5066 state->GEFlag &= ~(3 << 16);
5067
5068 if (h2 & 0xffff0000)
5069 state->GEFlag |= (3 << 18);
5070 else
5071 state->GEFlag &= ~(3 << 18);
5072 }
5073
5074 state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16));
5075 return 1;
5076 }
5077 else
5078 if ((instr & 0xFF0) == 0xF90 || (instr & 0xFF0) == 0xFF0) { // UADD8/USUB8
5079 u32 b1, b2, b3, b4;
5080 state->Cpsr &= 0xfff0ffff;
5081 if ((instr & 0x0F0) == 0x0F0) { // USUB8
5082 b1 = ((u8)from - (u8)to);
5083 b2 = ((u8)(from >> 8) - (u8)(to >> 8));
5084 b3 = ((u8)(from >> 16) - (u8)(to >> 16));
5085 b4 = ((u8)(from >> 24) - (u8)(to >> 24));
5086
5087 if (!(b1 & 0xffffff00))
5088 state->GEFlag |= (1 << 16);
5089 else
5090 state->GEFlag &= ~(1 << 16);
5091
5092 if (!(b2 & 0xffffff00))
5093 state->GEFlag |= (1 << 17);
5094 else
5095 state->GEFlag &= ~(1 << 17);
5096
5097 if (!(b3 & 0xffffff00))
5098 state->GEFlag |= (1 << 18);
5099 else
5100 state->GEFlag &= ~(1 << 18);
5101
5102 if (!(b4 & 0xffffff00))
5103 state->GEFlag |= (1 << 19);
5104 else
5105 state->GEFlag &= ~(1 << 19);
5106 }
5107 else { // UADD8
5108 b1 = ((u8)from + (u8)to);
5109 b2 = ((u8)(from >> 8) + (u8)(to >> 8));
5110 b3 = ((u8)(from >> 16) + (u8)(to >> 16));
5111 b4 = ((u8)(from >> 24) + (u8)(to >> 24));
5112
5113 if (b1 & 0xffffff00)
5114 state->GEFlag |= (1 << 16);
5115 else
5116 state->GEFlag &= ~(1 << 16);
5117
5118 if (b2 & 0xffffff00)
5119 state->GEFlag |= (1 << 17);
5120 else
5121 state->GEFlag &= ~(1 << 17);
5122
5123 if (b3 & 0xffffff00)
5124 state->GEFlag |= (1 << 18);
5125 else
5126 state->GEFlag &= ~(1 << 18);
5127
5128 if (b4 & 0xffffff00)
5129 state->GEFlag |= (1 << 19);
5130 else
5131 state->GEFlag &= ~(1 << 19);
5132 }
5133
5134 state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24);
5135 return 1;
5136 }
5137 }
5138 printf("Unhandled v6 insn: uasx/usax\n");
5139 break;
5140 case 0x66: // UQADD16, UQASX, UQSAX, UQSUB16, UQADD8, and UQSUB8
5141 {
5142 const u8 rd_idx = BITS(12, 15);
5143 const u8 rm_idx = BITS(0, 3);
5144 const u8 rn_idx = BITS(16, 19);
5145 const u8 op2 = BITS(5, 7);
5146 const u32 rm_val = state->Reg[rm_idx];
5147 const u32 rn_val = state->Reg[rn_idx];
5148
5149 u16 lo_val = 0;
5150 u16 hi_val = 0;
5151
5152 // UQADD16
5153 if (op2 == 0x00) {
5154 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
5155 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
5156 }
5157 // UQASX
5158 else if (op2 == 0x01) {
5159 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
5160 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
5161 }
5162 // UQSAX
5163 else if (op2 == 0x02) {
5164 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
5165 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
5166 }
5167 // UQSUB16
5168 else if (op2 == 0x03) {
5169 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
5170 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
5171 }
5172 // UQADD8
5173 else if (op2 == 0x04) {
5174 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
5175 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
5176 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
5177 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
5178 }
5179 // UQSUB8
5180 else {
5181 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
5182 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
5183 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
5184 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
5185 }
5186
5187 state->Reg[rd_idx] = ((lo_val & 0xFFFF) | hi_val << 16);
5188 return 1;
5189 }
5190 break;
5191 case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8.
5192 {
5193 const u8 op2 = BITS(5, 7);
5194
5195 const u8 rm_idx = BITS(0, 3);
5196 const u8 rn_idx = BITS(16, 19);
5197 const u8 rd_idx = BITS(12, 15);
5198
5199 const u32 rm_val = state->Reg[rm_idx];
5200 const u32 rn_val = state->Reg[rn_idx];
5201
5202 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
5203 {
5204 u32 lo_val = 0;
5205 u32 hi_val = 0;
5206
5207 // UHADD16
5208 if (op2 == 0x00) {
5209 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
5210 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
5211 }
5212 // UHASX
5213 else if (op2 == 0x01) {
5214 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
5215 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
5216 }
5217 // UHSAX
5218 else if (op2 == 0x02) {
5219 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
5220 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
5221 }
5222 // UHSUB16
5223 else if (op2 == 0x03) {
5224 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
5225 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
5226 }
5227
5228 lo_val >>= 1;
5229 hi_val >>= 1;
5230
5231 state->Reg[rd_idx] = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
5232 return 1;
5233 }
5234 else if (op2 == 0x04 || op2 == 0x07) {
5235 u32 sum1;
5236 u32 sum2;
5237 u32 sum3;
5238 u32 sum4;
5239
5240 // UHADD8
5241 if (op2 == 0x04) {
5242 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
5243 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
5244 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
5245 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
5246 }
5247 // UHSUB8
5248 else {
5249 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
5250 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
5251 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
5252 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
5253 }
5254
5255 sum1 >>= 1;
5256 sum2 >>= 1;
5257 sum3 >>= 1;
5258 sum4 >>= 1;
5259
5260 state->Reg[rd_idx] = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24);
5261 return 1;
5262 }
5263 }
5264 break;
5265 case 0x68:
5266 {
5267 u32 rd = (instr >> 12) & 0xF;
5268 u32 rn = (instr >> 16) & 0xF;
5269 u32 rm = (instr >> 0) & 0xF;
5270 u32 from = state->Reg[rn];
5271 u32 to = state->Reg[rm];
5272 u32 cpsr = ARMul_GetCPSR(state);
5273 if ((instr & 0xFF0) == 0xFB0) { // SEL
5274 u32 result;
5275 if (cpsr & (1 << 16))
5276 result = from & 0xff;
5277 else
5278 result = to & 0xff;
5279 if (cpsr & (1 << 17))
5280 result |= from & 0x0000ff00;
5281 else
5282 result |= to & 0x0000ff00;
5283 if (cpsr & (1 << 18))
5284 result |= from & 0x00ff0000;
5285 else
5286 result |= to & 0x00ff0000;
5287 if (cpsr & (1 << 19))
5288 result |= from & 0xff000000;
5289 else
5290 result |= to & 0xff000000;
5291 state->Reg[rd] = result;
5292 return 1;
5293 }
5294 }
5295 printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n");
5296 break;
5297
5298 case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB
5299 {
5300 const u8 op2 = BITS(5, 7);
5301
5302 // SSAT16
5303 if (op2 == 0x01) {
5304 const u8 rd_idx = BITS(12, 15);
5305 const u8 rn_idx = BITS(0, 3);
5306 const u8 num_bits = BITS(16, 19) + 1;
5307 const s16 min = -(0x8000 >> (16 - num_bits));
5308 const s16 max = (0x7FFF >> (16 - num_bits));
5309 s16 rn_lo = (state->Reg[rn_idx]);
5310 s16 rn_hi = (state->Reg[rn_idx] >> 16);
5311
5312 if (rn_lo > max) {
5313 rn_lo = max;
5314 SETQ;
5315 } else if (rn_lo < min) {
5316 rn_lo = min;
5317 SETQ;
5318 }
5319
5320 if (rn_hi > max) {
5321 rn_hi = max;
5322 SETQ;
5323 } else if (rn_hi < min) {
5324 rn_hi = min;
5325 SETQ;
5326 }
5327
5328 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
5329 return 1;
5330 }
5331 else if (op2 == 0x03) {
5332 const u8 rotation = BITS(10, 11) * 8;
5333 u32 rm = ((state->Reg[BITS(0, 3)] >> rotation) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotation)) & 0xFF) & 0xFF);
5334 if (rm & 0x80)
5335 rm |= 0xffffff00;
5336
5337 // SXTB, otherwise SXTAB
5338 if (BITS(16, 19) == 0xf)
5339 state->Reg[BITS(12, 15)] = rm;
5340 else
5341 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
5342
5343 return 1;
5344 }
5345 else {
5346 printf("Unimplemented op: SSAT");
5347 }
5348 }
5349 break;
5350
5351 case 0x6b: // REV, REV16, SXTH, and SXTAH
5352 {
5353 const u8 op2 = BITS(5, 7);
5354
5355 // REV
5356 if (op2 == 0x01) {
5357 DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24);
5358 return 1;
5359 }
5360 // REV16
5361 else if (op2 == 0x05) {
5362 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8);
5363 return 1;
5364 }
5365 else if (op2 == 0x03) {
5366 const u8 rotate = BITS(10, 11) * 8;
5367
5368 u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF);
5369 if (rm & 0x8000)
5370 rm |= 0xffff0000;
5371
5372 // SXTH, otherwise SXTAH
5373 if (BITS(16, 19) == 15)
5374 state->Reg[BITS(12, 15)] = rm;
5375 else
5376 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
5377
5378 return 1;
5379 }
5380 }
5381 break;
5382
5383 case 0x6c: // UXTB16 and UXTAB16
5384 {
5385 const u8 rm_idx = BITS(0, 3);
5386 const u8 rn_idx = BITS(16, 19);
5387 const u8 rd_idx = BITS(12, 15);
5388 const u32 rm_val = state->Reg[rm_idx];
5389 const u32 rn_val = state->Reg[rn_idx];
5390 const u32 rotation = BITS(10, 11) * 8;
5391 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
5392
5393 // UXTB16
5394 if ((instr & 0xf03f0) == 0xf0070) {
5395 state->Reg[rd_idx] = rotated_rm & 0x00FF00FF;
5396 }
5397 else { // UXTAB16
5398 const u8 lo_rotated = (rotated_rm & 0xFF);
5399 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
5400
5401 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
5402 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
5403
5404 state->Reg[rd_idx] = ((hi_result << 16) | (lo_result & 0xFFFF));
5405 }
5406
5407 return 1;
5408 }
5409 break;
5410 case 0x6e: // USAT, USAT16, UXTB, and UXTAB
5411 {
5412 const u8 op2 = BITS(5, 7);
5413
5414 // USAT16
5415 if (op2 == 0x01) {
5416 const u8 rd_idx = BITS(12, 15);
5417 const u8 rn_idx = BITS(0, 3);
5418 const u8 num_bits = BITS(16, 19);
5419 const s16 max = 0xFFFF >> (16 - num_bits);
5420 s16 rn_lo = (state->Reg[rn_idx]);
5421 s16 rn_hi = (state->Reg[rn_idx] >> 16);
5422
5423 if (max < rn_lo) {
5424 rn_lo = max;
5425 SETQ;
5426 } else if (rn_lo < 0) {
5427 rn_lo = 0;
5428 SETQ;
5429 }
5430
5431 if (max < rn_hi) {
5432 rn_hi = max;
5433 SETQ;
5434 } else if (rn_hi < 0) {
5435 rn_hi = 0;
5436 SETQ;
5437 }
5438
5439 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF);
5440 return 1;
5441 }
5442 else if (op2 == 0x03) {
5443 const u8 rotate = BITS(10, 11) * 8;
5444 const u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFF) & 0xFF);
5445
5446 if (BITS(16, 19) == 0xf)
5447 /* UXTB */
5448 state->Reg[BITS(12, 15)] = rm;
5449 else
5450 /* UXTAB */
5451 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
5452
5453 return 1;
5454 }
5455 else {
5456 printf("Unimplemented op: USAT");
5457 }
5458 }
5459 break;
5460
5461 case 0x6f: // UXTH, UXTAH, and REVSH.
5462 {
5463 const u8 op2 = BITS(5, 7);
5464
5465 // REVSH
5466 if (op2 == 0x05) {
5467 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8);
5468 if (DEST & 0x8000)
5469 DEST |= 0xffff0000;
5470 return 1;
5471 }
5472 // UXTH and UXTAH
5473 else if (op2 == 0x03) {
5474 const u8 rotate = BITS(10, 11) * 8;
5475 const ARMword rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF);
5476
5477 // UXTH
5478 if (BITS(16, 19) == 0xf) {
5479 state->Reg[BITS(12, 15)] = rm;
5480 }
5481 // UXTAH
5482 else {
5483 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
5484 }
5485
5486 return 1;
5487 }
5488 }
5489 case 0x70:
5490 // ichfly
5491 // SMUAD, SMUSD, SMLAD, and SMLSD
5492 if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 ||
5493 (instr & 0xd0) == 0x10 || (instr & 0xd0) == 0x50)
5494 {
5495 const u8 rd_idx = BITS(16, 19);
5496 const u8 rn_idx = BITS(0, 3);
5497 const u8 rm_idx = BITS(8, 11);
5498 const u8 ra_idx = BITS(12, 15);
5499 const bool do_swap = (BIT(5) == 1);
5500
5501 u32 rm_val = state->Reg[rm_idx];
5502 const u32 rn_val = state->Reg[rn_idx];
5503
5504 if (do_swap)
5505 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
5506
5507 const s16 rm_lo = (rm_val & 0xFFFF);
5508 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
5509 const s16 rn_lo = (rn_val & 0xFFFF);
5510 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
5511
5512 const u32 product1 = (rn_lo * rm_lo);
5513 const u32 product2 = (rn_hi * rm_hi);
5514
5515 // SMUAD and SMLAD
5516 if (BIT(6) == 0) {
5517 state->Reg[rd_idx] = product1 + product2;
5518
5519 if (BITS(12, 15) != 15) {
5520 state->Reg[rd_idx] += state->Reg[ra_idx];
5521 if (ARMul_AddOverflowQ(product1 + product2, state->Reg[ra_idx]))
5522 SETQ;
5523 }
5524
5525 if (ARMul_AddOverflowQ(product1, product2))
5526 SETQ;
5527 }
5528 // SMUSD and SMLSD
5529 else {
5530 state->Reg[rd_idx] = product1 - product2;
5531
5532 if (BITS(12, 15) != 15) {
5533 state->Reg[rd_idx] += state->Reg[ra_idx];
5534
5535 if (ARMul_AddOverflowQ(product1 - product2, state->Reg[ra_idx]))
5536 SETQ;
5537 }
5538 }
5539
5540 return 1;
5541 }
5542 break;
5543 case 0x74: // SMLALD and SMLSLD
5544 {
5545 const u8 rm_idx = BITS(8, 11);
5546 const u8 rn_idx = BITS(0, 3);
5547 const u8 rdlo_idx = BITS(12, 15);
5548 const u8 rdhi_idx = BITS(16, 19);
5549 const bool do_swap = (BIT(5) == 1);
5550
5551 const u32 rdlo_val = state->Reg[rdlo_idx];
5552 const u32 rdhi_val = state->Reg[rdhi_idx];
5553 const u32 rn_val = state->Reg[rn_idx];
5554 u32 rm_val = state->Reg[rm_idx];
5555
5556 if (do_swap)
5557 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
5558
5559 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
5560 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
5561 s64 result;
5562
5563 // SMLALD
5564 if (BIT(6) == 0) {
5565 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
5566 }
5567 // SMLSLD
5568 else {
5569 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
5570 }
5571
5572 state->Reg[rdlo_idx] = (result & 0xFFFFFFFF);
5573 state->Reg[rdhi_idx] = ((result >> 32) & 0xFFFFFFFF);
5574 return 1;
5575 }
5576 break;
5577 case 0x75: // SMMLA, SMMUL, and SMMLS
5578 {
5579 const u8 rm_idx = BITS(8, 11);
5580 const u8 rn_idx = BITS(0, 3);
5581 const u8 ra_idx = BITS(12, 15);
5582 const u8 rd_idx = BITS(16, 19);
5583 const bool do_round = (BIT(5) == 1);
5584
5585 const u32 rm_val = state->Reg[rm_idx];
5586 const u32 rn_val = state->Reg[rn_idx];
5587
5588 // Assume SMMUL by default.
5589 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val;
5590
5591 if (ra_idx != 15) {
5592 const u32 ra_val = state->Reg[ra_idx];
5593
5594 // SMMLA, otherwise SMMLS
5595 if (BIT(6) == 0)
5596 result += ((s64)ra_val << 32);
5597 else
5598 result = ((s64)ra_val << 32) - result;
5599 }
5600
5601 if (do_round)
5602 result += 0x80000000;
5603
5604 state->Reg[rd_idx] = ((result >> 32) & 0xFFFFFFFF);
5605 return 1;
5606 }
5607 break;
5608 case 0x78:
5609 if (BITS(20, 24) == 0x18)
5610 {
5611 const u8 rm_idx = BITS(8, 11);
5612 const u8 rn_idx = BITS(0, 3);
5613 const u8 rd_idx = BITS(16, 19);
5614
5615 const u32 rm_val = state->Reg[rm_idx];
5616 const u32 rn_val = state->Reg[rn_idx];
5617
5618 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
5619 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
5620 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
5621 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
5622
5623 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
5624
5625 // Op is USADA8 if true.
5626 const u8 ra_idx = BITS(12, 15);
5627 if (ra_idx != 15)
5628 finalDif += state->Reg[ra_idx];
5629
5630 state->Reg[rd_idx] = finalDif;
5631 return 1;
5632 }
5633 break;
5634 case 0x7a:
5635 printf ("Unhandled v6 insn: usbfx\n");
5636 break;
5637 case 0x7c:
5638 printf ("Unhandled v6 insn: bfc/bfi\n");
5639 break;
5640 case 0x84:
5641 printf ("Unhandled v6 insn: srs\n");
5642 break;
5643 default:
5644 break;
5645 }
5646 printf("Unhandled v6 insn: UNKNOWN: %08x %08X\n", instr, BITS(20, 27));
5647 return 0;
5648 } \ No newline at end of file
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index 8ab5ef160..7b502e240 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -25,24 +25,13 @@
25void ARMul_EmulateInit(); 25void ARMul_EmulateInit();
26ARMul_State* ARMul_NewState(ARMul_State* state); 26ARMul_State* ARMul_NewState(ARMul_State* state);
27void ARMul_Reset (ARMul_State* state); 27void ARMul_Reset (ARMul_State* state);
28ARMword ARMul_DoCycle(ARMul_State* state);
29unsigned ARMul_DoCoPro(ARMul_State* state);
30ARMword ARMul_DoProg(ARMul_State* state);
31ARMword ARMul_DoInstr(ARMul_State* state);
32void ARMul_Abort(ARMul_State* state, ARMword address);
33 28
34unsigned ARMul_MultTable[32] = { 29unsigned ARMul_MultTable[32] = {
35 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 30 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
36 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16 31 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16
37}; 32};
38ARMword ARMul_ImmedTable[4096]; /* immediate DP LHS values */ 33ARMword ARMul_ImmedTable[4096]; // immediate DP LHS values
39char ARMul_BitList[256]; /* number of bits in a byte table */ 34char ARMul_BitList[256]; // number of bits in a byte table
40
41void arm_dyncom_Abort(ARMul_State * state, ARMword vector)
42{
43 ARMul_Abort(state, vector);
44}
45
46 35
47/***************************************************************************\ 36/***************************************************************************\
48* Call this routine once to set up the emulator's tables. * 37* Call this routine once to set up the emulator's tables. *
@@ -51,18 +40,21 @@ void ARMul_EmulateInit()
51{ 40{
52 unsigned int i, j; 41 unsigned int i, j;
53 42
54 for (i = 0; i < 4096; i++) { /* the values of 12 bit dp rhs's */ 43 // the values of 12 bit dp rhs's
44 for (i = 0; i < 4096; i++) {
55 ARMul_ImmedTable[i] = ROTATER (i & 0xffL, (i >> 7L) & 0x1eL); 45 ARMul_ImmedTable[i] = ROTATER (i & 0xffL, (i >> 7L) & 0x1eL);
56 } 46 }
57 47
58 for (i = 0; i < 256; ARMul_BitList[i++] = 0); /* how many bits in LSM */ 48 // how many bits in LSM
49 for (i = 0; i < 256; ARMul_BitList[i++] = 0);
59 for (j = 1; j < 256; j <<= 1) 50 for (j = 1; j < 256; j <<= 1)
60 for (i = 0; i < 256; i++) 51 for (i = 0; i < 256; i++)
61 if ((i & j) > 0) 52 if ((i & j) > 0)
62 ARMul_BitList[i]++; 53 ARMul_BitList[i]++;
63 54
55 // you always need 4 times these values
64 for (i = 0; i < 256; i++) 56 for (i = 0; i < 256; i++)
65 ARMul_BitList[i] *= 4; /* you always need 4 times these values */ 57 ARMul_BitList[i] *= 4;
66 58
67} 59}
68 60
@@ -71,24 +63,22 @@ void ARMul_EmulateInit()
71\***************************************************************************/ 63\***************************************************************************/
72ARMul_State* ARMul_NewState(ARMul_State* state) 64ARMul_State* ARMul_NewState(ARMul_State* state)
73{ 65{
74 unsigned i, j;
75
76 memset (state, 0, sizeof (ARMul_State)); 66 memset (state, 0, sizeof (ARMul_State));
77 67
78 state->Emulate = RUN; 68 state->Emulate = RUN;
79 for (i = 0; i < 16; i++) { 69 for (unsigned int i = 0; i < 16; i++) {
80 state->Reg[i] = 0; 70 state->Reg[i] = 0;
81 for (j = 0; j < 7; j++) 71 for (unsigned int j = 0; j < 7; j++)
82 state->RegBank[j][i] = 0; 72 state->RegBank[j][i] = 0;
83 } 73 }
84 for (i = 0; i < 7; i++) 74 for (unsigned int i = 0; i < 7; i++)
85 state->Spsr[i] = 0; 75 state->Spsr[i] = 0;
76
86 state->Mode = 0; 77 state->Mode = 0;
87 78
88 state->Debug = FALSE;
89 state->VectorCatch = 0; 79 state->VectorCatch = 0;
90 state->Aborted = FALSE; 80 state->Aborted = false;
91 state->Reseted = FALSE; 81 state->Reseted = false;
92 state->Inted = 3; 82 state->Inted = 3;
93 state->LastInted = 3; 83 state->LastInted = 3;
94 84
@@ -103,12 +93,6 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
103 state->lateabtSig = HIGH; 93 state->lateabtSig = HIGH;
104 state->bigendSig = LOW; 94 state->bigendSig = LOW;
105 95
106 //chy:2003-08-19
107 state->CP14R0_CCD = -1;
108
109 memset(&state->exclusive_tag_array[0], 0xFF, sizeof(state->exclusive_tag_array[0]) * 128);
110 state->exclusive_access_state = 0;
111
112 return state; 96 return state;
113} 97}
114 98
@@ -126,15 +110,15 @@ void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
126 state->data32Sig = HIGH; 110 state->data32Sig = HIGH;
127 } 111 }
128 112
129 state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) ? HIGH : LOW; 113 state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
130 state->is_v5 = (properties & ARM_v5_Prop) ? HIGH : LOW; 114 state->is_v5 = (properties & ARM_v5_Prop) != 0;
131 state->is_v5e = (properties & ARM_v5e_Prop) ? HIGH : LOW; 115 state->is_v5e = (properties & ARM_v5e_Prop) != 0;
132 state->is_XScale = (properties & ARM_XScale_Prop) ? HIGH : LOW; 116 state->is_XScale = (properties & ARM_XScale_Prop) != 0;
133 state->is_iWMMXt = (properties & ARM_iWMMXt_Prop) ? HIGH : LOW; 117 state->is_iWMMXt = (properties & ARM_iWMMXt_Prop) != 0;
134 state->is_v6 = (properties & ARM_v6_Prop) ? HIGH : LOW; 118 state->is_v6 = (properties & ARM_v6_Prop) != 0;
135 state->is_ep9312 = (properties & ARM_ep9312_Prop) ? HIGH : LOW; 119 state->is_ep9312 = (properties & ARM_ep9312_Prop) != 0;
136 state->is_pxa27x = (properties & ARM_PXA27X_Prop) ? HIGH : LOW; 120 state->is_pxa27x = (properties & ARM_PXA27X_Prop) != 0;
137 state->is_v7 = (properties & ARM_v7_Prop) ? HIGH : LOW; 121 state->is_v7 = (properties & ARM_v7_Prop) != 0;
138 122
139 /* Only initialse the coprocessor support once we 123 /* Only initialse the coprocessor support once we
140 know what kind of chip we are dealing with. */ 124 know what kind of chip we are dealing with. */
@@ -172,121 +156,4 @@ void ARMul_Reset(ARMul_State* state)
172 state->AbortAddr = 1; 156 state->AbortAddr = 1;
173 157
174 state->NumInstrs = 0; 158 state->NumInstrs = 0;
175 state->NumNcycles = 0;
176 state->NumScycles = 0;
177 state->NumIcycles = 0;
178 state->NumCcycles = 0;
179 state->NumFcycles = 0;
180}
181
182
183/***************************************************************************\
184* Emulate the execution of an entire program. Start the correct emulator *
185* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the *
186* address of the last instruction that is executed. *
187\***************************************************************************/
188ARMword ARMul_DoProg(ARMul_State* state)
189{
190 ARMword pc = 0;
191
192 state->Emulate = RUN;
193 while (state->Emulate != STOP) {
194 state->Emulate = RUN;
195
196 if (state->prog32Sig && ARMul_MODE32BIT) {
197 pc = ARMul_Emulate32 (state);
198 }
199 else {
200 //pc = ARMul_Emulate26 (state);
201 }
202 }
203
204 return pc;
205}
206
207/***************************************************************************\
208* Emulate the execution of one instruction. Start the correct emulator *
209* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the *
210* address of the instruction that is executed. *
211\***************************************************************************/
212ARMword ARMul_DoInstr(ARMul_State* state)
213{
214 ARMword pc = 0;
215
216 state->Emulate = ONCE;
217
218 if (state->prog32Sig && ARMul_MODE32BIT) {
219 pc = ARMul_Emulate32 (state);
220 }
221
222 return pc;
223}
224
225/***************************************************************************\
226* This routine causes an Abort to occur, including selecting the correct *
227* mode, register bank, and the saving of registers. Call with the *
228* appropriate vector's memory address (0,4,8 ....) *
229\***************************************************************************/
230void ARMul_Abort(ARMul_State* state, ARMword vector)
231{
232 ARMword temp;
233 int isize = INSN_SIZE;
234 int esize = (TFLAG ? 0 : 4);
235 int e2size = (TFLAG ? -4 : 0);
236
237 state->Aborted = FALSE;
238
239 if (state->prog32Sig)
240 if (ARMul_MODE26BIT)
241 temp = R15PC;
242 else
243 temp = state->Reg[15];
244 else
245 temp = R15PC | ECC | ER15INT | EMODE;
246
247 switch (vector) {
248 case ARMul_ResetV: /* RESET */
249 SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE,
250 0);
251 break;
252 case ARMul_UndefinedInstrV: /* Undefined Instruction */
253 SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE,
254 isize);
255 break;
256 case ARMul_SWIV: /* Software Interrupt */
257 SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE,
258 isize);
259 break;
260 case ARMul_PrefetchAbortV: /* Prefetch Abort */
261 state->AbortAddr = 1;
262 SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
263 esize);
264 break;
265 case ARMul_DataAbortV: /* Data Abort */
266 SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
267 e2size);
268 break;
269 case ARMul_AddrExceptnV: /* Address Exception */
270 SETABORT (IBIT, SVC26MODE, isize);
271 break;
272 case ARMul_IRQV: /* IRQ */
273 SETABORT (IBIT,
274 state->prog32Sig ? IRQ32MODE : IRQ26MODE,
275 esize);
276 break;
277 case ARMul_FIQV: /* FIQ */
278 SETABORT (INTBITS,
279 state->prog32Sig ? FIQ32MODE : FIQ26MODE,
280 esize);
281 break;
282 }
283
284 if (ARMul_MODE32BIT) {
285 /*if (state->mmu.control & CONTROL_VECTOR)
286 vector += 0xffff0000; //for v4 high exception address*/
287 if (state->vector_remap_flag)
288 vector += state->vector_remap_addr; /* support some remap function in LPC processor */
289 ARMul_SetR15 (state, vector);
290 } else
291 ARMul_SetR15 (state, R15CCINTMODE | vector);
292} 159}
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 5a8f09b22..fd90fb0a4 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -20,395 +20,13 @@
20#include "core/arm/disassembler/arm_disasm.h" 20#include "core/arm/disassembler/arm_disasm.h"
21#include "core/mem_map.h" 21#include "core/mem_map.h"
22 22
23 23// Unsigned sum of absolute difference
24static ARMword ModeToBank (ARMword);
25
26/* This routine returns the value of a register from a mode. */
27
28ARMword
29ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
30{
31 mode &= MODEBITS;
32 if (mode != state->Mode)
33 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
34 else
35 return (state->Reg[reg]);
36}
37
38/* This routine sets the value of a register for a mode. */
39
40void
41ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
42{
43 mode &= MODEBITS;
44 if (mode != state->Mode)
45 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
46 else
47 state->Reg[reg] = value;
48}
49
50/* This routine returns the value of the PC, mode independently. */
51
52ARMword
53ARMul_GetPC (ARMul_State * state)
54{
55 if (state->Mode > SVC26MODE)
56 return state->Reg[15];
57 else
58 return R15PC;
59}
60
61/* This routine returns the value of the PC, mode independently. */
62
63ARMword
64ARMul_GetNextPC (ARMul_State * state)
65{
66 if (state->Mode > SVC26MODE)
67 return state->Reg[15] + INSN_SIZE;
68 else
69 return (state->Reg[15] + INSN_SIZE) & R15PCBITS;
70}
71
72/* This routine sets the value of the PC. */
73
74void
75ARMul_SetPC (ARMul_State * state, ARMword value)
76{
77 if (ARMul_MODE32BIT)
78 state->Reg[15] = value & PCBITS;
79 else
80 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
81 FLUSHPIPE;
82}
83
84/* This routine returns the value of register 15, mode independently. */
85
86ARMword
87ARMul_GetR15 (ARMul_State * state)
88{
89 if (state->Mode > SVC26MODE)
90 return (state->Reg[15]);
91 else
92 return (R15PC | ECC | ER15INT | EMODE);
93}
94
95/* This routine sets the value of Register 15. */
96
97void
98ARMul_SetR15 (ARMul_State * state, ARMword value)
99{
100 if (ARMul_MODE32BIT)
101 state->Reg[15] = value & PCBITS;
102 else {
103 state->Reg[15] = value;
104 ARMul_R15Altered (state);
105 }
106 FLUSHPIPE;
107}
108
109/* This routine returns the value of the CPSR. */
110
111ARMword
112ARMul_GetCPSR (ARMul_State * state)
113{
114 //chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator
115 //return (CPSR | state->Cpsr); for gdb20030716
116 return (CPSR); //had be tested in old skyeye with gdb5.0-5.3
117}
118
119/* This routine sets the value of the CPSR. */
120
121void
122ARMul_SetCPSR (ARMul_State * state, ARMword value)
123{
124 state->Cpsr = value;
125 ARMul_CPSRAltered (state);
126}
127
128/* This routine does all the nasty bits involved in a write to the CPSR,
129 including updating the register bank, given a MSR instruction. */
130
131void
132ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
133{
134 state->Cpsr = ARMul_GetCPSR (state);
135 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
136 if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
137 /* In user mode, only write flags. */
138 if (BIT (16))
139 SETPSR_C (state->Cpsr, rhs);
140 if (BIT (17))
141 SETPSR_X (state->Cpsr, rhs);
142 if (BIT (18))
143 SETPSR_S (state->Cpsr, rhs);
144 }
145 if (BIT (19))
146 SETPSR_F (state->Cpsr, rhs);
147 ARMul_CPSRAltered (state);
148}
149
150/* Get an SPSR from the specified mode. */
151
152ARMword
153ARMul_GetSPSR (ARMul_State * state, ARMword mode)
154{
155 ARMword bank = ModeToBank (mode & MODEBITS);
156
157 if (!BANK_CAN_ACCESS_SPSR (bank))
158 return ARMul_GetCPSR (state);
159
160 return state->Spsr[bank];
161}
162
163/* This routine does a write to an SPSR. */
164
165void
166ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
167{
168 ARMword bank = ModeToBank (mode & MODEBITS);
169
170 if (BANK_CAN_ACCESS_SPSR (bank))
171 state->Spsr[bank] = value;
172}
173
174/* This routine does a write to the current SPSR, given an MSR instruction. */
175
176void
177ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
178{
179 if (BANK_CAN_ACCESS_SPSR (state->Bank)) {
180 if (BIT (16))
181 SETPSR_C (state->Spsr[state->Bank], rhs);
182 if (BIT (17))
183 SETPSR_X (state->Spsr[state->Bank], rhs);
184 if (BIT (18))
185 SETPSR_S (state->Spsr[state->Bank], rhs);
186 if (BIT (19))
187 SETPSR_F (state->Spsr[state->Bank], rhs);
188 }
189}
190
191/* This routine updates the state of the emulator after the Cpsr has been
192 changed. Both the processor flags and register bank are updated. */
193
194void
195ARMul_CPSRAltered (ARMul_State * state)
196{
197 ARMword oldmode;
198
199 if (state->prog32Sig == LOW)
200 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
201
202 oldmode = state->Mode;
203
204 /*if (state->Mode != (state->Cpsr & MODEBITS)) {
205 state->Mode =
206 ARMul_SwitchMode (state, state->Mode,
207 state->Cpsr & MODEBITS);
208
209 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
210 }*/
211 //state->Cpsr &= ~MODEBITS;
212
213 ASSIGNINT (state->Cpsr & INTBITS);
214 //state->Cpsr &= ~INTBITS;
215 ASSIGNN ((state->Cpsr & NBIT) != 0);
216 //state->Cpsr &= ~NBIT;
217 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
218 //state->Cpsr &= ~ZBIT;
219 ASSIGNC ((state->Cpsr & CBIT) != 0);
220 //state->Cpsr &= ~CBIT;
221 ASSIGNV ((state->Cpsr & VBIT) != 0);
222 //state->Cpsr &= ~VBIT;
223 ASSIGNQ ((state->Cpsr & QBIT) != 0);
224 //state->Cpsr &= ~QBIT;
225 state->GEFlag = (state->Cpsr & 0x000F0000);
226#ifdef MODET
227 ASSIGNT ((state->Cpsr & TBIT) != 0);
228 //state->Cpsr &= ~TBIT;
229#endif
230
231 if (oldmode > SVC26MODE) {
232 if (state->Mode <= SVC26MODE) {
233 state->Emulate = CHANGEMODE;
234 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
235 }
236 } else {
237 if (state->Mode > SVC26MODE) {
238 state->Emulate = CHANGEMODE;
239 state->Reg[15] = R15PC;
240 } else
241 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
242 }
243}
244
245/* This routine updates the state of the emulator after register 15 has
246 been changed. Both the processor flags and register bank are updated.
247 This routine should only be called from a 26 bit mode. */
248
249void
250ARMul_R15Altered (ARMul_State * state)
251{
252 if (state->Mode != R15MODE) {
253 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
254 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
255 }
256
257 if (state->Mode > SVC26MODE)
258 state->Emulate = CHANGEMODE;
259
260 ASSIGNR15INT (R15INT);
261
262 ASSIGNN ((state->Reg[15] & NBIT) != 0);
263 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
264 ASSIGNC ((state->Reg[15] & CBIT) != 0);
265 ASSIGNV ((state->Reg[15] & VBIT) != 0);
266}
267
268/* This routine controls the saving and restoring of registers across mode
269 changes. The regbank matrix is largely unused, only rows 13 and 14 are
270 used across all modes, 8 to 14 are used for FIQ, all others use the USER
271 column. It's easier this way. old and new parameter are modes numbers.
272 Notice the side effect of changing the Bank variable. */
273
274ARMword
275ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
276{
277 unsigned i;
278 ARMword oldbank;
279 ARMword newbank;
280 static int revision_value = 53;
281
282 oldbank = ModeToBank (oldmode);
283 newbank = state->Bank = ModeToBank (newmode);
284
285 /* Do we really need to do it? */
286 if (oldbank != newbank) {
287 if (oldbank == 3 && newbank == 2) {
288 //printf("icounter is %d PC is %x MODE CHANGED : %d --> %d\n", state->NumInstrs, state->pc, oldbank, newbank);
289 if (state->NumInstrs >= 5832487) {
290// printf("%d, ", state->NumInstrs + revision_value);
291// printf("revision_value : %d\n", revision_value);
292 revision_value ++;
293 }
294 }
295 /* Save away the old registers. */
296 switch (oldbank) {
297 case USERBANK:
298 case IRQBANK:
299 case SVCBANK:
300 case ABORTBANK:
301 case UNDEFBANK:
302 if (newbank == FIQBANK)
303 for (i = 8; i < 13; i++)
304 state->RegBank[USERBANK][i] =
305 state->Reg[i];
306 state->RegBank[oldbank][13] = state->Reg[13];
307 state->RegBank[oldbank][14] = state->Reg[14];
308 break;
309 case FIQBANK:
310 for (i = 8; i < 15; i++)
311 state->RegBank[FIQBANK][i] = state->Reg[i];
312 break;
313 case DUMMYBANK:
314 for (i = 8; i < 15; i++)
315 state->RegBank[DUMMYBANK][i] = 0;
316 break;
317 default:
318 abort ();
319 }
320
321 /* Restore the new registers. */
322 switch (newbank) {
323 case USERBANK:
324 case IRQBANK:
325 case SVCBANK:
326 case ABORTBANK:
327 case UNDEFBANK:
328 if (oldbank == FIQBANK)
329 for (i = 8; i < 13; i++)
330 state->Reg[i] =
331 state->RegBank[USERBANK][i];
332 state->Reg[13] = state->RegBank[newbank][13];
333 state->Reg[14] = state->RegBank[newbank][14];
334 break;
335 case FIQBANK:
336 for (i = 8; i < 15; i++)
337 state->Reg[i] = state->RegBank[FIQBANK][i];
338 break;
339 case DUMMYBANK:
340 for (i = 8; i < 15; i++)
341 state->Reg[i] = 0;
342 break;
343 default:
344 abort ();
345 }
346 }
347
348 return newmode;
349}
350
351/* Given a processor mode, this routine returns the
352 register bank that will be accessed in that mode. */
353
354static ARMword
355ModeToBank (ARMword mode)
356{
357 static ARMword bankofmode[] = {
358 USERBANK, FIQBANK, IRQBANK, SVCBANK,
359 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
360 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
361 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
362 USERBANK, FIQBANK, IRQBANK, SVCBANK,
363 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
364 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
365 DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
366 };
367
368 if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0])))
369 return DUMMYBANK;
370
371 return bankofmode[mode];
372}
373
374/* Returns the register number of the nth register in a reg list. */
375
376unsigned
377ARMul_NthReg (ARMword instr, unsigned number)
378{
379 unsigned bit, upto;
380
381 for (bit = 0, upto = 0; upto <= number; bit++)
382 if (BIT (bit))
383 upto++;
384
385 return (bit - 1);
386}
387
388/* Unsigned sum of absolute difference */
389u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) 24u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
390{ 25{
391 if (left > right) 26 if (left > right)
392 return left - right; 27 return left - right;
393 28
394 return right - left; 29 return right - left;
395}
396
397/* Assigns the N and Z flags depending on the value of result. */
398
399void
400ARMul_NegZero (ARMul_State * state, ARMword result)
401{
402 if (NEG (result)) {
403 SETN;
404 CLEARZ;
405 } else if (result == 0) {
406 CLEARN;
407 SETZ;
408 } else {
409 CLEARN;
410 CLEARZ;
411 }
412} 30}
413 31
414// Add with carry, indicates if a carry-out or signed overflow occurred. 32// Add with carry, indicates if a carry-out or signed overflow occurred.
@@ -441,23 +59,6 @@ bool SubOverflow(ARMword a, ARMword b, ARMword result)
441 (POS(a) && NEG(b) && NEG(result))); 59 (POS(a) && NEG(b) && NEG(result)));
442} 60}
443 61
444/* Assigns the C flag after an addition of a and b to give result. */
445
446void
447ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
448{
449 ASSIGNC ((NEG (a) && NEG (b)) ||
450 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
451}
452
453/* Assigns the V flag after an addition of a and b to give result. */
454
455void
456ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
457{
458 ASSIGNV (AddOverflow (a, b, result));
459}
460
461// Returns true if the Q flag should be set as a result of overflow. 62// Returns true if the Q flag should be set as a result of overflow.
462bool ARMul_AddOverflowQ(ARMword a, ARMword b) 63bool ARMul_AddOverflowQ(ARMword a, ARMword b)
463{ 64{
@@ -468,24 +69,7 @@ bool ARMul_AddOverflowQ(ARMword a, ARMword b)
468 return false; 69 return false;
469} 70}
470 71
471/* Assigns the C flag after an subtraction of a and b to give result. */ 72// 8-bit signed saturated addition
472
473void
474ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
475{
476 ASSIGNC ((NEG (a) && POS (b)) ||
477 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
478}
479
480/* Assigns the V flag after an subtraction of a and b to give result. */
481
482void
483ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
484{
485 ASSIGNV (SubOverflow (a, b, result));
486}
487
488/* 8-bit signed saturated addition */
489u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) 73u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
490{ 74{
491 u8 result = left + right; 75 u8 result = left + right;
@@ -500,7 +84,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
500 return result; 84 return result;
501} 85}
502 86
503/* 8-bit signed saturated subtraction */ 87// 8-bit signed saturated subtraction
504u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) 88u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
505{ 89{
506 u8 result = left - right; 90 u8 result = left - right;
@@ -515,7 +99,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
515 return result; 99 return result;
516} 100}
517 101
518/* 16-bit signed saturated addition */ 102// 16-bit signed saturated addition
519u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) 103u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
520{ 104{
521 u16 result = left + right; 105 u16 result = left + right;
@@ -530,7 +114,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
530 return result; 114 return result;
531} 115}
532 116
533/* 16-bit signed saturated subtraction */ 117// 16-bit signed saturated subtraction
534u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) 118u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
535{ 119{
536 u16 result = left - right; 120 u16 result = left - right;
@@ -545,7 +129,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
545 return result; 129 return result;
546} 130}
547 131
548/* 8-bit unsigned saturated addition */ 132// 8-bit unsigned saturated addition
549u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) 133u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
550{ 134{
551 u8 result = left + right; 135 u8 result = left + right;
@@ -556,7 +140,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
556 return result; 140 return result;
557} 141}
558 142
559/* 16-bit unsigned saturated addition */ 143// 16-bit unsigned saturated addition
560u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) 144u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
561{ 145{
562 u16 result = left + right; 146 u16 result = left + right;
@@ -567,7 +151,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
567 return result; 151 return result;
568} 152}
569 153
570/* 8-bit unsigned saturated subtraction */ 154// 8-bit unsigned saturated subtraction
571u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) 155u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
572{ 156{
573 if (left <= right) 157 if (left <= right)
@@ -576,7 +160,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
576 return left - right; 160 return left - right;
577} 161}
578 162
579/* 16-bit unsigned saturated subtraction */ 163// 16-bit unsigned saturated subtraction
580u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) 164u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
581{ 165{
582 if (left <= right) 166 if (left <= right)
@@ -620,444 +204,3 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
620 *saturation_occurred = false; 204 *saturation_occurred = false;
621 return (u32)value; 205 return (u32)value;
622} 206}
623
624/* This function does the work of generating the addresses used in an
625 LDC instruction. The code here is always post-indexed, it's up to the
626 caller to get the input address correct and to handle base register
627 modification. It also handles the Busy-Waiting. */
628
629void
630ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
631{
632 unsigned cpab;
633 ARMword data;
634
635 UNDEF_LSCPCBaseWb;
636 //printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
637 /*chy 2004-05-23 should update this function in the future,should concern dataabort*/
638// chy 2004-05-25 , fix it now,so needn't printf
639// printf("SKYEYE ARMul_LDC, should update this function!!!!!\n");
640 //exit(-1);
641
642 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
643 if (!state->LDC[CPNum]) {
644 /*
645 printf
646 ("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n",
647 CPNum, instr, address);
648 */
649 ARMul_UndefInstr (state, instr);
650 return;
651 }
652
653 /*if (ADDREXCEPT (address))
654 INTERNALABORT (address);*/
655
656 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
657 while (cpab == ARMul_BUSY) {
658 ARMul_Icycles (state, 1, 0);
659
660 if (IntPending (state)) {
661 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT,
662 instr, 0);
663 return;
664 } else
665 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr,
666 0);
667 }
668 if (cpab == ARMul_CANT) {
669 /*
670 printf
671 ("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n",
672 CPNum, instr, address);
673 */
674 CPTAKEABORT;
675 return;
676 }
677
678 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
679 data = ARMul_LoadWordN (state, address);
680 //chy 2004-05-25
681 if (state->abortSig || state->Aborted)
682 goto L_ldc_takeabort;
683
684 BUSUSEDINCPCN;
685//chy 2004-05-25
686 /*
687 if (BIT (21))
688 LSBase = state->Base;
689 */
690
691 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
692
693 while (cpab == ARMul_INC) {
694 address += 4;
695 data = ARMul_LoadWordN (state, address);
696 //chy 2004-05-25
697 if (state->abortSig || state->Aborted)
698 goto L_ldc_takeabort;
699
700 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
701 }
702
703//chy 2004-05-25
704L_ldc_takeabort:
705 if (BIT (21)) {
706 if (!
707 ((state->abortSig || state->Aborted)
708 && state->lateabtSig == LOW))
709 LSBase = state->Base;
710 }
711
712 if (state->abortSig || state->Aborted)
713 TAKEABORT;
714}
715
716/* This function does the work of generating the addresses used in an
717 STC instruction. The code here is always post-indexed, it's up to the
718 caller to get the input address correct and to handle base register
719 modification. It also handles the Busy-Waiting. */
720
721void
722ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
723{
724 unsigned cpab;
725 ARMword data;
726
727 UNDEF_LSCPCBaseWb;
728
729 //printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
730 /*chy 2004-05-23 should update this function in the future,should concern dataabort */
731// skyeye_instr_debug=0;printf("SKYEYE debug end!!!!\n");
732// chy 2004-05-25 , fix it now,so needn't printf
733// printf("SKYEYE ARMul_STC, should update this function!!!!!\n");
734
735 //exit(-1);
736 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
737 if (!state->STC[CPNum]) {
738 /*
739 printf
740 ("SKYEYE ARMul_STC,NOT ALLOW, undefinstr, CPnum is %x, instr %x, addr %x\n",
741 CPNum, instr, address);
742 */
743 ARMul_UndefInstr (state, instr);
744 return;
745 }
746
747 /*if (ADDREXCEPT (address) || VECTORACCESS (address))
748 INTERNALABORT (address);*/
749
750 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
751 while (cpab == ARMul_BUSY) {
752 ARMul_Icycles (state, 1, 0);
753 if (IntPending (state)) {
754 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT,
755 instr, 0);
756 return;
757 } else
758 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr,
759 &data);
760 }
761
762 if (cpab == ARMul_CANT) {
763 /*
764 printf
765 ("SKYEYE ARMul_STC,CANT, undefinstr, CPnum is %x, instr %x, addr %x\n",
766 CPNum, instr, address);
767 */
768 CPTAKEABORT;
769 return;
770 }
771 /*#ifndef MODE32
772 if (ADDREXCEPT (address) || VECTORACCESS (address))
773 INTERNALABORT (address);
774 #endif*/
775 BUSUSEDINCPCN;
776//chy 2004-05-25
777 /*
778 if (BIT (21))
779 LSBase = state->Base;
780 */
781 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
782 ARMul_StoreWordN (state, address, data);
783 //chy 2004-05-25
784 if (state->abortSig || state->Aborted)
785 goto L_stc_takeabort;
786
787 while (cpab == ARMul_INC) {
788 address += 4;
789 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
790 ARMul_StoreWordN (state, address, data);
791 //chy 2004-05-25
792 if (state->abortSig || state->Aborted)
793 goto L_stc_takeabort;
794 }
795//chy 2004-05-25
796L_stc_takeabort:
797 if (BIT (21)) {
798 if (!
799 ((state->abortSig || state->Aborted)
800 && state->lateabtSig == LOW))
801 LSBase = state->Base;
802 }
803
804 if (state->abortSig || state->Aborted)
805 TAKEABORT;
806}
807
808/* This function does the Busy-Waiting for an MCR instruction. */
809
810void
811ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
812{
813 unsigned cpab;
814 int cm = BITS(0, 3) & 0xf;
815 int cp = BITS(5, 7) & 0x7;
816 int rd = BITS(12, 15) & 0xf;
817 int cn = BITS(16, 19) & 0xf;
818 int cpopc = BITS(21, 23) & 0x7;
819
820 if (CPNum == 15 && source == 0) //Cache flush
821 {
822 return;
823 }
824
825 //printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source);
826 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
827 if (!state->MCR[CPNum]) {
828 //chy 2004-07-19 should fix in the future ????!!!!
829 LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x",CPNum, source);
830 ARMul_UndefInstr (state, instr);
831 return;
832 }
833
834 //DEBUG("SKYEYE ARMul_MCR p%d, %d, r%d, c%d, c%d, %d\n", CPNum, cpopc, rd, cn, cm, cp);
835 //DEBUG("plutoo: MCR not implemented\n");
836 //exit(1);
837 //return;
838
839 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
840
841 while (cpab == ARMul_BUSY) {
842 ARMul_Icycles (state, 1, 0);
843
844 if (IntPending (state)) {
845 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT,
846 instr, 0);
847 return;
848 } else
849 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr,
850 source);
851 }
852
853 if (cpab == ARMul_CANT) {
854 LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x", instr, CPNum, source); //ichfly todo
855 //ARMul_Abort (state, ARMul_UndefinedInstrV);
856 } else {
857 BUSUSEDINCPCN;
858 ARMul_Ccycles (state, 1, 0);
859 }
860}
861
862/* This function does the Busy-Waiting for an MCRR instruction. */
863
864void
865ARMul_MCRR (ARMul_State * state, ARMword instr, ARMword source1, ARMword source2)
866{
867 unsigned cpab;
868
869 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
870 if (!state->MCRR[CPNum]) {
871 ARMul_UndefInstr (state, instr);
872 return;
873 }
874
875 cpab = (state->MCRR[CPNum]) (state, ARMul_FIRST, instr, source1, source2);
876
877 while (cpab == ARMul_BUSY) {
878 ARMul_Icycles (state, 1, 0);
879
880 if (IntPending (state)) {
881 cpab = (state->MCRR[CPNum]) (state, ARMul_INTERRUPT,
882 instr, 0, 0);
883 return;
884 } else
885 cpab = (state->MCRR[CPNum]) (state, ARMul_BUSY, instr,
886 source1, source2);
887 }
888 if (cpab == ARMul_CANT) {
889 printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x, source %x %x\n", __FUNCTION__, CPNum, instr, source1, source2);
890 ARMul_Abort (state, ARMul_UndefinedInstrV);
891 } else {
892 BUSUSEDINCPCN;
893 ARMul_Ccycles (state, 1, 0);
894 }
895}
896
897/* This function does the Busy-Waiting for an MRC instruction. */
898
899ARMword ARMul_MRC (ARMul_State * state, ARMword instr)
900{
901 int cm = BITS(0, 3) & 0xf;
902 int cp = BITS(5, 7) & 0x7;
903 int rd = BITS(12, 15) & 0xf;
904 int cn = BITS(16, 19) & 0xf;
905 int cpopc = BITS(21, 23) & 0x7;
906
907 if (cn == 13 && cm == 0 && cp == 3) { //c13,c0,3; returns CPU svc buffer
908 ARMword result = Memory::KERNEL_MEMORY_VADDR;
909
910 if (result != -1) {
911 return result;
912 }
913 }
914
915 //DEBUG("SKYEYE ARMul_MRC p%d, %d, r%d, c%d, c%d, %d\n", CPNum, cpopc, rd, cn, cm, cp);
916 //DEBUG("plutoo: MRC not implemented\n");
917 //return;
918
919 unsigned cpab;
920 ARMword result = 0;
921
922 //printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
923 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
924 if (!state->MRC[CPNum]) {
925 //chy 2004-07-19 should fix in the future????!!!!
926 LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x", CPNum, instr);
927 ARMul_UndefInstr (state, instr);
928 return -1;
929 }
930
931 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
932 while (cpab == ARMul_BUSY) {
933 ARMul_Icycles (state, 1, 0);
934 if (IntPending (state)) {
935 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
936 instr, 0);
937 return (0);
938 } else
939 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
940 &result);
941 }
942 if (cpab == ARMul_CANT) {
943 printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr);
944 ARMul_Abort (state, ARMul_UndefinedInstrV);
945 /* Parent will destroy the flags otherwise. */
946 result = ECC;
947 } else {
948 BUSUSEDINCPCN;
949 ARMul_Ccycles (state, 1, 0);
950 ARMul_Icycles (state, 1, 0);
951 }
952
953 return result;
954}
955
956/* This function does the Busy-Waiting for an MRRC instruction. (to verify) */
957
958void
959ARMul_MRRC (ARMul_State * state, ARMword instr, ARMword * dest1, ARMword * dest2)
960{
961 unsigned cpab;
962 ARMword result1 = 0;
963 ARMword result2 = 0;
964
965 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
966 if (!state->MRRC[CPNum]) {
967 ARMul_UndefInstr (state, instr);
968 return;
969 }
970
971 cpab = (state->MRRC[CPNum]) (state, ARMul_FIRST, instr, &result1, &result2);
972 while (cpab == ARMul_BUSY) {
973 ARMul_Icycles (state, 1, 0);
974 if (IntPending (state)) {
975 cpab = (state->MRRC[CPNum]) (state, ARMul_INTERRUPT,
976 instr, 0, 0);
977 return;
978 } else
979 cpab = (state->MRRC[CPNum]) (state, ARMul_BUSY, instr,
980 &result1, &result2);
981 }
982 if (cpab == ARMul_CANT) {
983 printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x\n", __FUNCTION__, CPNum, instr);
984 ARMul_Abort (state, ARMul_UndefinedInstrV);
985 } else {
986 BUSUSEDINCPCN;
987 ARMul_Ccycles (state, 1, 0);
988 ARMul_Icycles (state, 1, 0);
989 }
990
991 *dest1 = result1;
992 *dest2 = result2;
993}
994
995/* This function does the Busy-Waiting for an CDP instruction. */
996
997void
998ARMul_CDP (ARMul_State * state, ARMword instr)
999{
1000 unsigned cpab;
1001
1002 //if (!CP_ACCESS_ALLOWED (state, CPNum)) {
1003 if (!state->CDP[CPNum]) {
1004 ARMul_UndefInstr (state, instr);
1005 return;
1006 }
1007 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
1008 while (cpab == ARMul_BUSY) {
1009 ARMul_Icycles (state, 1, 0);
1010 if (IntPending (state)) {
1011 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT,
1012 instr);
1013 return;
1014 } else
1015 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
1016 }
1017 if (cpab == ARMul_CANT)
1018 ARMul_Abort (state, ARMul_UndefinedInstrV);
1019 else
1020 BUSUSEDN;
1021}
1022
1023/* This function handles Undefined instructions, as CP isntruction. */
1024
1025void
1026ARMul_UndefInstr (ARMul_State * state, ARMword instr)
1027{
1028 std::string disasm = ARM_Disasm::Disassemble(state->pc, instr);
1029 LOG_ERROR(Core_ARM11, "Undefined instruction!! Disasm: %s Opcode: 0x%x", disasm.c_str(), instr);
1030 ARMul_Abort (state, ARMul_UndefinedInstrV);
1031}
1032
1033/* Return TRUE if an interrupt is pending, FALSE otherwise. */
1034
1035unsigned
1036IntPending (ARMul_State * state)
1037{
1038 /* Any exceptions. */
1039 if (state->NresetSig == LOW) {
1040 ARMul_Abort (state, ARMul_ResetV);
1041 return TRUE;
1042 } else if (!state->NfiqSig && !FFLAG) {
1043 ARMul_Abort (state, ARMul_FIQV);
1044 return TRUE;
1045 } else if (!state->NirqSig && !IFLAG) {
1046 ARMul_Abort (state, ARMul_IRQV);
1047 return TRUE;
1048 }
1049
1050 return FALSE;
1051}
1052
1053/* Align a word access to a non word boundary. */
1054
1055ARMword
1056ARMul_Align (ARMul_State* state, ARMword address, ARMword data)
1057{
1058 /* This code assumes the address is really unaligned,
1059 as a shift by 32 is undefined in C. */
1060
1061 address = (address & 3) << 3; /* Get the word address. */
1062 return ((data >> address) | (data << (32 - address))); /* rot right */
1063}
diff --git a/src/core/arm/interpreter/armvirt.cpp b/src/core/arm/interpreter/armvirt.cpp
deleted file mode 100644
index 7845d1042..000000000
--- a/src/core/arm/interpreter/armvirt.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
1/* armvirt.c -- ARMulator virtual memory interace: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18/* This file contains a complete ARMulator memory model, modelling a
19"virtual memory" system. A much simpler model can be found in armfast.c,
20and that model goes faster too, but has a fixed amount of memory. This
21model's memory has 64K pages, allocated on demand from a 64K entry page
22table. The routines PutWord and GetWord implement this. Pages are never
23freed as they might be needed again. A single area of memory may be
24defined to generate aborts. */
25
26#include "core/arm/skyeye_common/armdefs.h"
27#include "core/arm/skyeye_common/armemu.h"
28
29#include "core/mem_map.h"
30
31#define dumpstack 1
32#define dumpstacksize 0x10
33#define maxdmupaddr 0x0033a850
34
35/*ARMword ARMul_GetCPSR (ARMul_State * state) {
36return 0;
37}
38ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) {
39return 0;
40}
41void ARMul_SetCPSR (ARMul_State * state, ARMword value) {
42
43}
44void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) {
45
46}*/
47
48void ARMul_Icycles(ARMul_State * state, unsigned number, ARMword address) {
49}
50
51void ARMul_Ccycles(ARMul_State * state, unsigned number, ARMword address) {
52}
53
54ARMword ARMul_LoadInstrS(ARMul_State * state, ARMword address, ARMword isize) {
55 state->NumScycles++;
56
57#ifdef HOURGLASS
58 if ((state->NumScycles & HOURGLASS_RATE) == 0) {
59 HOURGLASS;
60 }
61#endif
62 if (isize == 2)
63 return (u16)Memory::Read16(address);
64 else
65 return (u32)Memory::Read32(address);
66}
67
68ARMword ARMul_LoadInstrN(ARMul_State * state, ARMword address, ARMword isize) {
69 state->NumNcycles++;
70
71 if (isize == 2)
72 return (u16)Memory::Read16(address);
73 else
74 return (u32)Memory::Read32(address);
75}
76
77ARMword ARMul_ReLoadInstr(ARMul_State * state, ARMword address, ARMword isize) {
78 ARMword data;
79
80 if ((isize == 2) && (address & 0x2)) {
81 ARMword lo;
82 lo = (u16)Memory::Read16(address);
83 return lo;
84 }
85
86 data = (u32)Memory::Read32(address);
87 return data;
88}
89
90ARMword ARMul_ReadWord(ARMul_State * state, ARMword address) {
91 ARMword data;
92 data = Memory::Read32(address);
93 return data;
94}
95
96ARMword ARMul_LoadWordS(ARMul_State * state, ARMword address) {
97 state->NumScycles++;
98 return ARMul_ReadWord(state, address);
99}
100
101ARMword ARMul_LoadWordN(ARMul_State * state, ARMword address) {
102 state->NumNcycles++;
103 return ARMul_ReadWord(state, address);
104}
105
106ARMword ARMul_LoadHalfWord(ARMul_State * state, ARMword address) {
107 state->NumNcycles++;
108 return (u16)Memory::Read16(address);;
109}
110
111ARMword ARMul_ReadByte(ARMul_State * state, ARMword address) {
112 return (u8)Memory::Read8(address);
113}
114
115ARMword ARMul_LoadByte(ARMul_State * state, ARMword address) {
116 state->NumNcycles++;
117 return ARMul_ReadByte(state, address);
118}
119
120void ARMul_StoreHalfWord(ARMul_State * state, ARMword address, ARMword data) {
121 state->NumNcycles++;
122 Memory::Write16(address, data);
123}
124
125void ARMul_StoreByte(ARMul_State * state, ARMword address, ARMword data) {
126 state->NumNcycles++;
127 ARMul_WriteByte(state, address, data);
128}
129
130ARMword ARMul_SwapWord(ARMul_State * state, ARMword address, ARMword data) {
131 ARMword temp;
132 state->NumNcycles++;
133 temp = ARMul_ReadWord(state, address);
134 state->NumNcycles++;
135 Memory::Write32(address, data);
136 return temp;
137}
138
139ARMword ARMul_SwapByte(ARMul_State * state, ARMword address, ARMword data) {
140 ARMword temp;
141 temp = ARMul_LoadByte(state, address);
142 Memory::Write8(address, data);
143 return temp;
144}
145
146void ARMul_WriteWord(ARMul_State * state, ARMword address, ARMword data) {
147 Memory::Write32(address, data);
148}
149
150void ARMul_WriteByte(ARMul_State * state, ARMword address, ARMword data)
151{
152 Memory::Write8(address, data);
153}
154
155void ARMul_StoreWordS(ARMul_State * state, ARMword address, ARMword data)
156{
157 state->NumScycles++;
158 ARMul_WriteWord(state, address, data);
159}
160
161void ARMul_StoreWordN(ARMul_State * state, ARMword address, ARMword data)
162{
163 state->NumNcycles++;
164 ARMul_WriteWord(state, address, data);
165}
diff --git a/src/core/arm/interpreter/thumbemu.cpp b/src/core/arm/interpreter/thumbemu.cpp
deleted file mode 100644
index 9cf80672d..000000000
--- a/src/core/arm/interpreter/thumbemu.cpp
+++ /dev/null
@@ -1,513 +0,0 @@
1/* thumbemu.c -- Thumb instruction emulation.
2 Copyright (C) 1996, Cygnus Software Technologies Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18/* We can provide simple Thumb simulation by decoding the Thumb
19instruction into its corresponding ARM instruction, and using the
20existing ARM simulator. */
21
22#include "core/arm/skyeye_common/skyeye_defs.h"
23
24#ifndef MODET /* required for the Thumb instruction support */
25#if 1
26#error "MODET needs to be defined for the Thumb world to work"
27#else
28#define MODET (1)
29#endif
30#endif
31
32#include "core/arm/skyeye_common/armdefs.h"
33#include "core/arm/skyeye_common/armemu.h"
34#include "core/arm/skyeye_common/armos.h"
35
36
37/* Decode a 16bit Thumb instruction. The instruction is in the low
38 16-bits of the tinstr field, with the following Thumb instruction
39 held in the high 16-bits. Passing in two Thumb instructions allows
40 easier simulation of the special dual BL instruction. */
41
42tdstate
43ARMul_ThumbDecode (
44 ARMul_State *state,
45 ARMword pc,
46 ARMword tinstr,
47 ARMword *ainstr)
48{
49 tdstate valid = t_decoded; /* default assumes a valid instruction */
50 ARMword next_instr;
51
52 if (state->bigendSig) {
53 next_instr = tinstr & 0xFFFF;
54 tinstr >>= 16;
55 }
56 else {
57 next_instr = tinstr >> 16;
58 tinstr &= 0xFFFF;
59 }
60
61#if 1 /* debugging to catch non updates */
62 *ainstr = 0xDEADC0DE;
63#endif
64
65 switch ((tinstr & 0xF800) >> 11) {
66 case 0: /* LSL */
67 case 1: /* LSR */
68 case 2: /* ASR */
69 /* Format 1 */
70 *ainstr = 0xE1B00000 /* base opcode */
71 | ((tinstr & 0x1800) >> (11 - 5)) /* shift type */
72 |((tinstr & 0x07C0) << (7 - 6)) /* imm5 */
73 |((tinstr & 0x0038) >> 3) /* Rs */
74 |((tinstr & 0x0007) << 12); /* Rd */
75 break;
76 case 3: /* ADD/SUB */
77 /* Format 2 */
78 {
79 ARMword subset[4] = {
80 0xE0900000, /* ADDS Rd,Rs,Rn */
81 0xE0500000, /* SUBS Rd,Rs,Rn */
82 0xE2900000, /* ADDS Rd,Rs,#imm3 */
83 0xE2500000 /* SUBS Rd,Rs,#imm3 */
84 };
85 /* It is quicker indexing into a table, than performing switch
86 or conditionals: */
87 *ainstr = subset[(tinstr & 0x0600) >> 9] /* base opcode */
88 |((tinstr & 0x01C0) >> 6) /* Rn or imm3 */
89 |((tinstr & 0x0038) << (16 - 3)) /* Rs */
90 |((tinstr & 0x0007) << (12 - 0)); /* Rd */
91 }
92 break;
93 case 4: /* MOV */
94 case 5: /* CMP */
95 case 6: /* ADD */
96 case 7: /* SUB */
97 /* Format 3 */
98 {
99 ARMword subset[4] = {
100 0xE3B00000, /* MOVS Rd,#imm8 */
101 0xE3500000, /* CMP Rd,#imm8 */
102 0xE2900000, /* ADDS Rd,Rd,#imm8 */
103 0xE2500000, /* SUBS Rd,Rd,#imm8 */
104 };
105 *ainstr = subset[(tinstr & 0x1800) >> 11] /* base opcode */
106 |((tinstr & 0x00FF) >> 0) /* imm8 */
107 |((tinstr & 0x0700) << (16 - 8)) /* Rn */
108 |((tinstr & 0x0700) << (12 - 8)); /* Rd */
109 }
110 break;
111 case 8: /* Arithmetic and high register transfers */
112 /* TODO: Since the subsets for both Format 4 and Format 5
113 instructions are made up of different ARM encodings, we could
114 save the following conditional, and just have one large
115 subset. */
116 if ((tinstr & (1 << 10)) == 0) {
117 /* Format 4 */
118 enum OpcodeType { t_norm, t_shift, t_neg, t_mul };
119 struct ThumbOpcode {
120 ARMword opcode;
121 OpcodeType otype;
122 };
123
124 ThumbOpcode subset[16] = {
125 {
126 0xE0100000, t_norm}, /* ANDS Rd,Rd,Rs */
127 {
128 0xE0300000, t_norm}, /* EORS Rd,Rd,Rs */
129 {
130 0xE1B00010, t_shift}, /* MOVS Rd,Rd,LSL Rs */
131 {
132 0xE1B00030, t_shift}, /* MOVS Rd,Rd,LSR Rs */
133 {
134 0xE1B00050, t_shift}, /* MOVS Rd,Rd,ASR Rs */
135 {
136 0xE0B00000, t_norm}, /* ADCS Rd,Rd,Rs */
137 {
138 0xE0D00000, t_norm}, /* SBCS Rd,Rd,Rs */
139 {
140 0xE1B00070, t_shift}, /* MOVS Rd,Rd,ROR Rs */
141 {
142 0xE1100000, t_norm}, /* TST Rd,Rs */
143 {
144 0xE2700000, t_neg}, /* RSBS Rd,Rs,#0 */
145 {
146 0xE1500000, t_norm}, /* CMP Rd,Rs */
147 {
148 0xE1700000, t_norm}, /* CMN Rd,Rs */
149 {
150 0xE1900000, t_norm}, /* ORRS Rd,Rd,Rs */
151 {
152 0xE0100090, t_mul}, /* MULS Rd,Rd,Rs */
153 {
154 0xE1D00000, t_norm}, /* BICS Rd,Rd,Rs */
155 {
156 0xE1F00000, t_norm} /* MVNS Rd,Rs */
157 };
158 *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; /* base */
159 switch (subset[(tinstr & 0x03C0) >> 6].otype) {
160 case t_norm:
161 *ainstr |= ((tinstr & 0x0007) << 16) /* Rn */
162 |((tinstr & 0x0007) << 12) /* Rd */
163 |((tinstr & 0x0038) >> 3); /* Rs */
164 break;
165 case t_shift:
166 *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
167 |((tinstr & 0x0007) >> 0) /* Rm */
168 |((tinstr & 0x0038) << (8 - 3)); /* Rs */
169 break;
170 case t_neg:
171 *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
172 |((tinstr & 0x0038) << (16 - 3)); /* Rn */
173 break;
174 case t_mul:
175 *ainstr |= ((tinstr & 0x0007) << 16) /* Rd */
176 |((tinstr & 0x0007) << 8) /* Rs */
177 |((tinstr & 0x0038) >> 3); /* Rm */
178 break;
179 }
180 }
181 else {
182 /* Format 5 */
183 ARMword Rd = ((tinstr & 0x0007) >> 0);
184 ARMword Rs = ((tinstr & 0x0038) >> 3);
185 if (tinstr & (1 << 7))
186 Rd += 8;
187 if (tinstr & (1 << 6))
188 Rs += 8;
189 switch ((tinstr & 0x03C0) >> 6) {
190 case 0x1: /* ADD Rd,Rd,Hs */
191 case 0x2: /* ADD Hd,Hd,Rs */
192 case 0x3: /* ADD Hd,Hd,Hs */
193 *ainstr = 0xE0800000 /* base */
194 | (Rd << 16) /* Rn */
195 |(Rd << 12) /* Rd */
196 |(Rs << 0); /* Rm */
197 break;
198 case 0x5: /* CMP Rd,Hs */
199 case 0x6: /* CMP Hd,Rs */
200 case 0x7: /* CMP Hd,Hs */
201 *ainstr = 0xE1500000 /* base */
202 | (Rd << 16) /* Rn */
203 |(Rd << 12) /* Rd */
204 |(Rs << 0); /* Rm */
205 break;
206 case 0x9: /* MOV Rd,Hs */
207 case 0xA: /* MOV Hd,Rs */
208 case 0xB: /* MOV Hd,Hs */
209 *ainstr = 0xE1A00000 /* base */
210 | (Rd << 16) /* Rn */
211 |(Rd << 12) /* Rd */
212 |(Rs << 0); /* Rm */
213 break;
214 case 0xC: /* BX Rs */
215 case 0xD: /* BX Hs */
216 *ainstr = 0xE12FFF10 /* base */
217 | ((tinstr & 0x0078) >> 3); /* Rd */
218 break;
219 case 0x0: /* UNDEFINED */
220 case 0x4: /* UNDEFINED */
221 case 0x8: /* UNDEFINED */
222 valid = t_undefined;
223 break;
224 case 0xE: /* BLX */
225 case 0xF: /* BLX */
226 if (state->is_v5) {
227 *ainstr = 0xE1200030 /* base */
228 |(Rs << 0); /* Rm */
229 } else {
230 valid = t_undefined;
231 }
232 break;
233 }
234 }
235 break;
236 case 9: /* LDR Rd,[PC,#imm8] */
237 /* Format 6 */
238 *ainstr = 0xE59F0000 /* base */
239 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
240 |((tinstr & 0x00FF) << (2 - 0)); /* off8 */
241 break;
242 case 10:
243 case 11:
244 /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
245 the following could be merged into a single subset, saving on
246 the following boolean: */
247 if ((tinstr & (1 << 9)) == 0) {
248 /* Format 7 */
249 ARMword subset[4] = {
250 0xE7800000, /* STR Rd,[Rb,Ro] */
251 0xE7C00000, /* STRB Rd,[Rb,Ro] */
252 0xE7900000, /* LDR Rd,[Rb,Ro] */
253 0xE7D00000 /* LDRB Rd,[Rb,Ro] */
254 };
255 *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
256 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
257 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
258 |((tinstr & 0x01C0) >> 6); /* Ro */
259 }
260 else {
261 /* Format 8 */
262 ARMword subset[4] = {
263 0xE18000B0, /* STRH Rd,[Rb,Ro] */
264 0xE19000D0, /* LDRSB Rd,[Rb,Ro] */
265 0xE19000B0, /* LDRH Rd,[Rb,Ro] */
266 0xE19000F0 /* LDRSH Rd,[Rb,Ro] */
267 };
268 *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
269 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
270 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
271 |((tinstr & 0x01C0) >> 6); /* Ro */
272 }
273 break;
274 case 12: /* STR Rd,[Rb,#imm5] */
275 case 13: /* LDR Rd,[Rb,#imm5] */
276 case 14: /* STRB Rd,[Rb,#imm5] */
277 case 15: /* LDRB Rd,[Rb,#imm5] */
278 /* Format 9 */
279 {
280 ARMword subset[4] = {
281 0xE5800000, /* STR Rd,[Rb,#imm5] */
282 0xE5900000, /* LDR Rd,[Rb,#imm5] */
283 0xE5C00000, /* STRB Rd,[Rb,#imm5] */
284 0xE5D00000 /* LDRB Rd,[Rb,#imm5] */
285 };
286 /* The offset range defends on whether we are transferring a
287 byte or word value: */
288 *ainstr = subset[(tinstr & 0x1800) >> 11] /* base */
289 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
290 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
291 |((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); /* off5 */
292 }
293 break;
294 case 16: /* STRH Rd,[Rb,#imm5] */
295 case 17: /* LDRH Rd,[Rb,#imm5] */
296 /* Format 10 */
297 *ainstr = ((tinstr & (1 << 11)) /* base */
298 ? 0xE1D000B0 /* LDRH */
299 : 0xE1C000B0) /* STRH */
300 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
301 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
302 |((tinstr & 0x01C0) >> (6 - 1)) /* off5, low nibble */
303 |((tinstr & 0x0600) >> (9 - 8)); /* off5, high nibble */
304 break;
305 case 18: /* STR Rd,[SP,#imm8] */
306 case 19: /* LDR Rd,[SP,#imm8] */
307 /* Format 11 */
308 *ainstr = ((tinstr & (1 << 11)) /* base */
309 ? 0xE59D0000 /* LDR */
310 : 0xE58D0000) /* STR */
311 |((tinstr & 0x0700) << (12 - 8)) /* Rd */
312 |((tinstr & 0x00FF) << 2); /* off8 */
313 break;
314 case 20: /* ADD Rd,PC,#imm8 */
315 case 21: /* ADD Rd,SP,#imm8 */
316 /* Format 12 */
317 if ((tinstr & (1 << 11)) == 0) {
318 /* NOTE: The PC value used here should by word aligned */
319 /* We encode shift-left-by-2 in the rotate immediate field,
320 so no shift of off8 is needed. */
321 *ainstr = 0xE28F0F00 /* base */
322 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
323 |(tinstr & 0x00FF); /* off8 */
324 }
325 else {
326 /* We encode shift-left-by-2 in the rotate immediate field,
327 so no shift of off8 is needed. */
328 *ainstr = 0xE28D0F00 /* base */
329 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
330 |(tinstr & 0x00FF); /* off8 */
331 }
332 break;
333 case 22:
334 case 23:
335 if ((tinstr & 0x0F00) == 0x0000) {
336 /* Format 13 */
337 /* NOTE: The instruction contains a shift left of 2
338 equivalent (implemented as ROR #30): */
339 *ainstr = ((tinstr & (1 << 7)) /* base */
340 ? 0xE24DDF00 /* SUB */
341 : 0xE28DDF00) /* ADD */
342 |(tinstr & 0x007F); /* off7 */
343 }
344 else if ((tinstr & 0x0F00) == 0x0e00)
345 *ainstr = 0xEF000000 | SWI_Breakpoint;
346 else {
347 /* Format 14 */
348 ARMword subset[4] = {
349 0xE92D0000, /* STMDB sp!,{rlist} */
350 0xE92D4000, /* STMDB sp!,{rlist,lr} */
351 0xE8BD0000, /* LDMIA sp!,{rlist} */
352 0xE8BD8000 /* LDMIA sp!,{rlist,pc} */
353 };
354 *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] /* base */
355 |(tinstr & 0x00FF); /* mask8 */
356 }
357 break;
358 case 24: /* STMIA */
359 case 25: /* LDMIA */
360 /* Format 15 */
361 *ainstr = ((tinstr & (1 << 11)) /* base */
362 ? 0xE8B00000 /* LDMIA */
363 : 0xE8A00000) /* STMIA */
364 |((tinstr & 0x0700) << (16 - 8)) /* Rb */
365 |(tinstr & 0x00FF); /* mask8 */
366 break;
367 case 26: /* Bcc */
368 case 27: /* Bcc/SWI */
369 if ((tinstr & 0x0F00) == 0x0F00) {
370 if (tinstr == (ARMul_ABORTWORD & 0xffff) &&
371 state->AbortAddr == pc) {
372 *ainstr = ARMul_ABORTWORD;
373 break;
374 }
375 /* Format 17 : SWI */
376 *ainstr = 0xEF000000;
377 /* Breakpoint must be handled specially. */
378 if ((tinstr & 0x00FF) == 0x18)
379 *ainstr |= ((tinstr & 0x00FF) << 16);
380 /* New breakpoint value. See gdb/arm-tdep.c */
381 else if ((tinstr & 0x00FF) == 0xFE)
382 *ainstr |= SWI_Breakpoint;
383 else
384 *ainstr |= (tinstr & 0x00FF);
385 }
386 else if ((tinstr & 0x0F00) != 0x0E00) {
387 /* Format 16 */
388 int doit = FALSE;
389 /* TODO: Since we are doing a switch here, we could just add
390 the SWI and undefined instruction checks into this
391 switch to same on a couple of conditionals: */
392 switch ((tinstr & 0x0F00) >> 8) {
393 case EQ:
394 doit = ZFLAG;
395 break;
396 case NE:
397 doit = !ZFLAG;
398 break;
399 case VS:
400 doit = VFLAG;
401 break;
402 case VC:
403 doit = !VFLAG;
404 break;
405 case MI:
406 doit = NFLAG;
407 break;
408 case PL:
409 doit = !NFLAG;
410 break;
411 case CS:
412 doit = CFLAG;
413 break;
414 case CC:
415 doit = !CFLAG;
416 break;
417 case HI:
418 doit = (CFLAG && !ZFLAG);
419 break;
420 case LS:
421 doit = (!CFLAG || ZFLAG);
422 break;
423 case GE:
424 doit = ((!NFLAG && !VFLAG)
425 || (NFLAG && VFLAG));
426 break;
427 case LT:
428 doit = ((NFLAG && !VFLAG)
429 || (!NFLAG && VFLAG));
430 break;
431 case GT:
432 doit = ((!NFLAG && !VFLAG && !ZFLAG)
433 || (NFLAG && VFLAG && !ZFLAG));
434 break;
435 case LE:
436 doit = ((NFLAG && !VFLAG)
437 || (!NFLAG && VFLAG)) || ZFLAG;
438 break;
439 }
440 if (doit) {
441 state->Reg[15] = (pc + 4
442 + (((tinstr & 0x7F) << 1)
443 | ((tinstr & (1 << 7)) ?
444 0xFFFFFF00 : 0)));
445 FLUSHPIPE;
446 }
447 valid = t_branch;
448 }
449 else /* UNDEFINED : cc=1110(AL) uses different format */
450 valid = t_undefined;
451 break;
452 case 28: /* B */
453 /* Format 18 */
454 state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1)
455 | ((tinstr & (1 << 10)) ?
456 0xFFFFF800 : 0)));
457 FLUSHPIPE;
458 valid = t_branch;
459 break;
460 case 29:
461 if(tinstr & 0x1)
462 valid = t_undefined;
463 else{
464 /* BLX 1 for armv5t and above */
465 ARMword tmp = (pc + 2);
466 state->Reg[15] =
467 (state->Reg[14] + ((tinstr & 0x07FF) << 1)) & 0xFFFFFFFC;
468 state->Reg[14] = (tmp | 1);
469 CLEART;
470 LOG_DEBUG(Core_ARM11, "After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x", state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1);
471 valid = t_branch;
472 FLUSHPIPE;
473 }
474 break;
475 case 30: /* BL instruction 1 */
476 /* Format 19 */
477 /* There is no single ARM instruction equivalent for this Thumb
478 instruction. To keep the simulation simple (from the user
479 perspective) we check if the following instruction is the
480 second half of this BL, and if it is we simulate it
481 immediately. */
482 state->Reg[14] = state->Reg[15]
483 + (((tinstr & 0x07FF) << 12)
484 | ((tinstr & (1 << 10)) ? 0xFF800000 : 0));
485 valid = t_branch; /* in-case we don't have the 2nd half */
486 //tinstr = next_instr; /* move the instruction down */
487 //if (((tinstr & 0xF800) >> 11) != 31)
488 // break; /* exit, since not correct instruction */
489 /* else we fall through to process the second half of the BL */
490 //pc += 2; /* point the pc at the 2nd half */
491 state->Reg[15] = pc + 2;
492 FLUSHPIPE;
493 break;
494 case 31: /* BL instruction 2 */
495 /* Format 19 */
496 /* There is no single ARM instruction equivalent for this
497 instruction. Also, it should only ever be matched with the
498 fmt19 "BL instruction 1" instruction. However, we do allow
499 the simulation of it on its own, with undefined results if
500 r14 is not suitably initialised. */
501 {
502 ARMword tmp = (pc + 2);
503 state->Reg[15] =
504 (state->Reg[14] + ((tinstr & 0x07FF) << 1));
505 state->Reg[14] = (tmp | 1);
506 valid = t_branch;
507 FLUSHPIPE;
508 }
509 break;
510 }
511
512 return valid;
513}
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h
index 997874764..5be3a561f 100644
--- a/src/core/arm/skyeye_common/arm_regformat.h
+++ b/src/core/arm/skyeye_common/arm_regformat.h
@@ -86,7 +86,9 @@ enum {
86 CP15_IFAR, 86 CP15_IFAR,
87 CP15_PID, 87 CP15_PID,
88 CP15_CONTEXT_ID, 88 CP15_CONTEXT_ID,
89 CP15_THREAD_URO, 89 CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write
90 CP15_THREAD_URO, // Thread ID register - User Read Only (Privileged R/W)
91 CP15_THREAD_PRW, // Thread ID register - Privileged R/W only.
90 CP15_TLB_FAULT_ADDR, /* defined by SkyEye */ 92 CP15_TLB_FAULT_ADDR, /* defined by SkyEye */
91 CP15_TLB_FAULT_STATUS, /* defined by SkyEye */ 93 CP15_TLB_FAULT_STATUS, /* defined by SkyEye */
92 /* VFP registers */ 94 /* VFP registers */
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index a9c41ce5a..ff9296e0f 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -32,10 +32,8 @@
32#include "core/arm/skyeye_common/armmmu.h" 32#include "core/arm/skyeye_common/armmmu.h"
33#include "core/arm/skyeye_common/skyeye_defs.h" 33#include "core/arm/skyeye_common/skyeye_defs.h"
34 34
35#ifndef FALSE 35#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
36#define FALSE 0 36#define BIT(s, n) ((s >> (n)) & 1)
37#define TRUE 1
38#endif
39 37
40#define LOW 0 38#define LOW 0
41#define HIGH 1 39#define HIGH 1
@@ -71,88 +69,68 @@ typedef unsigned ARMul_CPWrites(ARMul_State* state, unsigned reg, ARMword value)
71#define VFP_REG_NUM 64 69#define VFP_REG_NUM 64
72struct ARMul_State 70struct ARMul_State
73{ 71{
74 ARMword Emulate; /* to start and stop emulation */ 72 ARMword Emulate; // To start and stop emulation
75 unsigned EndCondition; /* reason for stopping */ 73 unsigned EndCondition; // Reason for stopping
76 unsigned ErrorCode; /* type of illegal instruction */ 74 unsigned ErrorCode; // Type of illegal instruction
77 75
78 /* Order of the following register should not be modified */ 76 // Order of the following register should not be modified
79 ARMword Reg[16]; /* the current register file */ 77 ARMword Reg[16]; // The current register file
80 ARMword Cpsr; /* the current psr */ 78 ARMword Cpsr; // The current PSR
81 ARMword Spsr_copy; 79 ARMword Spsr_copy;
82 ARMword phys_pc; 80 ARMword phys_pc;
83 ARMword Reg_usr[2]; 81 ARMword Reg_usr[2];
84 ARMword Reg_svc[2]; /* R13_SVC R14_SVC */ 82 ARMword Reg_svc[2]; // R13_SVC R14_SVC
85 ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */ 83 ARMword Reg_abort[2]; // R13_ABORT R14_ABORT
86 ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */ 84 ARMword Reg_undef[2]; // R13 UNDEF R14 UNDEF
87 ARMword Reg_irq[2]; /* R13_IRQ R14_IRQ */ 85 ARMword Reg_irq[2]; // R13_IRQ R14_IRQ
88 ARMword Reg_firq[7]; /* R8---R14 FIRQ */ 86 ARMword Reg_firq[7]; // R8---R14 FIRQ
89 ARMword Spsr[7]; /* the exception psr's */ 87 ARMword Spsr[7]; // The exception psr's
90 ARMword Mode; /* the current mode */ 88 ARMword Mode; // The current mode
91 ARMword Bank; /* the current register bank */ 89 ARMword Bank; // The current register bank
92 ARMword exclusive_tag; /* the address for which the local monitor is in exclusive access mode */ 90 ARMword exclusive_tag; // The address for which the local monitor is in exclusive access mode
93 ARMword exclusive_state; 91 ARMword exclusive_state;
94 ARMword exclusive_result; 92 ARMword exclusive_result;
95 ARMword CP15[VFP_BASE - CP15_BASE]; 93 ARMword CP15[VFP_BASE - CP15_BASE];
96 ARMword VFP[3]; /* FPSID, FPSCR, and FPEXC */ 94 ARMword VFP[3]; // FPSID, FPSCR, and FPEXC
97 /* VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31). 95 // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
98 VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31), 96 // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
99 and only 32 singleword registers are accessible (S0-S31). */ 97 // and only 32 singleword registers are accessible (S0-S31).
100 ARMword ExtReg[VFP_REG_NUM]; 98 ARMword ExtReg[VFP_REG_NUM];
101 /* ---- End of the ordered registers ---- */ 99 /* ---- End of the ordered registers ---- */
102 100
103 ARMword RegBank[7][16]; /* all the registers */ 101 ARMword RegBank[7][16]; // all the registers
104 //chy:2003-08-19, used in arm xscale 102
105 /* 40 bit accumulator. We always keep this 64 bits wide, 103 ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
106 and move only 40 bits out of it in an MRA insn. */
107 ARMdword Accumulator;
108
109 ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; /* dummy flags for speed */
110 unsigned long long int icounter, debug_icounter, kernel_icounter;
111 unsigned int shifter_carry_out; 104 unsigned int shifter_carry_out;
112 105
113 /* add armv6 flags dyf:2010-08-09 */ 106 // Add armv6 flags dyf:2010-08-09
114 ARMword GEFlag, EFlag, AFlag, QFlag; 107 ARMword GEFlag, EFlag, AFlag, QFlag;
115 //chy:2003-08-19, used in arm v5e|xscale 108
116 ARMword SFlag;
117#ifdef MODET 109#ifdef MODET
118 ARMword TFlag; /* Thumb state */ 110 ARMword TFlag; // Thumb state
119#endif 111#endif
120 ARMword instr, pc, temp; /* saved register state */
121 ARMword loaded, decoded; /* saved pipeline state */
122 //chy 2006-04-12 for ICE breakpoint
123 ARMword loaded_addr, decoded_addr; /* saved pipeline state addr*/
124 unsigned int NumScycles, NumNcycles, NumIcycles, NumCcycles, NumFcycles; /* emulated cycles used */
125 unsigned long long NumInstrs; /* the number of instructions executed */
126 unsigned NumInstrsToExecute;
127 112
128 ARMword currentexaddr; 113 unsigned long long NumInstrs; // The number of instructions executed
129 ARMword currentexval; 114 unsigned NumInstrsToExecute;
130 ARMword currentexvald;
131 ARMword servaddr;
132 115
133 unsigned NextInstr; 116 unsigned NextInstr;
134 unsigned VectorCatch; /* caught exception mask */ 117 unsigned VectorCatch; // Caught exception mask
135 unsigned CallDebug; /* set to call the debugger */ 118
136 unsigned CanWatch; /* set by memory interface if its willing to suffer the 119 ARMul_CPInits* CPInit[16]; // Coprocessor initialisers
137 overhead of checking for watchpoints on each memory 120 ARMul_CPExits* CPExit[16]; // Coprocessor finalisers
138 access */ 121 ARMul_LDCs* LDC[16]; // LDC instruction
139 122 ARMul_STCs* STC[16]; // STC instruction
140 ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */ 123 ARMul_MRCs* MRC[16]; // MRC instruction
141 ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */ 124 ARMul_MCRs* MCR[16]; // MCR instruction
142 ARMul_LDCs *LDC[16]; /* LDC instruction */ 125 ARMul_MRRCs* MRRC[16]; // MRRC instruction
143 ARMul_STCs *STC[16]; /* STC instruction */ 126 ARMul_MCRRs* MCRR[16]; // MCRR instruction
144 ARMul_MRCs *MRC[16]; /* MRC instruction */ 127 ARMul_CDPs* CDP[16]; // CDP instruction
145 ARMul_MCRs *MCR[16]; /* MCR instruction */ 128 ARMul_CPReads* CPRead[16]; // Read CP register
146 ARMul_MRRCs *MRRC[16]; /* MRRC instruction */ 129 ARMul_CPWrites* CPWrite[16]; // Write CP register
147 ARMul_MCRRs *MCRR[16]; /* MCRR instruction */ 130 unsigned char* CPData[16]; // Coprocessor data
148 ARMul_CDPs *CDP[16]; /* CDP instruction */ 131 unsigned char const* CPRegWords[16]; // Map of coprocessor register sizes
149 ARMul_CPReads *CPRead[16]; /* Read CP register */ 132
150 ARMul_CPWrites *CPWrite[16]; /* Write CP register */ 133 unsigned NresetSig; // Reset the processor
151 unsigned char *CPData[16]; /* Coprocessor data */
152 unsigned char const *CPRegWords[16]; /* map of coprocessor register sizes */
153
154 unsigned Debug; /* show instructions as they are executed */
155 unsigned NresetSig; /* reset the processor */
156 unsigned NfiqSig; 134 unsigned NfiqSig;
157 unsigned NirqSig; 135 unsigned NirqSig;
158 136
@@ -196,54 +174,34 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
196*/ 174*/
197 unsigned lateabtSig; 175 unsigned lateabtSig;
198 176
199 ARMword Vector; /* synthesize aborts in cycle modes */ 177 bool Aborted; // Sticky flag for aborts
200 ARMword Aborted; /* sticky flag for aborts */ 178 bool Reseted; // Sticky flag for Reset
201 ARMword Reseted; /* sticky flag for Reset */ 179 ARMword Inted, LastInted; // Sticky flags for interrupts
202 ARMword Inted, LastInted; /* sticky flags for interrupts */ 180 ARMword Base; // Extra hand for base writeback
203 ARMword Base; /* extra hand for base writeback */ 181 ARMword AbortAddr; // To keep track of Prefetch aborts
204 ARMword AbortAddr; /* to keep track of Prefetch aborts */ 182 ARMword Vector; // Synthesize aborts in cycle modes
205 183
206 int verbose; /* non-zero means print various messages like the banner */ 184 // For differentiating ARM core emulaiton.
207 185 bool is_v4; // Are we emulating a v4 architecture (or higher)?
208 int mmu_inited; 186 bool is_v5; // Are we emulating a v5 architecture?
209 187 bool is_v5e; // Are we emulating a v5e architecture?
210 //chy: 2003-08-11, for different arm core type 188 bool is_v6; // Are we emulating a v6 architecture?
211 unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */ 189 bool is_v7; // Are we emulating a v7 architecture?
212 unsigned is_v5; /* Are we emulating a v5 architecture ? */ 190 bool is_XScale; // Are we emulating an XScale architecture?
213 unsigned is_v5e; /* Are we emulating a v5e architecture ? */ 191 bool is_iWMMXt; // Are we emulating an iWMMXt co-processor?
214 unsigned is_v6; /* Are we emulating a v6 architecture ? */ 192 bool is_ep9312; // Are we emulating a Cirrus Maverick co-processor?
215 unsigned is_v7; /* Are we emulating a v7 architecture ? */ 193 bool is_pxa27x; // Are we emulating a Intel PXA27x co-processor?
216 unsigned is_XScale; /* Are we emulating an XScale architecture ? */ 194
217 unsigned is_iWMMXt; /* Are we emulating an iWMMXt co-processor ? */ 195 // ARM_ARM A2-18
218 unsigned is_ep9312; /* Are we emulating a Cirrus Maverick co-processor ? */ 196 // 0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
219 unsigned is_pxa27x; /* Are we emulating a Intel PXA27x co-processor ? */ 197 int abort_model;
220 198
221 //chy: seems only used in xscale's CP14 199 // Added by ksh in 2005-10-1
222 ARMword CP14R0_CCD; /* used to count 64 clock cycles with CP14 R0 bit 3 set */ 200 cpu_config_t* cpu;
223
224 //teawater add for arm2x86 2005.07.05-------------------------------------------
225 //arm_arm A2-18
226 int abort_model; //0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
227
228 /*added by ksh in 2005-10-1*/
229 cpu_config_t *cpu;
230
231 /* added LPC remap function */
232 int vector_remap_flag;
233 u32 vector_remap_addr;
234 u32 vector_remap_size;
235
236 u32 step;
237 u32 cycle;
238
239 /* monitored memory for exclusice access */
240 ARMword exclusive_tag_array[128];
241 /* 1 means exclusive access and 0 means open access */
242 ARMword exclusive_access_state;
243 201
244 u32 CurrInstr; 202 u32 CurrInstr;
245 u32 last_pc; /* the last pc executed */ 203 u32 last_pc; // The last PC executed
246 u32 last_instr; /* the last inst executed */ 204 u32 last_instr; // The last instruction executed
247 u32 WriteAddr[17]; 205 u32 WriteAddr[17];
248 u32 WriteData[17]; 206 u32 WriteData[17];
249 u32 WritePc[17]; 207 u32 WritePc[17];
@@ -287,15 +245,6 @@ enum {
287 ARM620 = ARM6 245 ARM620 = ARM6
288}; 246};
289 247
290
291/***************************************************************************\
292* Macros to extract instruction fields *
293\***************************************************************************/
294
295#define BIT(n) ( (ARMword)(instr>>(n))&1) /* bit n of instruction */
296#define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) ) /* bits m to n of instr */
297#define TOPBITS(n) (instr >> (n)) /* bits 31 to n of instr */
298
299/***************************************************************************\ 248/***************************************************************************\
300* The hardware vector addresses * 249* The hardware vector addresses *
301\***************************************************************************/ 250\***************************************************************************/
@@ -339,13 +288,6 @@ enum {
339 SYSTEM32MODE = 31 288 SYSTEM32MODE = 31
340}; 289};
341 290
342#define ARM32BITMODE (state->Mode > 3)
343#define ARM26BITMODE (state->Mode <= 3)
344#define ARMMODE (state->Mode)
345#define ARMul_MODEBITS 0x1fL
346#define ARMul_MODE32BIT ARM32BITMODE
347#define ARMul_MODE26BIT ARM26BITMODE
348
349enum { 291enum {
350 USERBANK = 0, 292 USERBANK = 0,
351 FIQBANK = 1, 293 FIQBANK = 1,
@@ -357,10 +299,6 @@ enum {
357 SYSTEMBANK = USERBANK 299 SYSTEMBANK = USERBANK
358}; 300};
359 301
360#define BANK_CAN_ACCESS_SPSR(bank) \
361 ((bank) != USERBANK && (bank) != SYSTEMBANK && (bank) != DUMMYBANK)
362
363
364/***************************************************************************\ 302/***************************************************************************\
365* Definitons of things in the emulator * 303* Definitons of things in the emulator *
366\***************************************************************************/ 304\***************************************************************************/
@@ -372,85 +310,7 @@ extern void ARMul_Reset(ARMul_State* state);
372#ifdef __cplusplus 310#ifdef __cplusplus
373 } 311 }
374#endif 312#endif
375extern ARMul_State *ARMul_NewState(ARMul_State* state); 313extern ARMul_State* ARMul_NewState(ARMul_State* state);
376extern ARMword ARMul_DoProg(ARMul_State* state);
377extern ARMword ARMul_DoInstr(ARMul_State* state);
378
379/***************************************************************************\
380* Useful support routines *
381\***************************************************************************/
382
383extern ARMword ARMul_GetReg (ARMul_State* state, unsigned mode, unsigned reg);
384extern void ARMul_SetReg (ARMul_State* state, unsigned mode, unsigned reg, ARMword value);
385extern ARMword ARMul_GetPC(ARMul_State* state);
386extern ARMword ARMul_GetNextPC(ARMul_State* state);
387extern void ARMul_SetPC(ARMul_State* state, ARMword value);
388extern ARMword ARMul_GetR15(ARMul_State* state);
389extern void ARMul_SetR15(ARMul_State* state, ARMword value);
390
391extern ARMword ARMul_GetCPSR(ARMul_State* state);
392extern void ARMul_SetCPSR(ARMul_State* state, ARMword value);
393extern ARMword ARMul_GetSPSR(ARMul_State* state, ARMword mode);
394extern void ARMul_SetSPSR(ARMul_State* state, ARMword mode, ARMword value);
395
396/***************************************************************************\
397* Definitons of things to handle aborts *
398\***************************************************************************/
399
400extern void ARMul_Abort(ARMul_State* state, ARMword address);
401#ifdef MODET
402#define ARMul_ABORTWORD (state->TFlag ? 0xefffdfff : 0xefffffff) /* SWI -1 */
403#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
404 state->AbortAddr = (address & (state->TFlag ? ~1L : ~3L))
405#else
406#define ARMul_ABORTWORD 0xefffffff /* SWI -1 */
407#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
408 state->AbortAddr = (address & ~3L)
409#endif
410#define ARMul_DATAABORT(address) state->abortSig = HIGH ; \
411 state->Aborted = ARMul_DataAbortV ;
412#define ARMul_CLEARABORT state->abortSig = LOW
413
414/***************************************************************************\
415* Definitons of things in the memory interface *
416\***************************************************************************/
417
418extern unsigned ARMul_MemoryInit(ARMul_State* state, unsigned int initmemsize);
419extern void ARMul_MemoryExit(ARMul_State* state);
420
421extern ARMword ARMul_LoadInstrS(ARMul_State* state, ARMword address, ARMword isize);
422extern ARMword ARMul_LoadInstrN(ARMul_State* state, ARMword address, ARMword isize);
423#ifdef __cplusplus
424extern "C" {
425#endif
426extern ARMword ARMul_ReLoadInstr(ARMul_State* state, ARMword address, ARMword isize);
427#ifdef __cplusplus
428 }
429#endif
430extern ARMword ARMul_LoadWordS(ARMul_State* state, ARMword address);
431extern ARMword ARMul_LoadWordN(ARMul_State* state, ARMword address);
432extern ARMword ARMul_LoadHalfWord(ARMul_State* state, ARMword address);
433extern ARMword ARMul_LoadByte(ARMul_State* state, ARMword address);
434
435extern void ARMul_StoreWordS(ARMul_State* state, ARMword address, ARMword data);
436extern void ARMul_StoreWordN(ARMul_State* state, ARMword address, ARMword data);
437extern void ARMul_StoreHalfWord(ARMul_State* state, ARMword address, ARMword data);
438extern void ARMul_StoreByte(ARMul_State* state, ARMword address, ARMword data);
439
440extern ARMword ARMul_SwapWord(ARMul_State* state, ARMword address, ARMword data);
441extern ARMword ARMul_SwapByte(ARMul_State* state, ARMword address, ARMword data);
442
443extern void ARMul_Icycles(ARMul_State* state, unsigned number, ARMword address);
444extern void ARMul_Ccycles(ARMul_State* state, unsigned number, ARMword address);
445
446extern ARMword ARMul_ReadWord(ARMul_State* state, ARMword address);
447extern ARMword ARMul_ReadByte(ARMul_State* state, ARMword address);
448extern void ARMul_WriteWord(ARMul_State* state, ARMword address, ARMword data);
449extern void ARMul_WriteByte(ARMul_State* state, ARMword address, ARMword data);
450
451extern ARMword ARMul_MemAccess(ARMul_State* state, ARMword, ARMword,
452 ARMword, ARMword, ARMword, ARMword, ARMword,
453 ARMword, ARMword, ARMword);
454 314
455/***************************************************************************\ 315/***************************************************************************\
456* Definitons of things in the co-processor interface * 316* Definitons of things in the co-processor interface *
@@ -495,37 +355,10 @@ enum {
495 ARMul_CP15_DBCON_E0 = 0x0003 355 ARMul_CP15_DBCON_E0 = 0x0003
496}; 356};
497 357
498extern unsigned ARMul_CoProInit(ARMul_State* state);
499extern void ARMul_CoProExit(ARMul_State* state);
500extern void ARMul_CoProAttach (ARMul_State* state, unsigned number,
501 ARMul_CPInits* init, ARMul_CPExits* exit,
502 ARMul_LDCs* ldc, ARMul_STCs* stc,
503 ARMul_MRCs* mrc, ARMul_MCRs* mcr,
504 ARMul_MRRCs* mrrc, ARMul_MCRRs* mcrr,
505 ARMul_CDPs* cdp,
506 ARMul_CPReads* read, ARMul_CPWrites* write);
507extern void ARMul_CoProDetach(ARMul_State* state, unsigned number);
508
509/***************************************************************************\ 358/***************************************************************************\
510* Definitons of things in the host environment * 359* Definitons of things in the host environment *
511\***************************************************************************/ 360\***************************************************************************/
512 361
513extern unsigned ARMul_OSInit(ARMul_State* state);
514extern void ARMul_OSExit(ARMul_State* state);
515
516#ifdef __cplusplus
517 extern "C" {
518#endif
519
520extern unsigned ARMul_OSHandleSWI(ARMul_State* state, ARMword number);
521#ifdef __cplusplus
522}
523#endif
524
525extern ARMword ARMul_OSLastErrorP(ARMul_State* state);
526extern ARMword ARMul_Debug(ARMul_State* state, ARMword pc, ARMword instr);
527extern unsigned ARMul_OSException(ARMul_State* state, ARMword vector, ARMword pc);
528
529enum ConditionCode { 362enum ConditionCode {
530 EQ = 0, 363 EQ = 0,
531 NE = 1, 364 NE = 1,
@@ -545,40 +378,9 @@ enum ConditionCode {
545 NV = 15, 378 NV = 15,
546}; 379};
547 380
548#ifndef NFLAG
549#define NFLAG state->NFlag
550#endif //NFLAG
551
552#ifndef ZFLAG
553#define ZFLAG state->ZFlag
554#endif //ZFLAG
555
556#ifndef CFLAG
557#define CFLAG state->CFlag
558#endif //CFLAG
559
560#ifndef VFLAG
561#define VFLAG state->VFlag
562#endif //VFLAG
563
564#ifndef IFLAG
565#define IFLAG (state->IFFlags >> 1)
566#endif //IFLAG
567
568#ifndef FFLAG
569#define FFLAG (state->IFFlags & 1)
570#endif //FFLAG
571
572#ifndef IFFLAGS
573#define IFFLAGS state->IFFlags
574#endif //VFLAG
575
576extern bool AddOverflow(ARMword, ARMword, ARMword); 381extern bool AddOverflow(ARMword, ARMword, ARMword);
577extern bool SubOverflow(ARMword, ARMword, ARMword); 382extern bool SubOverflow(ARMword, ARMword, ARMword);
578 383
579extern void ARMul_UndefInstr(ARMul_State*, ARMword);
580extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword);
581extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword);
582extern void ARMul_SelectProcessor(ARMul_State*, unsigned); 384extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
583 385
584extern u32 AddWithCarry(u32, u32, u32, bool*, bool*); 386extern u32 AddWithCarry(u32, u32, u32, bool*, bool*);
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index 7e10dad86..beee54c9a 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -19,12 +19,6 @@
19 19
20#include "core/arm/skyeye_common/armdefs.h" 20#include "core/arm/skyeye_common/armdefs.h"
21 21
22/* Shift Opcodes. */
23#define LSL 0
24#define LSR 1
25#define ASR 2
26#define ROR 3
27
28/* Macros to twiddle the status flags and mode. */ 22/* Macros to twiddle the status flags and mode. */
29#define NBIT ((unsigned)1L << 31) 23#define NBIT ((unsigned)1L << 31)
30#define ZBIT (1L << 30) 24#define ZBIT (1L << 30)
@@ -38,73 +32,6 @@
38#define R15FBIT (1L << 26) 32#define R15FBIT (1L << 26)
39#define R15IFBITS (3L << 26) 33#define R15IFBITS (3L << 26)
40 34
41#ifdef MODET /* Thumb support. */
42/* ??? This bit is actually in the low order bit of the PC in the hardware.
43 It isn't clear if the simulator needs to model that or not. */
44#define TBIT (1L << 5)
45#define TFLAG state->TFlag
46#define SETT state->TFlag = 1
47#define CLEART state->TFlag = 0
48#define ASSIGNT(res) state->TFlag = res
49#define INSN_SIZE (TFLAG ? 2 : 4)
50#else
51#define INSN_SIZE 4
52#endif
53
54/*add armv6 CPSR feature*/
55#define EFLAG state->EFlag
56#define SETE state->EFlag = 1
57#define CLEARE state->EFlag = 0
58#define ASSIGNE(res) state->NFlag = res
59
60#define AFLAG state->AFlag
61#define SETA state->AFlag = 1
62#define CLEARA state->AFlag = 0
63#define ASSIGNA(res) state->NFlag = res
64
65#define QFLAG state->QFlag
66#define SETQ state->QFlag = 1
67#define CLEARQ state->AFlag = 0
68#define ASSIGNQ(res) state->QFlag = res
69
70/* add end */
71
72#define NFLAG state->NFlag
73#define SETN state->NFlag = 1
74#define CLEARN state->NFlag = 0
75#define ASSIGNN(res) state->NFlag = res
76
77#define ZFLAG state->ZFlag
78#define SETZ state->ZFlag = 1
79#define CLEARZ state->ZFlag = 0
80#define ASSIGNZ(res) state->ZFlag = res
81
82#define CFLAG state->CFlag
83#define SETC state->CFlag = 1
84#define CLEARC state->CFlag = 0
85#define ASSIGNC(res) state->CFlag = res
86
87#define VFLAG state->VFlag
88#define SETV state->VFlag = 1
89#define CLEARV state->VFlag = 0
90#define ASSIGNV(res) state->VFlag = res
91
92#define SFLAG state->SFlag
93#define SETS state->SFlag = 1
94#define CLEARS state->SFlag = 0
95#define ASSIGNS(res) state->SFlag = res
96
97#define IFLAG (state->IFFlags >> 1)
98#define FFLAG (state->IFFlags & 1)
99#define IFFLAGS state->IFFlags
100#define ASSIGNINT(res) state->IFFlags = (((res) >> 6) & 3)
101#define ASSIGNR15INT(res) state->IFFlags = (((res) >> 26) & 3) ;
102
103#define PSR_FBITS (0xff000000L)
104#define PSR_SBITS (0x00ff0000L)
105#define PSR_XBITS (0x0000ff00L)
106#define PSR_CBITS (0x000000ffL)
107
108#if defined MODE32 || defined MODET 35#if defined MODE32 || defined MODET
109#define CCBITS (0xf8000000L) 36#define CCBITS (0xf8000000L)
110#else 37#else
@@ -128,7 +55,6 @@
128#define R15PCBITS (0x03fffffcL) 55#define R15PCBITS (0x03fffffcL)
129#endif 56#endif
130 57
131#define R15PCMODEBITS (0x03ffffffL)
132#define R15MODEBITS (0x3L) 58#define R15MODEBITS (0x3L)
133 59
134#ifdef MODE32 60#ifdef MODE32
@@ -149,106 +75,7 @@
149#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS)) 75#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))
150#define R15MODE (state->Reg[15] & R15MODEBITS) 76#define R15MODE (state->Reg[15] & R15MODEBITS)
151 77
152#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (QFLAG << 27)) 78// Different ways to start the next instruction.
153#define EINT (IFFLAGS << 6)
154#define ER15INT (IFFLAGS << 26)
155#define EMODE (state->Mode)
156#define EGEBITS (state->GEFlag & 0x000F0000)
157
158#ifdef MODET
159#define CPSR (ECC | EGEBITS | (EFLAG << 9) | (AFLAG << 8) | EINT | (TFLAG << 5) | EMODE)
160#else
161#define CPSR (ECC | EINT | EMODE)
162#endif
163
164#ifdef MODE32
165#define PATCHR15
166#else
167#define PATCHR15 state->Reg[15] = ECC | ER15INT | EMODE | R15PC
168#endif
169
170#define GETSPSR(bank) (ARMul_GetSPSR (state, EMODE))
171#define SETPSR_F(d,s) d = ((d) & ~PSR_FBITS) | ((s) & PSR_FBITS)
172#define SETPSR_S(d,s) d = ((d) & ~PSR_SBITS) | ((s) & PSR_SBITS)
173#define SETPSR_X(d,s) d = ((d) & ~PSR_XBITS) | ((s) & PSR_XBITS)
174#define SETPSR_C(d,s) d = ((d) & ~PSR_CBITS) | ((s) & PSR_CBITS)
175
176#define SETR15PSR(s) \
177 do \
178 { \
179 if (state->Mode == USER26MODE) \
180 { \
181 state->Reg[15] = ((s) & CCBITS) | R15PC | ER15INT | EMODE; \
182 ASSIGNN ((state->Reg[15] & NBIT) != 0); \
183 ASSIGNZ ((state->Reg[15] & ZBIT) != 0); \
184 ASSIGNC ((state->Reg[15] & CBIT) != 0); \
185 ASSIGNV ((state->Reg[15] & VBIT) != 0); \
186 } \
187 else \
188 { \
189 state->Reg[15] = R15PC | ((s) & (CCBITS | R15INTBITS | R15MODEBITS)); \
190 ARMul_R15Altered (state); \
191 } \
192 } \
193 while (0)
194
195#define SETABORT(i, m, d) \
196 do \
197 { \
198 int SETABORT_mode = (m); \
199 \
200 ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state)); \
201 ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT)) \
202 | (i) | SETABORT_mode)); \
203 state->Reg[14] = temp - (d); \
204 } \
205 while (0)
206
207#ifndef MODE32
208#define VECTORS 0x20
209#define LEGALADDR 0x03ffffff
210#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig)
211#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig)
212#endif
213
214#define INTERNALABORT(address) \
215 do \
216 { \
217 if (address < VECTORS) \
218 state->Aborted = ARMul_DataAbortV; \
219 else \
220 state->Aborted = ARMul_AddrExceptnV; \
221 } \
222 while (0)
223
224#ifdef MODE32
225#define TAKEABORT ARMul_Abort (state, ARMul_DataAbortV)
226#else
227#define TAKEABORT \
228 do \
229 { \
230 if (state->Aborted == ARMul_AddrExceptnV) \
231 ARMul_Abort (state, ARMul_AddrExceptnV); \
232 else \
233 ARMul_Abort (state, ARMul_DataAbortV); \
234 } \
235 while (0)
236#endif
237
238#define CPTAKEABORT \
239 do \
240 { \
241 if (!state->Aborted) \
242 ARMul_Abort (state, ARMul_UndefinedInstrV); \
243 else if (state->Aborted == ARMul_AddrExceptnV) \
244 ARMul_Abort (state, ARMul_AddrExceptnV); \
245 else \
246 ARMul_Abort (state, ARMul_DataAbortV); \
247 } \
248 while (0);
249
250
251/* Different ways to start the next instruction. */
252#define SEQ 0 79#define SEQ 0
253#define NONSEQ 1 80#define NONSEQ 1
254#define PCINCEDSEQ 2 81#define PCINCEDSEQ 2
@@ -256,368 +83,27 @@
256#define PRIMEPIPE 4 83#define PRIMEPIPE 4
257#define RESUME 8 84#define RESUME 8
258 85
259/************************************/
260/* shenoubang 2012-3-11 */
261/* for armv7 DBG DMB DSB instr*/
262/************************************/
263#define MBReqTypes_Writes 0
264#define MBReqTypes_All 1
265
266#define NORMALCYCLE state->NextInstr = 0
267#define BUSUSEDN state->NextInstr |= 1 /* The next fetch will be an N cycle. */
268#define BUSUSEDINCPCS \
269 do \
270 { \
271 if (! state->is_v4) \
272 { \
273 /* A standard PC inc and an S cycle. */ \
274 state->Reg[15] += INSN_SIZE; \
275 state->NextInstr = (state->NextInstr & 0xff) | 2; \
276 } \
277 } \
278 while (0)
279
280#define BUSUSEDINCPCN \
281 do \
282 { \
283 if (state->is_v4) \
284 BUSUSEDN; \
285 else \
286 { \
287 /* A standard PC inc and an N cycle. */ \
288 state->Reg[15] += INSN_SIZE; \
289 state->NextInstr |= 3; \
290 } \
291 } \
292 while (0)
293
294#define INCPC \
295 do \
296 { \
297 /* A standard PC inc. */ \
298 state->Reg[15] += INSN_SIZE; \
299 state->NextInstr |= 2; \
300 } \
301 while (0)
302
303#define FLUSHPIPE state->NextInstr |= PRIMEPIPE 86#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
304 87
305/* Cycle based emulation. */ 88// Macro to rotate n right by b bits.
306
307#define OUTPUTCP(i,a,b)
308#define NCYCLE
309#define SCYCLE
310#define ICYCLE
311#define CCYCLE
312#define NEXTCYCLE(c)
313
314/* Macros to extract parts of instructions. */
315#define DESTReg (BITS (12, 15))
316#define LHSReg (BITS (16, 19))
317#define RHSReg (BITS ( 0, 3))
318
319#define DEST (state->Reg[DESTReg])
320
321#ifdef MODE32
322#ifdef MODET
323#define LHS ((LHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[LHSReg]))
324#define RHS ((RHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[RHSReg]))
325#else
326#define LHS (state->Reg[LHSReg])
327#define RHS (state->Reg[RHSReg])
328#endif
329#else
330#define LHS ((LHSReg == 15) ? R15PC : (state->Reg[LHSReg]))
331#define RHS ((RHSReg == 15) ? R15PC : (state->Reg[RHSReg]))
332#endif
333
334#define MULDESTReg (BITS (16, 19))
335#define MULLHSReg (BITS ( 0, 3))
336#define MULRHSReg (BITS ( 8, 11))
337#define MULACCReg (BITS (12, 15))
338
339#define DPImmRHS (ARMul_ImmedTable[BITS(0, 11)])
340#define DPSImmRHS temp = BITS(0,11) ; \
341 rhs = ARMul_ImmedTable[temp] ; \
342 if (temp > 255) /* There was a shift. */ \
343 ASSIGNC (rhs >> 31) ;
344
345#ifdef MODE32
346#define DPRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \
347 : GetDPRegRHS (state, instr))
348#define DPSRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \
349 : GetDPSRegRHS (state, instr))
350#else
351#define DPRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
352 : GetDPRegRHS (state, instr))
353#define DPSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
354 : GetDPSRegRHS (state, instr))
355#endif
356
357#define LSBase state->Reg[LHSReg]
358#define LSImmRHS (BITS(0,11))
359
360#ifdef MODE32
361#define LSRegRHS ((BITS (4, 11) == 0) ? state->Reg[RHSReg] \
362 : GetLSRegRHS (state, instr))
363#else
364#define LSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
365 : GetLSRegRHS (state, instr))
366#endif
367
368#define LSMNumRegs ((ARMword) ARMul_BitList[BITS (0, 7)] + \
369 (ARMword) ARMul_BitList[BITS (8, 15)] )
370#define LSMBaseFirst ((LHSReg == 0 && BIT (0)) || \
371 (BIT (LHSReg) && BITS (0, LHSReg - 1) == 0))
372
373#define SWAPSRC (state->Reg[RHSReg])
374
375#define LSCOff (BITS (0, 7) << 2)
376#define CPNum BITS (8, 11)
377
378/* Determine if access to coprocessor CP is permitted.
379 The XScale has a register in CP15 which controls access to CP0 - CP13. */
380//chy 2003-09-03, new CP_ACCESS_ALLOWED
381/*
382#define CP_ACCESS_ALLOWED(STATE, CP) \
383 ( ((CP) >= 14) \
384 || (! (STATE)->is_XScale) \
385 || (read_cp15_reg (15, 0, 1) & (1 << (CP))))
386*/
387#define CP_ACCESS_ALLOWED(STATE, CP) \
388 ( ((CP) >= 14) ) \
389
390/* Macro to rotate n right by b bits. */
391#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) 89#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))
392 90
393/* Macros to store results of instructions. */ 91// Values for Emulate.
394#define WRITEDEST(d) \ 92#define STOP 0 // stop
395 do \ 93#define CHANGEMODE 1 // change mode
396 { \ 94#define ONCE 2 // execute just one interation
397 if (DESTReg == 15) \ 95#define RUN 3 // continuous execution
398 WriteR15 (state, d); \ 96
399 else \ 97// Stuff that is shared across modes.
400 DEST = d; \ 98extern unsigned ARMul_MultTable[]; // Number of I cycles for a mult.
401 } \ 99extern ARMword ARMul_ImmedTable[]; // Immediate DP LHS values.
402 while (0) 100extern char ARMul_BitList[]; // Number of bits in a byte table.
403 101
404#define WRITESDEST(d) \ 102// Coprocessor support functions.
405 do \ 103extern void ARMul_CoProInit(ARMul_State*);
406 { \ 104extern void ARMul_CoProExit(ARMul_State*);
407 if (DESTReg == 15) \ 105extern void ARMul_CoProAttach(ARMul_State*, unsigned, ARMul_CPInits*,
408 WriteSR15 (state, d); \ 106 ARMul_CPExits*, ARMul_LDCs*, ARMul_STCs*,
409 else \ 107 ARMul_MRCs*, ARMul_MCRs*, ARMul_MRRCs*, ARMul_MCRRs*,
410 { \ 108 ARMul_CDPs*, ARMul_CPReads*, ARMul_CPWrites*);
411 DEST = d; \ 109extern void ARMul_CoProDetach(ARMul_State*, unsigned);
412 ARMul_NegZero (state, d); \
413 } \
414 } \
415 while (0)
416
417#define WRITEDESTB(d) \
418 do \
419 { \
420 if (DESTReg == 15){ \
421 WriteR15Branch (state, d); \
422 } \
423 else{ \
424 DEST = d; \
425 } \
426 } \
427 while (0)
428
429#define BYTETOBUS(data) ((data & 0xff) | \
430 ((data & 0xff) << 8) | \
431 ((data & 0xff) << 16) | \
432 ((data & 0xff) << 24))
433
434#define BUSTOBYTE(address, data) \
435 do \
436 { \
437 if (state->bigendSig) \
438 temp = (data >> (((address ^ 3) & 3) << 3)) & 0xff; \
439 else \
440 temp = (data >> ((address & 3) << 3)) & 0xff; \
441 } \
442 while (0)
443
444#define LOADMULT(instr, address, wb) LoadMult (state, instr, address, wb)
445#define LOADSMULT(instr, address, wb) LoadSMult (state, instr, address, wb)
446#define STOREMULT(instr, address, wb) StoreMult (state, instr, address, wb)
447#define STORESMULT(instr, address, wb) StoreSMult (state, instr, address, wb)
448
449#define POSBRANCH ((instr & 0x7fffff) << 2)
450#define NEGBRANCH ((0xff000000 |(instr & 0xffffff)) << 2)
451
452
453/* Values for Emulate. */
454#define STOP 0 /* stop */
455#define CHANGEMODE 1 /* change mode */
456#define ONCE 2 /* execute just one interation */
457#define RUN 3 /* continuous execution */
458
459/* Stuff that is shared across modes. */
460extern unsigned ARMul_MultTable[]; /* Number of I cycles for a mult. */
461extern ARMword ARMul_ImmedTable[]; /* Immediate DP LHS values. */
462extern char ARMul_BitList[]; /* Number of bits in a byte table. */
463
464#define EVENTLISTSIZE 1024L
465
466/* Thumb support. */
467typedef enum
468{
469 t_undefined, /* Undefined Thumb instruction. */
470 t_decoded, /* Instruction decoded to ARM equivalent. */
471 t_branch /* Thumb branch (already processed). */
472}
473tdstate;
474
475/*********************************************************************************
476 * Check all the possible undef or unpredict behavior, Some of them probably is
477 * out-of-updated with the newer ISA.
478 * -- Michael.Kang
479 ********************************************************************************/
480#define UNDEF_WARNING LOG_WARNING(Core_ARM11, "undefined or unpredicted behavior for arm instruction.");
481
482/* Macros to scrutinize instructions. */
483#define UNDEF_Test UNDEF_WARNING
484//#define UNDEF_Test
485
486//#define UNDEF_Shift UNDEF_WARNING
487#define UNDEF_Shift
488
489//#define UNDEF_MSRPC UNDEF_WARNING
490#define UNDEF_MSRPC
491
492//#define UNDEF_MRSPC UNDEF_WARNING
493#define UNDEF_MRSPC
494
495#define UNDEF_MULPCDest UNDEF_WARNING
496//#define UNDEF_MULPCDest
497
498#define UNDEF_MULDestEQOp1 UNDEF_WARNING
499//#define UNDEF_MULDestEQOp1
500
501//#define UNDEF_LSRBPC UNDEF_WARNING
502#define UNDEF_LSRBPC
503
504//#define UNDEF_LSRBaseEQOffWb UNDEF_WARNING
505#define UNDEF_LSRBaseEQOffWb
506
507//#define UNDEF_LSRBaseEQDestWb UNDEF_WARNING
508#define UNDEF_LSRBaseEQDestWb
509
510//#define UNDEF_LSRPCBaseWb UNDEF_WARNING
511#define UNDEF_LSRPCBaseWb
512
513//#define UNDEF_LSRPCOffWb UNDEF_WARNING
514#define UNDEF_LSRPCOffWb
515
516//#define UNDEF_LSMNoRegs UNDEF_WARNING
517#define UNDEF_LSMNoRegs
518
519//#define UNDEF_LSMPCBase UNDEF_WARNING
520#define UNDEF_LSMPCBase
521
522//#define UNDEF_LSMUserBankWb UNDEF_WARNING
523#define UNDEF_LSMUserBankWb
524
525//#define UNDEF_LSMBaseInListWb UNDEF_WARNING
526#define UNDEF_LSMBaseInListWb
527
528#define UNDEF_SWPPC UNDEF_WARNING
529//#define UNDEF_SWPPC
530
531#define UNDEF_CoProHS UNDEF_WARNING
532//#define UNDEF_CoProHS
533
534#define UNDEF_MCRPC UNDEF_WARNING
535//#define UNDEF_MCRPC
536
537//#define UNDEF_LSCPCBaseWb UNDEF_WARNING
538#define UNDEF_LSCPCBaseWb
539
540#define UNDEF_UndefNotBounced UNDEF_WARNING
541//#define UNDEF_UndefNotBounced
542
543#define UNDEF_ShortInt UNDEF_WARNING
544//#define UNDEF_ShortInt
545
546#define UNDEF_IllegalMode UNDEF_WARNING
547//#define UNDEF_IllegalMode
548
549#define UNDEF_Prog32SigChange UNDEF_WARNING
550//#define UNDEF_Prog32SigChange
551
552#define UNDEF_Data32SigChange UNDEF_WARNING
553//#define UNDEF_Data32SigChange
554
555/* Prototypes for exported functions. */
556extern unsigned ARMul_NthReg (ARMword, unsigned);
557
558/* Prototypes for exported functions. */
559#ifdef __cplusplus
560 extern "C" {
561#endif
562extern ARMword ARMul_Emulate26 (ARMul_State *);
563extern ARMword ARMul_Emulate32 (ARMul_State *);
564#ifdef __cplusplus
565 }
566#endif
567extern unsigned IntPending (ARMul_State *);
568extern void ARMul_CPSRAltered (ARMul_State *);
569extern void ARMul_R15Altered (ARMul_State *);
570extern ARMword ARMul_GetPC (ARMul_State *);
571extern ARMword ARMul_GetNextPC (ARMul_State *);
572extern ARMword ARMul_GetR15 (ARMul_State *);
573extern ARMword ARMul_GetCPSR (ARMul_State *);
574extern void ARMul_NegZero (ARMul_State *, ARMword);
575extern void ARMul_SetPC (ARMul_State *, ARMword);
576extern void ARMul_SetR15 (ARMul_State *, ARMword);
577extern void ARMul_SetCPSR (ARMul_State *, ARMword);
578extern ARMword ARMul_GetSPSR (ARMul_State *, ARMword);
579extern void ARMul_Abort26 (ARMul_State *, ARMword);
580extern void ARMul_Abort32 (ARMul_State *, ARMword);
581extern ARMword ARMul_MRC (ARMul_State *, ARMword);
582extern void ARMul_MRRC (ARMul_State *, ARMword, ARMword *, ARMword *);
583extern void ARMul_CDP (ARMul_State *, ARMword);
584extern void ARMul_LDC (ARMul_State *, ARMword, ARMword);
585extern void ARMul_STC (ARMul_State *, ARMword, ARMword);
586extern void ARMul_MCR (ARMul_State *, ARMword, ARMword);
587extern void ARMul_MCRR (ARMul_State *, ARMword, ARMword, ARMword);
588extern void ARMul_SetSPSR (ARMul_State *, ARMword, ARMword);
589extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
590extern ARMword ARMul_Align (ARMul_State *, ARMword, ARMword);
591extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
592extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);
593extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);
594extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword);
595extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword);
596extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword);
597extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *);
598extern ARMword ARMul_GetReg (ARMul_State *, unsigned, unsigned);
599extern void ARMul_SetReg (ARMul_State *, unsigned, unsigned, ARMword);
600
601/* Coprocessor support functions. */
602extern unsigned ARMul_CoProInit (ARMul_State *);
603extern void ARMul_CoProExit (ARMul_State *);
604extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *,
605 ARMul_CPExits *, ARMul_LDCs *, ARMul_STCs *,
606 ARMul_MRCs *, ARMul_MCRs *, ARMul_MRRCs *, ARMul_MCRRs *,
607 ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *);
608extern void ARMul_CoProDetach (ARMul_State *, unsigned);
609extern ARMword read_cp15_reg (unsigned, unsigned, unsigned);
610
611extern unsigned DSPLDC4 (ARMul_State *, unsigned, ARMword, ARMword);
612extern unsigned DSPMCR4 (ARMul_State *, unsigned, ARMword, ARMword);
613extern unsigned DSPMRC4 (ARMul_State *, unsigned, ARMword, ARMword *);
614extern unsigned DSPSTC4 (ARMul_State *, unsigned, ARMword, ARMword *);
615extern unsigned DSPCDP4 (ARMul_State *, unsigned, ARMword);
616extern unsigned DSPMCR5 (ARMul_State *, unsigned, ARMword, ARMword);
617extern unsigned DSPMRC5 (ARMul_State *, unsigned, ARMword, ARMword *);
618extern unsigned DSPLDC5 (ARMul_State *, unsigned, ARMword, ARMword);
619extern unsigned DSPSTC5 (ARMul_State *, unsigned, ARMword, ARMword *);
620extern unsigned DSPCDP5 (ARMul_State *, unsigned, ARMword);
621extern unsigned DSPMCR6 (ARMul_State *, unsigned, ARMword, ARMword);
622extern unsigned DSPMRC6 (ARMul_State *, unsigned, ARMword, ARMword *);
623extern unsigned DSPCDP6 (ARMul_State *, unsigned, ARMword);
diff --git a/src/core/arm/skyeye_common/vfp/asm_vfp.h b/src/core/arm/skyeye_common/vfp/asm_vfp.h
index e113eaf29..ccb7cf4d7 100644
--- a/src/core/arm/skyeye_common/vfp/asm_vfp.h
+++ b/src/core/arm/skyeye_common/vfp/asm_vfp.h
@@ -7,80 +7,77 @@
7 7
8#pragma once 8#pragma once
9 9
10#define FPSID cr0 10// FPSID Information
11#define FPSCR cr1 11// Note that these are used as values and not as flags.
12#define MVFR1 cr6 12enum : u32 {
13#define MVFR0 cr7 13 VFP_FPSID_IMPLMEN = 0, // Implementation code. Should be the same as cp15 0 c0 0
14#define FPEXC cr8 14 VFP_FPSID_SW = 0, // Software emulation bit value
15#define FPINST cr9 15 VFP_FPSID_SUBARCH = 0x2, // Subarchitecture version number
16#define FPINST2 cr10 16 VFP_FPSID_PARTNUM = 0x1, // Part number
17 VFP_FPSID_VARIANT = 0x1, // Variant number
18 VFP_FPSID_REVISION = 0x1 // Revision number
19};
17 20
18/* FPSID bits */ 21// FPEXC bits
19#define FPSID_IMPLEMENTER_BIT (24) 22enum : u32 {
20#define FPSID_IMPLEMENTER_MASK (0xff << FPSID_IMPLEMENTER_BIT) 23 FPEXC_EX = (1U << 31U),
21#define FPSID_SOFTWARE (1<<23) 24 FPEXC_EN = (1 << 30),
22#define FPSID_FORMAT_BIT (21) 25 FPEXC_DEX = (1 << 29),
23#define FPSID_FORMAT_MASK (0x3 << FPSID_FORMAT_BIT) 26 FPEXC_FP2V = (1 << 28),
24#define FPSID_NODOUBLE (1<<20) 27 FPEXC_VV = (1 << 27),
25#define FPSID_ARCH_BIT (16) 28 FPEXC_TFV = (1 << 26),
26#define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) 29 FPEXC_LENGTH_BIT = (8),
27#define FPSID_PART_BIT (8) 30 FPEXC_LENGTH_MASK = (7 << FPEXC_LENGTH_BIT),
28#define FPSID_PART_MASK (0xFF << FPSID_PART_BIT) 31 FPEXC_IDF = (1 << 7),
29#define FPSID_VARIANT_BIT (4) 32 FPEXC_IXF = (1 << 4),
30#define FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) 33 FPEXC_UFF = (1 << 3),
31#define FPSID_REV_BIT (0) 34 FPEXC_OFF = (1 << 2),
32#define FPSID_REV_MASK (0xF << FPSID_REV_BIT) 35 FPEXC_DZF = (1 << 1),
36 FPEXC_IOF = (1 << 0),
37 FPEXC_TRAP_MASK = (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF)
38};
33 39
34/* FPEXC bits */ 40// FPSCR Flags
35#define FPEXC_EX (1 << 31) 41enum : u32 {
36#define FPEXC_EN (1 << 30) 42 FPSCR_NFLAG = (1U << 31U), // Negative condition flag
37#define FPEXC_DEX (1 << 29) 43 FPSCR_ZFLAG = (1 << 30), // Zero condition flag
38#define FPEXC_FP2V (1 << 28) 44 FPSCR_CFLAG = (1 << 29), // Carry condition flag
39#define FPEXC_VV (1 << 27) 45 FPSCR_VFLAG = (1 << 28), // Overflow condition flag
40#define FPEXC_TFV (1 << 26)
41#define FPEXC_LENGTH_BIT (8)
42#define FPEXC_LENGTH_MASK (7 << FPEXC_LENGTH_BIT)
43#define FPEXC_IDF (1 << 7)
44#define FPEXC_IXF (1 << 4)
45#define FPEXC_UFF (1 << 3)
46#define FPEXC_OFF (1 << 2)
47#define FPEXC_DZF (1 << 1)
48#define FPEXC_IOF (1 << 0)
49#define FPEXC_TRAP_MASK (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF)
50 46
51/* FPSCR bits */ 47 FPSCR_QC = (1 << 27), // Cumulative saturation bit
52#define FPSCR_DEFAULT_NAN (1<<25) 48 FPSCR_AHP = (1 << 26), // Alternative half-precision control bit
53#define FPSCR_FLUSHTOZERO (1<<24) 49 FPSCR_DEFAULT_NAN = (1 << 25), // Default NaN mode control bit
54#define FPSCR_ROUND_NEAREST (0<<22) 50 FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit
55#define FPSCR_ROUND_PLUSINF (1<<22) 51 FPSCR_RMODE_MASK = (3 << 22), // Rounding Mode bit mask
56#define FPSCR_ROUND_MINUSINF (2<<22) 52 FPSCR_STRIDE_MASK = (3 << 20), // Vector stride bit mask
57#define FPSCR_ROUND_TOZERO (3<<22) 53 FPSCR_LENGTH_MASK = (7 << 16), // Vector length bit mask
58#define FPSCR_RMODE_BIT (22)
59#define FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT)
60#define FPSCR_STRIDE_BIT (20)
61#define FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT)
62#define FPSCR_LENGTH_BIT (16)
63#define FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT)
64#define FPSCR_IOE (1<<8)
65#define FPSCR_DZE (1<<9)
66#define FPSCR_OFE (1<<10)
67#define FPSCR_UFE (1<<11)
68#define FPSCR_IXE (1<<12)
69#define FPSCR_IDE (1<<15)
70#define FPSCR_IOC (1<<0)
71#define FPSCR_DZC (1<<1)
72#define FPSCR_OFC (1<<2)
73#define FPSCR_UFC (1<<3)
74#define FPSCR_IXC (1<<4)
75#define FPSCR_IDC (1<<7)
76 54
77/* MVFR0 bits */ 55 FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable.
78#define MVFR0_A_SIMD_BIT (0) 56 FPSCR_IXE = (1 << 12), // Inexact exception trap enable
79#define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT) 57 FPSCR_UFE = (1 << 11), // Undeflow exception trap enable
58 FPSCR_OFE = (1 << 10), // Overflow exception trap enable
59 FPSCR_DZE = (1 << 9), // Division by Zero exception trap enable
60 FPSCR_IOE = (1 << 8), // Invalid Operation exception trap enable
80 61
81/* Bit patterns for decoding the packaged operation descriptors */ 62 FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit
82#define VFPOPDESC_LENGTH_BIT (9) 63 FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit
83#define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT) 64 FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit
84#define VFPOPDESC_UNUSED_BIT (24) 65 FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit
85#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT) 66 FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit
86#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK)) 67 FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit
68};
69
70// FPSCR bit offsets
71enum : u32 {
72 FPSCR_RMODE_BIT = 22,
73 FPSCR_STRIDE_BIT = 20,
74 FPSCR_LENGTH_BIT = 16,
75};
76
77// FPSCR rounding modes
78enum : u32 {
79 FPSCR_ROUND_NEAREST = (0 << 22),
80 FPSCR_ROUND_PLUSINF = (1 << 22),
81 FPSCR_ROUND_MINUSINF = (2 << 22),
82 FPSCR_ROUND_TOZERO = (3 << 22)
83};
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index bff296448..1cf146c53 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -23,6 +23,7 @@
23#include "common/common.h" 23#include "common/common.h"
24 24
25#include "core/arm/skyeye_common/armdefs.h" 25#include "core/arm/skyeye_common/armdefs.h"
26#include "core/arm/skyeye_common/vfp/asm_vfp.h"
26#include "core/arm/skyeye_common/vfp/vfp.h" 27#include "core/arm/skyeye_common/vfp/vfp.h"
27 28
28//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */ 29//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
@@ -43,12 +44,12 @@ unsigned VFPInit(ARMul_State* state)
43unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value) 44unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
44{ 45{
45 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ 46 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
46 int CoProc = BITS (8, 11); /* 10 or 11 */ 47 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
47 int OPC_1 = BITS (21, 23); 48 int OPC_1 = BITS(instr, 21, 23);
48 int Rt = BITS (12, 15); 49 int Rt = BITS(instr, 12, 15);
49 int CRn = BITS (16, 19); 50 int CRn = BITS(instr, 16, 19);
50 int CRm = BITS (0, 3); 51 int CRm = BITS(instr, 0, 3);
51 int OPC_2 = BITS (5, 7); 52 int OPC_2 = BITS(instr, 5, 7);
52 53
53 /* TODO check access permission */ 54 /* TODO check access permission */
54 55
@@ -60,7 +61,7 @@ unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
60 { 61 {
61 /* VMOV r to s */ 62 /* VMOV r to s */
62 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */ 63 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
63 VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, value); 64 VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, value);
64 return ARMul_DONE; 65 return ARMul_DONE;
65 } 66 }
66 67
@@ -79,12 +80,12 @@ unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
79unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value) 80unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
80{ 81{
81 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ 82 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
82 int CoProc = BITS (8, 11); /* 10 or 11 */ 83 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
83 int OPC_1 = BITS (21, 23); 84 int OPC_1 = BITS(instr, 21, 23);
84 int Rt = BITS (12, 15); 85 int Rt = BITS(instr, 12, 15);
85 int CRn = BITS (16, 19); 86 int CRn = BITS(instr, 16, 19);
86 int CRm = BITS (0, 3); 87 int CRm = BITS(instr, 0, 3);
87 int OPC_2 = BITS (5, 7); 88 int OPC_2 = BITS(instr, 5, 7);
88 89
89 /* TODO check access permission */ 90 /* TODO check access permission */
90 91
@@ -95,7 +96,7 @@ unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
95 { 96 {
96 /* VMOV s to r */ 97 /* VMOV s to r */
97 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */ 98 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
98 VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, &value); 99 VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, &value);
99 return ARMul_DONE; 100 return ARMul_DONE;
100 } 101 }
101 102
@@ -126,24 +127,24 @@ unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
126unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2) 127unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2)
127{ 128{
128 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ 129 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
129 int CoProc = BITS (8, 11); /* 10 or 11 */ 130 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
130 int OPC_1 = BITS (4, 7); 131 int OPC_1 = BITS(instr, 4, 7);
131 int Rt = BITS (12, 15); 132 int Rt = BITS(instr, 12, 15);
132 int Rt2 = BITS (16, 19); 133 int Rt2 = BITS(instr, 16, 19);
133 int CRm = BITS (0, 3); 134 int CRm = BITS(instr, 0, 3);
134 135
135 if (CoProc == 10 || CoProc == 11) 136 if (CoProc == 10 || CoProc == 11)
136 { 137 {
137 if (CoProc == 10 && (OPC_1 & 0xD) == 1) 138 if (CoProc == 10 && (OPC_1 & 0xD) == 1)
138 { 139 {
139 VMOVBRRSS(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, value1, value2); 140 VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
140 return ARMul_DONE; 141 return ARMul_DONE;
141 } 142 }
142 143
143 if (CoProc == 11 && (OPC_1 & 0xD) == 1) 144 if (CoProc == 11 && (OPC_1 & 0xD) == 1)
144 { 145 {
145 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */ 146 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
146 VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, value1, value2); 147 VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
147 return ARMul_DONE; 148 return ARMul_DONE;
148 } 149 }
149 } 150 }
@@ -156,11 +157,11 @@ unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32*
156unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2) 157unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2)
157{ 158{
158 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ 159 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
159 int CoProc = BITS (8, 11); /* 10 or 11 */ 160 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
160 int OPC_1 = BITS (4, 7); 161 int OPC_1 = BITS(instr, 4, 7);
161 int Rt = BITS (12, 15); 162 int Rt = BITS(instr, 12, 15);
162 int Rt2 = BITS (16, 19); 163 int Rt2 = BITS(instr, 16, 19);
163 int CRm = BITS (0, 3); 164 int CRm = BITS(instr, 0, 3);
164 165
165 /* TODO check access permission */ 166 /* TODO check access permission */
166 167
@@ -170,14 +171,14 @@ unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 v
170 { 171 {
171 if (CoProc == 10 && (OPC_1 & 0xD) == 1) 172 if (CoProc == 10 && (OPC_1 & 0xD) == 1)
172 { 173 {
173 VMOVBRRSS(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, &value1, &value2); 174 VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
174 return ARMul_DONE; 175 return ARMul_DONE;
175 } 176 }
176 177
177 if (CoProc == 11 && (OPC_1 & 0xD) == 1) 178 if (CoProc == 11 && (OPC_1 & 0xD) == 1)
178 { 179 {
179 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */ 180 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
180 VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, &value1, &value2); 181 VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
181 return ARMul_DONE; 182 return ARMul_DONE;
182 } 183 }
183 } 184 }
@@ -190,14 +191,14 @@ unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 v
190unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value) 191unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
191{ 192{
192 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */ 193 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
193 int CoProc = BITS (8, 11); /* 10 or 11 */ 194 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
194 int CRd = BITS (12, 15); 195 int CRd = BITS(instr, 12, 15);
195 int Rn = BITS (16, 19); 196 int Rn = BITS(instr, 16, 19);
196 int imm8 = BITS (0, 7); 197 int imm8 = BITS(instr, 0, 7);
197 int P = BIT(24); 198 int P = BIT(instr, 24);
198 int U = BIT(23); 199 int U = BIT(instr, 23);
199 int D = BIT(22); 200 int D = BIT(instr, 22);
200 int W = BIT(21); 201 int W = BIT(instr, 21);
201 202
202 /* TODO check access permission */ 203 /* TODO check access permission */
203 204
@@ -239,14 +240,14 @@ unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
239unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value) 240unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
240{ 241{
241 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ 242 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
242 int CoProc = BITS (8, 11); /* 10 or 11 */ 243 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
243 int CRd = BITS (12, 15); 244 int CRd = BITS(instr, 12, 15);
244 int Rn = BITS (16, 19); 245 int Rn = BITS(instr, 16, 19);
245 int imm8 = BITS (0, 7); 246 int imm8 = BITS(instr, 0, 7);
246 int P = BIT(24); 247 int P = BIT(instr, 24);
247 int U = BIT(23); 248 int U = BIT(instr, 23);
248 int D = BIT(22); 249 int D = BIT(instr, 22);
249 int W = BIT(21); 250 int W = BIT(instr, 21);
250 251
251 /* TODO check access permission */ 252 /* TODO check access permission */
252 253
@@ -277,57 +278,12 @@ unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
277unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr) 278unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
278{ 279{
279 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */ 280 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
280 int CoProc = BITS (8, 11); /* 10 or 11 */ 281 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
281 int OPC_1 = BITS (20, 23); 282 int OPC_1 = BITS(instr, 20, 23);
282 int CRd = BITS (12, 15); 283 int CRd = BITS(instr, 12, 15);
283 int CRn = BITS (16, 19); 284 int CRn = BITS(instr, 16, 19);
284 int CRm = BITS (0, 3); 285 int CRm = BITS(instr, 0, 3);
285 int OPC_2 = BITS (5, 7); 286 int OPC_2 = BITS(instr, 5, 7);
286
287 //ichfly
288 /*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)
289 {
290 struct vfp_double vdd;
291 struct vfp_single vsd;
292 int dn = BITS(12, 15) + (BIT(22) << 4);
293 int sd = (BITS(0, 3) << 1) + BIT(5);
294 s32 n = vfp_get_float(state, sd);
295 vfp_single_unpack(&vsd, n);
296 if (vsd.exponent & 0x80)
297 {
298 vdd.exponent = (vsd.exponent&~0x80) | 0x400;
299 }
300 else
301 {
302 vdd.exponent = vsd.exponent | 0x380;
303 }
304 vdd.sign = vsd.sign;
305 vdd.significand = (u64)(vsd.significand & ~0xC0000000) << 32; // I have no idea why but the 2 uppern bits are not from the significand
306 vfp_put_double(state, vfp_double_pack(&vdd), dn);
307 return ARMul_DONE;
308 }
309 if ((instr & 0x0FBF0FD0) == 0x0EB70BC0) //vcvt.f32.f64 s15, d6
310 {
311 struct vfp_double vdd;
312 struct vfp_single vsd;
313 int sd = BITS(0, 3) + (BIT(5) << 4);
314 int dn = (BITS(12, 15) << 1) + BIT(22);
315 vfp_double_unpack(&vdd, vfp_get_double(state, sd));
316 if (vdd.exponent & 0x400) //todo if the exponent is to low or to high for this convert
317 {
318 vsd.exponent = (vdd.exponent) | 0x80;
319 }
320 else
321 {
322 vsd.exponent = vdd.exponent & ~0x80;
323 }
324 vsd.exponent &= 0xFF;
325 // vsd.exponent = vdd.exponent >> 3;
326 vsd.sign = vdd.sign;
327 vsd.significand = ((u64)(vdd.significand ) >> 32)& ~0xC0000000;
328 vfp_put_float(state, vfp_single_pack(&vsd), dn);
329 return ARMul_DONE;
330 }*/
331 287
332 /* TODO check access permission */ 288 /* TODO check access permission */
333 289
@@ -335,17 +291,17 @@ unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
335 291
336 if (CoProc == 10 || CoProc == 11) 292 if (CoProc == 10 || CoProc == 11)
337 { 293 {
338 if ((OPC_1 & 0xB) == 0xB && BITS(4, 7) == 0) 294 if ((OPC_1 & 0xB) == 0xB && BITS(instr, 4, 7) == 0)
339 { 295 {
340 unsigned int single = BIT(8) == 0; 296 unsigned int single = BIT(instr, 8) == 0;
341 unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4); 297 unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
342 unsigned int imm; 298 unsigned int imm;
343 instr = BITS(16, 19) << 4 | BITS(0, 3); /* FIXME dirty workaround to get a correct imm */ 299 instr = BITS(instr, 16, 19) << 4 | BITS(instr, 0, 3); // FIXME dirty workaround to get a correct imm
344 300
345 if (single) 301 if (single)
346 imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0x1f : 0)<<25 | BITS(0, 5)<<19; 302 imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0x1f : 0)<<25 | BITS(instr, 0, 5)<<19;
347 else 303 else
348 imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0xff : 0)<<22 | BITS(0, 5)<<16; 304 imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0xff : 0)<<22 | BITS(instr, 0, 5)<<16;
349 305
350 VMOVI(state, single, d, imm); 306 VMOVI(state, single, d, imm);
351 return ARMul_DONE; 307 return ARMul_DONE;
@@ -353,9 +309,9 @@ unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
353 309
354 if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2) 310 if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2)
355 { 311 {
356 unsigned int single = BIT(8) == 0; 312 unsigned int single = BIT(instr, 8) == 0;
357 unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4); 313 unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
358 unsigned int m = (single ? BITS( 0, 3)<<1 | BIT( 5) : BITS( 0, 3) | BIT( 5)<<4);; 314 unsigned int m = (single ? BITS(instr, 0, 3)<<1 | BIT(instr, 5) : BITS(instr, 0, 3) | BIT(instr, 5)<<4);
359 VMOVR(state, single, d, m); 315 VMOVR(state, single, d, m);
360 return ARMul_DONE; 316 return ARMul_DONE;
361 } 317 }
@@ -477,11 +433,11 @@ int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
477 static int single_reg, add, d, n, imm32, regs; 433 static int single_reg, add, d, n, imm32, regs;
478 if (type == ARMul_FIRST) 434 if (type == ARMul_FIRST)
479 { 435 {
480 single_reg = BIT(8) == 0; /* Double precision */ 436 single_reg = BIT(instr, 8) == 0; // Double precision
481 add = BIT(23); /* */ 437 add = BIT(instr, 23);
482 imm32 = BITS(0,7)<<2; /* may not be used */ 438 imm32 = BITS(instr, 0,7)<<2; // may not be used
483 d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ 439 d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); /* Base register */
484 n = BITS(16, 19); /* destination register */ 440 n = BITS(instr, 16, 19); // destination register
485 441
486 i = 0; 442 i = 0;
487 regs = 1; 443 regs = 1;
@@ -516,13 +472,13 @@ int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
516int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value) 472int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value)
517{ 473{
518 static int i = 0; 474 static int i = 0;
519 static int single_regs, add, wback, d, n, imm32, regs; 475 static int single_regs, d, imm32, regs;
520 if (type == ARMul_FIRST) 476 if (type == ARMul_FIRST)
521 { 477 {
522 single_regs = BIT(8) == 0; /* Single precision */ 478 single_regs = BIT(instr, 8) == 0; // Single precision
523 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ 479 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
524 imm32 = BITS(0,7)<<2; /* may not be used */ 480 imm32 = BITS(instr, 0,7)<<2; // may not be used
525 regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FSTMX if regs is odd */ 481 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FSTMX if regs is odd
526 482
527 state->Reg[R13] = state->Reg[R13] - imm32; 483 state->Reg[R13] = state->Reg[R13] - imm32;
528 484
@@ -561,13 +517,13 @@ int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
561 static int single_regs, add, wback, d, n, imm32, regs; 517 static int single_regs, add, wback, d, n, imm32, regs;
562 if (type == ARMul_FIRST) 518 if (type == ARMul_FIRST)
563 { 519 {
564 single_regs = BIT(8) == 0; /* Single precision */ 520 single_regs = BIT(instr, 8) == 0; // Single precision
565 add = BIT(23); /* */ 521 add = BIT(instr, 23);
566 wback = BIT(21); /* write-back */ 522 wback = BIT(instr, 21); // write-back
567 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ 523 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
568 n = BITS(16, 19); /* destination register */ 524 n = BITS(instr, 16, 19); // destination register
569 imm32 = BITS(0,7) * 4; /* may not be used */ 525 imm32 = BITS(instr, 0,7) * 4; // may not be used
570 regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FSTMX if regs is odd */ 526 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FSTMX if regs is odd
571 527
572 if (wback) { 528 if (wback) {
573 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32); 529 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
@@ -607,13 +563,13 @@ int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
607int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value) 563int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value)
608{ 564{
609 static int i = 0; 565 static int i = 0;
610 static int single_regs, add, wback, d, n, imm32, regs; 566 static int single_regs, d, imm32, regs;
611 if (type == ARMul_FIRST) 567 if (type == ARMul_FIRST)
612 { 568 {
613 single_regs = BIT(8) == 0; /* Single precision */ 569 single_regs = BIT(instr, 8) == 0; // Single precision
614 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ 570 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
615 imm32 = BITS(0,7)<<2; /* may not be used */ 571 imm32 = BITS(instr, 0, 7)<<2; // may not be used
616 regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FLDMX if regs is odd */ 572 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FLDMX if regs is odd
617 573
618 state->Reg[R13] = state->Reg[R13] + imm32; 574 state->Reg[R13] = state->Reg[R13] + imm32;
619 575
@@ -656,11 +612,11 @@ int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value)
656 static int single_reg, add, d, n, imm32, regs; 612 static int single_reg, add, d, n, imm32, regs;
657 if (type == ARMul_FIRST) 613 if (type == ARMul_FIRST)
658 { 614 {
659 single_reg = BIT(8) == 0; /* Double precision */ 615 single_reg = BIT(instr, 8) == 0; // Double precision
660 add = BIT(23); /* */ 616 add = BIT(instr, 23);
661 imm32 = BITS(0,7)<<2; /* may not be used */ 617 imm32 = BITS(instr, 0, 7)<<2; // may not be used
662 d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ 618 d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
663 n = BITS(16, 19); /* destination register */ 619 n = BITS(instr, 16, 19); // destination register
664 620
665 i = 0; 621 i = 0;
666 regs = 1; 622 regs = 1;
@@ -702,13 +658,13 @@ int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value)
702 static int single_regs, add, wback, d, n, imm32, regs; 658 static int single_regs, add, wback, d, n, imm32, regs;
703 if (type == ARMul_FIRST) 659 if (type == ARMul_FIRST)
704 { 660 {
705 single_regs = BIT(8) == 0; /* Single precision */ 661 single_regs = BIT(instr, 8) == 0; // Single precision
706 add = BIT(23); /* */ 662 add = BIT(instr, 23);
707 wback = BIT(21); /* write-back */ 663 wback = BIT(instr, 21); // write-back
708 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ 664 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
709 n = BITS(16, 19); /* destination register */ 665 n = BITS(instr, 16, 19); // destination register
710 imm32 = BITS(0,7) * 4; /* may not be used */ 666 imm32 = BITS(instr, 0, 7) * 4; // may not be used
711 regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FLDMX if regs is odd */ 667 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FLDMX if regs is odd
712 668
713 if (wback) { 669 if (wback) {
714 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32); 670 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
@@ -787,8 +743,7 @@ void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg)
787 743
788uint64_t vfp_get_double(arm_core_t* state, unsigned int reg) 744uint64_t vfp_get_double(arm_core_t* state, unsigned int reg)
789{ 745{
790 uint64_t result; 746 uint64_t result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
791 result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
792 LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]\n", reg * 2 + 1, reg * 2, result); 747 LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]\n", reg * 2 + 1, reg * 2, result);
793 return result; 748 return result;
794} 749}
@@ -805,8 +760,6 @@ void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg)
805 */ 760 */
806void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) 761void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr)
807{ 762{
808 int si_code = 0;
809
810 LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x\n", exceptions); 763 LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x\n", exceptions);
811 764
812 if (exceptions == VFP_EXCEPTION_ERROR) { 765 if (exceptions == VFP_EXCEPTION_ERROR) {
@@ -820,8 +773,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
820 * Comparison instructions always return at least one of 773 * Comparison instructions always return at least one of
821 * these flags set. 774 * these flags set.
822 */ 775 */
823 if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) 776 if (exceptions & (FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG))
824 fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); 777 fpscr &= ~(FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG);
825 778
826 fpscr |= exceptions; 779 fpscr |= exceptions;
827 780
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index 09c7520db..445a224bc 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -25,86 +25,42 @@
25#define VFP_DEBUG_UNIMPLEMENTED(x) LOG_ERROR(Core_ARM11, "in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1); 25#define VFP_DEBUG_UNIMPLEMENTED(x) LOG_ERROR(Core_ARM11, "in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1);
26#define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM11, "in func %s, " #x " untested\n", __FUNCTION__); 26#define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM11, "in func %s, " #x " untested\n", __FUNCTION__);
27#define CHECK_VFP_ENABLED 27#define CHECK_VFP_ENABLED
28#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]); //if (ret == -1) {printf("VFP CDP FAILURE %x\n", inst_cream->instr); exit(-1);} 28#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]); //if (ret == -1) {printf("VFP CDP FAILURE %x\n", inst_cream->instr); exit(-1);}
29 29
30unsigned VFPInit (ARMul_State *state); 30unsigned VFPInit(ARMul_State* state);
31unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value); 31unsigned VFPMRC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
32unsigned VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value); 32unsigned VFPMCR(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
33unsigned VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, ARMword * value2); 33unsigned VFPMRRC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
34unsigned VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMword value2); 34unsigned VFPMCRR(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
35unsigned VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value); 35unsigned VFPSTC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
36unsigned VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value); 36unsigned VFPLDC(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
37unsigned VFPCDP (ARMul_State * state, unsigned type, ARMword instr); 37unsigned VFPCDP(ARMul_State* state, unsigned type, ARMword instr);
38 38
39/* FPSID Information */ 39s32 vfp_get_float(ARMul_State* state, u32 reg);
40#define VFP_FPSID_IMPLMEN 0 /* should be the same as cp15 0 c0 0*/ 40void vfp_put_float(ARMul_State* state, s32 val, u32 reg);
41#define VFP_FPSID_SW 0 41u64 vfp_get_double(ARMul_State* state, u32 reg);
42#define VFP_FPSID_SUBARCH 0x2 /* VFP version. Current is v3 (not strict) */ 42void vfp_put_double(ARMul_State* state, u64 val, u32 reg);
43#define VFP_FPSID_PARTNUM 0x1 43void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr);
44#define VFP_FPSID_VARIANT 0x1
45#define VFP_FPSID_REVISION 0x1
46
47/* FPEXC Flags */
48#define VFP_FPEXC_EX 1<<31
49#define VFP_FPEXC_EN 1<<30
50
51/* FPSCR Flags */
52#define VFP_FPSCR_NFLAG 1<<31
53#define VFP_FPSCR_ZFLAG 1<<30
54#define VFP_FPSCR_CFLAG 1<<29
55#define VFP_FPSCR_VFLAG 1<<28
56
57#define VFP_FPSCR_AHP 1<<26 /* Alternative Half Precision */
58#define VFP_FPSCR_DN 1<<25 /* Default NaN */
59#define VFP_FPSCR_FZ 1<<24 /* Flush-to-zero */
60#define VFP_FPSCR_RMODE 3<<22 /* Rounding Mode */
61#define VFP_FPSCR_STRIDE 3<<20 /* Stride (vector) */
62#define VFP_FPSCR_LEN 7<<16 /* Stride (vector) */
63
64#define VFP_FPSCR_IDE 1<<15 /* Input Denormal exc */
65#define VFP_FPSCR_IXE 1<<12 /* Inexact exc */
66#define VFP_FPSCR_UFE 1<<11 /* Undeflow exc */
67#define VFP_FPSCR_OFE 1<<10 /* Overflow exc */
68#define VFP_FPSCR_DZE 1<<9 /* Division by Zero exc */
69#define VFP_FPSCR_IOE 1<<8 /* Invalid Operation exc */
70
71#define VFP_FPSCR_IDC 1<<7 /* Input Denormal cum exc */
72#define VFP_FPSCR_IXC 1<<4 /* Inexact cum exc */
73#define VFP_FPSCR_UFC 1<<3 /* Undeflow cum exc */
74#define VFP_FPSCR_OFC 1<<2 /* Overflow cum exc */
75#define VFP_FPSCR_DZC 1<<1 /* Division by Zero cum exc */
76#define VFP_FPSCR_IOC 1<<0 /* Invalid Operation cum exc */
77
78/* Inline instructions. Note: Used in a cpp file as well */
79#ifdef __cplusplus
80 extern "C" {
81#endif
82int32_t vfp_get_float(ARMul_State * state, unsigned int reg);
83void vfp_put_float(ARMul_State * state, int32_t val, unsigned int reg);
84uint64_t vfp_get_double(ARMul_State * state, unsigned int reg);
85void vfp_put_double(ARMul_State * state, uint64_t val, unsigned int reg);
86void vfp_raise_exceptions(ARMul_State * state, uint32_t exceptions, uint32_t inst, uint32_t fpscr);
87u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 44u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
88u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 45u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
89 46
90/* MRC */ 47// MRC
91void VMRS(ARMul_State * state, ARMword reg, ARMword Rt, ARMword *value); 48void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value);
92void VMOVBRS(ARMul_State * state, ARMword to_arm, ARMword t, ARMword n, ARMword *value); 49void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value);
93void VMOVBRRD(ARMul_State * state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword *value1, ARMword *value2); 50void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
94void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); 51void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
95void VMOVI(ARMul_State * state, ARMword single, ARMword d, ARMword imm); 52void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
96void VMOVR(ARMul_State * state, ARMword single, ARMword d, ARMword imm); 53void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
97/* MCR */ 54
98void VMSR(ARMul_State * state, ARMword reg, ARMword Rt); 55// MCR
99/* STC */ 56void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
100int VSTM(ARMul_State * state, int type, ARMword instr, ARMword* value); 57
101int VPUSH(ARMul_State * state, int type, ARMword instr, ARMword* value); 58// STC
102int VSTR(ARMul_State * state, int type, ARMword instr, ARMword* value); 59int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value);
103/* LDC */ 60int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value);
104int VLDM(ARMul_State * state, int type, ARMword instr, ARMword value); 61int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value);
105int VPOP(ARMul_State * state, int type, ARMword instr, ARMword value);
106int VLDR(ARMul_State * state, int type, ARMword instr, ARMword value);
107 62
108#ifdef __cplusplus 63// LDC
109 } 64int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value);
110#endif 65int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value);
66int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value);
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index 55e63f553..b68090b80 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -43,495 +43,402 @@
43#define pr_info //printf 43#define pr_info //printf
44#define pr_debug //printf 44#define pr_debug //printf
45 45
46static u32 fls(ARMword x);
47#define do_div(n, base) {n/=base;} 46#define do_div(n, base) {n/=base;}
48 47
49/* From vfpinstr.h */ 48enum : u32 {
50 49 FOP_MASK = 0x00b00040,
51#define INST_CPRTDO(inst) (((inst) & 0x0f000000) == 0x0e000000) 50 FOP_FMAC = 0x00000000,
52#define INST_CPRT(inst) ((inst) & (1 << 4)) 51 FOP_FNMAC = 0x00000040,
53#define INST_CPRT_L(inst) ((inst) & (1 << 20)) 52 FOP_FMSC = 0x00100000,
54#define INST_CPRT_Rd(inst) (((inst) & (15 << 12)) >> 12) 53 FOP_FNMSC = 0x00100040,
55#define INST_CPRT_OP(inst) (((inst) >> 21) & 7) 54 FOP_FMUL = 0x00200000,
56#define INST_CPNUM(inst) ((inst) & 0xf00) 55 FOP_FNMUL = 0x00200040,
57#define CPNUM(cp) ((cp) << 8) 56 FOP_FADD = 0x00300000,
58 57 FOP_FSUB = 0x00300040,
59#define FOP_MASK (0x00b00040) 58 FOP_FDIV = 0x00800000,
60#define FOP_FMAC (0x00000000) 59 FOP_EXT = 0x00b00040
61#define FOP_FNMAC (0x00000040) 60};
62#define FOP_FMSC (0x00100000) 61
63#define FOP_FNMSC (0x00100040) 62#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4)
64#define FOP_FMUL (0x00200000) 63
65#define FOP_FNMUL (0x00200040) 64enum : u32 {
66#define FOP_FADD (0x00300000) 65 FEXT_MASK = 0x000f0080,
67#define FOP_FSUB (0x00300040) 66 FEXT_FCPY = 0x00000000,
68#define FOP_FDIV (0x00800000) 67 FEXT_FABS = 0x00000080,
69#define FOP_EXT (0x00b00040) 68 FEXT_FNEG = 0x00010000,
70 69 FEXT_FSQRT = 0x00010080,
71#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4) 70 FEXT_FCMP = 0x00040000,
72 71 FEXT_FCMPE = 0x00040080,
73#define FEXT_MASK (0x000f0080) 72 FEXT_FCMPZ = 0x00050000,
74#define FEXT_FCPY (0x00000000) 73 FEXT_FCMPEZ = 0x00050080,
75#define FEXT_FABS (0x00000080) 74 FEXT_FCVT = 0x00070080,
76#define FEXT_FNEG (0x00010000) 75 FEXT_FUITO = 0x00080000,
77#define FEXT_FSQRT (0x00010080) 76 FEXT_FSITO = 0x00080080,
78#define FEXT_FCMP (0x00040000) 77 FEXT_FTOUI = 0x000c0000,
79#define FEXT_FCMPE (0x00040080) 78 FEXT_FTOUIZ = 0x000c0080,
80#define FEXT_FCMPZ (0x00050000) 79 FEXT_FTOSI = 0x000d0000,
81#define FEXT_FCMPEZ (0x00050080) 80 FEXT_FTOSIZ = 0x000d0080
82#define FEXT_FCVT (0x00070080) 81};
83#define FEXT_FUITO (0x00080000) 82
84#define FEXT_FSITO (0x00080080) 83#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
85#define FEXT_FTOUI (0x000c0000) 84
86#define FEXT_FTOUIZ (0x000c0080) 85#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
87#define FEXT_FTOSI (0x000d0000) 86#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18)
88#define FEXT_FTOSIZ (0x000d0080) 87#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
89 88#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
90#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) 89#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
91 90#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
92#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) 91
93#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18) 92#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00)
94#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
95#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
96#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
97#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
98
99#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00)
100
101#define FPSCR_N (1 << 31)
102#define FPSCR_Z (1 << 30)
103#define FPSCR_C (1 << 29)
104#define FPSCR_V (1 << 28)
105
106/* -------------- */
107
108/* From asm/include/vfp.h */
109
110/* FPSCR bits */
111#define FPSCR_DEFAULT_NAN (1<<25)
112#define FPSCR_FLUSHTOZERO (1<<24)
113#define FPSCR_ROUND_NEAREST (0<<22)
114#define FPSCR_ROUND_PLUSINF (1<<22)
115#define FPSCR_ROUND_MINUSINF (2<<22)
116#define FPSCR_ROUND_TOZERO (3<<22)
117#define FPSCR_RMODE_BIT (22)
118#define FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT)
119#define FPSCR_STRIDE_BIT (20)
120#define FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT)
121#define FPSCR_LENGTH_BIT (16)
122#define FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT)
123#define FPSCR_IOE (1<<8)
124#define FPSCR_DZE (1<<9)
125#define FPSCR_OFE (1<<10)
126#define FPSCR_UFE (1<<11)
127#define FPSCR_IXE (1<<12)
128#define FPSCR_IDE (1<<15)
129#define FPSCR_IOC (1<<0)
130#define FPSCR_DZC (1<<1)
131#define FPSCR_OFC (1<<2)
132#define FPSCR_UFC (1<<3)
133#define FPSCR_IXC (1<<4)
134#define FPSCR_IDC (1<<7)
135
136/* ---------------- */
137 93
138static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) 94static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
139{ 95{
140 if (shift) { 96 if (shift) {
141 if (shift < 32) 97 if (shift < 32)
142 val = val >> shift | ((val << (32 - shift)) != 0); 98 val = val >> shift | ((val << (32 - shift)) != 0);
143 else 99 else
144 val = val != 0; 100 val = val != 0;
145 } 101 }
146 return val; 102 return val;
147} 103}
148 104
149static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) 105static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
150{ 106{
151 if (shift) { 107 if (shift) {
152 if (shift < 64) 108 if (shift < 64)
153 val = val >> shift | ((val << (64 - shift)) != 0); 109 val = val >> shift | ((val << (64 - shift)) != 0);
154 else 110 else
155 val = val != 0; 111 val = val != 0;
156 } 112 }
157 return val; 113 return val;
158} 114}
159 115
160static inline u32 vfp_hi64to32jamming(u64 val) 116static inline u32 vfp_hi64to32jamming(u64 val)
161{ 117{
162 u32 v; 118 u32 v;
163 u32 highval = val >> 32; 119 u32 highval = val >> 32;
164 u32 lowval = val & 0xffffffff; 120 u32 lowval = val & 0xffffffff;
165 121
166 if (lowval >= 1) 122 if (lowval >= 1)
167 v = highval | 1; 123 v = highval | 1;
168 else 124 else
169 v = highval; 125 v = highval;
170 126
171 return v; 127 return v;
172} 128}
173 129
174static inline void add128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml) 130static inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
175{ 131{
176 *resl = nl + ml; 132 *resl = nl + ml;
177 *resh = nh + mh; 133 *resh = nh + mh;
178 if (*resl < nl) 134 if (*resl < nl)
179 *resh += 1; 135 *resh += 1;
180} 136}
181 137
182static inline void sub128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml) 138static inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
183{ 139{
184 *resl = nl - ml; 140 *resl = nl - ml;
185 *resh = nh - mh; 141 *resh = nh - mh;
186 if (*resl > nl) 142 if (*resl > nl)
187 *resh -= 1; 143 *resh -= 1;
188} 144}
189 145
190static inline void mul64to128(u64 *resh, u64 *resl, u64 n, u64 m) 146static inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
191{ 147{
192 u32 nh, nl, mh, ml; 148 u32 nh, nl, mh, ml;
193 u64 rh, rma, rmb, rl; 149 u64 rh, rma, rmb, rl;
194 150
195 nl = n; 151 nl = n;
196 ml = m; 152 ml = m;
197 rl = (u64)nl * ml; 153 rl = (u64)nl * ml;
198 154
199 nh = n >> 32; 155 nh = n >> 32;
200 rma = (u64)nh * ml; 156 rma = (u64)nh * ml;
201 157
202 mh = m >> 32; 158 mh = m >> 32;
203 rmb = (u64)nl * mh; 159 rmb = (u64)nl * mh;
204 rma += rmb; 160 rma += rmb;
205 161
206 rh = (u64)nh * mh; 162 rh = (u64)nh * mh;
207 rh += ((u64)(rma < rmb) << 32) + (rma >> 32); 163 rh += ((u64)(rma < rmb) << 32) + (rma >> 32);
208 164
209 rma <<= 32; 165 rma <<= 32;
210 rl += rma; 166 rl += rma;
211 rh += (rl < rma); 167 rh += (rl < rma);
212 168
213 *resl = rl; 169 *resl = rl;
214 *resh = rh; 170 *resh = rh;
215} 171}
216 172
217static inline void shift64left(u64 *resh, u64 *resl, u64 n) 173static inline void shift64left(u64* resh, u64* resl, u64 n)
218{ 174{
219 *resh = n >> 63; 175 *resh = n >> 63;
220 *resl = n << 1; 176 *resl = n << 1;
221} 177}
222 178
223static inline u64 vfp_hi64multiply64(u64 n, u64 m) 179static inline u64 vfp_hi64multiply64(u64 n, u64 m)
224{ 180{
225 u64 rh, rl; 181 u64 rh, rl;
226 mul64to128(&rh, &rl, n, m); 182 mul64to128(&rh, &rl, n, m);
227 return rh | (rl != 0); 183 return rh | (rl != 0);
228} 184}
229 185
230static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) 186static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
231{ 187{
232 u64 mh, ml, remh, reml, termh, terml, z; 188 u64 mh, ml, remh, reml, termh, terml, z;
233 189
234 if (nh >= m) 190 if (nh >= m)
235 return ~0ULL; 191 return ~0ULL;
236 mh = m >> 32; 192 mh = m >> 32;
237 if (mh << 32 <= nh) { 193 if (mh << 32 <= nh) {
238 z = 0xffffffff00000000ULL; 194 z = 0xffffffff00000000ULL;
239 } else { 195 } else {
240 z = nh; 196 z = nh;
241 do_div(z, mh); 197 do_div(z, mh);
242 z <<= 32; 198 z <<= 32;
243 } 199 }
244 mul64to128(&termh, &terml, m, z); 200 mul64to128(&termh, &terml, m, z);
245 sub128(&remh, &reml, nh, nl, termh, terml); 201 sub128(&remh, &reml, nh, nl, termh, terml);
246 ml = m << 32; 202 ml = m << 32;
247 while ((s64)remh < 0) { 203 while ((s64)remh < 0) {
248 z -= 0x100000000ULL; 204 z -= 0x100000000ULL;
249 add128(&remh, &reml, remh, reml, mh, ml); 205 add128(&remh, &reml, remh, reml, mh, ml);
250 } 206 }
251 remh = (remh << 32) | (reml >> 32); 207 remh = (remh << 32) | (reml >> 32);
252 if (mh << 32 <= remh) { 208 if (mh << 32 <= remh) {
253 z |= 0xffffffff; 209 z |= 0xffffffff;
254 } else { 210 } else {
255 do_div(remh, mh); 211 do_div(remh, mh);
256 z |= remh; 212 z |= remh;
257 } 213 }
258 return z; 214 return z;
259} 215}
260 216
261/* 217// Operations on unpacked elements
262 * Operations on unpacked elements 218#define vfp_sign_negate(sign) (sign ^ 0x8000)
263 */
264#define vfp_sign_negate(sign) (sign ^ 0x8000)
265 219
266/* 220// Single-precision
267 * Single-precision
268 */
269struct vfp_single { 221struct vfp_single {
270 s16 exponent; 222 s16 exponent;
271 u16 sign; 223 u16 sign;
272 u32 significand; 224 u32 significand;
273}; 225};
274 226
275#ifdef __cplusplus 227// VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
276 extern "C" { 228// VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent
277#endif 229// VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand
278extern s32 vfp_get_float(ARMul_State * state, unsigned int reg); 230// which are not propagated to the float upon packing.
279extern void vfp_put_float(ARMul_State * state, s32 val, unsigned int reg); 231#define VFP_SINGLE_MANTISSA_BITS (23)
280#ifdef __cplusplus 232#define VFP_SINGLE_EXPONENT_BITS (8)
281 } 233#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2)
282#endif 234#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1)
283
284/*
285 * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
286 * VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent
287 * VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand
288 * which are not propagated to the float upon packing.
289 */
290#define VFP_SINGLE_MANTISSA_BITS (23)
291#define VFP_SINGLE_EXPONENT_BITS (8)
292#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2)
293#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1)
294 235
295/* 236// The bit in an unpacked float which indicates that it is a quiet NaN
296 * The bit in an unpacked float which indicates that it is a quiet NaN
297 */
298#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS)) 237#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS))
299 238
300/* 239// Operations on packed single-precision numbers
301 * Operations on packed single-precision numbers 240#define vfp_single_packed_sign(v) ((v) & 0x80000000)
302 */ 241#define vfp_single_packed_negate(v) ((v) ^ 0x80000000)
303#define vfp_single_packed_sign(v) ((v) & 0x80000000) 242#define vfp_single_packed_abs(v) ((v) & ~0x80000000)
304#define vfp_single_packed_negate(v) ((v) ^ 0x80000000) 243#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
305#define vfp_single_packed_abs(v) ((v) & ~0x80000000) 244#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
306#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) 245
307#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) 246// Unpack a single-precision float. Note that this returns the magnitude
308 247// of the single-precision float mantissa with the 1. if necessary,
309/* 248// aligned to bit 30.
310 * Unpack a single-precision float. Note that this returns the magnitude 249static inline void vfp_single_unpack(vfp_single* s, s32 val)
311 * of the single-precision float mantissa with the 1. if necessary,
312 * aligned to bit 30.
313 */
314static inline void vfp_single_unpack(struct vfp_single *s, s32 val)
315{ 250{
316 u32 significand; 251 u32 significand;
317 252
318 s->sign = vfp_single_packed_sign(val) >> 16, 253 s->sign = vfp_single_packed_sign(val) >> 16,
319 s->exponent = vfp_single_packed_exponent(val); 254 s->exponent = vfp_single_packed_exponent(val);
320 255
321 significand = (u32) val; 256 significand = (u32) val;
322 significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2; 257 significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
323 if (s->exponent && s->exponent != 255) 258 if (s->exponent && s->exponent != 255)
324 significand |= 0x40000000; 259 significand |= 0x40000000;
325 s->significand = significand; 260 s->significand = significand;
326} 261}
327 262
328/* 263// Re-pack a single-precision float. This assumes that the float is
329 * Re-pack a single-precision float. This assumes that the float is 264// already normalised such that the MSB is bit 30, _not_ bit 31.
330 * already normalised such that the MSB is bit 30, _not_ bit 31. 265static inline s32 vfp_single_pack(vfp_single* s)
331 */
332static inline s32 vfp_single_pack(struct vfp_single *s)
333{ 266{
334 u32 val; 267 u32 val = (s->sign << 16) +
335 val = (s->sign << 16) + 268 (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
336 (s->exponent << VFP_SINGLE_MANTISSA_BITS) + 269 (s->significand >> VFP_SINGLE_LOW_BITS);
337 (s->significand >> VFP_SINGLE_LOW_BITS); 270 return (s32)val;
338 return (s32)val;
339} 271}
340 272
341#define VFP_NUMBER (1<<0) 273enum : u32 {
342#define VFP_ZERO (1<<1) 274 VFP_NUMBER = (1 << 0),
343#define VFP_DENORMAL (1<<2) 275 VFP_ZERO = (1 << 1),
344#define VFP_INFINITY (1<<3) 276 VFP_DENORMAL = (1 << 2),
345#define VFP_NAN (1<<4) 277 VFP_INFINITY = (1 << 3),
346#define VFP_NAN_SIGNAL (1<<5) 278 VFP_NAN = (1 << 4),
279 VFP_NAN_SIGNAL = (1 << 5),
347 280
348#define VFP_QNAN (VFP_NAN) 281 VFP_QNAN = (VFP_NAN),
349#define VFP_SNAN (VFP_NAN|VFP_NAN_SIGNAL) 282 VFP_SNAN = (VFP_NAN|VFP_NAN_SIGNAL)
283};
350 284
351static inline int vfp_single_type(struct vfp_single *s) 285static inline int vfp_single_type(vfp_single* s)
352{ 286{
353 int type = VFP_NUMBER; 287 int type = VFP_NUMBER;
354 if (s->exponent == 255) { 288 if (s->exponent == 255) {
355 if (s->significand == 0) 289 if (s->significand == 0)
356 type = VFP_INFINITY; 290 type = VFP_INFINITY;
357 else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN) 291 else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN)
358 type = VFP_QNAN; 292 type = VFP_QNAN;
359 else 293 else
360 type = VFP_SNAN; 294 type = VFP_SNAN;
361 } else if (s->exponent == 0) { 295 } else if (s->exponent == 0) {
362 if (s->significand == 0) 296 if (s->significand == 0)
363 type |= VFP_ZERO; 297 type |= VFP_ZERO;
364 else 298 else
365 type |= VFP_DENORMAL; 299 type |= VFP_DENORMAL;
366 } 300 }
367 return type; 301 return type;
368} 302}
369 303
370 304
371u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func); 305u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, u32 exceptions, const char* func);
372 306
373/* 307// Double-precision
374 * Double-precision
375 */
376struct vfp_double { 308struct vfp_double {
377 s16 exponent; 309 s16 exponent;
378 u16 sign; 310 u16 sign;
379 u64 significand; 311 u64 significand;
380}; 312};
381 313
382/* 314// VFP_REG_ZERO is a special register number for vfp_get_double
383 * VFP_REG_ZERO is a special register number for vfp_get_double 315// which returns (double)0.0. This is useful for the compare with
384 * which returns (double)0.0. This is useful for the compare with 316// zero instructions.
385 * zero instructions.
386 */
387#ifdef CONFIG_VFPv3 317#ifdef CONFIG_VFPv3
388#define VFP_REG_ZERO 32 318#define VFP_REG_ZERO 32
389#else 319#else
390#define VFP_REG_ZERO 16 320#define VFP_REG_ZERO 16
391#endif
392#ifdef __cplusplus
393 extern "C" {
394#endif 321#endif
395extern u64 vfp_get_double(ARMul_State * state, unsigned int reg);
396extern void vfp_put_double(ARMul_State * state, u64 val, unsigned int reg);
397#ifdef __cplusplus
398 }
399#endif
400#define VFP_DOUBLE_MANTISSA_BITS (52)
401#define VFP_DOUBLE_EXPONENT_BITS (11)
402#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2)
403#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1)
404 322
405/* 323#define VFP_DOUBLE_MANTISSA_BITS (52)
406 * The bit in an unpacked double which indicates that it is a quiet NaN 324#define VFP_DOUBLE_EXPONENT_BITS (11)
407 */ 325#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2)
408#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS)) 326#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1)
409 327
410/* 328// The bit in an unpacked double which indicates that it is a quiet NaN
411 * Operations on packed single-precision numbers 329#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS))
412 */ 330
413#define vfp_double_packed_sign(v) ((v) & (1ULL << 63)) 331// Operations on packed single-precision numbers
414#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63)) 332#define vfp_double_packed_sign(v) ((v) & (1ULL << 63))
415#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63)) 333#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63))
416#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) 334#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63))
417#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) 335#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
418 336#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
419/* 337
420 * Unpack a double-precision float. Note that this returns the magnitude 338// Unpack a double-precision float. Note that this returns the magnitude
421 * of the double-precision float mantissa with the 1. if necessary, 339// of the double-precision float mantissa with the 1. if necessary,
422 * aligned to bit 62. 340// aligned to bit 62.
423 */ 341static inline void vfp_double_unpack(vfp_double* s, s64 val)
424static inline void vfp_double_unpack(struct vfp_double *s, s64 val)
425{ 342{
426 u64 significand; 343 u64 significand;
427 344
428 s->sign = vfp_double_packed_sign(val) >> 48; 345 s->sign = vfp_double_packed_sign(val) >> 48;
429 s->exponent = vfp_double_packed_exponent(val); 346 s->exponent = vfp_double_packed_exponent(val);
430 347
431 significand = (u64) val; 348 significand = (u64) val;
432 significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2; 349 significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
433 if (s->exponent && s->exponent != 2047) 350 if (s->exponent && s->exponent != 2047)
434 significand |= (1ULL << 62); 351 significand |= (1ULL << 62);
435 s->significand = significand; 352 s->significand = significand;
436} 353}
437 354
438/* 355// Re-pack a double-precision float. This assumes that the float is
439 * Re-pack a double-precision float. This assumes that the float is 356// already normalised such that the MSB is bit 30, _not_ bit 31.
440 * already normalised such that the MSB is bit 30, _not_ bit 31. 357static inline s64 vfp_double_pack(vfp_double* s)
441 */
442static inline s64 vfp_double_pack(struct vfp_double *s)
443{ 358{
444 u64 val; 359 u64 val = ((u64)s->sign << 48) +
445 val = ((u64)s->sign << 48) + 360 ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
446 ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) + 361 (s->significand >> VFP_DOUBLE_LOW_BITS);
447 (s->significand >> VFP_DOUBLE_LOW_BITS); 362 return (s64)val;
448 return (s64)val;
449} 363}
450 364
451static inline int vfp_double_type(struct vfp_double *s) 365static inline int vfp_double_type(vfp_double* s)
452{ 366{
453 int type = VFP_NUMBER; 367 int type = VFP_NUMBER;
454 if (s->exponent == 2047) { 368 if (s->exponent == 2047) {
455 if (s->significand == 0) 369 if (s->significand == 0)
456 type = VFP_INFINITY; 370 type = VFP_INFINITY;
457 else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN) 371 else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
458 type = VFP_QNAN; 372 type = VFP_QNAN;
459 else 373 else
460 type = VFP_SNAN; 374 type = VFP_SNAN;
461 } else if (s->exponent == 0) { 375 } else if (s->exponent == 0) {
462 if (s->significand == 0) 376 if (s->significand == 0)
463 type |= VFP_ZERO; 377 type |= VFP_ZERO;
464 else 378 else
465 type |= VFP_DENORMAL; 379 type |= VFP_DENORMAL;
466 } 380 }
467 return type; 381 return type;
468} 382}
469 383
470u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func);
471
472u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); 384u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
473 385
474/* 386// A special flag to tell the normalisation code not to normalise.
475 * A special flag to tell the normalisation code not to normalise. 387#define VFP_NAN_FLAG 0x100
476 */ 388
477#define VFP_NAN_FLAG 0x100 389// A bit pattern used to indicate the initial (unset) value of the
478 390// exception mask, in case nothing handles an instruction. This
479/* 391// doesn't include the NAN flag, which get masked out before
480 * A bit pattern used to indicate the initial (unset) value of the 392// we check for an error.
481 * exception mask, in case nothing handles an instruction. This 393#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG)
482 * doesn't include the NAN flag, which get masked out before 394
483 * we check for an error. 395// A flag to tell vfp instruction type.
484 */ 396// OP_SCALAR - This operation always operates in scalar mode
485#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG) 397// OP_SD - The instruction exceptionally writes to a single precision result.
486 398// OP_DD - The instruction exceptionally writes to a double precision result.
487/* 399// OP_SM - The instruction exceptionally reads from a single precision operand.
488 * A flag to tell vfp instruction type. 400enum : u32 {
489 * OP_SCALAR - this operation always operates in scalar mode 401 OP_SCALAR = (1 << 0),
490 * OP_SD - the instruction exceptionally writes to a single precision result. 402 OP_SD = (1 << 1),
491 * OP_DD - the instruction exceptionally writes to a double precision result. 403 OP_DD = (1 << 1),
492 * OP_SM - the instruction exceptionally reads from a single precision operand. 404 OP_SM = (1 << 2)
493 */ 405};
494#define OP_SCALAR (1 << 0)
495#define OP_SD (1 << 1)
496#define OP_DD (1 << 1)
497#define OP_SM (1 << 2)
498 406
499struct op { 407struct op {
500 u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr); 408 u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr);
501 u32 flags; 409 u32 flags;
502}; 410};
503 411
504static u32 fls(ARMword x) 412static inline u32 fls(ARMword x)
505{ 413{
506 int r = 32; 414 int r = 32;
507 415
508 if (!x) 416 if (!x)
509 return 0; 417 return 0;
510 if (!(x & 0xffff0000u)) { 418 if (!(x & 0xffff0000u)) {
511 x <<= 16; 419 x <<= 16;
512 r -= 16; 420 r -= 16;
513 } 421 }
514 if (!(x & 0xff000000u)) { 422 if (!(x & 0xff000000u)) {
515 x <<= 8; 423 x <<= 8;
516 r -= 8; 424 r -= 8;
517 } 425 }
518 if (!(x & 0xf0000000u)) { 426 if (!(x & 0xf0000000u)) {
519 x <<= 4; 427 x <<= 4;
520 r -= 4; 428 r -= 4;
521 } 429 }
522 if (!(x & 0xc0000000u)) { 430 if (!(x & 0xc0000000u)) {
523 x <<= 2; 431 x <<= 2;
524 r -= 2; 432 r -= 2;
525 } 433 }
526 if (!(x & 0x80000000u)) { 434 if (!(x & 0x80000000u)) {
527 x <<= 1; 435 x <<= 1;
528 r -= 1; 436 r -= 1;
529 } 437 }
530 return r; 438 return r;
531 439
532} 440}
533 441
534u32 vfp_double_normaliseroundintern(ARMul_State* state, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func); 442u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr);
535u32 vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, struct vfp_double *vdm, u32 fpscr); 443u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double *vdm, u32 fpscr);
536u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn, struct vfp_double *vdm, u32 fpscr); 444u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, u32 exceptions, const char* func);
537u32 vfp_double_fcvtsinterncutting(ARMul_State* state, int sd, struct vfp_double* dm, u32 fpscr);
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index 15a5d1265..9a7088088 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -83,134 +83,6 @@ static void vfp_double_normalise_denormal(struct vfp_double *vd)
83 vfp_double_dump("normalise_denormal: out", vd); 83 vfp_double_dump("normalise_denormal: out", vd);
84} 84}
85 85
86u32 vfp_double_normaliseroundintern(ARMul_State* state, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
87{
88 u64 significand, incr;
89 int exponent, shift, underflow;
90 u32 rmode;
91
92 vfp_double_dump("pack: in", vd);
93
94 /*
95 * Infinities and NaNs are a special case.
96 */
97 if (vd->exponent == 2047 && (vd->significand == 0 || exceptions))
98 goto pack;
99
100 /*
101 * Special-case zero.
102 */
103 if (vd->significand == 0) {
104 vd->exponent = 0;
105 goto pack;
106 }
107
108 exponent = vd->exponent;
109 significand = vd->significand;
110
111 shift = 32 - fls((ARMword)(significand >> 32));
112 if (shift == 32)
113 shift = 64 - fls((ARMword)significand);
114 if (shift) {
115 exponent -= shift;
116 significand <<= shift;
117 }
118
119#if 1
120 vd->exponent = exponent;
121 vd->significand = significand;
122 vfp_double_dump("pack: normalised", vd);
123#endif
124
125 /*
126 * Tiny number?
127 */
128 underflow = exponent < 0;
129 if (underflow) {
130 significand = vfp_shiftright64jamming(significand, -exponent);
131 exponent = 0;
132#if 1
133 vd->exponent = exponent;
134 vd->significand = significand;
135 vfp_double_dump("pack: tiny number", vd);
136#endif
137 if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1)))
138 underflow = 0;
139 }
140
141 /*
142 * Select rounding increment.
143 */
144 incr = 0;
145 rmode = fpscr & FPSCR_RMODE_MASK;
146
147 if (rmode == FPSCR_ROUND_NEAREST) {
148 incr = 1ULL << VFP_DOUBLE_LOW_BITS;
149 if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
150 incr -= 1;
151 }
152 else if (rmode == FPSCR_ROUND_TOZERO) {
153 incr = 0;
154 }
155 else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
156 incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
157
158 LOG_TRACE(Core_ARM11, "VFP: rounding increment = 0x%08llx\n", incr);
159
160 /*
161 * Is our rounding going to overflow?
162 */
163 if ((significand + incr) < significand) {
164 exponent += 1;
165 significand = (significand >> 1) | (significand & 1);
166 incr >>= 1;
167#if 1
168 vd->exponent = exponent;
169 vd->significand = significand;
170 vfp_double_dump("pack: overflow", vd);
171#endif
172 }
173
174 /*
175 * If any of the low bits (which will be shifted out of the
176 * number) are non-zero, the result is inexact.
177 */
178 if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1))
179 exceptions |= FPSCR_IXC;
180
181 /*
182 * Do our rounding.
183 */
184 significand += incr;
185
186 /*
187 * Infinity?
188 */
189 if (exponent >= 2046) {
190 exceptions |= FPSCR_OFC | FPSCR_IXC;
191 if (incr == 0) {
192 vd->exponent = 2045;
193 vd->significand = 0x7fffffffffffffffULL;
194 }
195 else {
196 vd->exponent = 2047; /* infinity */
197 vd->significand = 0;
198 }
199 }
200 else {
201 if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
202 exponent = 0;
203 if (exponent || significand > 0x8000000000000000ULL)
204 underflow = 0;
205 if (underflow)
206 exceptions |= FPSCR_UFC;
207 vd->exponent = exponent;
208 vd->significand = significand >> 1;
209 }
210 pack:
211 return 0;
212}
213
214u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func) 86u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
215{ 87{
216 u64 significand, incr; 88 u64 significand, incr;
@@ -511,7 +383,7 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
511 LOG_TRACE(Core_ARM11, "In %s, state=0x%x, fpscr=0x%x\n", __FUNCTION__, state, fpscr); 383 LOG_TRACE(Core_ARM11, "In %s, state=0x%x, fpscr=0x%x\n", __FUNCTION__, state, fpscr);
512 m = vfp_get_double(state, dm); 384 m = vfp_get_double(state, dm);
513 if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) { 385 if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) {
514 ret |= FPSCR_C | FPSCR_V; 386 ret |= FPSCR_CFLAG | FPSCR_VFLAG;
515 if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) 387 if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
516 /* 388 /*
517 * Signalling NaN, or signalling on quiet NaN 389 * Signalling NaN, or signalling on quiet NaN
@@ -521,7 +393,7 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
521 393
522 d = vfp_get_double(state, dd); 394 d = vfp_get_double(state, dd);
523 if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) { 395 if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) {
524 ret |= FPSCR_C | FPSCR_V; 396 ret |= FPSCR_CFLAG | FPSCR_VFLAG;
525 if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) 397 if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
526 /* 398 /*
527 * Signalling NaN, or signalling on quiet NaN 399 * Signalling NaN, or signalling on quiet NaN
@@ -535,7 +407,7 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
535 /* 407 /*
536 * equal 408 * equal
537 */ 409 */
538 ret |= FPSCR_Z | FPSCR_C; 410 ret |= FPSCR_ZFLAG | FPSCR_CFLAG;
539 //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret); 411 //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret);
540 } else if (vfp_double_packed_sign(d ^ m)) { 412 } else if (vfp_double_packed_sign(d ^ m)) {
541 /* 413 /*
@@ -545,22 +417,22 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
545 /* 417 /*
546 * d is negative, so d < m 418 * d is negative, so d < m
547 */ 419 */
548 ret |= FPSCR_N; 420 ret |= FPSCR_NFLAG;
549 else 421 else
550 /* 422 /*
551 * d is positive, so d > m 423 * d is positive, so d > m
552 */ 424 */
553 ret |= FPSCR_C; 425 ret |= FPSCR_CFLAG;
554 } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) { 426 } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) {
555 /* 427 /*
556 * d < m 428 * d < m
557 */ 429 */
558 ret |= FPSCR_N; 430 ret |= FPSCR_NFLAG;
559 } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) { 431 } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) {
560 /* 432 /*
561 * d > m 433 * d > m
562 */ 434 */
563 ret |= FPSCR_C; 435 ret |= FPSCR_CFLAG;
564 } 436 }
565 } 437 }
566 LOG_TRACE(Core_ARM11, "In %s, state=0x%x, ret=0x%x\n", __FUNCTION__, state, ret); 438 LOG_TRACE(Core_ARM11, "In %s, state=0x%x, ret=0x%x\n", __FUNCTION__, state, ret);
@@ -592,49 +464,6 @@ static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32
592 return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr); 464 return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr);
593} 465}
594 466
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 LOG_TRACE(Core_ARM11, "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;
636}
637
638static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 467static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
639{ 468{
640 struct vfp_double vdm; 469 struct vfp_double vdm;
@@ -723,7 +552,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32
723 exceptions |= FPSCR_IDC; 552 exceptions |= FPSCR_IDC;
724 553
725 if (tm & VFP_NAN) 554 if (tm & VFP_NAN)
726 vdm.sign = 0; 555 vdm.sign = 1;
727 556
728 if (vdm.exponent >= 1023 + 32) { 557 if (vdm.exponent >= 1023 + 32) {
729 d = vdm.sign ? 0 : 0xffffffff; 558 d = vdm.sign ? 0 : 0xffffffff;
@@ -880,18 +709,18 @@ static struct op fops_ext[] = {
880 { NULL, 0 }, 709 { NULL, 0 },
881 { NULL, 0 }, 710 { NULL, 0 },
882 { vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT 711 { vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT
883 { vfp_double_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO 712 { vfp_double_fuito, OP_SCALAR|OP_SM }, //0x00000010 - FEXT_FUITO
884 { vfp_double_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO 713 { vfp_double_fsito, OP_SCALAR|OP_SM }, //0x00000011 - FEXT_FSITO
885 { NULL, 0 }, 714 { NULL, 0 },
886 { NULL, 0 }, 715 { NULL, 0 },
887 { NULL, 0 }, 716 { NULL, 0 },
888 { NULL, 0 }, 717 { NULL, 0 },
889 { NULL, 0 }, 718 { NULL, 0 },
890 { NULL, 0 }, 719 { NULL, 0 },
891 { vfp_double_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI 720 { vfp_double_ftoui, OP_SCALAR|OP_SD }, //0x00000018 - FEXT_FTOUI
892 { vfp_double_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ 721 { vfp_double_ftouiz, OP_SCALAR|OP_SD }, //0x00000019 - FEXT_FTOUIZ
893 { vfp_double_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI 722 { vfp_double_ftosi, OP_SCALAR|OP_SD }, //0x0000001A - FEXT_FTOSI
894 { vfp_double_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ 723 { vfp_double_ftosiz, OP_SCALAR|OP_SD }, //0x0000001B - FEXT_FTOSIZ
895}; 724};
896 725
897static u32 726static u32
@@ -1079,6 +908,9 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f
1079 vdp.sign = vfp_sign_negate(vdp.sign); 908 vdp.sign = vfp_sign_negate(vdp.sign);
1080 909
1081 vfp_double_unpack(&vdn, vfp_get_double(state, dd)); 910 vfp_double_unpack(&vdn, vfp_get_double(state, dd));
911 if (vdn.exponent == 0 && vdn.significand != 0)
912 vfp_double_normalise_denormal(&vdn);
913
1082 if (negate & NEG_SUBTRACT) 914 if (negate & NEG_SUBTRACT)
1083 vdn.sign = vfp_sign_negate(vdn.sign); 915 vdn.sign = vfp_sign_negate(vdn.sign);
1084 916
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 1bdbfec8e..0aa2d5089 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -59,73 +59,6 @@ VMLA_INST:
59} 59}
60#endif 60#endif
61 61
62#ifdef VFP_DYNCOM_TABLE
63DYNCOM_FILL_ACTION(vmla),
64#endif
65#ifdef VFP_DYNCOM_TAG
66int DYNCOM_TAG(vmla)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
67{
68 int instr_size = INSTR_SIZE;
69 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
70 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
71 return instr_size;
72}
73#endif
74#ifdef VFP_DYNCOM_TRANS
75int DYNCOM_TRANS(vmla)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
76 //arch_arm_undef(cpu, bb, instr);
77 int m;
78 int n;
79 int d ;
80 int add = (BIT(6) == 0);
81 int s = BIT(8) == 0;
82 Value *mm;
83 Value *nn;
84 Value *tmp;
85 if(s){
86 m = BIT(5) | BITS(0,3) << 1;
87 n = BIT(7) | BITS(16,19) << 1;
88 d = BIT(22) | BITS(12,15) << 1;
89 mm = FR32(m);
90 nn = FR32(n);
91 tmp = FPMUL(nn,mm);
92 if(!add)
93 tmp = FPNEG32(tmp);
94 mm = FR32(d);
95 tmp = FPADD(mm,tmp);
96 //LETS(d,tmp);
97 LETFPS(d,tmp);
98 }else {
99 m = BITS(0,3) | BIT(5) << 4;
100 n = BITS(16,19) | BIT(7) << 4;
101 d = BIT(22) << 4 | BITS(12,15);
102 //mm = SITOFP(32,RSPR(m));
103 //LETS(d,tmp);
104 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
105 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
106 tmp = OR(SHL(nn,CONST64(32)),mm);
107 mm = FPBITCAST64(tmp);
108 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
109 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
110 nn = OR(SHL(nn,CONST64(32)),tmp);
111 nn = FPBITCAST64(nn);
112 tmp = FPMUL(nn,mm);
113 if(!add)
114 tmp = FPNEG64(tmp);
115 mm = ZEXT64(IBITCAST32(FR32(2 * d)));
116 nn = ZEXT64(IBITCAST32(FR32(2 * d + 1)));
117 mm = OR(SHL(nn,CONST64(32)),mm);
118 mm = FPBITCAST64(mm);
119 tmp = FPADD(mm,tmp);
120 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
121 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
122 LETFPS(2*d ,FPBITCAST32(nn));
123 LETFPS(d*2 + 1 , FPBITCAST32(mm));
124 }
125 return No_exp;
126}
127#endif
128
129/* ----------------------------------------------------------------------- */ 62/* ----------------------------------------------------------------------- */
130/* VNMLS */ 63/* VNMLS */
131/* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */ 64/* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */
@@ -176,74 +109,6 @@ VMLS_INST:
176} 109}
177#endif 110#endif
178 111
179#ifdef VFP_DYNCOM_TABLE
180DYNCOM_FILL_ACTION(vmls),
181#endif
182#ifdef VFP_DYNCOM_TAG
183int DYNCOM_TAG(vmls)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
184{
185 int instr_size = INSTR_SIZE;
186 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
187 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
188 return instr_size;
189}
190#endif
191#ifdef VFP_DYNCOM_TRANS
192int DYNCOM_TRANS(vmls)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
193 LOG_TRACE(Core_ARM11, "\t\tin %s VMLS instruction is executed out of here.\n", __FUNCTION__);
194 //arch_arm_undef(cpu, bb, instr);
195 int m;
196 int n;
197 int d ;
198 int add = (BIT(6) == 0);
199 int s = BIT(8) == 0;
200 Value *mm;
201 Value *nn;
202 Value *tmp;
203 if(s){
204 m = BIT(5) | BITS(0,3) << 1;
205 n = BIT(7) | BITS(16,19) << 1;
206 d = BIT(22) | BITS(12,15) << 1;
207 mm = FR32(m);
208 nn = FR32(n);
209 tmp = FPMUL(nn,mm);
210 if(!add)
211 tmp = FPNEG32(tmp);
212 mm = FR32(d);
213 tmp = FPADD(mm,tmp);
214 //LETS(d,tmp);
215 LETFPS(d,tmp);
216 }else {
217 m = BITS(0,3) | BIT(5) << 4;
218 n = BITS(16,19) | BIT(7) << 4;
219 d = BIT(22) << 4 | BITS(12,15);
220 //mm = SITOFP(32,RSPR(m));
221 //LETS(d,tmp);
222 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
223 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
224 tmp = OR(SHL(nn,CONST64(32)),mm);
225 mm = FPBITCAST64(tmp);
226 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
227 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
228 nn = OR(SHL(nn,CONST64(32)),tmp);
229 nn = FPBITCAST64(nn);
230 tmp = FPMUL(nn,mm);
231 if(!add)
232 tmp = FPNEG64(tmp);
233 mm = ZEXT64(IBITCAST32(FR32(2 * d)));
234 nn = ZEXT64(IBITCAST32(FR32(2 * d + 1)));
235 mm = OR(SHL(nn,CONST64(32)),mm);
236 mm = FPBITCAST64(mm);
237 tmp = FPADD(mm,tmp);
238 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
239 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
240 LETFPS(2*d ,FPBITCAST32(nn));
241 LETFPS(d*2 + 1 , FPBITCAST32(mm));
242 }
243 return No_exp;
244}
245#endif
246
247/* ----------------------------------------------------------------------- */ 112/* ----------------------------------------------------------------------- */
248/* VNMLA */ 113/* VNMLA */
249/* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */ 114/* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */
@@ -294,75 +159,6 @@ VNMLA_INST:
294} 159}
295#endif 160#endif
296 161
297#ifdef VFP_DYNCOM_TABLE
298DYNCOM_FILL_ACTION(vnmla),
299DYNCOM_FILL_ACTION(vnmla),
300#endif
301#ifdef VFP_DYNCOM_TAG
302int DYNCOM_TAG(vnmla)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
303{
304 int instr_size = INSTR_SIZE;
305 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
306 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
307 return instr_size;
308}
309#endif
310#ifdef VFP_DYNCOM_TRANS
311int DYNCOM_TRANS(vnmla)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
312 LOG_TRACE(Core_ARM11, "\t\tin %s VNMLA instruction is executed out of here.\n", __FUNCTION__);
313 //arch_arm_undef(cpu, bb, instr);
314 int m;
315 int n;
316 int d ;
317 int add = (BIT(6) == 0);
318 int s = BIT(8) == 0;
319 Value *mm;
320 Value *nn;
321 Value *tmp;
322 if(s){
323 m = BIT(5) | BITS(0,3) << 1;
324 n = BIT(7) | BITS(16,19) << 1;
325 d = BIT(22) | BITS(12,15) << 1;
326 mm = FR32(m);
327 nn = FR32(n);
328 tmp = FPMUL(nn,mm);
329 if(!add)
330 tmp = FPNEG32(tmp);
331 mm = FR32(d);
332 tmp = FPADD(FPNEG32(mm),tmp);
333 //LETS(d,tmp);
334 LETFPS(d,tmp);
335 }else {
336 m = BITS(0,3) | BIT(5) << 4;
337 n = BITS(16,19) | BIT(7) << 4;
338 d = BIT(22) << 4 | BITS(12,15);
339 //mm = SITOFP(32,RSPR(m));
340 //LETS(d,tmp);
341 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
342 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
343 tmp = OR(SHL(nn,CONST64(32)),mm);
344 mm = FPBITCAST64(tmp);
345 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
346 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
347 nn = OR(SHL(nn,CONST64(32)),tmp);
348 nn = FPBITCAST64(nn);
349 tmp = FPMUL(nn,mm);
350 if(!add)
351 tmp = FPNEG64(tmp);
352 mm = ZEXT64(IBITCAST32(FR32(2 * d)));
353 nn = ZEXT64(IBITCAST32(FR32(2 * d + 1)));
354 mm = OR(SHL(nn,CONST64(32)),mm);
355 mm = FPBITCAST64(mm);
356 tmp = FPADD(FPNEG64(mm),tmp);
357 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
358 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
359 LETFPS(2*d ,FPBITCAST32(nn));
360 LETFPS(d*2 + 1 , FPBITCAST32(mm));
361 }
362 return No_exp;
363}
364#endif
365
366/* ----------------------------------------------------------------------- */ 162/* ----------------------------------------------------------------------- */
367/* VNMLS */ 163/* VNMLS */
368/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */ 164/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */
@@ -414,75 +210,6 @@ VNMLS_INST:
414} 210}
415#endif 211#endif
416 212
417#ifdef VFP_DYNCOM_TABLE
418DYNCOM_FILL_ACTION(vnmls),
419#endif
420#ifdef VFP_DYNCOM_TAG
421int DYNCOM_TAG(vnmls)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
422{
423 int instr_size = INSTR_SIZE;
424 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
425 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
426 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
427 return instr_size;
428}
429#endif
430#ifdef VFP_DYNCOM_TRANS
431int DYNCOM_TRANS(vnmls)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
432 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
433 //arch_arm_undef(cpu, bb, instr);
434 int m;
435 int n;
436 int d ;
437 int add = (BIT(6) == 0);
438 int s = BIT(8) == 0;
439 Value *mm;
440 Value *nn;
441 Value *tmp;
442 if(s){
443 m = BIT(5) | BITS(0,3) << 1;
444 n = BIT(7) | BITS(16,19) << 1;
445 d = BIT(22) | BITS(12,15) << 1;
446 mm = FR32(m);
447 nn = FR32(n);
448 tmp = FPMUL(nn,mm);
449 if(!add)
450 tmp = FPNEG32(tmp);
451 mm = FR32(d);
452 tmp = FPADD(FPNEG32(mm),tmp);
453 //LETS(d,tmp);
454 LETFPS(d,tmp);
455 }else {
456 m = BITS(0,3) | BIT(5) << 4;
457 n = BITS(16,19) | BIT(7) << 4;
458 d = BIT(22) << 4 | BITS(12,15);
459 //mm = SITOFP(32,RSPR(m));
460 //LETS(d,tmp);
461 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
462 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
463 tmp = OR(SHL(nn,CONST64(32)),mm);
464 mm = FPBITCAST64(tmp);
465 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
466 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
467 nn = OR(SHL(nn,CONST64(32)),tmp);
468 nn = FPBITCAST64(nn);
469 tmp = FPMUL(nn,mm);
470 if(!add)
471 tmp = FPNEG64(tmp);
472 mm = ZEXT64(IBITCAST32(FR32(2 * d)));
473 nn = ZEXT64(IBITCAST32(FR32(2 * d + 1)));
474 mm = OR(SHL(nn,CONST64(32)),mm);
475 mm = FPBITCAST64(mm);
476 tmp = FPADD(FPNEG64(mm),tmp);
477 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
478 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
479 LETFPS(2*d ,FPBITCAST32(nn));
480 LETFPS(d*2 + 1 , FPBITCAST32(mm));
481 }
482 return No_exp;
483}
484#endif
485
486/* ----------------------------------------------------------------------- */ 213/* ----------------------------------------------------------------------- */
487/* VNMUL */ 214/* VNMUL */
488/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ 215/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
@@ -533,65 +260,6 @@ VNMUL_INST:
533} 260}
534#endif 261#endif
535 262
536#ifdef VFP_DYNCOM_TABLE
537DYNCOM_FILL_ACTION(vnmul),
538#endif
539#ifdef VFP_DYNCOM_TAG
540int DYNCOM_TAG(vnmul)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
541{
542 int instr_size = INSTR_SIZE;
543 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
544 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
545 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
546 return instr_size;
547}
548#endif
549#ifdef VFP_DYNCOM_TRANS
550int DYNCOM_TRANS(vnmul)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
551 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
552 //arch_arm_undef(cpu, bb, instr);
553 int m;
554 int n;
555 int d ;
556 int add = (BIT(6) == 0);
557 int s = BIT(8) == 0;
558 Value *mm;
559 Value *nn;
560 Value *tmp;
561 if(s){
562 m = BIT(5) | BITS(0,3) << 1;
563 n = BIT(7) | BITS(16,19) << 1;
564 d = BIT(22) | BITS(12,15) << 1;
565 mm = FR32(m);
566 nn = FR32(n);
567 tmp = FPMUL(nn,mm);
568 //LETS(d,tmp);
569 LETFPS(d,FPNEG32(tmp));
570 }else {
571 m = BITS(0,3) | BIT(5) << 4;
572 n = BITS(16,19) | BIT(7) << 4;
573 d = BIT(22) << 4 | BITS(12,15);
574 //mm = SITOFP(32,RSPR(m));
575 //LETS(d,tmp);
576 mm = ZEXT64(IBITCAST32(FR32(2 * m)));
577 nn = ZEXT64(IBITCAST32(FR32(2 * m + 1)));
578 tmp = OR(SHL(nn,CONST64(32)),mm);
579 mm = FPBITCAST64(tmp);
580 tmp = ZEXT64(IBITCAST32(FR32(2 * n)));
581 nn = ZEXT64(IBITCAST32(FR32(2 * n + 1)));
582 nn = OR(SHL(nn,CONST64(32)),tmp);
583 nn = FPBITCAST64(nn);
584 tmp = FPMUL(nn,mm);
585 tmp = FPNEG64(tmp);
586 mm = TRUNC32(LSHR(IBITCAST64(tmp),CONST64(32)));
587 nn = TRUNC32(AND(IBITCAST64(tmp),CONST64(0xffffffff)));
588 LETFPS(2*d ,FPBITCAST32(nn));
589 LETFPS(d*2 + 1 , FPBITCAST32(mm));
590 }
591 return No_exp;
592}
593#endif
594
595/* ----------------------------------------------------------------------- */ 263/* ----------------------------------------------------------------------- */
596/* VMUL */ 264/* VMUL */
597/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ 265/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
@@ -642,77 +310,6 @@ VMUL_INST:
642} 310}
643#endif 311#endif
644 312
645#ifdef VFP_DYNCOM_TABLE
646DYNCOM_FILL_ACTION(vmul),
647#endif
648#ifdef VFP_DYNCOM_TAG
649int DYNCOM_TAG(vmul)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
650{
651 int instr_size = INSTR_SIZE;
652 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
653 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
654 return instr_size;
655}
656#endif
657#ifdef VFP_DYNCOM_TRANS
658int DYNCOM_TRANS(vmul)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
659 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
660 //arch_arm_undef(cpu, bb, instr);
661 int m;
662 int n;
663 int d ;
664 int s = BIT(8) == 0;
665 Value *mm;
666 Value *nn;
667 Value *tmp;
668 if(s){
669 m = BIT(5) | BITS(0,3) << 1;
670 n = BIT(7) | BITS(16,19) << 1;
671 d = BIT(22) | BITS(12,15) << 1;
672 //mm = SITOFP(32,FR(m));
673 //nn = SITOFP(32,FRn));
674 mm = FR32(m);
675 nn = FR32(n);
676 tmp = FPMUL(nn,mm);
677 //LETS(d,tmp);
678 LETFPS(d,tmp);
679 }else {
680 m = BITS(0,3) | BIT(5) << 4;
681 n = BITS(16,19) | BIT(7) << 4;
682 d = BIT(22) << 4 | BITS(12,15);
683 //mm = SITOFP(32,RSPR(m));
684 //LETS(d,tmp);
685 Value *lo = FR32(2 * m);
686 Value *hi = FR32(2 * m + 1);
687 hi = IBITCAST32(hi);
688 lo = IBITCAST32(lo);
689 Value *hi64 = ZEXT64(hi);
690 Value* lo64 = ZEXT64(lo);
691 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
692 Value* m0 = FPBITCAST64(v64);
693 lo = FR32(2 * n);
694 hi = FR32(2 * n + 1);
695 hi = IBITCAST32(hi);
696 lo = IBITCAST32(lo);
697 hi64 = ZEXT64(hi);
698 lo64 = ZEXT64(lo);
699 v64 = OR(SHL(hi64,CONST64(32)),lo64);
700 Value *n0 = FPBITCAST64(v64);
701 tmp = FPMUL(n0,m0);
702 Value *val64 = IBITCAST64(tmp);
703 hi = LSHR(val64,CONST64(32));
704 lo = AND(val64,CONST64(0xffffffff));
705 hi = TRUNC32(hi);
706 lo = TRUNC32(lo);
707 hi = FPBITCAST32(hi);
708 lo = FPBITCAST32(lo);
709 LETFPS(2*d ,lo);
710 LETFPS(d*2 + 1 , hi);
711 }
712 return No_exp;
713}
714#endif
715
716/* ----------------------------------------------------------------------- */ 313/* ----------------------------------------------------------------------- */
717/* VADD */ 314/* VADD */
718/* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */ 315/* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */
@@ -763,73 +360,6 @@ VADD_INST:
763} 360}
764#endif 361#endif
765 362
766#ifdef VFP_DYNCOM_TABLE
767DYNCOM_FILL_ACTION(vadd),
768#endif
769#ifdef VFP_DYNCOM_TAG
770int DYNCOM_TAG(vadd)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
771{
772 int instr_size = INSTR_SIZE;
773 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
774 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
775 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
776 return instr_size;
777}
778#endif
779#ifdef VFP_DYNCOM_TRANS
780int DYNCOM_TRANS(vadd)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
781 LOG_TRACE(Core_ARM11, "\t\tin %s instruction will implement out of JIT.\n", __FUNCTION__);
782 //arch_arm_undef(cpu, bb, instr);
783 int m;
784 int n;
785 int d ;
786 int s = BIT(8) == 0;
787 Value *mm;
788 Value *nn;
789 Value *tmp;
790 if(s){
791 m = BIT(5) | BITS(0,3) << 1;
792 n = BIT(7) | BITS(16,19) << 1;
793 d = BIT(22) | BITS(12,15) << 1;
794 mm = FR32(m);
795 nn = FR32(n);
796 tmp = FPADD(nn,mm);
797 LETFPS(d,tmp);
798 }else {
799 m = BITS(0,3) | BIT(5) << 4;
800 n = BITS(16,19) | BIT(7) << 4;
801 d = BIT(22) << 4 | BITS(12,15);
802 Value *lo = FR32(2 * m);
803 Value *hi = FR32(2 * m + 1);
804 hi = IBITCAST32(hi);
805 lo = IBITCAST32(lo);
806 Value *hi64 = ZEXT64(hi);
807 Value* lo64 = ZEXT64(lo);
808 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
809 Value* m0 = FPBITCAST64(v64);
810 lo = FR32(2 * n);
811 hi = FR32(2 * n + 1);
812 hi = IBITCAST32(hi);
813 lo = IBITCAST32(lo);
814 hi64 = ZEXT64(hi);
815 lo64 = ZEXT64(lo);
816 v64 = OR(SHL(hi64,CONST64(32)),lo64);
817 Value *n0 = FPBITCAST64(v64);
818 tmp = FPADD(n0,m0);
819 Value *val64 = IBITCAST64(tmp);
820 hi = LSHR(val64,CONST64(32));
821 lo = AND(val64,CONST64(0xffffffff));
822 hi = TRUNC32(hi);
823 lo = TRUNC32(lo);
824 hi = FPBITCAST32(hi);
825 lo = FPBITCAST32(lo);
826 LETFPS(2*d ,lo);
827 LETFPS(d*2 + 1 , hi);
828 }
829 return No_exp;
830}
831#endif
832
833/* ----------------------------------------------------------------------- */ 363/* ----------------------------------------------------------------------- */
834/* VSUB */ 364/* VSUB */
835/* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */ 365/* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */
@@ -879,71 +409,6 @@ VSUB_INST:
879 GOTO_NEXT_INST; 409 GOTO_NEXT_INST;
880} 410}
881#endif 411#endif
882#ifdef VFP_DYNCOM_TABLE
883DYNCOM_FILL_ACTION(vsub),
884#endif
885#ifdef VFP_DYNCOM_TAG
886int DYNCOM_TAG(vsub)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
887{
888 int instr_size = INSTR_SIZE;
889 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
890 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
891 return instr_size;
892}
893#endif
894#ifdef VFP_DYNCOM_TRANS
895int DYNCOM_TRANS(vsub)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
896 LOG_TRACE(Core_ARM11, "\t\tin %s instr=0x%x, instruction is executed out of JIT.\n", __FUNCTION__, instr);
897 //arch_arm_undef(cpu, bb, instr);
898 int m;
899 int n;
900 int d ;
901 int s = BIT(8) == 0;
902 Value *mm;
903 Value *nn;
904 Value *tmp;
905 if(s){
906 m = BIT(5) | BITS(0,3) << 1;
907 n = BIT(7) | BITS(16,19) << 1;
908 d = BIT(22) | BITS(12,15) << 1;
909 mm = FR32(m);
910 nn = FR32(n);
911 tmp = FPSUB(nn,mm);
912 LETFPS(d,tmp);
913 }else {
914 m = BITS(0,3) | BIT(5) << 4;
915 n = BITS(16,19) | BIT(7) << 4;
916 d = BIT(22) << 4 | BITS(12,15);
917 Value *lo = FR32(2 * m);
918 Value *hi = FR32(2 * m + 1);
919 hi = IBITCAST32(hi);
920 lo = IBITCAST32(lo);
921 Value *hi64 = ZEXT64(hi);
922 Value* lo64 = ZEXT64(lo);
923 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
924 Value* m0 = FPBITCAST64(v64);
925 lo = FR32(2 * n);
926 hi = FR32(2 * n + 1);
927 hi = IBITCAST32(hi);
928 lo = IBITCAST32(lo);
929 hi64 = ZEXT64(hi);
930 lo64 = ZEXT64(lo);
931 v64 = OR(SHL(hi64,CONST64(32)),lo64);
932 Value *n0 = FPBITCAST64(v64);
933 tmp = FPSUB(n0,m0);
934 Value *val64 = IBITCAST64(tmp);
935 hi = LSHR(val64,CONST64(32));
936 lo = AND(val64,CONST64(0xffffffff));
937 hi = TRUNC32(hi);
938 lo = TRUNC32(lo);
939 hi = FPBITCAST32(hi);
940 lo = FPBITCAST32(lo);
941 LETFPS(2*d ,lo);
942 LETFPS(d*2 + 1 , hi);
943 }
944 return No_exp;
945}
946#endif
947 412
948/* ----------------------------------------------------------------------- */ 413/* ----------------------------------------------------------------------- */
949/* VDIV */ 414/* VDIV */
@@ -995,73 +460,6 @@ VDIV_INST:
995} 460}
996#endif 461#endif
997 462
998#ifdef VFP_DYNCOM_TABLE
999DYNCOM_FILL_ACTION(vdiv),
1000#endif
1001#ifdef VFP_DYNCOM_TAG
1002int DYNCOM_TAG(vdiv)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1003{
1004 int instr_size = INSTR_SIZE;
1005 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1006 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1007 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1008 return instr_size;
1009}
1010#endif
1011#ifdef VFP_DYNCOM_TRANS
1012int DYNCOM_TRANS(vdiv)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1013 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1014 //arch_arm_undef(cpu, bb, instr);
1015 int m;
1016 int n;
1017 int d ;
1018 int s = BIT(8) == 0;
1019 Value *mm;
1020 Value *nn;
1021 Value *tmp;
1022 if(s){
1023 m = BIT(5) | BITS(0,3) << 1;
1024 n = BIT(7) | BITS(16,19) << 1;
1025 d = BIT(22) | BITS(12,15) << 1;
1026 mm = FR32(m);
1027 nn = FR32(n);
1028 tmp = FPDIV(nn,mm);
1029 LETFPS(d,tmp);
1030 }else {
1031 m = BITS(0,3) | BIT(5) << 4;
1032 n = BITS(16,19) | BIT(7) << 4;
1033 d = BIT(22) << 4 | BITS(12,15);
1034 Value *lo = FR32(2 * m);
1035 Value *hi = FR32(2 * m + 1);
1036 hi = IBITCAST32(hi);
1037 lo = IBITCAST32(lo);
1038 Value *hi64 = ZEXT64(hi);
1039 Value* lo64 = ZEXT64(lo);
1040 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
1041 Value* m0 = FPBITCAST64(v64);
1042 lo = FR32(2 * n);
1043 hi = FR32(2 * n + 1);
1044 hi = IBITCAST32(hi);
1045 lo = IBITCAST32(lo);
1046 hi64 = ZEXT64(hi);
1047 lo64 = ZEXT64(lo);
1048 v64 = OR(SHL(hi64,CONST64(32)),lo64);
1049 Value *n0 = FPBITCAST64(v64);
1050 tmp = FPDIV(n0,m0);
1051 Value *val64 = IBITCAST64(tmp);
1052 hi = LSHR(val64,CONST64(32));
1053 lo = AND(val64,CONST64(0xffffffff));
1054 hi = TRUNC32(hi);
1055 lo = TRUNC32(lo);
1056 hi = FPBITCAST32(hi);
1057 lo = FPBITCAST32(lo);
1058 LETFPS(2*d ,lo);
1059 LETFPS(d*2 + 1 , hi);
1060 }
1061 return No_exp;
1062}
1063#endif
1064
1065/* ----------------------------------------------------------------------- */ 463/* ----------------------------------------------------------------------- */
1066/* VMOVI move immediate */ 464/* VMOVI move immediate */
1067/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */ 465/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */
@@ -1111,46 +509,6 @@ VMOVI_INST:
1111} 509}
1112#endif 510#endif
1113 511
1114#ifdef VFP_DYNCOM_TABLE
1115DYNCOM_FILL_ACTION(vmovi),
1116#endif
1117#ifdef VFP_DYNCOM_TAG
1118int DYNCOM_TAG(vmovi)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1119{
1120 int instr_size = INSTR_SIZE;
1121 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1122 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1123 return instr_size;
1124}
1125#endif
1126#ifdef VFP_DYNCOM_TRANS
1127int DYNCOM_TRANS(vmovi)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1128 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1129 //arch_arm_undef(cpu, bb, instr);
1130 int single = (BIT(8) == 0);
1131 int d;
1132 int imm32;
1133 Value *v;
1134 Value *tmp;
1135 v = CONST32(BITS(0,3) | BITS(16,19) << 4);
1136 //v = CONST64(0x3ff0000000000000);
1137 if(single){
1138 d = BIT(22) | BITS(12,15) << 1;
1139 }else {
1140 d = BITS(12,15) | BIT(22) << 4;
1141 }
1142 if(single){
1143 LETFPS(d,FPBITCAST32(v));
1144 }else {
1145 //v = UITOFP(64,v);
1146 //tmp = IBITCAST64(v);
1147 LETFPS(d*2 ,FPBITCAST32(TRUNC32(AND(v,CONST64(0xffffffff)))));
1148 LETFPS(d * 2 + 1,FPBITCAST32(TRUNC32(LSHR(v,CONST64(32)))));
1149 }
1150 return No_exp;
1151}
1152#endif
1153
1154/* ----------------------------------------------------------------------- */ 512/* ----------------------------------------------------------------------- */
1155/* VMOVR move register */ 513/* VMOVR move register */
1156/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */ 514/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */
@@ -1196,40 +554,6 @@ VMOVR_INST:
1196} 554}
1197#endif 555#endif
1198 556
1199#ifdef VFP_DYNCOM_TABLE
1200DYNCOM_FILL_ACTION(vmovr),
1201#endif
1202#ifdef VFP_DYNCOM_TAG
1203int DYNCOM_TAG(vmovr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1204{
1205 int instr_size = INSTR_SIZE;
1206 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1207 if(instr >> 28 != 0xe)
1208 *tag |= TAG_CONDITIONAL;
1209
1210 return instr_size;
1211}
1212#endif
1213#ifdef VFP_DYNCOM_TRANS
1214int DYNCOM_TRANS(vmovr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1215 int single = BIT(8) == 0;
1216 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15));
1217 int m = (single ? BITS(0, 3)<<1 | BIT(5) : BITS(0, 3) | BIT(5)<<4);
1218
1219 if (single)
1220 {
1221 LETFPS(d, FR32(m));
1222 }
1223 else
1224 {
1225 /* Check endian please */
1226 LETFPS((d*2 + 1), FR32(m*2 + 1));
1227 LETFPS((d * 2), FR32(m * 2));
1228 }
1229 return No_exp;
1230}
1231#endif
1232
1233/* ----------------------------------------------------------------------- */ 557/* ----------------------------------------------------------------------- */
1234/* VABS */ 558/* VABS */
1235/* cond 1110 1D11 0000 Vd-- 101X 11M0 Vm-- */ 559/* cond 1110 1D11 0000 Vd-- 101X 11M0 Vm-- */
@@ -1280,57 +604,6 @@ VABS_INST:
1280} 604}
1281#endif 605#endif
1282 606
1283#ifdef VFP_DYNCOM_TABLE
1284DYNCOM_FILL_ACTION(vabs),
1285#endif
1286#ifdef VFP_DYNCOM_TAG
1287int DYNCOM_TAG(vabs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1288{
1289 int instr_size = INSTR_SIZE;
1290 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1291 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1292 return instr_size;
1293}
1294#endif
1295#ifdef VFP_DYNCOM_TRANS
1296int DYNCOM_TRANS(vabs)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1297 //arch_arm_undef(cpu, bb, instr);
1298 int single = BIT(8) == 0;
1299 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15));
1300 int m = (single ? BITS(0, 3)<<1 | BIT(5) : BITS(0, 3) | BIT(5)<<4);
1301 Value* m0;
1302 if (single)
1303 {
1304 m0 = FR32(m);
1305 m0 = SELECT(FPCMP_OLT(m0,FPCONST32(0.0)),FPNEG32(m0),m0);
1306 LETFPS(d,m0);
1307 }
1308 else
1309 {
1310 /* Check endian please */
1311 Value *lo = FR32(2 * m);
1312 Value *hi = FR32(2 * m + 1);
1313 hi = IBITCAST32(hi);
1314 lo = IBITCAST32(lo);
1315 Value *hi64 = ZEXT64(hi);
1316 Value* lo64 = ZEXT64(lo);
1317 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
1318 m0 = FPBITCAST64(v64);
1319 m0 = SELECT(FPCMP_OLT(m0,FPCONST64(0.0)),FPNEG64(m0),m0);
1320 Value *val64 = IBITCAST64(m0);
1321 hi = LSHR(val64,CONST64(32));
1322 lo = AND(val64,CONST64(0xffffffff));
1323 hi = TRUNC32(hi);
1324 lo = TRUNC32(lo);
1325 hi = FPBITCAST32(hi);
1326 lo = FPBITCAST32(lo);
1327 LETFPS(2*d ,lo);
1328 LETFPS(d*2 + 1 , hi);
1329 }
1330 return No_exp;
1331}
1332#endif
1333
1334/* ----------------------------------------------------------------------- */ 607/* ----------------------------------------------------------------------- */
1335/* VNEG */ 608/* VNEG */
1336/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ 609/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
@@ -1382,59 +655,6 @@ VNEG_INST:
1382} 655}
1383#endif 656#endif
1384 657
1385#ifdef VFP_DYNCOM_TABLE
1386DYNCOM_FILL_ACTION(vneg),
1387#endif
1388#ifdef VFP_DYNCOM_TAG
1389int DYNCOM_TAG(vneg)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1390{
1391 int instr_size = INSTR_SIZE;
1392 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1393 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1394 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1395 return instr_size;
1396}
1397#endif
1398#ifdef VFP_DYNCOM_TRANS
1399int DYNCOM_TRANS(vneg)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1400 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1401 //arch_arm_undef(cpu, bb, instr);
1402 int single = BIT(8) == 0;
1403 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15));
1404 int m = (single ? BITS(0, 3)<<1 | BIT(5) : BITS(0, 3) | BIT(5)<<4);
1405 Value* m0;
1406 if (single)
1407 {
1408 m0 = FR32(m);
1409 m0 = FPNEG32(m0);
1410 LETFPS(d,m0);
1411 }
1412 else
1413 {
1414 /* Check endian please */
1415 Value *lo = FR32(2 * m);
1416 Value *hi = FR32(2 * m + 1);
1417 hi = IBITCAST32(hi);
1418 lo = IBITCAST32(lo);
1419 Value *hi64 = ZEXT64(hi);
1420 Value* lo64 = ZEXT64(lo);
1421 Value* v64 = OR(SHL(hi64,CONST64(32)),lo64);
1422 m0 = FPBITCAST64(v64);
1423 m0 = FPNEG64(m0);
1424 Value *val64 = IBITCAST64(m0);
1425 hi = LSHR(val64,CONST64(32));
1426 lo = AND(val64,CONST64(0xffffffff));
1427 hi = TRUNC32(hi);
1428 lo = TRUNC32(lo);
1429 hi = FPBITCAST32(hi);
1430 lo = FPBITCAST32(lo);
1431 LETFPS(2*d ,lo);
1432 LETFPS(d*2 + 1 , hi);
1433 }
1434 return No_exp;
1435}
1436#endif
1437
1438/* ----------------------------------------------------------------------- */ 658/* ----------------------------------------------------------------------- */
1439/* VSQRT */ 659/* VSQRT */
1440/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ 660/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
@@ -1485,47 +705,6 @@ VSQRT_INST:
1485} 705}
1486#endif 706#endif
1487 707
1488#ifdef VFP_DYNCOM_TABLE
1489DYNCOM_FILL_ACTION(vsqrt),
1490#endif
1491#ifdef VFP_DYNCOM_TAG
1492int DYNCOM_TAG(vsqrt)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1493{
1494 int instr_size = INSTR_SIZE;
1495 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1496 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1497 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1498 return instr_size;
1499}
1500#endif
1501#ifdef VFP_DYNCOM_TRANS
1502int DYNCOM_TRANS(vsqrt)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1503 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1504 //arch_arm_undef(cpu, bb, instr);
1505 int dp_op = (BIT(8) == 1);
1506 int d = dp_op ? BITS(12,15) | BIT(22) << 4 : BIT(22) | BITS(12,15) << 1;
1507 int m = dp_op ? BITS(0,3) | BIT(5) << 4 : BIT(5) | BITS(0,3) << 1;
1508 Value* v;
1509 Value* tmp;
1510 if(dp_op){
1511 v = SHL(ZEXT64(IBITCAST32(FR32(2 * m + 1))),CONST64(32));
1512 tmp = ZEXT64(IBITCAST32(FR32(2 * m)));
1513 v = OR(v,tmp);
1514 v = FPSQRT(FPBITCAST64(v));
1515 tmp = TRUNC32(LSHR(IBITCAST64(v),CONST64(32)));
1516 v = TRUNC32(AND(IBITCAST64(v),CONST64( 0xffffffff)));
1517 LETFPS(2 * d , FPBITCAST32(v));
1518 LETFPS(2 * d + 1, FPBITCAST32(tmp));
1519 }else {
1520 v = FR32(m);
1521 v = FPSQRT(FPEXT(64,v));
1522 v = FPTRUNC(32,v);
1523 LETFPS(d,v);
1524 }
1525 return No_exp;
1526}
1527#endif
1528
1529/* ----------------------------------------------------------------------- */ 708/* ----------------------------------------------------------------------- */
1530/* VCMP VCMPE */ 709/* VCMP VCMPE */
1531/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */ 710/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */
@@ -1576,74 +755,6 @@ VCMP_INST:
1576} 755}
1577#endif 756#endif
1578 757
1579#ifdef VFP_DYNCOM_TABLE
1580DYNCOM_FILL_ACTION(vcmp),
1581#endif
1582#ifdef VFP_DYNCOM_TAG
1583int DYNCOM_TAG(vcmp)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1584{
1585 int instr_size = INSTR_SIZE;
1586 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1587 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1588 return instr_size;
1589}
1590#endif
1591#ifdef VFP_DYNCOM_TRANS
1592int DYNCOM_TRANS(vcmp)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1593 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is executed out of JIT.\n", __FUNCTION__);
1594 //arch_arm_undef(cpu, bb, instr);
1595 int dp_op = (BIT(8) == 1);
1596 int d = dp_op ? BITS(12,15) | BIT(22) << 4 : BIT(22) | BITS(12,15) << 1;
1597 int m = dp_op ? BITS(0,3) | BIT(5) << 4 : BIT(5) | BITS(0,3) << 1;
1598 Value* v;
1599 Value* tmp;
1600 Value* n;
1601 Value* z;
1602 Value* c;
1603 Value* vt;
1604 Value* v1;
1605 Value* nzcv;
1606 if(dp_op){
1607 v = SHL(ZEXT64(IBITCAST32(FR32(2 * m + 1))),CONST64(32));
1608 tmp = ZEXT64(IBITCAST32(FR32(2 * m)));
1609 v1 = OR(v,tmp);
1610 v = SHL(ZEXT64(IBITCAST32(FR32(2 * d + 1))),CONST64(32));
1611 tmp = ZEXT64(IBITCAST32(FR32(2 * d)));
1612 v = OR(v,tmp);
1613 z = FPCMP_OEQ(FPBITCAST64(v),FPBITCAST64(v1));
1614 n = FPCMP_OLT(FPBITCAST64(v),FPBITCAST64(v1));
1615 c = FPCMP_OGE(FPBITCAST64(v),FPBITCAST64(v1));
1616 tmp = FPCMP_UNO(FPBITCAST64(v),FPBITCAST64(v1));
1617 v1 = tmp;
1618 c = OR(c,tmp);
1619 n = SHL(ZEXT32(n),CONST32(31));
1620 z = SHL(ZEXT32(z),CONST32(30));
1621 c = SHL(ZEXT32(c),CONST32(29));
1622 v1 = SHL(ZEXT32(v1),CONST(28));
1623 nzcv = OR(OR(OR(n,z),c),v1);
1624 v = R(VFP_FPSCR);
1625 tmp = OR(nzcv,AND(v,CONST32(0x0fffffff)));
1626 LET(VFP_FPSCR,tmp);
1627 }else {
1628 z = FPCMP_OEQ(FR32(d),FR32(m));
1629 n = FPCMP_OLT(FR32(d),FR32(m));
1630 c = FPCMP_OGE(FR32(d),FR32(m));
1631 tmp = FPCMP_UNO(FR32(d),FR32(m));
1632 c = OR(c,tmp);
1633 v1 = tmp;
1634 n = SHL(ZEXT32(n),CONST32(31));
1635 z = SHL(ZEXT32(z),CONST32(30));
1636 c = SHL(ZEXT32(c),CONST32(29));
1637 v1 = SHL(ZEXT32(v1),CONST(28));
1638 nzcv = OR(OR(OR(n,z),c),v1);
1639 v = R(VFP_FPSCR);
1640 tmp = OR(nzcv,AND(v,CONST32(0x0fffffff)));
1641 LET(VFP_FPSCR,tmp);
1642 }
1643 return No_exp;
1644}
1645#endif
1646
1647/* ----------------------------------------------------------------------- */ 758/* ----------------------------------------------------------------------- */
1648/* VCMP VCMPE */ 759/* VCMP VCMPE */
1649/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */ 760/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */
@@ -1694,74 +805,6 @@ VCMP2_INST:
1694} 805}
1695#endif 806#endif
1696 807
1697#ifdef VFP_DYNCOM_TABLE
1698DYNCOM_FILL_ACTION(vcmp2),
1699#endif
1700#ifdef VFP_DYNCOM_TAG
1701int DYNCOM_TAG(vcmp2)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1702{
1703 int instr_size = INSTR_SIZE;
1704 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1705 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1706 return instr_size;
1707}
1708#endif
1709#ifdef VFP_DYNCOM_TRANS
1710int DYNCOM_TRANS(vcmp2)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1711 LOG_TRACE(Core_ARM11, "\t\tin %s instruction will executed out of JIT.\n", __FUNCTION__);
1712 //arch_arm_undef(cpu, bb, instr);
1713 int dp_op = (BIT(8) == 1);
1714 int d = dp_op ? BITS(12,15) | BIT(22) << 4 : BIT(22) | BITS(12,15) << 1;
1715 //int m = dp_op ? BITS(0,3) | BIT(5) << 4 : BIT(5) | BITS(0,3) << 1;
1716 Value* v;
1717 Value* tmp;
1718 Value* n;
1719 Value* z;
1720 Value* c;
1721 Value* vt;
1722 Value* v1;
1723 Value* nzcv;
1724 if(dp_op){
1725 v1 = CONST64(0);
1726 v = SHL(ZEXT64(IBITCAST32(FR32(2 * d + 1))),CONST64(32));
1727 tmp = ZEXT64(IBITCAST32(FR32(2 * d)));
1728 v = OR(v,tmp);
1729 z = FPCMP_OEQ(FPBITCAST64(v),FPBITCAST64(v1));
1730 n = FPCMP_OLT(FPBITCAST64(v),FPBITCAST64(v1));
1731 c = FPCMP_OGE(FPBITCAST64(v),FPBITCAST64(v1));
1732 tmp = FPCMP_UNO(FPBITCAST64(v),FPBITCAST64(v1));
1733 v1 = tmp;
1734 c = OR(c,tmp);
1735 n = SHL(ZEXT32(n),CONST32(31));
1736 z = SHL(ZEXT32(z),CONST32(30));
1737 c = SHL(ZEXT32(c),CONST32(29));
1738 v1 = SHL(ZEXT32(v1),CONST(28));
1739 nzcv = OR(OR(OR(n,z),c),v1);
1740 v = R(VFP_FPSCR);
1741 tmp = OR(nzcv,AND(v,CONST32(0x0fffffff)));
1742 LET(VFP_FPSCR,tmp);
1743 }else {
1744 v1 = CONST(0);
1745 v1 = FPBITCAST32(v1);
1746 z = FPCMP_OEQ(FR32(d),v1);
1747 n = FPCMP_OLT(FR32(d),v1);
1748 c = FPCMP_OGE(FR32(d),v1);
1749 tmp = FPCMP_UNO(FR32(d),v1);
1750 c = OR(c,tmp);
1751 v1 = tmp;
1752 n = SHL(ZEXT32(n),CONST32(31));
1753 z = SHL(ZEXT32(z),CONST32(30));
1754 c = SHL(ZEXT32(c),CONST32(29));
1755 v1 = SHL(ZEXT32(v1),CONST(28));
1756 nzcv = OR(OR(OR(n,z),c),v1);
1757 v = R(VFP_FPSCR);
1758 tmp = OR(nzcv,AND(v,CONST32(0x0fffffff)));
1759 LET(VFP_FPSCR,tmp);
1760 }
1761 return No_exp;
1762}
1763#endif
1764
1765/* ----------------------------------------------------------------------- */ 808/* ----------------------------------------------------------------------- */
1766/* VCVTBDS between double and single */ 809/* VCVTBDS between double and single */
1767/* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */ 810/* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */
@@ -1812,48 +855,6 @@ VCVTBDS_INST:
1812} 855}
1813#endif 856#endif
1814 857
1815#ifdef VFP_DYNCOM_TABLE
1816DYNCOM_FILL_ACTION(vcvtbds),
1817#endif
1818#ifdef VFP_DYNCOM_TAG
1819int DYNCOM_TAG(vcvtbds)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1820{
1821 int instr_size = INSTR_SIZE;
1822 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1823 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1824 return instr_size;
1825}
1826#endif
1827#ifdef VFP_DYNCOM_TRANS
1828int DYNCOM_TRANS(vcvtbds)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1829 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is executed out.\n", __FUNCTION__);
1830 //arch_arm_undef(cpu, bb, instr);
1831 int dp_op = (BIT(8) == 1);
1832 int d = dp_op ? BITS(12,15) << 1 | BIT(22) : BIT(22) << 4 | BITS(12,15);
1833 int m = dp_op ? BITS(0,3) | BIT(5) << 4 : BIT(5) | BITS(0,3) << 1;
1834 int d2s = dp_op;
1835 Value* v;
1836 Value* tmp;
1837 Value* v1;
1838 if(d2s){
1839 v = SHL(ZEXT64(IBITCAST32(FR32(2 * m + 1))),CONST64(32));
1840 tmp = ZEXT64(IBITCAST32(FR32(2 * m)));
1841 v1 = OR(v,tmp);
1842 tmp = FPTRUNC(32,FPBITCAST64(v1));
1843 LETFPS(d,tmp);
1844 }else {
1845 v = FR32(m);
1846 tmp = FPEXT(64,v);
1847 v = IBITCAST64(tmp);
1848 tmp = TRUNC32(AND(v,CONST64(0xffffffff)));
1849 v1 = TRUNC32(LSHR(v,CONST64(32)));
1850 LETFPS(2 * d, FPBITCAST32(tmp) );
1851 LETFPS(2 * d + 1, FPBITCAST32(v1));
1852 }
1853 return No_exp;
1854}
1855#endif
1856
1857/* ----------------------------------------------------------------------- */ 858/* ----------------------------------------------------------------------- */
1858/* VCVTBFF between floating point and fixed point */ 859/* VCVTBFF between floating point and fixed point */
1859/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ 860/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
@@ -1906,26 +907,6 @@ VCVTBFF_INST:
1906} 907}
1907#endif 908#endif
1908 909
1909#ifdef VFP_DYNCOM_TABLE
1910DYNCOM_FILL_ACTION(vcvtbff),
1911#endif
1912#ifdef VFP_DYNCOM_TAG
1913int DYNCOM_TAG(vcvtbff)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1914{
1915 int instr_size = INSTR_SIZE;
1916 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1917 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1918 return instr_size;
1919}
1920#endif
1921#ifdef VFP_DYNCOM_TRANS
1922int DYNCOM_TRANS(vcvtbff)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1923 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1924 arch_arm_undef(cpu, bb, instr);
1925 return No_exp;
1926}
1927#endif
1928
1929/* ----------------------------------------------------------------------- */ 910/* ----------------------------------------------------------------------- */
1930/* VCVTBFI between floating point and integer */ 911/* VCVTBFI between floating point and integer */
1931/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ 912/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
@@ -1976,114 +957,6 @@ VCVTBFI_INST:
1976} 957}
1977#endif 958#endif
1978 959
1979#ifdef VFP_DYNCOM_TABLE
1980DYNCOM_FILL_ACTION(vcvtbfi),
1981#endif
1982#ifdef VFP_DYNCOM_TAG
1983int DYNCOM_TAG(vcvtbfi)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1984{
1985 int instr_size = INSTR_SIZE;
1986 LOG_TRACE(Core_ARM11, "\t\tin %s, instruction will be executed out of JIT.\n", __FUNCTION__);
1987 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
1988 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
1989 return instr_size;
1990}
1991#endif
1992#ifdef VFP_DYNCOM_TRANS
1993int DYNCOM_TRANS(vcvtbfi)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1994 LOG_TRACE(Core_ARM11, "\t\tin %s, instruction will be executed out of JIT.\n", __FUNCTION__);
1995 //arch_arm_undef(cpu, bb, instr);
1996 unsigned int opc2 = BITS(16,18);
1997 int to_integer = ((opc2 >> 2) == 1);
1998 int dp_op = (BIT(8) == 1);
1999 unsigned int op = BIT(7);
2000 int m,d;
2001 Value* v;
2002 Value* hi;
2003 Value* lo;
2004 Value* v64;
2005 if(to_integer){
2006 d = BIT(22) | (BITS(12,15) << 1);
2007 if(dp_op)
2008 m = BITS(0,3) | BIT(5) << 4;
2009 else
2010 m = BIT(5) | BITS(0,3) << 1;
2011 }else {
2012 m = BIT(5) | BITS(0,3) << 1;
2013 if(dp_op)
2014 d = BITS(12,15) | BIT(22) << 4;
2015 else
2016 d = BIT(22) | BITS(12,15) << 1;
2017 }
2018 if(to_integer){
2019 if(dp_op){
2020 lo = FR32(m * 2);
2021 hi = FR32(m * 2 + 1);
2022 hi = ZEXT64(IBITCAST32(hi));
2023 lo = ZEXT64(IBITCAST32(lo));
2024 v64 = OR(SHL(hi,CONST64(32)),lo);
2025 if(BIT(16)){
2026 v = FPTOSI(32,FPBITCAST64(v64));
2027 }
2028 else
2029 v = FPTOUI(32,FPBITCAST64(v64));
2030
2031 v = FPBITCAST32(v);
2032 LETFPS(d,v);
2033 }else {
2034 v = FR32(m);
2035 if(BIT(16)){
2036 v = FPTOSI(32,v);
2037 }
2038 else
2039 v = FPTOUI(32,v);
2040 LETFPS(d,FPBITCAST32(v));
2041 }
2042 }else {
2043 if(dp_op){
2044 v = IBITCAST32(FR32(m));
2045 if(BIT(7))
2046 v64 = SITOFP(64,v);
2047 else
2048 v64 = UITOFP(64,v);
2049 v = IBITCAST64(v64);
2050 hi = FPBITCAST32(TRUNC32(LSHR(v,CONST64(32))));
2051 lo = FPBITCAST32(TRUNC32(AND(v,CONST64(0xffffffff))));
2052 LETFPS(2 * d , lo);
2053 LETFPS(2 * d + 1, hi);
2054 }else {
2055 v = IBITCAST32(FR32(m));
2056 if(BIT(7))
2057 v = SITOFP(32,v);
2058 else
2059 v = UITOFP(32,v);
2060 LETFPS(d,v);
2061 }
2062 }
2063 return No_exp;
2064}
2065
2066/**
2067* @brief The implementation of c language for vcvtbfi instruction of dyncom
2068*
2069* @param cpu
2070* @param instr
2071*
2072* @return
2073*/
2074int vcvtbfi_instr_impl(arm_core_t* cpu, uint32 instr){
2075 int dp_operation = BIT(8);
2076 int ret;
2077 if (dp_operation)
2078 ret = vfp_double_cpdo(cpu, instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2079 else
2080 ret = vfp_single_cpdo(cpu, instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2081
2082 vfp_raise_exceptions(cpu, ret, instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
2083 return 0;
2084}
2085#endif
2086
2087/* ----------------------------------------------------------------------- */ 960/* ----------------------------------------------------------------------- */
2088/* MRC / MCR instructions */ 961/* MRC / MCR instructions */
2089/* cond 1110 AAAL XXXX XXXX 101C XBB1 XXXX */ 962/* cond 1110 AAAL XXXX XXXX 101C XBB1 XXXX */
@@ -2135,35 +1008,6 @@ VMOVBRS_INST:
2135} 1008}
2136#endif 1009#endif
2137 1010
2138#ifdef VFP_DYNCOM_TABLE
2139DYNCOM_FILL_ACTION(vmovbrs),
2140#endif
2141#ifdef VFP_DYNCOM_TAG
2142int DYNCOM_TAG(vmovbrs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2143{
2144 int instr_size = INSTR_SIZE;
2145 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2146 return instr_size;
2147}
2148#endif
2149#ifdef VFP_DYNCOM_TRANS
2150int DYNCOM_TRANS(vmovbrs)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2151 int to_arm = BIT(20) == 1;
2152 int t = BITS(12, 15);
2153 int n = BIT(7) | BITS(16, 19)<<1;
2154
2155 if (to_arm)
2156 {
2157 LET(t, IBITCAST32(FR32(n)));
2158 }
2159 else
2160 {
2161 LETFPS(n, FPBITCAST32(R(t)));
2162 }
2163 return No_exp;
2164}
2165#endif
2166
2167/* ----------------------------------------------------------------------- */ 1011/* ----------------------------------------------------------------------- */
2168/* VMSR */ 1012/* VMSR */
2169/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */ 1013/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */
@@ -2211,48 +1055,6 @@ VMSR_INST:
2211} 1055}
2212#endif 1056#endif
2213 1057
2214#ifdef VFP_DYNCOM_TABLE
2215DYNCOM_FILL_ACTION(vmsr),
2216#endif
2217#ifdef VFP_DYNCOM_TAG
2218int DYNCOM_TAG(vmsr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2219{
2220 int instr_size = INSTR_SIZE;
2221 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2222 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2223 return instr_size;
2224}
2225#endif
2226#ifdef VFP_DYNCOM_TRANS
2227int DYNCOM_TRANS(vmsr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2228 //arch_arm_undef(cpu, bb, instr);
2229 if(RD == 15) {
2230 LOG_ERROR(Core_ARM11, "in %s is not implementation.\n", __FUNCTION__);
2231 exit(-1);
2232 }
2233
2234 Value *data = NULL;
2235 int reg = RN;
2236 int Rt = RD;
2237 if (reg == 1)
2238 {
2239 LET(VFP_FPSCR, R(Rt));
2240 }
2241 else
2242 {
2243 switch (reg)
2244 {
2245 case 8:
2246 LET(VFP_FPEXC, R(Rt));
2247 break;
2248 default:
2249 break;
2250 }
2251 }
2252 return No_exp;
2253}
2254#endif
2255
2256/* ----------------------------------------------------------------------- */ 1058/* ----------------------------------------------------------------------- */
2257/* VMOVBRC register to scalar */ 1059/* VMOVBRC register to scalar */
2258/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */ 1060/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */
@@ -2302,26 +1104,6 @@ VMOVBRC_INST:
2302} 1104}
2303#endif 1105#endif
2304 1106
2305#ifdef VFP_DYNCOM_TABLE
2306DYNCOM_FILL_ACTION(vmovbrc),
2307#endif
2308#ifdef VFP_DYNCOM_TAG
2309int DYNCOM_TAG(vmovbrc)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2310{
2311 int instr_size = INSTR_SIZE;
2312 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2313 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2314 return instr_size;
2315}
2316#endif
2317#ifdef VFP_DYNCOM_TRANS
2318int DYNCOM_TRANS(vmovbrc)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2319 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2320 arch_arm_undef(cpu, bb, instr);
2321 return No_exp;
2322}
2323#endif
2324
2325/* ----------------------------------------------------------------------- */ 1107/* ----------------------------------------------------------------------- */
2326/* VMRS */ 1108/* VMRS */
2327/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */ 1109/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */
@@ -2404,64 +1186,6 @@ VMRS_INST:
2404} 1186}
2405#endif 1187#endif
2406 1188
2407#ifdef VFP_DYNCOM_TABLE
2408DYNCOM_FILL_ACTION(vmrs),
2409#endif
2410#ifdef VFP_DYNCOM_TAG
2411int DYNCOM_TAG(vmrs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2412{
2413 int instr_size = INSTR_SIZE;
2414 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2415 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2416 return instr_size;
2417}
2418#endif
2419#ifdef VFP_DYNCOM_TRANS
2420int DYNCOM_TRANS(vmrs)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2421 //arch_arm_undef(cpu, bb, instr);
2422
2423 Value *data = NULL;
2424 int reg = BITS(16, 19);;
2425 int Rt = BITS(12, 15);
2426 if (reg == 1)
2427 {
2428 if (Rt != 15)
2429 {
2430 LET(Rt, R(VFP_FPSCR));
2431 }
2432 else
2433 {
2434 //LET(Rt, R(VFP_FPSCR));
2435 update_cond_from_fpscr(cpu, instr, bb, pc);
2436 }
2437 }
2438 else
2439 {
2440 switch (reg)
2441 {
2442 case 0:
2443 LET(Rt, R(VFP_FPSID));
2444 break;
2445 case 6:
2446 /* MVFR1, VFPv3 only ? */
2447 LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", Rt);
2448 break;
2449 case 7:
2450 /* MVFR0, VFPv3 only? */
2451 LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", Rt);
2452 break;
2453 case 8:
2454 LET(Rt, R(VFP_FPEXC));
2455 break;
2456 default:
2457 break;
2458 }
2459 }
2460
2461 return No_exp;
2462}
2463#endif
2464
2465/* ----------------------------------------------------------------------- */ 1189/* ----------------------------------------------------------------------- */
2466/* VMOVBCR scalar to register */ 1190/* VMOVBCR scalar to register */
2467/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */ 1191/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */
@@ -2511,26 +1235,6 @@ VMOVBCR_INST:
2511} 1235}
2512#endif 1236#endif
2513 1237
2514#ifdef VFP_DYNCOM_TABLE
2515DYNCOM_FILL_ACTION(vmovbcr),
2516#endif
2517#ifdef VFP_DYNCOM_TAG
2518int DYNCOM_TAG(vmovbcr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2519{
2520 int instr_size = INSTR_SIZE;
2521 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2522 arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
2523 return instr_size;
2524}
2525#endif
2526#ifdef VFP_DYNCOM_TRANS
2527int DYNCOM_TRANS(vmovbcr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2528 LOG_TRACE(Core_ARM11, "\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2529 arch_arm_undef(cpu, bb, instr);
2530 return No_exp;
2531}
2532#endif
2533
2534/* ----------------------------------------------------------------------- */ 1238/* ----------------------------------------------------------------------- */
2535/* MRRC / MCRR instructions */ 1239/* MRRC / MCRR instructions */
2536/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ 1240/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
@@ -2584,39 +1288,6 @@ VMOVBRRSS_INST:
2584 GOTO_NEXT_INST; 1288 GOTO_NEXT_INST;
2585} 1289}
2586#endif 1290#endif
2587#ifdef VFP_DYNCOM_TABLE
2588DYNCOM_FILL_ACTION(vmovbrrss),
2589#endif
2590#ifdef VFP_DYNCOM_TAG
2591int DYNCOM_TAG(vmovbrrss)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2592{
2593 int instr_size = INSTR_SIZE;
2594
2595 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2596 if (instr >> 28 != 0xE)
2597 *tag |= TAG_CONDITIONAL;
2598
2599 return instr_size;
2600}
2601#endif
2602#ifdef VFP_DYNCOM_TRANS
2603int DYNCOM_TRANS(vmovbrrss)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc)
2604{
2605 int to_arm = BIT(20) == 1;
2606 int t = BITS(12, 15);
2607 int t2 = BITS(16, 19);
2608 int n = BIT(5)<<4 | BITS(0, 3);
2609 if (to_arm) {
2610 LET(t, IBITCAST32(FR32(n + 0)));
2611 LET(t2, IBITCAST32(FR32(n + 1)));
2612 }
2613 else {
2614 LETFPS(n + 0, FPBITCAST32(R(t)));
2615 LETFPS(n + 1, FPBITCAST32(R(t2)));
2616 }
2617 return No_exp;
2618}
2619#endif
2620 1291
2621/* ----------------------------------------------------------------------- */ 1292/* ----------------------------------------------------------------------- */
2622/* VMOVBRRD between 2 registers and 1 double */ 1293/* VMOVBRRD between 2 registers and 1 double */
@@ -2667,38 +1338,6 @@ VMOVBRRD_INST:
2667} 1338}
2668#endif 1339#endif
2669 1340
2670#ifdef VFP_DYNCOM_TABLE
2671DYNCOM_FILL_ACTION(vmovbrrd),
2672#endif
2673#ifdef VFP_DYNCOM_TAG
2674int DYNCOM_TAG(vmovbrrd)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2675{
2676 int instr_size = INSTR_SIZE;
2677 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2678 if(instr >> 28 != 0xe)
2679 *tag |= TAG_CONDITIONAL;
2680 return instr_size;
2681}
2682#endif
2683#ifdef VFP_DYNCOM_TRANS
2684int DYNCOM_TRANS(vmovbrrd)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2685 //arch_arm_undef(cpu, bb, instr);
2686 int to_arm = BIT(20) == 1;
2687 int t = BITS(12, 15);
2688 int t2 = BITS(16, 19);
2689 int n = BIT(5)<<4 | BITS(0, 3);
2690 if(to_arm){
2691 LET(t, IBITCAST32(FR32(n * 2)));
2692 LET(t2, IBITCAST32(FR32(n * 2 + 1)));
2693 }
2694 else{
2695 LETFPS(n * 2, FPBITCAST32(R(t)));
2696 LETFPS(n * 2 + 1, FPBITCAST32(R(t2)));
2697 }
2698 return No_exp;
2699}
2700#endif
2701
2702/* ----------------------------------------------------------------------- */ 1341/* ----------------------------------------------------------------------- */
2703/* LDC/STC between 2 registers and 1 double */ 1342/* LDC/STC between 2 registers and 1 double */
2704/* cond 110X XXX1 Rn-- CRd- copr imm- imm- LDC */ 1343/* cond 110X XXX1 Rn-- CRd- copr imm- imm- LDC */
@@ -2764,53 +1403,6 @@ VSTR_INST:
2764} 1403}
2765#endif 1404#endif
2766 1405
2767#ifdef VFP_DYNCOM_TABLE
2768DYNCOM_FILL_ACTION(vstr),
2769#endif
2770#ifdef VFP_DYNCOM_TAG
2771int DYNCOM_TAG(vstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2772{
2773 int instr_size = INSTR_SIZE;
2774 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2775 *tag |= TAG_NEW_BB;
2776 if(instr >> 28 != 0xe)
2777 *tag |= TAG_CONDITIONAL;
2778
2779 return instr_size;
2780}
2781#endif
2782#ifdef VFP_DYNCOM_TRANS
2783int DYNCOM_TRANS(vstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2784 int single = BIT(8) == 0;
2785 int add = BIT(23);
2786 int imm32 = BITS(0,7) << 2;
2787 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
2788 int n = BITS(16, 19);
2789
2790 Value* base = (n == 15) ? ADD(AND(R(n), CONST(0xFFFFFFFC)), CONST(8)): R(n);
2791 Value* Addr = add ? ADD(base, CONST(imm32)) : SUB(base, CONST(imm32));
2792 //if(single)
2793 // bb = arch_check_mm(cpu, bb, Addr, 4, 0, cpu->dyncom_engine->bb_trap);
2794 //else
2795 // bb = arch_check_mm(cpu, bb, Addr, 8, 0, cpu->dyncom_engine->bb_trap);
2796 //Value* phys_addr;
2797 if(single){
2798 //memory_write(cpu, bb, Addr, RSPR(d), 32);
2799 memory_write(cpu, bb, Addr, IBITCAST32(FR32(d)), 32);
2800 bb = cpu->dyncom_engine->bb;
2801 }
2802 else{
2803 //memory_write(cpu, bb, Addr, RSPR(d * 2), 32);
2804 memory_write(cpu, bb, Addr, IBITCAST32(FR32(d * 2)), 32);
2805 bb = cpu->dyncom_engine->bb;
2806 //memory_write(cpu, bb, ADD(Addr, CONST(4)), RSPR(d * 2 + 1), 32);
2807 memory_write(cpu, bb, ADD(Addr, CONST(4)), IBITCAST32(FR32(d * 2 + 1)), 32);
2808 bb = cpu->dyncom_engine->bb;
2809 }
2810 return No_exp;
2811}
2812#endif
2813
2814/* ----------------------------------------------------------------------- */ 1406/* ----------------------------------------------------------------------- */
2815/* VPUSH */ 1407/* VPUSH */
2816/* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */ 1408/* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */
@@ -2873,63 +1465,6 @@ VPUSH_INST:
2873 GOTO_NEXT_INST; 1465 GOTO_NEXT_INST;
2874} 1466}
2875#endif 1467#endif
2876#ifdef VFP_DYNCOM_TABLE
2877DYNCOM_FILL_ACTION(vpush),
2878#endif
2879#ifdef VFP_DYNCOM_TAG
2880int DYNCOM_TAG(vpush)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2881{
2882 int instr_size = INSTR_SIZE;
2883 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
2884 *tag |= TAG_NEW_BB;
2885 if(instr >> 28 != 0xe)
2886 *tag |= TAG_CONDITIONAL;
2887
2888 return instr_size;
2889}
2890#endif
2891#ifdef VFP_DYNCOM_TRANS
2892int DYNCOM_TRANS(vpush)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2893 int single = BIT(8) == 0;
2894 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
2895 int imm32 = BITS(0, 7)<<2;
2896 int regs = (single ? BITS(0, 7) : BITS(1, 7));
2897
2898 Value* Addr = SUB(R(13), CONST(imm32));
2899 //if(single)
2900 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 0, cpu->dyncom_engine->bb_trap);
2901 //else
2902 // bb = arch_check_mm(cpu, bb, Addr, regs * 8, 0, cpu->dyncom_engine->bb_trap);
2903 //Value* phys_addr;
2904
2905 for (int i = 0; i < regs; i++)
2906 {
2907 if (single)
2908 {
2909 //Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]);
2910 //memory_write(cpu, bb, Addr, RSPR(d + i), 32);
2911 memory_write(cpu, bb, Addr, IBITCAST32(FR32(d + i)), 32);
2912 bb = cpu->dyncom_engine->bb;
2913 Addr = ADD(Addr, CONST(4));
2914 }
2915 else
2916 {
2917 /* Careful of endianness, little by default */
2918 //memory_write(cpu, bb, Addr, RSPR((d + i) * 2), 32);
2919 memory_write(cpu, bb, Addr, IBITCAST32(FR32((d + i) * 2)), 32);
2920 bb = cpu->dyncom_engine->bb;
2921 //memory_write(cpu, bb, ADD(Addr, CONST(4)), RSPR((d + i) * 2 + 1), 32);
2922 memory_write(cpu, bb, ADD(Addr, CONST(4)), IBITCAST32(FR32((d + i) * 2 + 1)), 32);
2923 bb = cpu->dyncom_engine->bb;
2924
2925 Addr = ADD(Addr, CONST(8));
2926 }
2927 }
2928 LET(13, SUB(R(13), CONST(imm32)));
2929
2930 return No_exp;
2931}
2932#endif
2933 1468
2934/* ----------------------------------------------------------------------- */ 1469/* ----------------------------------------------------------------------- */
2935/* VSTM */ 1470/* VSTM */
@@ -3004,76 +1539,6 @@ VSTM_INST: /* encoding 1 */
3004} 1539}
3005#endif 1540#endif
3006 1541
3007#ifdef VFP_DYNCOM_TABLE
3008DYNCOM_FILL_ACTION(vstm),
3009#endif
3010#ifdef VFP_DYNCOM_TAG
3011int DYNCOM_TAG(vstm)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3012{
3013 int instr_size = INSTR_SIZE;
3014 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
3015 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
3016 *tag |= TAG_NEW_BB;
3017 if(instr >> 28 != 0xe)
3018 *tag |= TAG_CONDITIONAL;
3019
3020 return instr_size;
3021}
3022#endif
3023#ifdef VFP_DYNCOM_TRANS
3024int DYNCOM_TRANS(vstm)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3025 //arch_arm_undef(cpu, bb, instr);
3026 int single = BIT(8) == 0;
3027 int add = BIT(23);
3028 int wback = BIT(21);
3029 int d = single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4);
3030 int n = BITS(16, 19);
3031 int imm32 = BITS(0, 7)<<2;
3032 int regs = single ? BITS(0, 7) : BITS(1, 7);
3033
3034 Value* Addr = SELECT(CONST1(add), R(n), SUB(R(n), CONST(imm32)));
3035 //if(single)
3036 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 0, cpu->dyncom_engine->bb_trap);
3037 //else
3038 // bb = arch_check_mm(cpu, bb, Addr, regs * 8, 0, cpu->dyncom_engine->bb_trap);
3039
3040 int i;
3041 Value* phys_addr;
3042 for (i = 0; i < regs; i++)
3043 {
3044 if (single)
3045 {
3046 //Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]);
3047 /* if R(i) is R15? */
3048 //memory_write(cpu, bb, Addr, RSPR(d + i), 32);
3049 memory_write(cpu, bb, Addr, IBITCAST32(FR32(d + i)),32);
3050 bb = cpu->dyncom_engine->bb;
3051 Addr = ADD(Addr, CONST(4));
3052 }
3053 else
3054 {
3055 //Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]);
3056 //memory_write(cpu, bb, Addr, RSPR((d + i) * 2), 32);
3057 memory_write(cpu, bb, Addr, IBITCAST32(FR32((d + i) * 2)),32);
3058 bb = cpu->dyncom_engine->bb;
3059
3060 //Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]);
3061 //memory_write(cpu, bb, ADD(Addr, CONST(4)), RSPR((d + i) * 2 + 1), 32);
3062 memory_write(cpu, bb, ADD(Addr, CONST(4)), IBITCAST32(FR32((d + i) * 2 + 1)), 32);
3063 bb = cpu->dyncom_engine->bb;
3064 //addr += 8;
3065 Addr = ADD(Addr, CONST(8));
3066 }
3067 }
3068 if (wback){
3069 //cpu->Reg[n] = (add ? cpu->Reg[n] + imm32 :
3070 // cpu->Reg[n] - imm32);
3071 LET(n, SELECT(CONST1(add), ADD(R(n), CONST(imm32)), SUB(R(n), CONST(imm32))));
3072 }
3073 return No_exp;
3074}
3075#endif
3076
3077/* ----------------------------------------------------------------------- */ 1542/* ----------------------------------------------------------------------- */
3078/* VPOP */ 1543/* VPOP */
3079/* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */ 1544/* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */
@@ -3142,70 +1607,6 @@ VPOP_INST:
3142} 1607}
3143#endif 1608#endif
3144 1609
3145#ifdef VFP_DYNCOM_TABLE
3146DYNCOM_FILL_ACTION(vpop),
3147#endif
3148#ifdef VFP_DYNCOM_TAG
3149int DYNCOM_TAG(vpop)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3150{
3151 int instr_size = INSTR_SIZE;
3152 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
3153 /* Should check if PC is destination register */
3154 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
3155 *tag |= TAG_NEW_BB;
3156 if(instr >> 28 != 0xe)
3157 *tag |= TAG_CONDITIONAL;
3158
3159 return instr_size;
3160}
3161#endif
3162#ifdef VFP_DYNCOM_TRANS
3163int DYNCOM_TRANS(vpop)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3164 //arch_arm_undef(cpu, bb, instr);
3165 int single = BIT(8) == 0;
3166 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
3167 int imm32 = BITS(0, 7)<<2;
3168 int regs = (single ? BITS(0, 7) : BITS(1, 7));
3169
3170 int i;
3171 unsigned int value1, value2;
3172
3173 Value* Addr = R(13);
3174 Value* val;
3175 //if(single)
3176 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 1, cpu->dyncom_engine->bb_trap);
3177 //else
3178 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 1, cpu->dyncom_engine->bb_trap);
3179 //Value* phys_addr;
3180 for (i = 0; i < regs; i++)
3181 {
3182 if (single)
3183 {
3184 memory_read(cpu, bb, Addr, 0, 32);
3185 bb = cpu->dyncom_engine->bb;
3186 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3187 LETFPS(d + i, FPBITCAST32(val));
3188 Addr = ADD(Addr, CONST(4));
3189 }
3190 else
3191 {
3192 /* Careful of endianness, little by default */
3193 memory_read(cpu, bb, Addr, 0, 32);
3194 bb = cpu->dyncom_engine->bb;
3195 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3196 LETFPS((d + i) * 2, FPBITCAST32(val));
3197 memory_read(cpu, bb, ADD(Addr, CONST(4)), 0, 32);
3198 bb = cpu->dyncom_engine->bb;
3199 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3200 LETFPS((d + i) * 2 + 1, FPBITCAST32(val));
3201
3202 Addr = ADD(Addr, CONST(8));
3203 }
3204 }
3205 LET(13, ADD(R(13), CONST(imm32)));
3206 return No_exp;
3207}
3208#endif
3209 1610
3210/* ----------------------------------------------------------------------- */ 1611/* ----------------------------------------------------------------------- */
3211/* VLDR */ 1612/* VLDR */
@@ -3271,67 +1672,6 @@ VLDR_INST:
3271} 1672}
3272#endif 1673#endif
3273 1674
3274#ifdef VFP_DYNCOM_TABLE
3275DYNCOM_FILL_ACTION(vldr),
3276#endif
3277#ifdef VFP_DYNCOM_TAG
3278int DYNCOM_TAG(vldr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3279{
3280 int instr_size = INSTR_SIZE;
3281 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
3282 /* Should check if PC is destination register */
3283 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
3284 *tag |= TAG_NEW_BB;
3285 if(instr >> 28 != 0xe)
3286 *tag |= TAG_CONDITIONAL;
3287
3288 return instr_size;
3289}
3290#endif
3291#ifdef VFP_DYNCOM_TRANS
3292int DYNCOM_TRANS(vldr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3293 int single = BIT(8) == 0;
3294 int add = BIT(23);
3295 int wback = BIT(21);
3296 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
3297 int n = BITS(16, 19);
3298 int imm32 = BITS(0, 7)<<2;
3299 int regs = (single ? BITS(0, 7) : BITS(1, 7));
3300 Value* base = R(n);
3301 if(n == 15){
3302 base = ADD(AND(base, CONST(0xFFFFFFFC)), CONST(8));
3303 }
3304 Value* Addr = add ? (ADD(base, CONST(imm32))) : (SUB(base, CONST(imm32)));
3305 //if(single)
3306 // bb = arch_check_mm(cpu, bb, Addr, 4, 1, cpu->dyncom_engine->bb_trap);
3307 //else
3308 // bb = arch_check_mm(cpu, bb, Addr, 8, 1, cpu->dyncom_engine->bb_trap);
3309 //Value* phys_addr;
3310 Value* val;
3311 if(single){
3312 memory_read(cpu, bb, Addr, 0, 32);
3313 bb = cpu->dyncom_engine->bb;
3314 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3315 //LETS(d, val);
3316 LETFPS(d,FPBITCAST32(val));
3317 }
3318 else{
3319 memory_read(cpu, bb, Addr, 0, 32);
3320 bb = cpu->dyncom_engine->bb;
3321 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3322 //LETS(d * 2, val);
3323 LETFPS(d * 2,FPBITCAST32(val));
3324 memory_read(cpu, bb, ADD(Addr, CONST(4)), 0,32);
3325 bb = cpu->dyncom_engine->bb;
3326 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3327 //LETS(d * 2 + 1, val);
3328 LETFPS( d * 2 + 1,FPBITCAST32(val));
3329 }
3330
3331 return No_exp;
3332}
3333#endif
3334
3335/* ----------------------------------------------------------------------- */ 1675/* ----------------------------------------------------------------------- */
3336/* VLDM */ 1676/* VLDM */
3337/* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */ 1677/* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */
@@ -3403,76 +1743,3 @@ VLDM_INST:
3403 GOTO_NEXT_INST; 1743 GOTO_NEXT_INST;
3404} 1744}
3405#endif 1745#endif
3406
3407#ifdef VFP_DYNCOM_TABLE
3408DYNCOM_FILL_ACTION(vldm),
3409#endif
3410#ifdef VFP_DYNCOM_TAG
3411int DYNCOM_TAG(vldm)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3412{
3413 int instr_size = INSTR_SIZE;
3414 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
3415 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
3416 *tag |= TAG_NEW_BB;
3417 if(instr >> 28 != 0xe)
3418 *tag |= TAG_CONDITIONAL;
3419
3420 return instr_size;
3421}
3422#endif
3423#ifdef VFP_DYNCOM_TRANS
3424int DYNCOM_TRANS(vldm)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3425 int single = BIT(8) == 0;
3426 int add = BIT(23);
3427 int wback = BIT(21);
3428 int d = single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|BIT(22)<<4;
3429 int n = BITS(16, 19);
3430 int imm32 = BITS(0, 7)<<2;
3431 int regs = single ? BITS(0, 7) : BITS(1, 7);
3432
3433 Value* Addr = SELECT(CONST1(add), R(n), SUB(R(n), CONST(imm32)));
3434 //if(single)
3435 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 1, cpu->dyncom_engine->bb_trap);
3436 //else
3437 // bb = arch_check_mm(cpu, bb, Addr, regs * 4, 1, cpu->dyncom_engine->bb_trap);
3438
3439 int i;
3440 //Value* phys_addr;
3441 Value* val;
3442 for (i = 0; i < regs; i++)
3443 {
3444 if (single)
3445 {
3446 //Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]);
3447 /* if R(i) is R15? */
3448 memory_read(cpu, bb, Addr, 0, 32);
3449 bb = cpu->dyncom_engine->bb;
3450 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3451 //LETS(d + i, val);
3452 LETFPS(d + i, FPBITCAST32(val));
3453 Addr = ADD(Addr, CONST(4));
3454 }
3455 else
3456 {
3457 memory_read(cpu, bb, Addr, 0, 32);
3458 bb = cpu->dyncom_engine->bb;
3459 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3460 LETFPS((d + i) * 2, FPBITCAST32(val));
3461 memory_read(cpu, bb, Addr, 0, 32);
3462 bb = cpu->dyncom_engine->bb;
3463 val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
3464 LETFPS((d + i) * 2 + 1, FPBITCAST32(val));
3465
3466 //Memory::Write(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
3467 //addr += 8;
3468 Addr = ADD(Addr, CONST(8));
3469 }
3470 }
3471 if (wback){
3472 //cpu->Reg[n] = (add ? cpu->Reg[n] + imm32 :
3473 // cpu->Reg[n] - imm32);
3474 LET(n, SELECT(CONST1(add), ADD(R(n), CONST(imm32)), SUB(R(n), CONST(imm32))));
3475 }
3476 return No_exp;
3477}
3478#endif
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index b7872bdc4..8b2dfa388 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -419,7 +419,7 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3
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_CFLAG | FPSCR_VFLAG;
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
@@ -428,7 +428,7 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3
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_CFLAG | FPSCR_VFLAG;
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
@@ -441,7 +441,7 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3
441 /* 441 /*
442 * equal 442 * equal
443 */ 443 */
444 ret |= FPSCR_Z | FPSCR_C; 444 ret |= FPSCR_ZFLAG | FPSCR_CFLAG;
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
@@ -450,22 +450,22 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3
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_NFLAG;
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_CFLAG;
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_NFLAG;
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_CFLAG;
469 } 469 }
470 } 470 }
471 return ret; 471 return ret;
@@ -491,46 +491,6 @@ static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32
491 return vfp_compare(state, sd, 1, 0, fpscr); 491 return vfp_compare(state, sd, 1, 0, fpscr);
492} 492}
493 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 } else if (tm & VFP_ZERO)
526 vdd.exponent = 0;
527 else
528 vdd.exponent = vsm.exponent + (1023 - 127);
529pack_nan:
530 vfp_double_normaliseroundintern(state, &vdd, fpscr, exceptions, "fcvtd");
531 return vfp_double_pack(&vdd);
532}
533
534static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr) 494static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr)
535{ 495{
536 struct vfp_single vsm; 496 struct vfp_single vsm;
@@ -981,6 +941,9 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
981 v = vfp_get_float(state, sd); 941 v = vfp_get_float(state, sd);
982 pr_debug("VFP: s%u = %08x\n", sd, v); 942 pr_debug("VFP: s%u = %08x\n", sd, v);
983 vfp_single_unpack(&vsn, v); 943 vfp_single_unpack(&vsn, v);
944 if (vsn.exponent == 0 && vsn.significand != 0)
945 vfp_single_normalise_denormal(&vsn);
946
984 if (negate & NEG_SUBTRACT) 947 if (negate & NEG_SUBTRACT)
985 vsn.sign = vfp_sign_negate(vsn.sign); 948 vsn.sign = vfp_sign_negate(vsn.sign);
986 949
diff --git a/src/core/core.cpp b/src/core/core.cpp
index e9e5c35cc..63be27be2 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -10,7 +10,6 @@
10#include "core/settings.h" 10#include "core/settings.h"
11#include "core/arm/arm_interface.h" 11#include "core/arm/arm_interface.h"
12#include "core/arm/disassembler/arm_disasm.h" 12#include "core/arm/disassembler/arm_disasm.h"
13#include "core/arm/interpreter/arm_interpreter.h"
14#include "core/arm/dyncom/arm_dyncom.h" 13#include "core/arm/dyncom/arm_dyncom.h"
15#include "core/hle/hle.h" 14#include "core/hle/hle.h"
16#include "core/hle/kernel/thread.h" 15#include "core/hle/kernel/thread.h"
@@ -59,17 +58,8 @@ void Stop() {
59int Init() { 58int Init() {
60 LOG_DEBUG(Core, "initialized OK"); 59 LOG_DEBUG(Core, "initialized OK");
61 60
62 g_sys_core = new ARM_Interpreter(); 61 g_sys_core = new ARM_DynCom();
63 62 g_app_core = new ARM_DynCom();
64 switch (Settings::values.cpu_core) {
65 case CPU_Interpreter:
66 g_app_core = new ARM_DynCom();
67 break;
68 case CPU_OldInterpreter:
69 default:
70 g_app_core = new ARM_Interpreter();
71 break;
72 }
73 63
74 return 0; 64 return 0;
75} 65}
diff --git a/src/core/core.h b/src/core/core.h
index 2f5e8bc6b..5e132cb5a 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -12,11 +12,6 @@ class ARM_Interface;
12 12
13namespace Core { 13namespace Core {
14 14
15enum CPUCore {
16 CPU_Interpreter,
17 CPU_OldInterpreter,
18};
19
20struct ThreadContext { 15struct ThreadContext {
21 u32 cpu_registers[13]; 16 u32 cpu_registers[13];
22 u32 sp; 17 u32 sp;
@@ -28,7 +23,6 @@ struct ThreadContext {
28 u32 fpexc; 23 u32 fpexc;
29 24
30 // These are not part of native ThreadContext, but needed by emu 25 // These are not part of native ThreadContext, but needed by emu
31 u32 reg_15;
32 u32 mode; 26 u32 mode;
33}; 27};
34 28
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index 390178f67..43a106549 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -181,20 +181,6 @@ public:
181 } 181 }
182 182
183 /** 183 /**
184 * Tries to open the archive of this type with the specified path
185 * @param path Path to the archive
186 * @return ResultCode of the operation
187 */
188 virtual ResultCode Open(const Path& path) = 0;
189
190 /**
191 * Deletes the archive contents and then re-creates the base folder
192 * @param path Path to the archive
193 * @return ResultCode of the operation, 0 on success
194 */
195 virtual ResultCode Format(const Path& path) const = 0;
196
197 /**
198 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) 184 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
199 */ 185 */
200 virtual std::string GetName() const = 0; 186 virtual std::string GetName() const = 0;
@@ -260,4 +246,29 @@ public:
260 virtual std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const = 0; 246 virtual std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const = 0;
261}; 247};
262 248
249class ArchiveFactory : NonCopyable {
250public:
251 virtual ~ArchiveFactory() {
252 }
253
254 /**
255 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
256 */
257 virtual std::string GetName() const = 0;
258
259 /**
260 * Tries to open the archive of this type with the specified path
261 * @param path Path to the archive
262 * @return An ArchiveBackend corresponding operating specified archive path.
263 */
264 virtual ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) = 0;
265
266 /**
267 * Deletes the archive contents and then re-creates the base folder
268 * @param path Path to the archive
269 * @return ResultCode of the operation, 0 on success
270 */
271 virtual ResultCode Format(const Path& path) = 0;
272};
273
263} // namespace FileSys 274} // namespace FileSys
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp
index 33e4e76f8..0363c9771 100644
--- a/src/core/file_sys/archive_extsavedata.cpp
+++ b/src/core/file_sys/archive_extsavedata.cpp
@@ -6,6 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "common/make_unique.h"
9 10
10#include "core/file_sys/archive_extsavedata.h" 11#include "core/file_sys/archive_extsavedata.h"
11#include "core/file_sys/disk_archive.h" 12#include "core/file_sys/disk_archive.h"
@@ -33,12 +34,12 @@ std::string GetExtDataContainerPath(const std::string& mount_point, bool shared)
33 SYSTEM_ID.c_str(), SDCARD_ID.c_str()); 34 SYSTEM_ID.c_str(), SDCARD_ID.c_str());
34} 35}
35 36
36Archive_ExtSaveData::Archive_ExtSaveData(const std::string& mount_location, bool shared) 37ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, bool shared)
37 : DiskArchive(GetExtDataContainerPath(mount_location, shared)) { 38 : mount_point(GetExtDataContainerPath(mount_location, shared)) {
38 LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); 39 LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str());
39} 40}
40 41
41bool Archive_ExtSaveData::Initialize() { 42bool ArchiveFactory_ExtSaveData::Initialize() {
42 if (!FileUtil::CreateFullPath(mount_point)) { 43 if (!FileUtil::CreateFullPath(mount_point)) {
43 LOG_ERROR(Service_FS, "Unable to create ExtSaveData base path."); 44 LOG_ERROR(Service_FS, "Unable to create ExtSaveData base path.");
44 return false; 45 return false;
@@ -47,18 +48,18 @@ bool Archive_ExtSaveData::Initialize() {
47 return true; 48 return true;
48} 49}
49 50
50ResultCode Archive_ExtSaveData::Open(const Path& path) { 51ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) {
51 std::string fullpath = GetExtSaveDataPath(mount_point, path); 52 std::string fullpath = GetExtSaveDataPath(mount_point, path);
52 if (!FileUtil::Exists(fullpath)) { 53 if (!FileUtil::Exists(fullpath)) {
53 // TODO(Subv): Check error code, this one is probably wrong 54 // TODO(Subv): Check error code, this one is probably wrong
54 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, 55 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
55 ErrorSummary::InvalidState, ErrorLevel::Status); 56 ErrorSummary::InvalidState, ErrorLevel::Status);
56 } 57 }
57 concrete_mount_point = fullpath; 58 auto archive = Common::make_unique<DiskArchive>(fullpath);
58 return RESULT_SUCCESS; 59 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
59} 60}
60 61
61ResultCode Archive_ExtSaveData::Format(const Path& path) const { 62ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path) {
62 std::string fullpath = GetExtSaveDataPath(mount_point, path); 63 std::string fullpath = GetExtSaveDataPath(mount_point, path);
63 FileUtil::CreateFullPath(fullpath); 64 FileUtil::CreateFullPath(fullpath);
64 return RESULT_SUCCESS; 65 return RESULT_SUCCESS;
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h
index 802a11b5f..83c6b0291 100644
--- a/src/core/file_sys/archive_extsavedata.h
+++ b/src/core/file_sys/archive_extsavedata.h
@@ -15,9 +15,9 @@
15namespace FileSys { 15namespace FileSys {
16 16
17/// File system interface to the ExtSaveData archive 17/// File system interface to the ExtSaveData archive
18class Archive_ExtSaveData final : public DiskArchive { 18class ArchiveFactory_ExtSaveData final : public ArchiveFactory {
19public: 19public:
20 Archive_ExtSaveData(const std::string& mount_point, bool shared); 20 ArchiveFactory_ExtSaveData(const std::string& mount_point, bool shared);
21 21
22 /** 22 /**
23 * Initialize the archive. 23 * Initialize the archive.
@@ -25,21 +25,20 @@ public:
25 */ 25 */
26 bool Initialize(); 26 bool Initialize();
27 27
28 ResultCode Open(const Path& path) override;
29 ResultCode Format(const Path& path) const override;
30 std::string GetName() const override { return "ExtSaveData"; } 28 std::string GetName() const override { return "ExtSaveData"; }
31 29
32 const std::string& GetMountPoint() const override { 30 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
33 return concrete_mount_point; 31 ResultCode Format(const Path& path) override;
34 }
35 32
36protected: 33 const std::string& GetMountPoint() const { return mount_point; }
34
35private:
37 /** 36 /**
38 * This holds the full directory path for this archive, it is only set after a successful call to Open, 37 * This holds the full directory path for this archive, it is only set after a successful call
39 * this is formed as <base extsavedatapath>/<type>/<high>/<low>. 38 * to Open, this is formed as <base extsavedatapath>/<type>/<high>/<low>.
40 * See GetExtSaveDataPath for the code that extracts this data from an archive path. 39 * See GetExtSaveDataPath for the code that extracts this data from an archive path.
41 */ 40 */
42 std::string concrete_mount_point; 41 std::string mount_point;
43}; 42};
44 43
45/** 44/**
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index a30f73d0e..bf54a3866 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -15,11 +15,24 @@
15 15
16namespace FileSys { 16namespace FileSys {
17 17
18Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) { 18ArchiveFactory_RomFS::ArchiveFactory_RomFS(const Loader::AppLoader& app_loader)
19 : romfs_data(std::make_shared<std::vector<u8>>()) {
19 // Load the RomFS from the app 20 // Load the RomFS from the app
20 if (Loader::ResultStatus::Success != app_loader.ReadRomFS(raw_data)) { 21 if (Loader::ResultStatus::Success != app_loader.ReadRomFS(*romfs_data)) {
21 LOG_ERROR(Service_FS, "Unable to read RomFS!"); 22 LOG_ERROR(Service_FS, "Unable to read RomFS!");
22 } 23 }
23} 24}
24 25
26ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_RomFS::Open(const Path& path) {
27 auto archive = Common::make_unique<IVFCArchive>(romfs_data);
28 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
29}
30
31ResultCode ArchiveFactory_RomFS::Format(const Path& path) {
32 LOG_ERROR(Service_FS, "Attempted to format a RomFS archive.");
33 // TODO: Verify error code
34 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS,
35 ErrorSummary::NotSupported, ErrorLevel::Permanent);
36}
37
25} // namespace FileSys 38} // namespace FileSys
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index 5cb75e04d..409bc670a 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <memory>
7#include <vector> 8#include <vector>
8 9
9#include "common/common_types.h" 10#include "common/common_types.h"
@@ -17,12 +18,16 @@
17namespace FileSys { 18namespace FileSys {
18 19
19/// File system interface to the RomFS archive 20/// File system interface to the RomFS archive
20class Archive_RomFS final : public IVFCArchive { 21class ArchiveFactory_RomFS final : public ArchiveFactory {
21public: 22public:
22 Archive_RomFS(const Loader::AppLoader& app_loader); 23 ArchiveFactory_RomFS(const Loader::AppLoader& app_loader);
23 24
24 std::string GetName() const override { return "RomFS"; } 25 std::string GetName() const override { return "RomFS"; }
25 ResultCode Open(const Path& path) override { return RESULT_SUCCESS; } 26 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
27 ResultCode Format(const Path& path) override;
28
29private:
30 std::shared_ptr<std::vector<u8>> romfs_data;
26}; 31};
27 32
28} // namespace FileSys 33} // namespace FileSys
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp
index 3baee5294..8496e06f3 100644
--- a/src/core/file_sys/archive_savedata.cpp
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -6,6 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "common/make_unique.h"
9 10
10#include "core/file_sys/archive_savedata.h" 11#include "core/file_sys/archive_savedata.h"
11#include "core/file_sys/disk_archive.h" 12#include "core/file_sys/disk_archive.h"
@@ -28,26 +29,28 @@ static std::string GetSaveDataPath(const std::string& mount_location, u64 progra
28 return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low); 29 return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low);
29} 30}
30 31
31Archive_SaveData::Archive_SaveData(const std::string& sdmc_directory) 32ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory)
32 : DiskArchive(GetSaveDataContainerPath(sdmc_directory)) { 33 : mount_point(GetSaveDataContainerPath(sdmc_directory)) {
33 LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); 34 LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str());
34} 35}
35 36
36ResultCode Archive_SaveData::Open(const Path& path) { 37ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) {
37 if (concrete_mount_point.empty()) 38 std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id);
38 concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id);
39 if (!FileUtil::Exists(concrete_mount_point)) { 39 if (!FileUtil::Exists(concrete_mount_point)) {
40 // When a SaveData archive is created for the first time, it is not yet formatted 40 // When a SaveData archive is created for the first time, it is not yet formatted
41 // and the save file/directory structure expected by the game has not yet been initialized. 41 // and the save file/directory structure expected by the game has not yet been initialized.
42 // Returning the NotFormatted error code will signal the game to provision the SaveData archive 42 // Returning the NotFormatted error code will signal the game to provision the SaveData archive
43 // with the files and folders that it expects. 43 // with the files and folders that it expects.
44 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, 44 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
45 ErrorSummary::InvalidState, ErrorLevel::Status); 45 ErrorSummary::InvalidState, ErrorLevel::Status);
46 } 46 }
47 return RESULT_SUCCESS; 47
48 auto archive = Common::make_unique<DiskArchive>(std::move(concrete_mount_point));
49 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
48} 50}
49 51
50ResultCode Archive_SaveData::Format(const Path& path) const { 52ResultCode ArchiveFactory_SaveData::Format(const Path& path) {
53 std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id);
51 FileUtil::DeleteDirRecursively(concrete_mount_point); 54 FileUtil::DeleteDirRecursively(concrete_mount_point);
52 FileUtil::CreateFullPath(concrete_mount_point); 55 FileUtil::CreateFullPath(concrete_mount_point);
53 return RESULT_SUCCESS; 56 return RESULT_SUCCESS;
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h
index 07c7f7eff..db17afc92 100644
--- a/src/core/file_sys/archive_savedata.h
+++ b/src/core/file_sys/archive_savedata.h
@@ -15,22 +15,17 @@
15namespace FileSys { 15namespace FileSys {
16 16
17/// File system interface to the SaveData archive 17/// File system interface to the SaveData archive
18class Archive_SaveData final : public DiskArchive { 18class ArchiveFactory_SaveData final : public ArchiveFactory {
19public: 19public:
20 Archive_SaveData(const std::string& mount_point); 20 ArchiveFactory_SaveData(const std::string& mount_point);
21 21
22 std::string GetName() const override { return "SaveData"; } 22 std::string GetName() const override { return "SaveData"; }
23 23
24 ResultCode Open(const Path& path) override; 24 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
25 ResultCode Format(const Path& path) override;
25 26
26 ResultCode Format(const Path& path) const override; 27private:
27 28 std::string mount_point;
28 const std::string& GetMountPoint() const override {
29 return concrete_mount_point;
30 }
31
32protected:
33 std::string concrete_mount_point;
34}; 29};
35 30
36} // namespace FileSys 31} // namespace FileSys
diff --git a/src/core/file_sys/archive_savedatacheck.cpp b/src/core/file_sys/archive_savedatacheck.cpp
index a7a507536..47d8a9d25 100644
--- a/src/core/file_sys/archive_savedatacheck.cpp
+++ b/src/core/file_sys/archive_savedatacheck.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/file_util.h" 5#include "common/file_util.h"
6#include "common/make_unique.h"
6 7
7#include "core/file_sys/archive_savedatacheck.h" 8#include "core/file_sys/archive_savedatacheck.h"
8#include "core/hle/service/fs/archive.h" 9#include "core/hle/service/fs/archive.h"
@@ -21,32 +22,33 @@ static std::string GetSaveDataCheckPath(const std::string& mount_point, u32 high
21 mount_point.c_str(), high, low); 22 mount_point.c_str(), high, low);
22} 23}
23 24
24Archive_SaveDataCheck::Archive_SaveDataCheck(const std::string& nand_directory) : 25ArchiveFactory_SaveDataCheck::ArchiveFactory_SaveDataCheck(const std::string& nand_directory) :
25 mount_point(GetSaveDataCheckContainerPath(nand_directory)) { 26 mount_point(GetSaveDataCheckContainerPath(nand_directory)) {
26} 27}
27 28
28ResultCode Archive_SaveDataCheck::Open(const Path& path) { 29ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(const Path& path) {
29 // TODO(Subv): We should not be overwriting raw_data everytime this function is called,
30 // but until we use factory classes to create the archives at runtime instead of creating them beforehand
31 // and allow multiple archives of the same type to be open at the same time without clobbering each other,
32 // we won't be able to maintain the state of each archive, hence we overwrite it every time it's needed.
33 // There are a number of problems with this, for example opening a file in this archive, then opening
34 // this archive again with a different path, will corrupt the previously open file.
35 auto vec = path.AsBinary(); 30 auto vec = path.AsBinary();
36 const u32* data = reinterpret_cast<u32*>(vec.data()); 31 const u32* data = reinterpret_cast<u32*>(vec.data());
37 std::string file_path = GetSaveDataCheckPath(mount_point, data[1], data[0]); 32 std::string file_path = GetSaveDataCheckPath(mount_point, data[1], data[0]);
38 FileUtil::IOFile file(file_path, "rb"); 33 FileUtil::IOFile file(file_path, "rb");
39 34
40 std::fill(raw_data.begin(), raw_data.end(), 0);
41
42 if (!file.IsOpen()) { 35 if (!file.IsOpen()) {
43 return ResultCode(-1); // TODO(Subv): Find the right error code 36 return ResultCode(-1); // TODO(Subv): Find the right error code
44 } 37 }
45 auto size = file.GetSize(); 38 auto size = file.GetSize();
46 raw_data.resize(size); 39 auto raw_data = std::make_shared<std::vector<u8>>(size);
47 file.ReadBytes(raw_data.data(), size); 40 file.ReadBytes(raw_data->data(), size);
48 file.Close(); 41 file.Close();
49 return RESULT_SUCCESS; 42
43 auto archive = Common::make_unique<IVFCArchive>(std::move(raw_data));
44 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
45}
46
47ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path) {
48 LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive.");
49 // TODO: Verify error code
50 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS,
51 ErrorSummary::NotSupported, ErrorLevel::Permanent);
50} 52}
51 53
52} // namespace FileSys 54} // namespace FileSys
diff --git a/src/core/file_sys/archive_savedatacheck.h b/src/core/file_sys/archive_savedatacheck.h
index f6e73e803..f78a6f02e 100644
--- a/src/core/file_sys/archive_savedatacheck.h
+++ b/src/core/file_sys/archive_savedatacheck.h
@@ -17,12 +17,14 @@
17namespace FileSys { 17namespace FileSys {
18 18
19/// File system interface to the SaveDataCheck archive 19/// File system interface to the SaveDataCheck archive
20class Archive_SaveDataCheck final : public IVFCArchive { 20class ArchiveFactory_SaveDataCheck final : public ArchiveFactory {
21public: 21public:
22 Archive_SaveDataCheck(const std::string& mount_point); 22 ArchiveFactory_SaveDataCheck(const std::string& mount_point);
23 23
24 std::string GetName() const override { return "SaveDataCheck"; } 24 std::string GetName() const override { return "SaveDataCheck"; }
25 ResultCode Open(const Path& path) override; 25
26 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
27 ResultCode Format(const Path& path) override;
26 28
27private: 29private:
28 std::string mount_point; 30 std::string mount_point;
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 26b03e82f..92b20c7f6 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -6,6 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "common/make_unique.h"
9 10
10#include "core/file_sys/archive_sdmc.h" 11#include "core/file_sys/archive_sdmc.h"
11#include "core/file_sys/disk_archive.h" 12#include "core/file_sys/disk_archive.h"
@@ -16,17 +17,17 @@
16 17
17namespace FileSys { 18namespace FileSys {
18 19
19Archive_SDMC::Archive_SDMC(const std::string& sdmc_directory) : DiskArchive(sdmc_directory) { 20ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory) : sdmc_directory(sdmc_directory) {
20 LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str()); 21 LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str());
21} 22}
22 23
23bool Archive_SDMC::Initialize() { 24bool ArchiveFactory_SDMC::Initialize() {
24 if (!Settings::values.use_virtual_sd) { 25 if (!Settings::values.use_virtual_sd) {
25 LOG_WARNING(Service_FS, "SDMC disabled by config."); 26 LOG_WARNING(Service_FS, "SDMC disabled by config.");
26 return false; 27 return false;
27 } 28 }
28 29
29 if (!FileUtil::CreateFullPath(mount_point)) { 30 if (!FileUtil::CreateFullPath(sdmc_directory)) {
30 LOG_ERROR(Service_FS, "Unable to create SDMC path."); 31 LOG_ERROR(Service_FS, "Unable to create SDMC path.");
31 return false; 32 return false;
32 } 33 }
@@ -34,4 +35,14 @@ bool Archive_SDMC::Initialize() {
34 return true; 35 return true;
35} 36}
36 37
38ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path) {
39 auto archive = Common::make_unique<DiskArchive>(sdmc_directory);
40 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
41}
42
43ResultCode ArchiveFactory_SDMC::Format(const Path& path) {
44 // This is kind of an undesirable operation, so let's just ignore it. :)
45 return RESULT_SUCCESS;
46}
47
37} // namespace FileSys 48} // namespace FileSys
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 1b801f217..1becf6c0f 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -15,9 +15,9 @@
15namespace FileSys { 15namespace FileSys {
16 16
17/// File system interface to the SDMC archive 17/// File system interface to the SDMC archive
18class Archive_SDMC final : public DiskArchive { 18class ArchiveFactory_SDMC final : public ArchiveFactory {
19public: 19public:
20 Archive_SDMC(const std::string& mount_point); 20 ArchiveFactory_SDMC(const std::string& mount_point);
21 21
22 /** 22 /**
23 * Initialize the archive. 23 * Initialize the archive.
@@ -26,6 +26,12 @@ public:
26 bool Initialize(); 26 bool Initialize();
27 27
28 std::string GetName() const override { return "SDMC"; } 28 std::string GetName() const override { return "SDMC"; }
29
30 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
31 ResultCode Format(const Path& path) override;
32
33private:
34 std::string sdmc_directory;
29}; 35};
30 36
31} // namespace FileSys 37} // namespace FileSys
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp
index c6e033fcd..f53fd57db 100644
--- a/src/core/file_sys/disk_archive.cpp
+++ b/src/core/file_sys/disk_archive.cpp
@@ -18,26 +18,26 @@ namespace FileSys {
18 18
19std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode mode) const { 19std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode mode) const {
20 LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); 20 LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex);
21 auto file = Common::make_unique<DiskFile>(this, path, mode); 21 auto file = Common::make_unique<DiskFile>(*this, path, mode);
22 if (!file->Open()) 22 if (!file->Open())
23 return nullptr; 23 return nullptr;
24 return std::move(file); 24 return std::move(file);
25} 25}
26 26
27bool DiskArchive::DeleteFile(const Path& path) const { 27bool DiskArchive::DeleteFile(const Path& path) const {
28 return FileUtil::Delete(GetMountPoint() + path.AsString()); 28 return FileUtil::Delete(mount_point + path.AsString());
29} 29}
30 30
31bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const { 31bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const {
32 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString()); 32 return FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString());
33} 33}
34 34
35bool DiskArchive::DeleteDirectory(const Path& path) const { 35bool DiskArchive::DeleteDirectory(const Path& path) const {
36 return FileUtil::DeleteDir(GetMountPoint() + path.AsString()); 36 return FileUtil::DeleteDir(mount_point + path.AsString());
37} 37}
38 38
39ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const { 39ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const {
40 std::string full_path = GetMountPoint() + path.AsString(); 40 std::string full_path = mount_point + path.AsString();
41 41
42 if (FileUtil::Exists(full_path)) 42 if (FileUtil::Exists(full_path))
43 return ResultCode(ErrorDescription::AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Info); 43 return ResultCode(ErrorDescription::AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Info);
@@ -58,16 +58,16 @@ ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const {
58 58
59 59
60bool DiskArchive::CreateDirectory(const Path& path) const { 60bool DiskArchive::CreateDirectory(const Path& path) const {
61 return FileUtil::CreateDir(GetMountPoint() + path.AsString()); 61 return FileUtil::CreateDir(mount_point + path.AsString());
62} 62}
63 63
64bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { 64bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const {
65 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString()); 65 return FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString());
66} 66}
67 67
68std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) const { 68std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) const {
69 LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); 69 LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str());
70 auto directory = Common::make_unique<DiskDirectory>(this, path); 70 auto directory = Common::make_unique<DiskDirectory>(*this, path);
71 if (!directory->Open()) 71 if (!directory->Open())
72 return nullptr; 72 return nullptr;
73 return std::move(directory); 73 return std::move(directory);
@@ -75,13 +75,12 @@ std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) c
75 75
76//////////////////////////////////////////////////////////////////////////////////////////////////// 76////////////////////////////////////////////////////////////////////////////////////////////////////
77 77
78DiskFile::DiskFile(const DiskArchive* archive, const Path& path, const Mode mode) { 78DiskFile::DiskFile(const DiskArchive& archive, const Path& path, const Mode mode) {
79 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass 79 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
80 // the root directory we set while opening the archive. 80 // the root directory we set while opening the archive.
81 // For example, opening /../../etc/passwd can give the emulated program your users list. 81 // For example, opening /../../etc/passwd can give the emulated program your users list.
82 this->path = archive->GetMountPoint() + path.AsString(); 82 this->path = archive.mount_point + path.AsString();
83 this->mode.hex = mode.hex; 83 this->mode.hex = mode.hex;
84 this->archive = archive;
85} 84}
86 85
87bool DiskFile::Open() { 86bool DiskFile::Open() {
@@ -134,12 +133,11 @@ bool DiskFile::Close() const {
134 133
135//////////////////////////////////////////////////////////////////////////////////////////////////// 134////////////////////////////////////////////////////////////////////////////////////////////////////
136 135
137DiskDirectory::DiskDirectory(const DiskArchive* archive, const Path& path) { 136DiskDirectory::DiskDirectory(const DiskArchive& archive, const Path& path) {
138 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass 137 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
139 // the root directory we set while opening the archive. 138 // the root directory we set while opening the archive.
140 // For example, opening /../../usr/bin can give the emulated program your installed programs. 139 // For example, opening /../../usr/bin can give the emulated program your installed programs.
141 this->path = archive->GetMountPoint() + path.AsString(); 140 this->path = archive.mount_point + path.AsString();
142 this->archive = archive;
143} 141}
144 142
145bool DiskDirectory::Open() { 143bool DiskDirectory::Open() {
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h
index 3472f6874..dbbdced74 100644
--- a/src/core/file_sys/disk_archive.h
+++ b/src/core/file_sys/disk_archive.h
@@ -24,8 +24,8 @@ class DiskArchive : public ArchiveBackend {
24public: 24public:
25 DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {} 25 DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {}
26 26
27 virtual std::string GetName() const = 0; 27 virtual std::string GetName() const { return "DiskArchive: " + mount_point; }
28 virtual ResultCode Format(const Path& path) const { return RESULT_SUCCESS; } 28
29 std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; 29 std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override;
30 bool DeleteFile(const Path& path) const override; 30 bool DeleteFile(const Path& path) const override;
31 bool RenameFile(const Path& src_path, const Path& dest_path) const override; 31 bool RenameFile(const Path& src_path, const Path& dest_path) const override;
@@ -35,26 +35,17 @@ public:
35 bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; 35 bool RenameDirectory(const Path& src_path, const Path& dest_path) const override;
36 std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; 36 std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override;
37 37
38 virtual ResultCode Open(const Path& path) override {
39 return RESULT_SUCCESS;
40 }
41
42 /**
43 * Getter for the path used for this Archive
44 * @return Mount point of that passthrough archive
45 */
46 virtual const std::string& GetMountPoint() const {
47 return mount_point;
48 }
49
50protected: 38protected:
39 friend class DiskFile;
40 friend class DiskDirectory;
41
51 std::string mount_point; 42 std::string mount_point;
52}; 43};
53 44
54class DiskFile : public FileBackend { 45class DiskFile : public FileBackend {
55public: 46public:
56 DiskFile(); 47 DiskFile();
57 DiskFile(const DiskArchive* archive, const Path& path, const Mode mode); 48 DiskFile(const DiskArchive& archive, const Path& path, const Mode mode);
58 49
59 bool Open() override; 50 bool Open() override;
60 size_t Read(const u64 offset, const u32 length, u8* buffer) const override; 51 size_t Read(const u64 offset, const u32 length, u8* buffer) const override;
@@ -68,7 +59,6 @@ public:
68 } 59 }
69 60
70protected: 61protected:
71 const DiskArchive* archive;
72 std::string path; 62 std::string path;
73 Mode mode; 63 Mode mode;
74 std::unique_ptr<FileUtil::IOFile> file; 64 std::unique_ptr<FileUtil::IOFile> file;
@@ -77,7 +67,7 @@ protected:
77class DiskDirectory : public DirectoryBackend { 67class DiskDirectory : public DirectoryBackend {
78public: 68public:
79 DiskDirectory(); 69 DiskDirectory();
80 DiskDirectory(const DiskArchive* archive, const Path& path); 70 DiskDirectory(const DiskArchive& archive, const Path& path);
81 71
82 ~DiskDirectory() override { 72 ~DiskDirectory() override {
83 Close(); 73 Close();
@@ -91,7 +81,6 @@ public:
91 } 81 }
92 82
93protected: 83protected:
94 const DiskArchive* archive;
95 std::string path; 84 std::string path;
96 u32 total_entries_in_directory; 85 u32 total_entries_in_directory;
97 FileUtil::FSTEntry directory; 86 FileUtil::FSTEntry directory;
diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp
index 68c3c8b81..35aca54fa 100644
--- a/src/core/file_sys/ivfc_archive.cpp
+++ b/src/core/file_sys/ivfc_archive.cpp
@@ -15,11 +15,15 @@
15 15
16namespace FileSys { 16namespace FileSys {
17 17
18IVFCArchive::IVFCArchive() { 18IVFCArchive::IVFCArchive(std::shared_ptr<const std::vector<u8>> data) : data(data) {
19}
20
21std::string IVFCArchive::GetName() const {
22 return "IVFC";
19} 23}
20 24
21std::unique_ptr<FileBackend> IVFCArchive::OpenFile(const Path& path, const Mode mode) const { 25std::unique_ptr<FileBackend> IVFCArchive::OpenFile(const Path& path, const Mode mode) const {
22 return Common::make_unique<IVFCFile>(this); 26 return Common::make_unique<IVFCFile>(data);
23} 27}
24 28
25bool IVFCArchive::DeleteFile(const Path& path) const { 29bool IVFCArchive::DeleteFile(const Path& path) const {
@@ -57,31 +61,25 @@ std::unique_ptr<DirectoryBackend> IVFCArchive::OpenDirectory(const Path& path) c
57 return Common::make_unique<IVFCDirectory>(); 61 return Common::make_unique<IVFCDirectory>();
58} 62}
59 63
60ResultCode IVFCArchive::Format(const Path& path) const {
61 LOG_CRITICAL(Service_FS, "Attempted to format an IVFC archive (%s).", GetName().c_str());
62 // TODO: Verify error code
63 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent);
64}
65
66//////////////////////////////////////////////////////////////////////////////////////////////////// 64////////////////////////////////////////////////////////////////////////////////////////////////////
67 65
68size_t IVFCFile::Read(const u64 offset, const u32 length, u8* buffer) const { 66size_t IVFCFile::Read(const u64 offset, const u32 length, u8* buffer) const {
69 LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); 67 LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length);
70 memcpy(buffer, &archive->raw_data[(u32)offset], length); 68 memcpy(buffer, data->data() + offset, length);
71 return length; 69 return length;
72} 70}
73 71
74size_t IVFCFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { 72size_t IVFCFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const {
75 LOG_CRITICAL(Service_FS, "Attempted to write to IVFC file in archive %s.", archive->GetName().c_str()); 73 LOG_ERROR(Service_FS, "Attempted to write to IVFC file");
76 return 0; 74 return 0;
77} 75}
78 76
79size_t IVFCFile::GetSize() const { 77size_t IVFCFile::GetSize() const {
80 return sizeof(u8) * archive->raw_data.size(); 78 return sizeof(u8) * data->size();
81} 79}
82 80
83bool IVFCFile::SetSize(const u64 size) const { 81bool IVFCFile::SetSize(const u64 size) const {
84 LOG_CRITICAL(Service_FS, "Attempted to set the size of an IVFC file in archive %s", archive->GetName().c_str()); 82 LOG_ERROR(Service_FS, "Attempted to set the size of an IVFC file");
85 return false; 83 return false;
86} 84}
87 85
diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h
index 6f4cc86df..1aff9e0a4 100644
--- a/src/core/file_sys/ivfc_archive.h
+++ b/src/core/file_sys/ivfc_archive.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <memory>
7#include <vector> 8#include <vector>
8 9
9#include "common/common_types.h" 10#include "common/common_types.h"
@@ -23,7 +24,9 @@ namespace FileSys {
23 */ 24 */
24class IVFCArchive : public ArchiveBackend { 25class IVFCArchive : public ArchiveBackend {
25public: 26public:
26 IVFCArchive(); 27 IVFCArchive(std::shared_ptr<const std::vector<u8>> data);
28
29 std::string GetName() const override;
27 30
28 std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; 31 std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override;
29 bool DeleteFile(const Path& path) const override; 32 bool DeleteFile(const Path& path) const override;
@@ -33,16 +36,14 @@ public:
33 bool CreateDirectory(const Path& path) const override; 36 bool CreateDirectory(const Path& path) const override;
34 bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; 37 bool RenameDirectory(const Path& src_path, const Path& dest_path) const override;
35 std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; 38 std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override;
36 ResultCode Format(const Path& path) const override;
37 39
38protected: 40protected:
39 friend class IVFCFile; 41 std::shared_ptr<const std::vector<u8>> data;
40 std::vector<u8> raw_data;
41}; 42};
42 43
43class IVFCFile : public FileBackend { 44class IVFCFile : public FileBackend {
44public: 45public:
45 IVFCFile(const IVFCArchive* archive) : archive(archive) {} 46 IVFCFile(std::shared_ptr<const std::vector<u8>> data) : data(data) {}
46 47
47 bool Open() override { return true; } 48 bool Open() override { return true; }
48 size_t Read(const u64 offset, const u32 length, u8* buffer) const override; 49 size_t Read(const u64 offset, const u32 length, u8* buffer) const override;
@@ -53,7 +54,7 @@ public:
53 void Flush() const override { } 54 void Flush() const override { }
54 55
55private: 56private:
56 const IVFCArchive* archive; 57 std::shared_ptr<const std::vector<u8>> data;
57}; 58};
58 59
59class IVFCDirectory : public DirectoryBackend { 60class IVFCDirectory : public DirectoryBackend {
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 2d01e2ef5..42f8ce2d9 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -15,14 +15,15 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18ResultVal<SharedPtr<AddressArbiter>> AddressArbiter::Create(std::string name) { 18AddressArbiter::AddressArbiter() {}
19AddressArbiter::~AddressArbiter() {}
20
21SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
19 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); 22 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter);
20 // TOOD(yuriks): Don't create Handle (see Thread::Create())
21 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(address_arbiter));
22 23
23 address_arbiter->name = std::move(name); 24 address_arbiter->name = std::move(name);
24 25
25 return MakeResult<SharedPtr<AddressArbiter>>(std::move(address_arbiter)); 26 return address_arbiter;
26} 27}
27 28
28ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, 29ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
@@ -51,7 +52,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
51 case ArbitrationType::WaitIfLessThanWithTimeout: 52 case ArbitrationType::WaitIfLessThanWithTimeout:
52 if ((s32)Memory::Read32(address) <= value) { 53 if ((s32)Memory::Read32(address) <= value) {
53 Kernel::WaitCurrentThread_ArbitrateAddress(address); 54 Kernel::WaitCurrentThread_ArbitrateAddress(address);
54 Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); 55 GetCurrentThread()->WakeAfterDelay(nanoseconds);
55 HLE::Reschedule(__func__); 56 HLE::Reschedule(__func__);
56 } 57 }
57 break; 58 break;
@@ -71,7 +72,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
71 Memory::Write32(address, memory_value); 72 Memory::Write32(address, memory_value);
72 if (memory_value <= value) { 73 if (memory_value <= value) {
73 Kernel::WaitCurrentThread_ArbitrateAddress(address); 74 Kernel::WaitCurrentThread_ArbitrateAddress(address);
74 Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); 75 GetCurrentThread()->WakeAfterDelay(nanoseconds);
75 HLE::Reschedule(__func__); 76 HLE::Reschedule(__func__);
76 } 77 }
77 break; 78 break;
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 638afff9e..8f6a1a8df 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -34,7 +34,7 @@ public:
34 * @param name Optional name used for debugging. 34 * @param name Optional name used for debugging.
35 * @returns The created AddressArbiter. 35 * @returns The created AddressArbiter.
36 */ 36 */
37 static ResultVal<SharedPtr<AddressArbiter>> Create(std::string name = "Unknown"); 37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown");
38 38
39 std::string GetTypeName() const override { return "Arbiter"; } 39 std::string GetTypeName() const override { return "Arbiter"; }
40 std::string GetName() const override { return name; } 40 std::string GetName() const override { return name; }
@@ -47,7 +47,8 @@ public:
47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); 47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
48 48
49private: 49private:
50 AddressArbiter() = default; 50 AddressArbiter();
51 ~AddressArbiter() override;
51}; 52};
52 53
53} // namespace FileSys 54} // namespace FileSys
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index d9ad40c6a..898e1c98f 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -14,16 +14,17 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17ResultVal<SharedPtr<Event>> Event::Create(ResetType reset_type, std::string name) { 17Event::Event() {}
18Event::~Event() {}
19
20SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
18 SharedPtr<Event> evt(new Event); 21 SharedPtr<Event> evt(new Event);
19 // TOOD(yuriks): Don't create Handle (see Thread::Create())
20 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt));
21 22
22 evt->signaled = false; 23 evt->signaled = false;
23 evt->reset_type = evt->intitial_reset_type = reset_type; 24 evt->reset_type = evt->intitial_reset_type = reset_type;
24 evt->name = std::move(name); 25 evt->name = std::move(name);
25 26
26 return MakeResult<SharedPtr<Event>>(evt); 27 return evt;
27} 28}
28 29
29bool Event::ShouldWait() { 30bool Event::ShouldWait() {
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 2c3e6b14e..fba960d2a 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -18,7 +18,7 @@ public:
18 * @param reset_type ResetType describing how to create event 18 * @param reset_type ResetType describing how to create event
19 * @param name Optional name of event 19 * @param name Optional name of event
20 */ 20 */
21 static ResultVal<SharedPtr<Event>> Create(ResetType reset_type, std::string name = "Unknown"); 21 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
22 22
23 std::string GetTypeName() const override { return "Event"; } 23 std::string GetTypeName() const override { return "Event"; }
24 std::string GetName() const override { return name; } 24 std::string GetName() const override { return name; }
@@ -39,7 +39,8 @@ public:
39 void Clear(); 39 void Clear();
40 40
41private: 41private:
42 Event() = default; 42 Event();
43 ~Event() override;
43}; 44};
44 45
45} // namespace 46} // namespace
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index d7fa4dcea..a2ffbcdb7 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -14,14 +14,16 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17unsigned int Object::next_object_id = 0;
18
17SharedPtr<Thread> g_main_thread = nullptr; 19SharedPtr<Thread> g_main_thread = nullptr;
18HandleTable g_handle_table; 20HandleTable g_handle_table;
19u64 g_program_id = 0; 21u64 g_program_id = 0;
20 22
21void WaitObject::AddWaitingThread(Thread* thread) { 23void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
22 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); 24 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
23 if (itr == waiting_threads.end()) 25 if (itr == waiting_threads.end())
24 waiting_threads.push_back(thread); 26 waiting_threads.push_back(std::move(thread));
25} 27}
26 28
27void WaitObject::RemoveWaitingThread(Thread* thread) { 29void WaitObject::RemoveWaitingThread(Thread* thread) {
@@ -30,11 +32,11 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
30 waiting_threads.erase(itr); 32 waiting_threads.erase(itr);
31} 33}
32 34
33Thread* WaitObject::WakeupNextThread() { 35SharedPtr<Thread> WaitObject::WakeupNextThread() {
34 if (waiting_threads.empty()) 36 if (waiting_threads.empty())
35 return nullptr; 37 return nullptr;
36 38
37 auto next_thread = waiting_threads.front(); 39 auto next_thread = std::move(waiting_threads.front());
38 waiting_threads.erase(waiting_threads.begin()); 40 waiting_threads.erase(waiting_threads.begin());
39 41
40 next_thread->ReleaseWaitObject(this); 42 next_thread->ReleaseWaitObject(this);
@@ -74,13 +76,10 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
74 // CTR-OS doesn't use generation 0, so skip straight to 1. 76 // CTR-OS doesn't use generation 0, so skip straight to 1.
75 if (next_generation >= (1 << 15)) next_generation = 1; 77 if (next_generation >= (1 << 15)) next_generation = 1;
76 78
77 Handle handle = generation | (slot << 15);
78 if (obj->handle == INVALID_HANDLE)
79 obj->handle = handle;
80
81 generations[slot] = generation; 79 generations[slot] = generation;
82 objects[slot] = std::move(obj); 80 objects[slot] = std::move(obj);
83 81
82 Handle handle = generation | (slot << 15);
84 return MakeResult<Handle>(handle); 83 return MakeResult<Handle>(handle);
85} 84}
86 85
@@ -98,11 +97,10 @@ ResultCode HandleTable::Close(Handle handle) {
98 return ERR_INVALID_HANDLE; 97 return ERR_INVALID_HANDLE;
99 98
100 size_t slot = GetSlot(handle); 99 size_t slot = GetSlot(handle);
101 u16 generation = GetGeneration(handle);
102 100
103 objects[slot] = nullptr; 101 objects[slot] = nullptr;
104 102
105 generations[generation] = next_free_slot; 103 generations[slot] = next_free_slot;
106 next_free_slot = slot; 104 next_free_slot = slot;
107 return RESULT_SUCCESS; 105 return RESULT_SUCCESS;
108} 106}
@@ -155,12 +153,8 @@ void Shutdown() {
155 * @return True on success, otherwise false 153 * @return True on success, otherwise false
156 */ 154 */
157bool LoadExec(u32 entry_point) { 155bool LoadExec(u32 entry_point) {
158 Core::g_app_core->SetPC(entry_point);
159
160 // 0x30 is the typical main thread priority I've seen used so far 156 // 0x30 is the typical main thread priority I've seen used so far
161 g_main_thread = Kernel::SetupMainThread(0x30, Kernel::DEFAULT_STACK_SIZE); 157 g_main_thread = Kernel::SetupMainThread(Kernel::DEFAULT_STACK_SIZE, entry_point, 0x30);
162 // Setup the idle thread
163 Kernel::SetupIdleThread();
164 158
165 return true; 159 return true;
166} 160}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 9860479ac..4d8e388b6 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -58,14 +58,12 @@ enum {
58 DEFAULT_STACK_SIZE = 0x4000, 58 DEFAULT_STACK_SIZE = 0x4000,
59}; 59};
60 60
61class HandleTable;
62
63class Object : NonCopyable { 61class Object : NonCopyable {
64 friend class HandleTable;
65 u32 handle = INVALID_HANDLE;
66public: 62public:
67 virtual ~Object() {} 63 virtual ~Object() {}
68 Handle GetHandle() const { return handle; } 64
65 /// Returns a unique identifier for the object. For debugging purposes only.
66 unsigned int GetObjectId() const { return object_id; }
69 67
70 virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } 68 virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
71 virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } 69 virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
@@ -101,7 +99,10 @@ private:
101 friend void intrusive_ptr_add_ref(Object*); 99 friend void intrusive_ptr_add_ref(Object*);
102 friend void intrusive_ptr_release(Object*); 100 friend void intrusive_ptr_release(Object*);
103 101
102 static unsigned int next_object_id;
103
104 unsigned int ref_count = 0; 104 unsigned int ref_count = 0;
105 unsigned int object_id = next_object_id++;
105}; 106};
106 107
107// Special functions used by boost::instrusive_ptr to do automatic ref-counting 108// Special functions used by boost::instrusive_ptr to do automatic ref-counting
@@ -135,25 +136,26 @@ public:
135 * Add a thread to wait on this object 136 * Add a thread to wait on this object
136 * @param thread Pointer to thread to add 137 * @param thread Pointer to thread to add
137 */ 138 */
138 void AddWaitingThread(Thread* thread); 139 void AddWaitingThread(SharedPtr<Thread> thread);
139 140
140 /** 141 /**
141 * Removes a thread from waiting on this object (e.g. if it was resumed already) 142 * Removes a thread from waiting on this object (e.g. if it was resumed already)
142 * @param thread Pointer to thread to remove 143 * @param thread Pointer to thread to remove
143 */ 144 */
144 void RemoveWaitingThread(Thread* thead); 145 void RemoveWaitingThread(Thread* thread);
145 146
146 /** 147 /**
147 * Wake up the next thread waiting on this object 148 * Wake up the next thread waiting on this object
148 * @return Pointer to the thread that was resumed, nullptr if no threads are waiting 149 * @return Pointer to the thread that was resumed, nullptr if no threads are waiting
149 */ 150 */
150 Thread* WakeupNextThread(); 151 SharedPtr<Thread> WakeupNextThread();
151 152
152 /// Wake up all threads waiting on this object 153 /// Wake up all threads waiting on this object
153 void WakeupAllWaitingThreads(); 154 void WakeupAllWaitingThreads();
154 155
155private: 156private:
156 std::vector<Thread*> waiting_threads; ///< Threads waiting for this object to become available 157 /// Threads waiting for this object to become available
158 std::vector<SharedPtr<Thread>> waiting_threads;
157}; 159};
158 160
159/** 161/**
@@ -274,7 +276,6 @@ private:
274}; 276};
275 277
276extern HandleTable g_handle_table; 278extern HandleTable g_handle_table;
277extern SharedPtr<Thread> g_main_thread;
278 279
279/// The ID code of the currently running game 280/// The ID code of the currently running game
280/// TODO(Subv): This variable should not be here, 281/// TODO(Subv): This variable should not be here,
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index acf484659..a811db392 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -5,6 +5,8 @@
5#include <map> 5#include <map>
6#include <vector> 6#include <vector>
7 7
8#include <boost/range/algorithm_ext/erase.hpp>
9
8#include "common/common.h" 10#include "common/common.h"
9 11
10#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
@@ -13,16 +15,13 @@
13 15
14namespace Kernel { 16namespace Kernel {
15 17
16typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
17static MutexMap g_mutex_held_locks;
18
19/** 18/**
20 * Resumes a thread waiting for the specified mutex 19 * Resumes a thread waiting for the specified mutex
21 * @param mutex The mutex that some thread is waiting on 20 * @param mutex The mutex that some thread is waiting on
22 */ 21 */
23static void ResumeWaitingThread(Mutex* mutex) { 22static void ResumeWaitingThread(Mutex* mutex) {
24 // Reset mutex lock thread handle, nothing is waiting 23 // Reset mutex lock thread handle, nothing is waiting
25 mutex->locked = false; 24 mutex->lock_count = 0;
26 mutex->holding_thread = nullptr; 25 mutex->holding_thread = nullptr;
27 26
28 // Find the next waiting thread for the mutex... 27 // Find the next waiting thread for the mutex...
@@ -33,24 +32,19 @@ static void ResumeWaitingThread(Mutex* mutex) {
33} 32}
34 33
35void ReleaseThreadMutexes(Thread* thread) { 34void ReleaseThreadMutexes(Thread* thread) {
36 auto locked_range = g_mutex_held_locks.equal_range(thread); 35 for (auto& mtx : thread->held_mutexes) {
37 36 ResumeWaitingThread(mtx.get());
38 // Release every mutex that the thread holds, and resume execution on the waiting threads
39 for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
40 ResumeWaitingThread(iter->second.get());
41 } 37 }
42 38 thread->held_mutexes.clear();
43 // Erase all the locks that this thread holds
44 g_mutex_held_locks.erase(thread);
45} 39}
46 40
47ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) { 41Mutex::Mutex() {}
42Mutex::~Mutex() {}
43
44SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
48 SharedPtr<Mutex> mutex(new Mutex); 45 SharedPtr<Mutex> mutex(new Mutex);
49 // TOOD(yuriks): Don't create Handle (see Thread::Create())
50 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex));
51 46
52 mutex->initial_locked = initial_locked; 47 mutex->lock_count = 0;
53 mutex->locked = false;
54 mutex->name = std::move(name); 48 mutex->name = std::move(name);
55 mutex->holding_thread = nullptr; 49 mutex->holding_thread = nullptr;
56 50
@@ -58,42 +52,40 @@ ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name)
58 if (initial_locked) 52 if (initial_locked)
59 mutex->Acquire(); 53 mutex->Acquire();
60 54
61 return MakeResult<SharedPtr<Mutex>>(mutex); 55 return mutex;
62} 56}
63 57
64bool Mutex::ShouldWait() { 58bool Mutex::ShouldWait() {
65 return locked && holding_thread != GetCurrentThread(); 59 return lock_count > 0 && holding_thread != GetCurrentThread();;
66} 60}
67 61
68void Mutex::Acquire() { 62void Mutex::Acquire() {
69 Acquire(GetCurrentThread()); 63 Acquire(GetCurrentThread());
70} 64}
71 65
72void Mutex::Acquire(Thread* thread) { 66void Mutex::Acquire(SharedPtr<Thread> thread) {
73 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); 67 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
74 if (locked)
75 return;
76 68
77 locked = true; 69 // Actually "acquire" the mutex only if we don't already have it...
70 if (lock_count == 0) {
71 thread->held_mutexes.insert(this);
72 holding_thread = std::move(thread);
73 }
78 74
79 g_mutex_held_locks.insert(std::make_pair(thread, this)); 75 lock_count++;
80 holding_thread = thread;
81} 76}
82 77
83void Mutex::Release() { 78void Mutex::Release() {
84 if (!locked) 79 // Only release if the mutex is held...
85 return; 80 if (lock_count > 0) {
86 81 lock_count--;
87 auto locked_range = g_mutex_held_locks.equal_range(holding_thread); 82
88 83 // Yield to the next thread only if we've fully released the mutex...
89 for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) { 84 if (lock_count == 0) {
90 if (iter->second == this) { 85 holding_thread->held_mutexes.erase(this);
91 g_mutex_held_locks.erase(iter); 86 ResumeWaitingThread(this);
92 break;
93 } 87 }
94 } 88 }
95
96 ResumeWaitingThread(this);
97} 89}
98 90
99} // namespace 91} // namespace
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 1e69528f1..d6d5328be 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -22,7 +22,7 @@ public:
22 * @param name Optional name of mutex 22 * @param name Optional name of mutex
23 * @return Pointer to new Mutex object 23 * @return Pointer to new Mutex object
24 */ 24 */
25 static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown"); 25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
26 26
27 std::string GetTypeName() const override { return "Mutex"; } 27 std::string GetTypeName() const override { return "Mutex"; }
28 std::string GetName() const override { return name; } 28 std::string GetName() const override { return name; }
@@ -30,8 +30,7 @@ public:
30 static const HandleType HANDLE_TYPE = HandleType::Mutex; 30 static const HandleType HANDLE_TYPE = HandleType::Mutex;
31 HandleType GetHandleType() const override { return HANDLE_TYPE; } 31 HandleType GetHandleType() const override { return HANDLE_TYPE; }
32 32
33 bool initial_locked; ///< Initial lock state when mutex was created 33 int lock_count; ///< Number of times the mutex has been acquired
34 bool locked; ///< Current locked state
35 std::string name; ///< Name of mutex (optional) 34 std::string name; ///< Name of mutex (optional)
36 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex 35 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
37 36
@@ -43,11 +42,12 @@ public:
43 * @param mutex Mutex that is to be acquired 42 * @param mutex Mutex that is to be acquired
44 * @param thread Thread that will acquire the mutex 43 * @param thread Thread that will acquire the mutex
45 */ 44 */
46 void Acquire(Thread* thread); 45 void Acquire(SharedPtr<Thread> thread);
47 void Release(); 46 void Release();
48 47
49private: 48private:
50 Mutex() = default; 49 Mutex();
50 ~Mutex() override;
51}; 51};
52 52
53/** 53/**
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index a9e406ef4..c8cf8b9a2 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -10,6 +10,9 @@
10 10
11namespace Kernel { 11namespace Kernel {
12 12
13Semaphore::Semaphore() {}
14Semaphore::~Semaphore() {}
15
13ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, 16ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
14 std::string name) { 17 std::string name) {
15 18
@@ -18,8 +21,6 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_cou
18 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 21 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
19 22
20 SharedPtr<Semaphore> semaphore(new Semaphore); 23 SharedPtr<Semaphore> semaphore(new Semaphore);
21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore));
23 24
24 // When the semaphore is created, some slots are reserved for other threads, 25 // When the semaphore is created, some slots are reserved for other threads,
25 // and the rest is reserved for the caller thread 26 // and the rest is reserved for the caller thread
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 9bb404ab6..d8dc1fd78 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -47,7 +47,8 @@ public:
47 ResultVal<s32> Release(s32 release_count); 47 ResultVal<s32> Release(s32 release_count);
48 48
49private: 49private:
50 Semaphore() = default; 50 Semaphore();
51 ~Semaphore() override;
51}; 52};
52 53
53} // namespace 54} // namespace
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp
new file mode 100644
index 000000000..0594967f8
--- /dev/null
+++ b/src/core/hle/kernel/session.cpp
@@ -0,0 +1,13 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/session.h"
6#include "core/hle/kernel/thread.h"
7
8namespace Kernel {
9
10Session::Session() {}
11Session::~Session() {}
12
13}
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 1788e4375..7cc9332c9 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
8#include "core/mem_map.h"
8 9
9namespace Kernel { 10namespace Kernel {
10 11
@@ -43,6 +44,9 @@ inline static u32* GetCommandBuffer(const int offset=0) {
43 */ 44 */
44class Session : public WaitObject { 45class Session : public WaitObject {
45public: 46public:
47 Session();
48 ~Session() override;
49
46 std::string GetTypeName() const override { return "Session"; } 50 std::string GetTypeName() const override { return "Session"; }
47 51
48 static const HandleType HANDLE_TYPE = HandleType::Session; 52 static const HandleType HANDLE_TYPE = HandleType::Session;
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 536d134b0..4211fcf04 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -9,30 +9,31 @@
9 9
10namespace Kernel { 10namespace Kernel {
11 11
12ResultVal<SharedPtr<SharedMemory>> SharedMemory::Create(std::string name) { 12SharedMemory::SharedMemory() {}
13 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 13SharedMemory::~SharedMemory() {}
14 14
15 // TOOD(yuriks): Don't create Handle (see Thread::Create()) 15SharedPtr<SharedMemory> SharedMemory::Create(std::string name) {
16 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory)); 16 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
17 17
18 shared_memory->name = std::move(name); 18 shared_memory->name = std::move(name);
19 return MakeResult<SharedPtr<SharedMemory>>(std::move(shared_memory)); 19
20 return shared_memory;
20} 21}
21 22
22ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, 23ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
23 MemoryPermission other_permissions) { 24 MemoryPermission other_permissions) {
24 25
25 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { 26 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
26 LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", 27 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X outside of shared mem bounds!",
27 GetHandle(), address); 28 GetObjectId(), address);
28 // TODO: Verify error code with hardware 29 // TODO: Verify error code with hardware
29 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 30 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
30 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 31 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
31 } 32 }
32 33
33 base_address = address; 34 this->base_address = address;
34 permissions = permissions; 35 this->permissions = permissions;
35 other_permissions = other_permissions; 36 this->other_permissions = other_permissions;
36 37
37 return RESULT_SUCCESS; 38 return RESULT_SUCCESS;
38} 39}
@@ -41,7 +42,7 @@ ResultVal<u8*> SharedMemory::GetPointer(u32 offset) {
41 if (base_address != 0) 42 if (base_address != 0)
42 return MakeResult<u8*>(Memory::GetPointer(base_address + offset)); 43 return MakeResult<u8*>(Memory::GetPointer(base_address + offset));
43 44
44 LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle()); 45 LOG_ERROR(Kernel_SVC, "memory block id=%u not mapped!", GetObjectId());
45 // TODO(yuriks): Verify error code. 46 // TODO(yuriks): Verify error code.
46 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 47 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
47 ErrorSummary::InvalidState, ErrorLevel::Permanent); 48 ErrorSummary::InvalidState, ErrorLevel::Permanent);
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index f9ae23e93..5833b411c 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -29,7 +29,7 @@ public:
29 * Creates a shared memory object 29 * Creates a shared memory object
30 * @param name Optional object name, used only for debugging purposes. 30 * @param name Optional object name, used only for debugging purposes.
31 */ 31 */
32 static ResultVal<SharedPtr<SharedMemory>> Create(std::string name = "Unknown"); 32 static SharedPtr<SharedMemory> Create(std::string name = "Unknown");
33 33
34 std::string GetTypeName() const override { return "SharedMemory"; } 34 std::string GetTypeName() const override { return "SharedMemory"; }
35 35
@@ -51,13 +51,14 @@ public:
51 */ 51 */
52 ResultVal<u8*> GetPointer(u32 offset = 0); 52 ResultVal<u8*> GetPointer(u32 offset = 0);
53 53
54 VAddr base_address; ///< Address of shared memory block in RAM 54 VAddr base_address; ///< Address of shared memory block in RAM
55 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field) 55 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field)
56 MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field) 56 MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field)
57 std::string name; ///< Name of shared memory object (optional) 57 std::string name; ///< Name of shared memory object (optional)
58 58
59private: 59private:
60 SharedMemory() = default; 60 SharedMemory();
61 ~SharedMemory() override;
61}; 62};
62 63
63} // namespace 64} // namespace
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 03b492c75..7f629c20e 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -4,7 +4,6 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <list> 6#include <list>
7#include <map>
8#include <vector> 7#include <vector>
9 8
10#include "common/common.h" 9#include "common/common.h"
@@ -22,8 +21,11 @@
22 21
23namespace Kernel { 22namespace Kernel {
24 23
24/// Event type for the thread wake up event
25static int ThreadWakeupEventType = -1;
26
25bool Thread::ShouldWait() { 27bool Thread::ShouldWait() {
26 return status != THREADSTATUS_DORMANT; 28 return status != THREADSTATUS_DEAD;
27} 29}
28 30
29void Thread::Acquire() { 31void Thread::Acquire() {
@@ -34,94 +36,75 @@ void Thread::Acquire() {
34static std::vector<SharedPtr<Thread>> thread_list; 36static std::vector<SharedPtr<Thread>> thread_list;
35 37
36// Lists only ready thread ids. 38// Lists only ready thread ids.
37static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue; 39static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> ready_queue;
38 40
39static Thread* current_thread; 41static Thread* current_thread;
40 42
41static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup 43// The first available thread id at startup
42static u32 next_thread_id; ///< The next available thread id 44static u32 next_thread_id = 1;
43 45
44Thread* GetCurrentThread() { 46/**
45 return current_thread; 47 * Creates a new thread ID
48 * @return The new thread ID
49 */
50inline static u32 const NewThreadId() {
51 return next_thread_id++;
46} 52}
47 53
48/// Resets a thread 54Thread::Thread() {}
49static void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { 55Thread::~Thread() {}
50 memset(&t->context, 0, sizeof(Core::ThreadContext));
51 56
52 t->context.cpu_registers[0] = arg; 57Thread* GetCurrentThread() {
53 t->context.pc = t->context.reg_15 = t->entry_point; 58 return current_thread;
54 t->context.sp = t->stack_top;
55 t->context.cpsr = 0x1F; // Usermode
56
57 // TODO(bunnei): This instructs the CPU core to start the execution as if it is "resuming" a
58 // thread. This is somewhat Sky-Eye specific, and should be re-architected in the future to be
59 // agnostic of the CPU core.
60 t->context.mode = 8;
61
62 if (t->current_priority < lowest_priority) {
63 t->current_priority = t->initial_priority;
64 }
65
66 t->wait_objects.clear();
67 t->wait_address = 0;
68}
69
70/// Change a thread to "ready" state
71static void ChangeReadyState(Thread* t, bool ready) {
72 if (t->IsReady()) {
73 if (!ready) {
74 thread_ready_queue.remove(t->current_priority, t);
75 }
76 } else if (ready) {
77 if (t->IsRunning()) {
78 thread_ready_queue.push_front(t->current_priority, t);
79 } else {
80 thread_ready_queue.push_back(t->current_priority, t);
81 }
82 t->status = THREADSTATUS_READY;
83 }
84} 59}
85 60
86/// Check if a thread is waiting on a the specified wait object 61/**
62 * Check if a thread is waiting on the specified wait object
63 * @param thread The thread to test
64 * @param wait_object The object to test against
65 * @return True if the thread is waiting, false otherwise
66 */
87static bool CheckWait_WaitObject(const Thread* thread, WaitObject* wait_object) { 67static bool CheckWait_WaitObject(const Thread* thread, WaitObject* wait_object) {
88 auto itr = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object); 68 if (thread->status != THREADSTATUS_WAIT_SYNCH)
69 return false;
89 70
90 if (itr != thread->wait_objects.end()) 71 auto itr = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object);
91 return thread->IsWaiting(); 72 return itr != thread->wait_objects.end();
92
93 return false;
94} 73}
95 74
96/// Check if the specified thread is waiting on the specified address to be arbitrated 75/**
76 * Check if the specified thread is waiting on the specified address to be arbitrated
77 * @param thread The thread to test
78 * @param wait_address The address to test against
79 * @return True if the thread is waiting, false otherwise
80 */
97static bool CheckWait_AddressArbiter(const Thread* thread, VAddr wait_address) { 81static bool CheckWait_AddressArbiter(const Thread* thread, VAddr wait_address) {
98 return thread->IsWaiting() && thread->wait_objects.empty() && wait_address == thread->wait_address; 82 return thread->status == THREADSTATUS_WAIT_ARB && wait_address == thread->wait_address;
99} 83}
100 84
101/// Stops the current thread 85void Thread::Stop() {
102void Thread::Stop(const char* reason) {
103 // Release all the mutexes that this thread holds 86 // Release all the mutexes that this thread holds
104 ReleaseThreadMutexes(this); 87 ReleaseThreadMutexes(this);
105 88
106 ChangeReadyState(this, false); 89 // Cancel any outstanding wakeup events for this thread
107 status = THREADSTATUS_DORMANT; 90 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
108 WakeupAllWaitingThreads();
109 91
110 // Stopped threads are never waiting. 92 // Clean up thread from ready queue
111 wait_objects.clear(); 93 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
112 wait_address = 0; 94 if (status == THREADSTATUS_READY){
113} 95 ready_queue.remove(current_priority, this);
96 }
114 97
115/// Changes a threads state 98 status = THREADSTATUS_DEAD;
116static void ChangeThreadState(Thread* t, ThreadStatus new_status) { 99
117 if (!t || t->status == new_status) { 100 WakeupAllWaitingThreads();
118 return; 101
102 // Clean up any dangling references in objects that this thread was waiting for
103 for (auto& wait_object : wait_objects) {
104 wait_object->RemoveWaitingThread(this);
119 } 105 }
120 ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0);
121 t->status = new_status;
122} 106}
123 107
124/// Arbitrate the highest priority thread that is waiting
125Thread* ArbitrateHighestPriorityThread(u32 address) { 108Thread* ArbitrateHighestPriorityThread(u32 address) {
126 Thread* highest_priority_thread = nullptr; 109 Thread* highest_priority_thread = nullptr;
127 s32 priority = THREADPRIO_LOWEST; 110 s32 priority = THREADPRIO_LOWEST;
@@ -148,118 +131,124 @@ Thread* ArbitrateHighestPriorityThread(u32 address) {
148 return highest_priority_thread; 131 return highest_priority_thread;
149} 132}
150 133
151/// Arbitrate all threads currently waiting
152void ArbitrateAllThreads(u32 address) { 134void ArbitrateAllThreads(u32 address) {
153 135 // Resume all threads found to be waiting on the address
154 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
155 for (auto& thread : thread_list) { 136 for (auto& thread : thread_list) {
156 if (CheckWait_AddressArbiter(thread.get(), address)) 137 if (CheckWait_AddressArbiter(thread.get(), address))
157 thread->ResumeFromWait(); 138 thread->ResumeFromWait();
158 } 139 }
159} 140}
160 141
161/// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields) 142/**
162static void CallThread(Thread* t) { 143 * Switches the CPU's active thread context to that of the specified thread
163 // Stop waiting 144 * @param new_thread The thread to switch to
164 ChangeThreadState(t, THREADSTATUS_READY); 145 */
165} 146static void SwitchContext(Thread* new_thread) {
147 _dbg_assert_msg_(Kernel, new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running.");
166 148
167/// Switches CPU context to that of the specified thread 149 Thread* previous_thread = GetCurrentThread();
168static void SwitchContext(Thread* t) {
169 Thread* cur = GetCurrentThread();
170 150
171 // Save context for current thread 151 // Save context for previous thread
172 if (cur) { 152 if (previous_thread) {
173 Core::g_app_core->SaveContext(cur->context); 153 Core::g_app_core->SaveContext(previous_thread->context);
174 154
175 if (cur->IsRunning()) { 155 if (previous_thread->status == THREADSTATUS_RUNNING) {
176 ChangeReadyState(cur, true); 156 // This is only the case when a reschedule is triggered without the current thread
157 // yielding execution (i.e. an event triggered, system core time-sliced, etc)
158 ready_queue.push_front(previous_thread->current_priority, previous_thread);
159 previous_thread->status = THREADSTATUS_READY;
177 } 160 }
178 } 161 }
162
179 // Load context of new thread 163 // Load context of new thread
180 if (t) { 164 if (new_thread) {
181 current_thread = t; 165 current_thread = new_thread;
182 ChangeReadyState(t, false); 166
183 t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; 167 ready_queue.remove(new_thread->current_priority, new_thread);
184 Core::g_app_core->LoadContext(t->context); 168 new_thread->status = THREADSTATUS_RUNNING;
169
170 Core::g_app_core->LoadContext(new_thread->context);
185 } else { 171 } else {
186 current_thread = nullptr; 172 current_thread = nullptr;
187 } 173 }
188} 174}
189 175
190/// Gets the next thread that is ready to be run by priority 176/**
191static Thread* NextThread() { 177 * Pops and returns the next thread from the thread queue
178 * @return A pointer to the next ready thread
179 */
180static Thread* PopNextReadyThread() {
192 Thread* next; 181 Thread* next;
193 Thread* cur = GetCurrentThread(); 182 Thread* thread = GetCurrentThread();
194 183
195 if (cur && cur->IsRunning()) { 184 if (thread && thread->status == THREADSTATUS_RUNNING) {
196 next = thread_ready_queue.pop_first_better(cur->current_priority); 185 // We have to do better than the current thread.
186 // This call returns null when that's not possible.
187 next = ready_queue.pop_first_better(thread->current_priority);
197 } else { 188 } else {
198 next = thread_ready_queue.pop_first(); 189 next = ready_queue.pop_first();
199 }
200 if (next == 0) {
201 return nullptr;
202 } 190 }
191
203 return next; 192 return next;
204} 193}
205 194
206void WaitCurrentThread_Sleep() { 195void WaitCurrentThread_Sleep() {
207 Thread* thread = GetCurrentThread(); 196 Thread* thread = GetCurrentThread();
208 ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); 197 thread->status = THREADSTATUS_WAIT_SLEEP;
209} 198}
210 199
211void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bool wait_set_output, bool wait_all) { 200void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all) {
212 Thread* thread = GetCurrentThread(); 201 Thread* thread = GetCurrentThread();
213 thread->wait_set_output = wait_set_output; 202 thread->wait_set_output = wait_set_output;
214 thread->wait_all = wait_all; 203 thread->wait_all = wait_all;
215 204 thread->wait_objects = std::move(wait_objects);
216 // It's possible to call WaitSynchronizationN without any objects passed in... 205 thread->status = THREADSTATUS_WAIT_SYNCH;
217 if (wait_object != nullptr)
218 thread->wait_objects.push_back(wait_object);
219
220 ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
221} 206}
222 207
223void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { 208void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) {
224 Thread* thread = GetCurrentThread(); 209 Thread* thread = GetCurrentThread();
225 thread->wait_address = wait_address; 210 thread->wait_address = wait_address;
226 ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); 211 thread->status = THREADSTATUS_WAIT_ARB;
227} 212}
228 213
229/// Event type for the thread wake up event 214// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
230static int ThreadWakeupEventType = -1; 215// us to simply use a pool index or similar.
231 216static Kernel::HandleTable wakeup_callback_handle_table;
232/// Callback that will wake up the thread it was scheduled for 217
233static void ThreadWakeupCallback(u64 parameter, int cycles_late) { 218/**
234 Handle handle = static_cast<Handle>(parameter); 219 * Callback that will wake up the thread it was scheduled for
235 SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle); 220 * @param thread_handle The handle of the thread that's been awoken
221 * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
222 */
223static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
224 SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle);
236 if (thread == nullptr) { 225 if (thread == nullptr) {
237 LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); 226 LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", (Handle)thread_handle);
238 return; 227 return;
239 } 228 }
240 229
241 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 230 if (thread->status == THREADSTATUS_WAIT_SYNCH) {
242 ErrorSummary::StatusChanged, ErrorLevel::Info)); 231 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
232 ErrorSummary::StatusChanged, ErrorLevel::Info));
243 233
244 if (thread->wait_set_output) 234 if (thread->wait_set_output)
245 thread->SetWaitSynchronizationOutput(-1); 235 thread->SetWaitSynchronizationOutput(-1);
236 }
246 237
247 thread->ResumeFromWait(); 238 thread->ResumeFromWait();
248} 239}
249 240
250 241void Thread::WakeAfterDelay(s64 nanoseconds) {
251void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) {
252 // Don't schedule a wakeup if the thread wants to wait forever 242 // Don't schedule a wakeup if the thread wants to wait forever
253 if (nanoseconds == -1) 243 if (nanoseconds == -1)
254 return; 244 return;
255 _dbg_assert_(Kernel, thread != nullptr);
256 245
257 u64 microseconds = nanoseconds / 1000; 246 u64 microseconds = nanoseconds / 1000;
258 CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle()); 247 CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, callback_handle);
259} 248}
260 249
261void Thread::ReleaseWaitObject(WaitObject* wait_object) { 250void Thread::ReleaseWaitObject(WaitObject* wait_object) {
262 if (wait_objects.empty()) { 251 if (status != THREADSTATUS_WAIT_SYNCH || wait_objects.empty()) {
263 LOG_CRITICAL(Kernel, "thread is not waiting on any objects!"); 252 LOG_CRITICAL(Kernel, "thread is not waiting on any objects!");
264 return; 253 return;
265 } 254 }
@@ -301,49 +290,56 @@ void Thread::ReleaseWaitObject(WaitObject* wait_object) {
301} 290}
302 291
303void Thread::ResumeFromWait() { 292void Thread::ResumeFromWait() {
304 // Cancel any outstanding wakeup events 293 // Cancel any outstanding wakeup events for this thread
305 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle()); 294 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
306 295
307 status &= ~THREADSTATUS_WAIT; 296 switch (status) {
308 297 case THREADSTATUS_WAIT_SYNCH:
309 // Remove this thread from all other WaitObjects 298 // Remove this thread from all other WaitObjects
310 for (auto wait_object : wait_objects) 299 for (auto wait_object : wait_objects)
311 wait_object->RemoveWaitingThread(this); 300 wait_object->RemoveWaitingThread(this);
312 301 break;
313 wait_objects.clear(); 302 case THREADSTATUS_WAIT_ARB:
314 wait_set_output = false; 303 case THREADSTATUS_WAIT_SLEEP:
315 wait_all = false; 304 break;
316 wait_address = 0; 305 case THREADSTATUS_RUNNING:
317 306 case THREADSTATUS_READY:
318 if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { 307 LOG_ERROR(Kernel, "Thread with object id %u has already resumed.", GetObjectId());
319 ChangeReadyState(this, true); 308 _dbg_assert_(Kernel, false);
309 return;
310 case THREADSTATUS_DEAD:
311 // This should never happen, as threads must complete before being stopped.
312 LOG_CRITICAL(Kernel, "Thread with object id %u cannot be resumed because it's DEAD.",
313 GetObjectId());
314 _dbg_assert_(Kernel, false);
315 return;
320 } 316 }
317
318 ready_queue.push_back(current_priority, this);
319 status = THREADSTATUS_READY;
321} 320}
322 321
323/// Prints the thread queue for debugging purposes 322/**
323 * Prints the thread queue for debugging purposes
324 */
324static void DebugThreadQueue() { 325static void DebugThreadQueue() {
325 Thread* thread = GetCurrentThread(); 326 Thread* thread = GetCurrentThread();
326 if (!thread) { 327 if (!thread) {
327 return; 328 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD");
329 } else {
330 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId());
328 } 331 }
329 LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); 332
330 for (auto& t : thread_list) { 333 for (auto& t : thread_list) {
331 s32 priority = thread_ready_queue.contains(t.get()); 334 s32 priority = ready_queue.contains(t.get());
332 if (priority != -1) { 335 if (priority != -1) {
333 LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle()); 336 LOG_DEBUG(Kernel, "0x%02X %u", priority, t->GetObjectId());
334 } 337 }
335 } 338 }
336} 339}
337 340
338ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, 341ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority,
339 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size) { 342 u32 arg, s32 processor_id, VAddr stack_top) {
340 if (stack_size < 0x200) {
341 LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name.c_str(), stack_size);
342 // TODO: Verify error
343 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Kernel,
344 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
345 }
346
347 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 343 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
348 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 344 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
349 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 345 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d",
@@ -362,22 +358,13 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
362 358
363 SharedPtr<Thread> thread(new Thread); 359 SharedPtr<Thread> thread(new Thread);
364 360
365 // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for
366 // the time being. Create a handle here, it will be copied to the handle field in
367 // the object and use by the rest of the code. This should be removed when other
368 // code doesn't rely on the handle anymore.
369 ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread);
370 if (handle.Failed())
371 return handle.Code();
372
373 thread_list.push_back(thread); 361 thread_list.push_back(thread);
374 thread_ready_queue.prepare(priority); 362 ready_queue.prepare(priority);
375 363
376 thread->thread_id = next_thread_id++; 364 thread->thread_id = NewThreadId();
377 thread->status = THREADSTATUS_DORMANT; 365 thread->status = THREADSTATUS_DORMANT;
378 thread->entry_point = entry_point; 366 thread->entry_point = entry_point;
379 thread->stack_top = stack_top; 367 thread->stack_top = stack_top;
380 thread->stack_size = stack_size;
381 thread->initial_priority = thread->current_priority = priority; 368 thread->initial_priority = thread->current_priority = priority;
382 thread->processor_id = processor_id; 369 thread->processor_id = processor_id;
383 thread->wait_set_output = false; 370 thread->wait_set_output = false;
@@ -385,88 +372,86 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
385 thread->wait_objects.clear(); 372 thread->wait_objects.clear();
386 thread->wait_address = 0; 373 thread->wait_address = 0;
387 thread->name = std::move(name); 374 thread->name = std::move(name);
375 thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom();
376
377 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
378 // to initialize the context
379 Core::g_app_core->ResetContext(thread->context, stack_top, entry_point, arg);
388 380
389 ResetThread(thread.get(), arg, 0); 381 ready_queue.push_back(thread->current_priority, thread.get());
390 CallThread(thread.get()); 382 thread->status = THREADSTATUS_READY;
391 383
392 return MakeResult<SharedPtr<Thread>>(std::move(thread)); 384 return MakeResult<SharedPtr<Thread>>(std::move(thread));
393} 385}
394 386
395/// Set the priority of the thread specified by handle 387// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be returned.
396void Thread::SetPriority(s32 priority) { 388static void ClampPriority(const Thread* thread, s32* priority) {
397 // If priority is invalid, clamp to valid range 389 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) {
398 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 390 _dbg_assert_msg_(Kernel, false, "Application passed an out of range priority. An error should be returned.");
399 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 391
400 LOG_WARNING(Kernel_SVC, "invalid priority=%d, clamping to %d", priority, new_priority); 392 s32 new_priority = CLAMP(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
393 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d",
394 thread->name.c_str(), *priority, new_priority);
401 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm 395 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
402 // validity of this 396 // validity of this
403 priority = new_priority; 397 *priority = new_priority;
404 } 398 }
399}
405 400
406 // Change thread priority 401void Thread::SetPriority(s32 priority) {
407 s32 old = current_priority; 402 ClampPriority(this, &priority);
408 thread_ready_queue.remove(old, this);
409 current_priority = priority;
410 thread_ready_queue.prepare(current_priority);
411 403
412 // Change thread status to "ready" and push to ready queue 404 if (current_priority == priority) {
413 if (IsRunning()) { 405 return;
414 status = (status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY;
415 } 406 }
416 if (IsReady()) { 407
417 thread_ready_queue.push_back(current_priority, this); 408 if (status == THREADSTATUS_READY) {
409 // If thread was ready, adjust queues
410 ready_queue.remove(current_priority, this);
411 ready_queue.prepare(priority);
412 ready_queue.push_back(priority, this);
418 } 413 }
414
415 current_priority = priority;
419} 416}
420 417
421Handle SetupIdleThread() { 418SharedPtr<Thread> SetupIdleThread() {
422 // We need to pass a few valid values to get around parameter checking in Thread::Create. 419 // We need to pass a few valid values to get around parameter checking in Thread::Create.
423 auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, 420 auto thread = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
424 THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE); 421 THREADPROCESSORID_0, 0).MoveFrom();
425 _dbg_assert_(Kernel, thread_res.Succeeded());
426 SharedPtr<Thread> thread = std::move(*thread_res);
427 422
428 thread->idle = true; 423 thread->idle = true;
429 CallThread(thread.get()); 424 return thread;
430 return thread->GetHandle();
431} 425}
432 426
433SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) { 427SharedPtr<Thread> SetupMainThread(u32 stack_size, u32 entry_point, s32 priority) {
428 _dbg_assert_(Kernel, !GetCurrentThread());
429
434 // Initialize new "main" thread 430 // Initialize new "main" thread
435 auto thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0, 431 auto thread_res = Thread::Create("main", entry_point, priority, 0,
436 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); 432 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END);
437 // TODO(yuriks): Propagate error 433
438 _dbg_assert_(Kernel, thread_res.Succeeded()); 434 SharedPtr<Thread> thread = thread_res.MoveFrom();
439 SharedPtr<Thread> thread = std::move(*thread_res);
440
441 // If running another thread already, set it to "ready" state
442 Thread* cur = GetCurrentThread();
443 if (cur && cur->IsRunning()) {
444 ChangeReadyState(cur, true);
445 }
446 435
447 // Run new "main" thread 436 // Run new "main" thread
448 current_thread = thread.get(); 437 SwitchContext(thread.get());
449 thread->status = THREADSTATUS_RUNNING;
450 Core::g_app_core->LoadContext(thread->context);
451 438
452 return thread; 439 return thread;
453} 440}
454 441
455
456/// Reschedules to the next available thread (call after current thread is suspended)
457void Reschedule() { 442void Reschedule() {
458 Thread* prev = GetCurrentThread(); 443 Thread* prev = GetCurrentThread();
459 Thread* next = NextThread(); 444 Thread* next = PopNextReadyThread();
460 HLE::g_reschedule = false; 445 HLE::g_reschedule = false;
461 446
462 if (next != nullptr) { 447 if (next != nullptr) {
463 LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); 448 LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId());
464 SwitchContext(next); 449 SwitchContext(next);
465 } else { 450 } else {
466 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); 451 LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId());
467 452
468 for (auto& thread : thread_list) { 453 for (auto& thread : thread_list) {
469 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X", thread->GetHandle(), 454 LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(),
470 thread->current_priority, thread->status); 455 thread->current_priority, thread->status);
471 } 456 }
472 } 457 }
@@ -483,8 +468,10 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
483//////////////////////////////////////////////////////////////////////////////////////////////////// 468////////////////////////////////////////////////////////////////////////////////////////////////////
484 469
485void ThreadingInit() { 470void ThreadingInit() {
486 next_thread_id = INITIAL_THREAD_ID;
487 ThreadWakeupEventType = CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); 471 ThreadWakeupEventType = CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
472
473 // Setup the idle thread
474 SetupIdleThread();
488} 475}
489 476
490void ThreadingShutdown() { 477void ThreadingShutdown() {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index d6299364a..cfd073a70 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -7,6 +7,8 @@
7#include <string> 7#include <string>
8#include <vector> 8#include <vector>
9 9
10#include <boost/container/flat_set.hpp>
11
10#include "common/common_types.h" 12#include "common/common_types.h"
11 13
12#include "core/core.h" 14#include "core/core.h"
@@ -29,21 +31,34 @@ enum ThreadProcessorId {
29}; 31};
30 32
31enum ThreadStatus { 33enum ThreadStatus {
32 THREADSTATUS_RUNNING = 1, 34 THREADSTATUS_RUNNING, ///< Currently running
33 THREADSTATUS_READY = 2, 35 THREADSTATUS_READY, ///< Ready to run
34 THREADSTATUS_WAIT = 4, 36 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter
35 THREADSTATUS_SUSPEND = 8, 37 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC
36 THREADSTATUS_DORMANT = 16, 38 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC
37 THREADSTATUS_DEAD = 32, 39 THREADSTATUS_DORMANT, ///< Created but not yet made ready
38 THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND 40 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
39}; 41};
40 42
41namespace Kernel { 43namespace Kernel {
42 44
45class Mutex;
46
43class Thread final : public WaitObject { 47class Thread final : public WaitObject {
44public: 48public:
49 /**
50 * Creates and returns a new thread. The new thread is immediately scheduled
51 * @param name The friendly name desired for the thread
52 * @param entry_point The address at which the thread should start execution
53 * @param priority The thread's priority
54 * @param arg User data to pass to the thread
55 * @param processor_id The ID(s) of the processors on which the thread is desired to be run
56 * @param stack_top The address of the thread's stack top
57 * @param stack_size The size of the thread's stack
58 * @return A shared pointer to the newly created thread
59 */
45 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, 60 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
46 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size); 61 u32 arg, s32 processor_id, VAddr stack_top);
47 62
48 std::string GetName() const override { return name; } 63 std::string GetName() const override { return name; }
49 std::string GetTypeName() const override { return "Thread"; } 64 std::string GetTypeName() const override { return "Thread"; }
@@ -51,22 +66,32 @@ public:
51 static const HandleType HANDLE_TYPE = HandleType::Thread; 66 static const HandleType HANDLE_TYPE = HandleType::Thread;
52 HandleType GetHandleType() const override { return HANDLE_TYPE; } 67 HandleType GetHandleType() const override { return HANDLE_TYPE; }
53 68
54 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; }
55 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; }
56 inline bool IsReady() const { return (status & THREADSTATUS_READY) != 0; }
57 inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; }
58 inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; }
59 inline bool IsIdle() const { return idle; }
60
61 bool ShouldWait() override; 69 bool ShouldWait() override;
62 void Acquire() override; 70 void Acquire() override;
63 71
72 /**
73 * Checks if the thread is an idle (stub) thread
74 * @return True if the thread is an idle (stub) thread, false otherwise
75 */
76 inline bool IsIdle() const { return idle; }
77
78 /**
79 * Gets the thread's current priority
80 * @return The current thread's priority
81 */
64 s32 GetPriority() const { return current_priority; } 82 s32 GetPriority() const { return current_priority; }
83
84 /**
85 * Sets the thread's current priority
86 * @param priority The new priority
87 */
65 void SetPriority(s32 priority); 88 void SetPriority(s32 priority);
66 89
90 /**
91 * Gets the thread's thread ID
92 * @return The thread's ID
93 */
67 u32 GetThreadId() const { return thread_id; } 94 u32 GetThreadId() const { return thread_id; }
68
69 void Stop(const char* reason);
70 95
71 /** 96 /**
72 * Release an acquired wait object 97 * Release an acquired wait object
@@ -74,10 +99,18 @@ public:
74 */ 99 */
75 void ReleaseWaitObject(WaitObject* wait_object); 100 void ReleaseWaitObject(WaitObject* wait_object);
76 101
77 /// Resumes a thread from waiting by marking it as "ready" 102 /**
103 * Resumes a thread from waiting
104 */
78 void ResumeFromWait(); 105 void ResumeFromWait();
79 106
80 /** 107 /**
108 * Schedules an event to wake up the specified thread after the specified delay
109 * @param nanoseconds The time this thread will be allowed to sleep for
110 */
111 void WakeAfterDelay(s64 nanoseconds);
112
113 /**
81 * Sets the result after the thread awakens (from either WaitSynchronization SVC) 114 * Sets the result after the thread awakens (from either WaitSynchronization SVC)
82 * @param result Value to set to the returned result 115 * @param result Value to set to the returned result
83 */ 116 */
@@ -89,6 +122,11 @@ public:
89 */ 122 */
90 void SetWaitSynchronizationOutput(s32 output); 123 void SetWaitSynchronizationOutput(s32 output);
91 124
125 /**
126 * Stops a thread, invalidating it from further use
127 */
128 void Stop();
129
92 Core::ThreadContext context; 130 Core::ThreadContext context;
93 131
94 u32 thread_id; 132 u32 thread_id;
@@ -96,15 +134,16 @@ public:
96 u32 status; 134 u32 status;
97 u32 entry_point; 135 u32 entry_point;
98 u32 stack_top; 136 u32 stack_top;
99 u32 stack_size;
100 137
101 s32 initial_priority; 138 s32 initial_priority;
102 s32 current_priority; 139 s32 current_priority;
103 140
104 s32 processor_id; 141 s32 processor_id;
105 142
106 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on 143 /// Mutexes currently held by this thread, which will be released when it exits.
144 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
107 145
146 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on
108 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address 147 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
109 bool wait_all; ///< True if the thread is waiting on all objects before resuming 148 bool wait_all; ///< True if the thread is waiting on all objects before resuming
110 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup 149 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup
@@ -115,34 +154,58 @@ public:
115 bool idle = false; 154 bool idle = false;
116 155
117private: 156private:
118 Thread() = default; 157 Thread();
158 ~Thread() override;
159
160 /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
161 Handle callback_handle;
119}; 162};
120 163
121/// Sets up the primary application thread 164extern SharedPtr<Thread> g_main_thread;
122SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); 165
166/**
167 * Sets up the primary application thread
168 * @param stack_size The size of the thread's stack
169 * @param entry_point The address at which the thread should start execution
170 * @param priority The priority to give the main thread
171 * @return A shared pointer to the main thread
172 */
173SharedPtr<Thread> SetupMainThread(u32 stack_size, u32 entry_point, s32 priority);
123 174
124/// Reschedules to the next available thread (call after current thread is suspended) 175/**
176 * Reschedules to the next available thread (call after current thread is suspended)
177 */
125void Reschedule(); 178void Reschedule();
126 179
127/// Arbitrate the highest priority thread that is waiting 180/**
181 * Arbitrate the highest priority thread that is waiting
182 * @param address The address for which waiting threads should be arbitrated
183 */
128Thread* ArbitrateHighestPriorityThread(u32 address); 184Thread* ArbitrateHighestPriorityThread(u32 address);
129 185
130/// Arbitrate all threads currently waiting... 186/**
187 * Arbitrate all threads currently waiting.
188 * @param address The address for which waiting threads should be arbitrated
189 */
131void ArbitrateAllThreads(u32 address); 190void ArbitrateAllThreads(u32 address);
132 191
133/// Gets the current thread 192/**
193 * Gets the current thread
194 */
134Thread* GetCurrentThread(); 195Thread* GetCurrentThread();
135 196
136/// Waits the current thread on a sleep 197/**
198 * Waits the current thread on a sleep
199 */
137void WaitCurrentThread_Sleep(); 200void WaitCurrentThread_Sleep();
138 201
139/** 202/**
140 * Waits the current thread from a WaitSynchronization call 203 * Waits the current thread from a WaitSynchronization call
141 * @param wait_object Kernel object that we are waiting on 204 * @param wait_objects Kernel objects that we are waiting on
142 * @param wait_set_output If true, set the output parameter on thread wakeup (for WaitSynchronizationN only) 205 * @param wait_set_output If true, set the output parameter on thread wakeup (for WaitSynchronizationN only)
143 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) 206 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only)
144 */ 207 */
145void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bool wait_set_output, bool wait_all); 208void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all);
146 209
147/** 210/**
148 * Waits the current thread from an ArbitrateAddress call 211 * Waits the current thread from an ArbitrateAddress call
@@ -151,24 +214,21 @@ void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bo
151void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); 214void WaitCurrentThread_ArbitrateAddress(VAddr wait_address);
152 215
153/** 216/**
154 * Schedules an event to wake up the specified thread after the specified delay.
155 * @param handle The thread handle.
156 * @param nanoseconds The time this thread will be allowed to sleep for.
157 */
158void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds);
159
160/**
161 * Sets up the idle thread, this is a thread that is intended to never execute instructions, 217 * Sets up the idle thread, this is a thread that is intended to never execute instructions,
162 * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue 218 * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue
163 * and will try to yield on every call. 219 * and will try to yield on every call.
164 * @returns The handle of the idle thread 220 * @return The handle of the idle thread
165 */ 221 */
166Handle SetupIdleThread(); 222SharedPtr<Thread> SetupIdleThread();
167 223
168/// Initialize threading 224/**
225 * Initialize threading
226 */
169void ThreadingInit(); 227void ThreadingInit();
170 228
171/// Shutdown threading 229/**
230 * Shutdown threading
231 */
172void ThreadingShutdown(); 232void ThreadingShutdown();
173 233
174} // namespace 234} // namespace
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 503a5d2ce..4352fc99c 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <set>
6
7#include "common/common.h" 5#include "common/common.h"
8 6
9#include "core/core_timing.h" 7#include "core/core_timing.h"
@@ -15,18 +13,24 @@ namespace Kernel {
15 13
16/// The event type of the generic timer callback event 14/// The event type of the generic timer callback event
17static int timer_callback_event_type = -1; 15static int timer_callback_event_type = -1;
16// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing
17// us to simply use a pool index or similar.
18static Kernel::HandleTable timer_callback_handle_table;
19
20Timer::Timer() {}
21Timer::~Timer() {}
18 22
19ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name) { 23SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
20 SharedPtr<Timer> timer(new Timer); 24 SharedPtr<Timer> timer(new Timer);
21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(timer));
23 25
24 timer->reset_type = reset_type; 26 timer->reset_type = reset_type;
25 timer->signaled = false; 27 timer->signaled = false;
26 timer->name = std::move(name); 28 timer->name = std::move(name);
27 timer->initial_delay = 0; 29 timer->initial_delay = 0;
28 timer->interval_delay = 0; 30 timer->interval_delay = 0;
29 return MakeResult<SharedPtr<Timer>>(timer); 31 timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom();
32
33 return timer;
30} 34}
31 35
32bool Timer::ShouldWait() { 36bool Timer::ShouldWait() {
@@ -38,17 +42,19 @@ void Timer::Acquire() {
38} 42}
39 43
40void Timer::Set(s64 initial, s64 interval) { 44void Timer::Set(s64 initial, s64 interval) {
45 // Ensure we get rid of any previous scheduled event
46 Cancel();
47
41 initial_delay = initial; 48 initial_delay = initial;
42 interval_delay = interval; 49 interval_delay = interval;
43 50
44 u64 initial_microseconds = initial / 1000; 51 u64 initial_microseconds = initial / 1000;
45 // TODO(yuriks): Figure out a replacement for GetHandle here 52 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds),
46 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, 53 timer_callback_event_type, callback_handle);
47 GetHandle());
48} 54}
49 55
50void Timer::Cancel() { 56void Timer::Cancel() {
51 CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle()); 57 CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle);
52} 58}
53 59
54void Timer::Clear() { 60void Timer::Clear() {
@@ -57,7 +63,7 @@ void Timer::Clear() {
57 63
58/// The timer callback event, called when a timer is fired 64/// The timer callback event, called when a timer is fired
59static void TimerCallback(u64 timer_handle, int cycles_late) { 65static void TimerCallback(u64 timer_handle, int cycles_late) {
60 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle); 66 SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(timer_handle);
61 67
62 if (timer == nullptr) { 68 if (timer == nullptr) {
63 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle); 69 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle);
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index c45e79954..540e4e187 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -19,7 +19,7 @@ public:
19 * @param name Optional name of timer 19 * @param name Optional name of timer
20 * @return The created Timer 20 * @return The created Timer
21 */ 21 */
22 static ResultVal<SharedPtr<Timer>> Create(ResetType reset_type, std::string name = "Unknown"); 22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
23 23
24 std::string GetTypeName() const override { return "Timer"; } 24 std::string GetTypeName() const override { return "Timer"; }
25 std::string GetName() const override { return name; } 25 std::string GetName() const override { return name; }
@@ -49,7 +49,11 @@ public:
49 void Clear(); 49 void Clear();
50 50
51private: 51private:
52 Timer() = default; 52 Timer();
53 ~Timer() override;
54
55 /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
56 Handle callback_handle;
53}; 57};
54 58
55/// Initializes the required variables for timers 59/// Initializes the required variables for timers
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 948b9e38e..9c6ca29e5 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -307,14 +307,14 @@ public:
307 } 307 }
308 308
309 ResultVal& operator=(const ResultVal& o) { 309 ResultVal& operator=(const ResultVal& o) {
310 if (*this) { 310 if (!empty()) {
311 if (o) { 311 if (!o.empty()) {
312 *GetPointer() = *o.GetPointer(); 312 *GetPointer() = *o.GetPointer();
313 } else { 313 } else {
314 GetPointer()->~T(); 314 GetPointer()->~T();
315 } 315 }
316 } else { 316 } else {
317 if (o) { 317 if (!o.empty()) {
318 new (&storage) T(*o.GetPointer()); 318 new (&storage) T(*o.GetPointer());
319 } 319 }
320 } 320 }
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 20a3fa2e5..53d920de1 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -53,7 +53,7 @@ const Interface::FunctionInfo FunctionTable[] = {
53// Interface class 53// Interface class
54 54
55Interface::Interface() { 55Interface::Interface() {
56 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 56 Register(FunctionTable);
57} 57}
58 58
59} // namespace 59} // namespace
diff --git a/src/core/hle/service/act_u.cpp b/src/core/hle/service/act_u.cpp
index 10870f14b..4ea7a9fb2 100644
--- a/src/core/hle/service/act_u.cpp
+++ b/src/core/hle/service/act_u.cpp
@@ -18,7 +18,7 @@ namespace ACT_U {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/am_app.cpp b/src/core/hle/service/am_app.cpp
index 0b396b6d3..df10db87f 100644
--- a/src/core/hle/service/am_app.cpp
+++ b/src/core/hle/service/am_app.cpp
@@ -18,7 +18,7 @@ namespace AM_APP {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am_net.cpp
index 112844e5b..c74012d9d 100644
--- a/src/core/hle/service/am_net.cpp
+++ b/src/core/hle/service/am_net.cpp
@@ -38,7 +38,7 @@ const Interface::FunctionInfo FunctionTable[] = {
38// Interface class 38// Interface class
39 39
40Interface::Interface() { 40Interface::Interface() {
41 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 41 Register(FunctionTable);
42} 42}
43 43
44} // namespace 44} // namespace
diff --git a/src/core/hle/service/am_sys.cpp b/src/core/hle/service/am_sys.cpp
index b63c8c087..c5df8abda 100644
--- a/src/core/hle/service/am_sys.cpp
+++ b/src/core/hle/service/am_sys.cpp
@@ -18,7 +18,7 @@ namespace AM_SYS {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/apt_a.cpp b/src/core/hle/service/apt_a.cpp
index 42f2879c1..e1dd2a5fb 100644
--- a/src/core/hle/service/apt_a.cpp
+++ b/src/core/hle/service/apt_a.cpp
@@ -39,7 +39,7 @@ const Interface::FunctionInfo FunctionTable[] = {
39// Interface class 39// Interface class
40 40
41Interface::Interface() { 41Interface::Interface() {
42 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 42 Register(FunctionTable);
43} 43}
44 44
45} // namespace 45} // namespace
diff --git a/src/core/hle/service/apt_s.cpp b/src/core/hle/service/apt_s.cpp
index 7ad428ee7..686335428 100644
--- a/src/core/hle/service/apt_s.cpp
+++ b/src/core/hle/service/apt_s.cpp
@@ -117,7 +117,7 @@ const Interface::FunctionInfo FunctionTable[] = {
117// Interface class 117// Interface class
118 118
119Interface::Interface() { 119Interface::Interface() {
120 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 120 Register(FunctionTable);
121} 121}
122 122
123} // namespace 123} // namespace
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 4c3f621d0..ccfd04591 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -69,8 +69,8 @@ void Initialize(Service::Interface* self) {
69 u32* cmd_buff = Kernel::GetCommandBuffer(); 69 u32* cmd_buff = Kernel::GetCommandBuffer();
70 70
71 // TODO(bunnei): Check if these are created in Initialize or on APT process startup. 71 // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
72 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification").MoveFrom(); 72 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification");
73 pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause").MoveFrom(); 73 pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause");
74 74
75 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); 75 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
76 cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom(); 76 cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom();
@@ -512,15 +512,15 @@ Interface::Interface() {
512 file.ReadBytes(shared_font.data(), (size_t)file.GetSize()); 512 file.ReadBytes(shared_font.data(), (size_t)file.GetSize());
513 513
514 // Create shared font memory object 514 // Create shared font memory object
515 shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem").MoveFrom(); 515 shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem");
516 } else { 516 } else {
517 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str()); 517 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str());
518 shared_font_mem = nullptr; 518 shared_font_mem = nullptr;
519 } 519 }
520 520
521 lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom(); 521 lock = Kernel::Mutex::Create(false, "APT_U:Lock");
522 522
523 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 523 Register(FunctionTable);
524} 524}
525 525
526} // namespace 526} // namespace
diff --git a/src/core/hle/service/boss_p.cpp b/src/core/hle/service/boss_p.cpp
index f245a38e9..b3aa6acee 100644
--- a/src/core/hle/service/boss_p.cpp
+++ b/src/core/hle/service/boss_p.cpp
@@ -18,7 +18,7 @@ namespace BOSS_P {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/boss_u.cpp b/src/core/hle/service/boss_u.cpp
index 1820ea7ad..50bb5d426 100644
--- a/src/core/hle/service/boss_u.cpp
+++ b/src/core/hle/service/boss_u.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
19// Interface class 19// Interface class
20 20
21Interface::Interface() { 21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 22 Register(FunctionTable);
23} 23}
24 24
25} // namespace 25} // namespace
diff --git a/src/core/hle/service/cam_u.cpp b/src/core/hle/service/cam_u.cpp
index 549095339..cf3b27664 100644
--- a/src/core/hle/service/cam_u.cpp
+++ b/src/core/hle/service/cam_u.cpp
@@ -18,7 +18,7 @@ namespace CAM_U {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/cecd_s.cpp b/src/core/hle/service/cecd_s.cpp
index 9c4992f13..2c707baff 100644
--- a/src/core/hle/service/cecd_s.cpp
+++ b/src/core/hle/service/cecd_s.cpp
@@ -18,7 +18,7 @@ namespace CECD_S {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/cecd_u.cpp b/src/core/hle/service/cecd_u.cpp
index b7655ef0b..b7ea3a186 100644
--- a/src/core/hle/service/cecd_u.cpp
+++ b/src/core/hle/service/cecd_u.cpp
@@ -18,7 +18,7 @@ namespace CECD_U {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
index 7c1ee8ac3..555b7884a 100644
--- a/src/core/hle/service/cfg/cfg_i.cpp
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -104,7 +104,7 @@ const Interface::FunctionInfo FunctionTable[] = {
104// Interface class 104// Interface class
105 105
106Interface::Interface() { 106Interface::Interface() {
107 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 107 Register(FunctionTable);
108} 108}
109 109
110} // namespace 110} // namespace
diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp
index cf4e82152..2170894d6 100644
--- a/src/core/hle/service/cfg/cfg_s.cpp
+++ b/src/core/hle/service/cfg/cfg_s.cpp
@@ -92,7 +92,7 @@ const Interface::FunctionInfo FunctionTable[] = {
92// Interface class 92// Interface class
93 93
94Interface::Interface() { 94Interface::Interface() {
95 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 95 Register(FunctionTable);
96} 96}
97 97
98} // namespace 98} // namespace
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 5d212a9a2..5aa53cf75 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -246,7 +246,7 @@ const Interface::FunctionInfo FunctionTable[] = {
246// Interface class 246// Interface class
247 247
248Interface::Interface() { 248Interface::Interface() {
249 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 249 Register(FunctionTable);
250} 250}
251 251
252} // namespace 252} // namespace
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 3a557efe1..39b00982c 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = {
29// Interface class 29// Interface class
30 30
31Interface::Interface() { 31Interface::Interface() {
32 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 32 Register(FunctionTable);
33} 33}
34 34
35} // namespace 35} // namespace
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index f413c6f54..a720b63f3 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -261,12 +261,11 @@ const Interface::FunctionInfo FunctionTable[] = {
261// Interface class 261// Interface class
262 262
263Interface::Interface() { 263Interface::Interface() {
264 semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, 264 semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
265 "DSP_DSP::semaphore_event").MoveFrom();
266 interrupt_event = nullptr; 265 interrupt_event = nullptr;
267 read_pipe_count = 0; 266 read_pipe_count = 0;
268 267
269 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 268 Register(FunctionTable);
270} 269}
271 270
272} // namespace 271} // namespace
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 8c900eabc..962de2170 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
19// Interface class 19// Interface class
20 20
21Interface::Interface() { 21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 22 Register(FunctionTable);
23} 23}
24 24
25} // namespace 25} // namespace
diff --git a/src/core/hle/service/frd_a.cpp b/src/core/hle/service/frd_a.cpp
index 53edc2cd8..79140a756 100644
--- a/src/core/hle/service/frd_a.cpp
+++ b/src/core/hle/service/frd_a.cpp
@@ -18,7 +18,7 @@ namespace FRD_A {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/frd_u.cpp b/src/core/hle/service/frd_u.cpp
index 021186e57..59faca77a 100644
--- a/src/core/hle/service/frd_u.cpp
+++ b/src/core/hle/service/frd_u.cpp
@@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = {
27// Interface class 27// Interface class
28 28
29Interface::Interface() { 29Interface::Interface() {
30 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 30 Register(FunctionTable);
31} 31}
32 32
33} // namespace 33} // namespace
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 43eef034e..e197d3599 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -5,6 +5,8 @@
5#include <memory> 5#include <memory>
6#include <unordered_map> 6#include <unordered_map>
7 7
8#include <boost/container/flat_map.hpp>
9
8#include "common/common_types.h" 10#include "common/common_types.h"
9#include "common/file_util.h" 11#include "common/file_util.h"
10#include "common/make_unique.h" 12#include "common/make_unique.h"
@@ -18,7 +20,6 @@
18#include "core/file_sys/archive_sdmc.h" 20#include "core/file_sys/archive_sdmc.h"
19#include "core/file_sys/directory_backend.h" 21#include "core/file_sys/directory_backend.h"
20#include "core/hle/service/fs/archive.h" 22#include "core/hle/service/fs/archive.h"
21#include "core/hle/kernel/session.h"
22#include "core/hle/result.h" 23#include "core/hle/result.h"
23 24
24// Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. 25// Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map.
@@ -74,43 +75,19 @@ enum class DirectoryCommand : u32 {
74 Close = 0x08020000, 75 Close = 0x08020000,
75}; 76};
76 77
77class Archive { 78ResultVal<bool> File::SyncRequest() {
78public: 79 u32* cmd_buff = Kernel::GetCommandBuffer();
79 Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) 80 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
80 : id_code(id_code), backend(std::move(backend)) { 81 switch (cmd) {
81 }
82
83 std::string GetName() const { return "Archive: " + backend->GetName(); }
84
85 ArchiveIdCode id_code; ///< Id code of the archive
86 std::unique_ptr<FileSys::ArchiveBackend> backend; ///< Archive backend interface
87};
88
89class File : public Kernel::Session {
90public:
91 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path)
92 : path(path), priority(0), backend(std::move(backend)) {
93 }
94
95 std::string GetName() const override { return "Path: " + path.DebugStr(); }
96
97 FileSys::Path path; ///< Path of the file
98 u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means
99 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
100
101 ResultVal<bool> SyncRequest() override {
102 u32* cmd_buff = Kernel::GetCommandBuffer();
103 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
104 switch (cmd) {
105 82
106 // Read from file... 83 // Read from file...
107 case FileCommand::Read: 84 case FileCommand::Read:
108 { 85 {
109 u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; 86 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32;
110 u32 length = cmd_buff[3]; 87 u32 length = cmd_buff[3];
111 u32 address = cmd_buff[5]; 88 u32 address = cmd_buff[5];
112 LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", 89 LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x",
113 GetTypeName().c_str(), GetName().c_str(), offset, length, address); 90 GetTypeName().c_str(), GetName().c_str(), offset, length, address);
114 cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); 91 cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address));
115 break; 92 break;
116 } 93 }
@@ -118,12 +95,12 @@ public:
118 // Write to file... 95 // Write to file...
119 case FileCommand::Write: 96 case FileCommand::Write:
120 { 97 {
121 u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; 98 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32;
122 u32 length = cmd_buff[3]; 99 u32 length = cmd_buff[3];
123 u32 flush = cmd_buff[4]; 100 u32 flush = cmd_buff[4];
124 u32 address = cmd_buff[6]; 101 u32 address = cmd_buff[6];
125 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", 102 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
126 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); 103 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
127 cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); 104 cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address));
128 break; 105 break;
129 } 106 }
@@ -141,7 +118,7 @@ public:
141 { 118 {
142 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); 119 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
143 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", 120 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu",
144 GetTypeName().c_str(), GetName().c_str(), size); 121 GetTypeName().c_str(), GetName().c_str(), size);
145 backend->SetSize(size); 122 backend->SetSize(size);
146 break; 123 break;
147 } 124 }
@@ -163,7 +140,7 @@ public:
163 case FileCommand::OpenLinkFile: 140 case FileCommand::OpenLinkFile:
164 { 141 {
165 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); 142 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
166 cmd_buff[3] = GetHandle(); 143 cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE);
167 break; 144 break;
168 } 145 }
169 146
@@ -187,27 +164,15 @@ public:
187 ResultCode error = UnimplementedFunction(ErrorModule::FS); 164 ResultCode error = UnimplementedFunction(ErrorModule::FS);
188 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 165 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
189 return error; 166 return error;
190 }
191 cmd_buff[1] = 0; // No error
192 return MakeResult<bool>(false);
193 } 167 }
194}; 168 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
195 169 return MakeResult<bool>(false);
196class Directory : public Kernel::Session { 170}
197public:
198 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path)
199 : path(path), backend(std::move(backend)) {
200 }
201
202 std::string GetName() const override { return "Directory: " + path.DebugStr(); }
203
204 FileSys::Path path; ///< Path of the directory
205 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface
206 171
207 ResultVal<bool> SyncRequest() override { 172ResultVal<bool> Directory::SyncRequest() {
208 u32* cmd_buff = Kernel::GetCommandBuffer(); 173 u32* cmd_buff = Kernel::GetCommandBuffer();
209 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 174 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
210 switch (cmd) { 175 switch (cmd) {
211 176
212 // Read from directory... 177 // Read from directory...
213 case DirectoryCommand::Read: 178 case DirectoryCommand::Read:
@@ -216,7 +181,7 @@ public:
216 u32 address = cmd_buff[3]; 181 u32 address = cmd_buff[3];
217 auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); 182 auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address));
218 LOG_TRACE(Service_FS, "Read %s %s: count=%d", 183 LOG_TRACE(Service_FS, "Read %s %s: count=%d",
219 GetTypeName().c_str(), GetName().c_str(), count); 184 GetTypeName().c_str(), GetName().c_str(), count);
220 185
221 // Number of entries actually read 186 // Number of entries actually read
222 cmd_buff[2] = backend->Read(count, entries); 187 cmd_buff[2] = backend->Read(count, entries);
@@ -236,29 +201,31 @@ public:
236 ResultCode error = UnimplementedFunction(ErrorModule::FS); 201 ResultCode error = UnimplementedFunction(ErrorModule::FS);
237 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 202 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
238 return MakeResult<bool>(false); 203 return MakeResult<bool>(false);
239 }
240 cmd_buff[1] = 0; // No error
241 return MakeResult<bool>(false);
242 } 204 }
243}; 205 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
206 return MakeResult<bool>(false);
207}
244 208
245//////////////////////////////////////////////////////////////////////////////////////////////////// 209////////////////////////////////////////////////////////////////////////////////////////////////////
246 210
211using FileSys::ArchiveBackend;
212using FileSys::ArchiveFactory;
213
247/** 214/**
248 * Map of registered archives, identified by id code. Once an archive is registered here, it is 215 * Map of registered archives, identified by id code. Once an archive is registered here, it is
249 * never removed until the FS service is shut down. 216 * never removed until the FS service is shut down.
250 */ 217 */
251static std::unordered_map<ArchiveIdCode, std::unique_ptr<Archive>> id_code_map; 218static boost::container::flat_map<ArchiveIdCode, std::unique_ptr<ArchiveFactory>> id_code_map;
252 219
253/** 220/**
254 * Map of active archive handles. Values are pointers to the archives in `idcode_map`. 221 * Map of active archive handles. Values are pointers to the archives in `idcode_map`.
255 */ 222 */
256static std::unordered_map<ArchiveHandle, Archive*> handle_map; 223static std::unordered_map<ArchiveHandle, std::unique_ptr<ArchiveBackend>> handle_map;
257static ArchiveHandle next_handle; 224static ArchiveHandle next_handle;
258 225
259static Archive* GetArchive(ArchiveHandle handle) { 226static ArchiveBackend* GetArchive(ArchiveHandle handle) {
260 auto itr = handle_map.find(handle); 227 auto itr = handle_map.find(handle);
261 return (itr == handle_map.end()) ? nullptr : itr->second; 228 return (itr == handle_map.end()) ? nullptr : itr->second.get();
262} 229}
263 230
264ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) { 231ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) {
@@ -271,15 +238,13 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
271 ErrorSummary::NotFound, ErrorLevel::Permanent); 238 ErrorSummary::NotFound, ErrorLevel::Permanent);
272 } 239 }
273 240
274 ResultCode res = itr->second->backend->Open(archive_path); 241 CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
275 if (!res.IsSuccess())
276 return res;
277 242
278 // This should never even happen in the first place with 64-bit handles, 243 // This should never even happen in the first place with 64-bit handles,
279 while (handle_map.count(next_handle) != 0) { 244 while (handle_map.count(next_handle) != 0) {
280 ++next_handle; 245 ++next_handle;
281 } 246 }
282 handle_map.emplace(next_handle, itr->second.get()); 247 handle_map.emplace(next_handle, std::move(res));
283 return MakeResult<ArchiveHandle>(next_handle++); 248 return MakeResult<ArchiveHandle>(next_handle++);
284} 249}
285 250
@@ -292,40 +257,39 @@ ResultCode CloseArchive(ArchiveHandle handle) {
292 257
293// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in 258// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in
294// http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 259// http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22
295ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) { 260ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) {
296 auto result = id_code_map.emplace(id_code, Common::make_unique<Archive>(std::move(backend), id_code)); 261 auto result = id_code_map.emplace(id_code, std::move(factory));
297 262
298 bool inserted = result.second; 263 bool inserted = result.second;
299 _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); 264 _assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code");
300 265
301 auto& archive = result.first->second; 266 auto& archive = result.first->second;
302 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); 267 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code);
303 return RESULT_SUCCESS; 268 return RESULT_SUCCESS;
304} 269}
305 270
306ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { 271ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle,
307 Archive* archive = GetArchive(archive_handle); 272 const FileSys::Path& path, const FileSys::Mode mode) {
273 ArchiveBackend* archive = GetArchive(archive_handle);
308 if (archive == nullptr) 274 if (archive == nullptr)
309 return ERR_INVALID_HANDLE; 275 return ERR_INVALID_HANDLE;
310 276
311 std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); 277 std::unique_ptr<FileSys::FileBackend> backend = archive->OpenFile(path, mode);
312 if (backend == nullptr) { 278 if (backend == nullptr) {
313 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, 279 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS,
314 ErrorSummary::NotFound, ErrorLevel::Status); 280 ErrorSummary::NotFound, ErrorLevel::Status);
315 } 281 }
316 282
317 auto file = Common::make_unique<File>(std::move(backend), path); 283 auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path));
318 // TOOD(yuriks): Fix error reporting 284 return MakeResult<Kernel::SharedPtr<File>>(std::move(file));
319 Handle handle = Kernel::g_handle_table.Create(file.release()).ValueOr(INVALID_HANDLE);
320 return MakeResult<Handle>(handle);
321} 285}
322 286
323ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { 287ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
324 Archive* archive = GetArchive(archive_handle); 288 ArchiveBackend* archive = GetArchive(archive_handle);
325 if (archive == nullptr) 289 if (archive == nullptr)
326 return ERR_INVALID_HANDLE; 290 return ERR_INVALID_HANDLE;
327 291
328 if (archive->backend->DeleteFile(path)) 292 if (archive->DeleteFile(path))
329 return RESULT_SUCCESS; 293 return RESULT_SUCCESS;
330 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description 294 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
331 ErrorSummary::Canceled, ErrorLevel::Status); 295 ErrorSummary::Canceled, ErrorLevel::Status);
@@ -333,13 +297,13 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa
333 297
334ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 298ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path,
335 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { 299 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) {
336 Archive* src_archive = GetArchive(src_archive_handle); 300 ArchiveBackend* src_archive = GetArchive(src_archive_handle);
337 Archive* dest_archive = GetArchive(dest_archive_handle); 301 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle);
338 if (src_archive == nullptr || dest_archive == nullptr) 302 if (src_archive == nullptr || dest_archive == nullptr)
339 return ERR_INVALID_HANDLE; 303 return ERR_INVALID_HANDLE;
340 304
341 if (src_archive == dest_archive) { 305 if (src_archive == dest_archive) {
342 if (src_archive->backend->RenameFile(src_path, dest_path)) 306 if (src_archive->RenameFile(src_path, dest_path))
343 return RESULT_SUCCESS; 307 return RESULT_SUCCESS;
344 } else { 308 } else {
345 // TODO: Implement renaming across archives 309 // TODO: Implement renaming across archives
@@ -353,30 +317,30 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil
353} 317}
354 318
355ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { 319ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
356 Archive* archive = GetArchive(archive_handle); 320 ArchiveBackend* archive = GetArchive(archive_handle);
357 if (archive == nullptr) 321 if (archive == nullptr)
358 return ERR_INVALID_HANDLE; 322 return ERR_INVALID_HANDLE;
359 323
360 if (archive->backend->DeleteDirectory(path)) 324 if (archive->DeleteDirectory(path))
361 return RESULT_SUCCESS; 325 return RESULT_SUCCESS;
362 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description 326 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
363 ErrorSummary::Canceled, ErrorLevel::Status); 327 ErrorSummary::Canceled, ErrorLevel::Status);
364} 328}
365 329
366ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { 330ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) {
367 Archive* archive = GetArchive(archive_handle); 331 ArchiveBackend* archive = GetArchive(archive_handle);
368 if (archive == nullptr) 332 if (archive == nullptr)
369 return ERR_INVALID_HANDLE; 333 return ERR_INVALID_HANDLE;
370 334
371 return archive->backend->CreateFile(path, file_size); 335 return archive->CreateFile(path, file_size);
372} 336}
373 337
374ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { 338ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
375 Archive* archive = GetArchive(archive_handle); 339 ArchiveBackend* archive = GetArchive(archive_handle);
376 if (archive == nullptr) 340 if (archive == nullptr)
377 return ERR_INVALID_HANDLE; 341 return ERR_INVALID_HANDLE;
378 342
379 if (archive->backend->CreateDirectory(path)) 343 if (archive->CreateDirectory(path))
380 return RESULT_SUCCESS; 344 return RESULT_SUCCESS;
381 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description 345 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
382 ErrorSummary::Canceled, ErrorLevel::Status); 346 ErrorSummary::Canceled, ErrorLevel::Status);
@@ -384,13 +348,13 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
384 348
385ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 349ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path,
386 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { 350 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) {
387 Archive* src_archive = GetArchive(src_archive_handle); 351 ArchiveBackend* src_archive = GetArchive(src_archive_handle);
388 Archive* dest_archive = GetArchive(dest_archive_handle); 352 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle);
389 if (src_archive == nullptr || dest_archive == nullptr) 353 if (src_archive == nullptr || dest_archive == nullptr)
390 return ERR_INVALID_HANDLE; 354 return ERR_INVALID_HANDLE;
391 355
392 if (src_archive == dest_archive) { 356 if (src_archive == dest_archive) {
393 if (src_archive->backend->RenameDirectory(src_path, dest_path)) 357 if (src_archive->RenameDirectory(src_path, dest_path))
394 return RESULT_SUCCESS; 358 return RESULT_SUCCESS;
395 } else { 359 } else {
396 // TODO: Implement renaming across archives 360 // TODO: Implement renaming across archives
@@ -403,38 +367,29 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
403 ErrorSummary::NothingHappened, ErrorLevel::Status); 367 ErrorSummary::NothingHappened, ErrorLevel::Status);
404} 368}
405 369
406/** 370ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
407 * Open a Directory from an Archive 371 const FileSys::Path& path) {
408 * @param archive_handle Handle to an open Archive object 372 ArchiveBackend* archive = GetArchive(archive_handle);
409 * @param path Path to the Directory inside of the Archive
410 * @return Opened Directory object
411 */
412ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
413 Archive* archive = GetArchive(archive_handle);
414 if (archive == nullptr) 373 if (archive == nullptr)
415 return ERR_INVALID_HANDLE; 374 return ERR_INVALID_HANDLE;
416 375
417 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path); 376 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path);
418 if (backend == nullptr) { 377 if (backend == nullptr) {
419 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, 378 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
420 ErrorSummary::NotFound, ErrorLevel::Permanent); 379 ErrorSummary::NotFound, ErrorLevel::Permanent);
421 } 380 }
422 381
423 auto directory = Common::make_unique<Directory>(std::move(backend), path); 382 auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path));
424 // TOOD(yuriks): Fix error reporting 383 return MakeResult<Kernel::SharedPtr<Directory>>(std::move(directory));
425 Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE);
426 return MakeResult<Handle>(handle);
427} 384}
428 385
429ResultCode FormatSaveData() { 386ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) {
430 // Do not create the archive again if it already exists 387 auto archive_itr = id_code_map.find(id_code);
431 auto archive_itr = id_code_map.find(ArchiveIdCode::SaveData);
432 if (archive_itr == id_code_map.end()) { 388 if (archive_itr == id_code_map.end()) {
433 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 389 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
434 } 390 }
435 391
436 // Use an empty path, we do not use it when formatting the savedata 392 return archive_itr->second->Format(path);
437 return archive_itr->second->backend->Format(FileSys::Path());
438} 393}
439 394
440ResultCode CreateExtSaveData(u32 high, u32 low) { 395ResultCode CreateExtSaveData(u32 high, u32 low) {
@@ -468,32 +423,32 @@ void ArchiveInit() {
468 423
469 std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); 424 std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX);
470 std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); 425 std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
471 auto sdmc_archive = Common::make_unique<FileSys::Archive_SDMC>(sdmc_directory); 426 auto sdmc_factory = Common::make_unique<FileSys::ArchiveFactory_SDMC>(sdmc_directory);
472 if (sdmc_archive->Initialize()) 427 if (sdmc_factory->Initialize())
473 CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC); 428 RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC);
474 else 429 else
475 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); 430 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str());
476 431
477 // Create the SaveData archive 432 // Create the SaveData archive
478 auto savedata_archive = Common::make_unique<FileSys::Archive_SaveData>(sdmc_directory); 433 auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory);
479 CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData); 434 RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData);
480 435
481 auto extsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(sdmc_directory, false); 436 auto extsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false);
482 if (extsavedata_archive->Initialize()) 437 if (extsavedata_factory->Initialize())
483 CreateArchive(std::move(extsavedata_archive), ArchiveIdCode::ExtSaveData); 438 RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData);
484 else 439 else
485 LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_archive->GetMountPoint().c_str()); 440 LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str());
486 441
487 auto sharedextsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true); 442 auto sharedextsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true);
488 if (sharedextsavedata_archive->Initialize()) 443 if (sharedextsavedata_factory->Initialize())
489 CreateArchive(std::move(sharedextsavedata_archive), ArchiveIdCode::SharedExtSaveData); 444 RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData);
490 else 445 else
491 LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", 446 LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",
492 sharedextsavedata_archive->GetMountPoint().c_str()); 447 sharedextsavedata_factory->GetMountPoint().c_str());
493 448
494 // Create the SaveDataCheck archive, basically a small variation of the RomFS archive 449 // Create the SaveDataCheck archive, basically a small variation of the RomFS archive
495 auto savedatacheck_archive = Common::make_unique<FileSys::Archive_SaveDataCheck>(nand_directory); 450 auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory);
496 CreateArchive(std::move(savedatacheck_archive), ArchiveIdCode::SaveDataCheck); 451 RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck);
497} 452}
498 453
499/// Shutdown archives 454/// Shutdown archives
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index ba674d7f6..c490327d0 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -8,6 +8,7 @@
8 8
9#include "core/file_sys/archive_backend.h" 9#include "core/file_sys/archive_backend.h"
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/session.h"
11#include "core/hle/result.h" 12#include "core/hle/result.h"
12 13
13/// The unique system identifier hash, also known as ID0 14/// The unique system identifier hash, also known as ID0
@@ -15,6 +16,10 @@ extern const std::string SYSTEM_ID;
15/// The scrambled SD card CID, also known as ID1 16/// The scrambled SD card CID, also known as ID1
16extern const std::string SDCARD_ID; 17extern const std::string SDCARD_ID;
17 18
19namespace Kernel {
20 class Session;
21}
22
18namespace Service { 23namespace Service {
19namespace FS { 24namespace FS {
20 25
@@ -32,6 +37,35 @@ enum class ArchiveIdCode : u32 {
32 37
33typedef u64 ArchiveHandle; 38typedef u64 ArchiveHandle;
34 39
40class File : public Kernel::Session {
41public:
42 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path)
43 : path(path), priority(0), backend(std::move(backend)) {
44 }
45
46 std::string GetName() const override { return "Path: " + path.DebugStr(); }
47
48 FileSys::Path path; ///< Path of the file
49 u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means
50 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
51
52 ResultVal<bool> SyncRequest() override;
53};
54
55class Directory : public Kernel::Session {
56public:
57 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path)
58 : path(path), backend(std::move(backend)) {
59 }
60
61 std::string GetName() const override { return "Directory: " + path.DebugStr(); }
62
63 FileSys::Path path; ///< Path of the directory
64 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface
65
66 ResultVal<bool> SyncRequest() override;
67};
68
35/** 69/**
36 * Opens an archive 70 * Opens an archive
37 * @param id_code IdCode of the archive to open 71 * @param id_code IdCode of the archive to open
@@ -47,20 +81,21 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
47ResultCode CloseArchive(ArchiveHandle handle); 81ResultCode CloseArchive(ArchiveHandle handle);
48 82
49/** 83/**
50 * Creates an Archive 84 * Registers an Archive type, instances of which can later be opened using its IdCode.
51 * @param backend File system backend interface to the archive 85 * @param backend File system backend interface to the archive
52 * @param id_code Id code used to access this type of archive 86 * @param id_code Id code used to access this type of archive
53 */ 87 */
54ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code); 88ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code);
55 89
56/** 90/**
57 * Open a File from an Archive 91 * Open a File from an Archive
58 * @param archive_handle Handle to an open Archive object 92 * @param archive_handle Handle to an open Archive object
59 * @param path Path to the File inside of the Archive 93 * @param path Path to the File inside of the Archive
60 * @param mode Mode under which to open the File 94 * @param mode Mode under which to open the File
61 * @return Handle to the opened File object 95 * @return The opened File object as a Session
62 */ 96 */
63ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); 97ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle,
98 const FileSys::Path& path, const FileSys::Mode mode);
64 99
65/** 100/**
66 * Delete a File from an Archive 101 * Delete a File from an Archive
@@ -121,15 +156,19 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
121 * Open a Directory from an Archive 156 * Open a Directory from an Archive
122 * @param archive_handle Handle to an open Archive object 157 * @param archive_handle Handle to an open Archive object
123 * @param path Path to the Directory inside of the Archive 158 * @param path Path to the Directory inside of the Archive
124 * @return Handle to the opened File object 159 * @return The opened Directory object as a Session
125 */ 160 */
126ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); 161ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
162 const FileSys::Path& path);
127 163
128/** 164/**
129 * Creates a blank SaveData archive. 165 * Erases the contents of the physical folder that contains the archive
166 * identified by the specified id code and path
167 * @param id_code The id of the archive to format
168 * @param path The path to the archive, if relevant.
130 * @return ResultCode 0 on success or the corresponding code on error 169 * @return ResultCode 0 on success or the corresponding code on error
131 */ 170 */
132ResultCode FormatSaveData(); 171ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = FileSys::Path());
133 172
134/** 173/**
135 * Creates a blank SharedExtSaveData archive for the specified extdata ID 174 * Creates a blank SharedExtSaveData archive for the specified extdata ID
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index c495b6f3c..71ee4ff55 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -14,6 +14,9 @@
14//////////////////////////////////////////////////////////////////////////////////////////////////// 14////////////////////////////////////////////////////////////////////////////////////////////////////
15// Namespace FS_User 15// Namespace FS_User
16 16
17using Kernel::SharedPtr;
18using Kernel::Session;
19
17namespace Service { 20namespace Service {
18namespace FS { 21namespace FS {
19 22
@@ -58,10 +61,10 @@ static void OpenFile(Service::Interface* self) {
58 61
59 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); 62 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
60 63
61 ResultVal<Handle> handle = OpenFileFromArchive(archive_handle, file_path, mode); 64 ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode);
62 cmd_buff[1] = handle.Code().raw; 65 cmd_buff[1] = file_res.Code().raw;
63 if (handle.Succeeded()) { 66 if (file_res.Succeeded()) {
64 cmd_buff[3] = *handle; 67 cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
65 } else { 68 } else {
66 cmd_buff[3] = 0; 69 cmd_buff[3] = 0;
67 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); 70 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
@@ -114,10 +117,10 @@ static void OpenFileDirectly(Service::Interface* self) {
114 } 117 }
115 SCOPE_EXIT({ CloseArchive(*archive_handle); }); 118 SCOPE_EXIT({ CloseArchive(*archive_handle); });
116 119
117 ResultVal<Handle> handle = OpenFileFromArchive(*archive_handle, file_path, mode); 120 ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode);
118 cmd_buff[1] = handle.Code().raw; 121 cmd_buff[1] = file_res.Code().raw;
119 if (handle.Succeeded()) { 122 if (file_res.Succeeded()) {
120 cmd_buff[3] = *handle; 123 cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
121 } else { 124 } else {
122 cmd_buff[3] = 0; 125 cmd_buff[3] = 0;
123 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); 126 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
@@ -334,10 +337,10 @@ static void OpenDirectory(Service::Interface* self) {
334 337
335 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 338 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
336 339
337 ResultVal<Handle> handle = OpenDirectoryFromArchive(archive_handle, dir_path); 340 ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path);
338 cmd_buff[1] = handle.Code().raw; 341 cmd_buff[1] = dir_res.Code().raw;
339 if (handle.Succeeded()) { 342 if (dir_res.Succeeded()) {
340 cmd_buff[3] = *handle; 343 cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom();
341 } else { 344 } else {
342 LOG_ERROR(Service_FS, "failed to get a handle for directory"); 345 LOG_ERROR(Service_FS, "failed to get a handle for directory");
343 } 346 }
@@ -465,7 +468,7 @@ static void FormatSaveData(Service::Interface* self) {
465 return; 468 return;
466 } 469 }
467 470
468 cmd_buff[1] = FormatSaveData().raw; 471 cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw;
469} 472}
470 473
471/** 474/**
@@ -481,7 +484,7 @@ static void FormatThisUserSaveData(Service::Interface* self) {
481 484
482 // TODO(Subv): Find out what the inputs and outputs of this function are 485 // TODO(Subv): Find out what the inputs and outputs of this function are
483 486
484 cmd_buff[1] = FormatSaveData().raw; 487 cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw;
485} 488}
486 489
487static void CreateExtSaveData(Service::Interface* self) { 490static void CreateExtSaveData(Service::Interface* self) {
@@ -588,7 +591,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = {
588// Interface class 591// Interface class
589 592
590FSUserInterface::FSUserInterface() { 593FSUserInterface::FSUserInterface() {
591 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 594 Register(FunctionTable);
592} 595}
593 596
594} // namespace FS 597} // namespace FS
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 5b91f17d2..495c117ee 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -187,7 +187,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
187 187
188 g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]); 188 g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]);
189 _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!"); 189 _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!");
190 g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom(); 190 g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem");
191 191
192 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); 192 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom();
193 193
@@ -389,7 +389,7 @@ const Interface::FunctionInfo FunctionTable[] = {
389// Interface class 389// Interface class
390 390
391Interface::Interface() { 391Interface::Interface() {
392 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 392 Register(FunctionTable);
393 393
394 g_interrupt_event = 0; 394 g_interrupt_event = 0;
395 g_shared_memory = 0; 395 g_shared_memory = 0;
diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp
index 6213472ff..d63fa1ee2 100644
--- a/src/core/hle/service/gsp_lcd.cpp
+++ b/src/core/hle/service/gsp_lcd.cpp
@@ -20,7 +20,7 @@ namespace GSP_LCD {
20// Interface class 20// Interface class
21 21
22Interface::Interface() { 22Interface::Interface() {
23 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 23 //Register(FunctionTable);
24} 24}
25 25
26} // namespace 26} // namespace
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 835055af4..7cb01729e 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -30,6 +30,8 @@ static s16 next_circle_y = 0;
30 * Gets a pointer to the PadData structure inside HID shared memory 30 * Gets a pointer to the PadData structure inside HID shared memory
31 */ 31 */
32static inline PadData* GetPadData() { 32static inline PadData* GetPadData() {
33 if (g_shared_mem == nullptr)
34 return nullptr;
33 return reinterpret_cast<PadData*>(g_shared_mem->GetPointer().ValueOr(nullptr)); 35 return reinterpret_cast<PadData*>(g_shared_mem->GetPointer().ValueOr(nullptr));
34} 36}
35 37
@@ -122,14 +124,14 @@ void PadUpdateComplete() {
122void HIDInit() { 124void HIDInit() {
123 using namespace Kernel; 125 using namespace Kernel;
124 126
125 g_shared_mem = SharedMemory::Create("HID:SharedMem").MoveFrom(); 127 g_shared_mem = SharedMemory::Create("HID:SharedMem");
126 128
127 // Create event handles 129 // Create event handles
128 g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1").MoveFrom(); 130 g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1");
129 g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2").MoveFrom(); 131 g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2");
130 g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer").MoveFrom(); 132 g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer");
131 g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope").MoveFrom(); 133 g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope");
132 g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad").MoveFrom(); 134 g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad");
133} 135}
134 136
135void HIDShutdown() { 137void HIDShutdown() {
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
index 76c40b659..054aa8b59 100644
--- a/src/core/hle/service/hid/hid_spvr.cpp
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -32,7 +32,7 @@ const Interface::FunctionInfo FunctionTable[] = {
32// Interface class 32// Interface class
33 33
34Interface::Interface() { 34Interface::Interface() {
35 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 35 Register(FunctionTable);
36} 36}
37 37
38} // namespace 38} // namespace
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
index 5444aa5ee..68edafebb 100644
--- a/src/core/hle/service/hid/hid_user.cpp
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -72,7 +72,7 @@ const Interface::FunctionInfo FunctionTable[] = {
72// Interface class 72// Interface class
73 73
74Interface::Interface() { 74Interface::Interface() {
75 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 75 Register(FunctionTable);
76} 76}
77 77
78} // namespace 78} // namespace
diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp
index d0bff552f..6595ca572 100644
--- a/src/core/hle/service/http_c.cpp
+++ b/src/core/hle/service/http_c.cpp
@@ -58,7 +58,7 @@ const Interface::FunctionInfo FunctionTable[] = {
58// Interface class 58// Interface class
59 59
60Interface::Interface() { 60Interface::Interface() {
61 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 61 Register(FunctionTable);
62} 62}
63 63
64} // namespace 64} // namespace
diff --git a/src/core/hle/service/ir_rst.cpp b/src/core/hle/service/ir_rst.cpp
index d49bd5335..31da8e160 100644
--- a/src/core/hle/service/ir_rst.cpp
+++ b/src/core/hle/service/ir_rst.cpp
@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
22// Interface class 22// Interface class
23 23
24Interface::Interface() { 24Interface::Interface() {
25 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 25 Register(FunctionTable);
26} 26}
27 27
28} // namespace 28} // namespace
diff --git a/src/core/hle/service/ir_u.cpp b/src/core/hle/service/ir_u.cpp
index da6f38e41..7fa233048 100644
--- a/src/core/hle/service/ir_u.cpp
+++ b/src/core/hle/service/ir_u.cpp
@@ -36,7 +36,7 @@ const Interface::FunctionInfo FunctionTable[] = {
36// Interface class 36// Interface class
37 37
38Interface::Interface() { 38Interface::Interface() {
39 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 39 Register(FunctionTable);
40} 40}
41 41
42} // namespace 42} // namespace
diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp
index 83bb9eabe..ea96f64af 100644
--- a/src/core/hle/service/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro.cpp
@@ -87,7 +87,7 @@ const Interface::FunctionInfo FunctionTable[] = {
87// Interface class 87// Interface class
88 88
89Interface::Interface() { 89Interface::Interface() {
90 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 90 Register(FunctionTable);
91} 91}
92 92
93} // namespace 93} // namespace
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index 82bce9180..af967b5b6 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -34,7 +34,7 @@ const Interface::FunctionInfo FunctionTable[] = {
34// Interface class 34// Interface class
35 35
36Interface::Interface() { 36Interface::Interface() {
37 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 37 Register(FunctionTable);
38} 38}
39 39
40} // namespace 40} // namespace
diff --git a/src/core/hle/service/ndm_u.cpp b/src/core/hle/service/ndm_u.cpp
index 0f03de6ae..df3c97193 100644
--- a/src/core/hle/service/ndm_u.cpp
+++ b/src/core/hle/service/ndm_u.cpp
@@ -24,7 +24,7 @@ const Interface::FunctionInfo FunctionTable[] = {
24// Interface class 24// Interface class
25 25
26Interface::Interface() { 26Interface::Interface() {
27 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 27 Register(FunctionTable);
28} 28}
29 29
30} // namespace 30} // namespace
diff --git a/src/core/hle/service/news_s.cpp b/src/core/hle/service/news_s.cpp
index 1850f59bd..d7537875b 100644
--- a/src/core/hle/service/news_s.cpp
+++ b/src/core/hle/service/news_s.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
19// Interface class 19// Interface class
20 20
21Interface::Interface() { 21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 22 Register(FunctionTable);
23} 23}
24 24
25} // namespace 25} // namespace
diff --git a/src/core/hle/service/news_u.cpp b/src/core/hle/service/news_u.cpp
index b5adad4c6..a9e161c23 100644
--- a/src/core/hle/service/news_u.cpp
+++ b/src/core/hle/service/news_u.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
19// Interface class 19// Interface class
20 20
21Interface::Interface() { 21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 22 Register(FunctionTable);
23} 23}
24 24
25} // namespace 25} // namespace
diff --git a/src/core/hle/service/nim_aoc.cpp b/src/core/hle/service/nim_aoc.cpp
index 17d1c4ff5..ab2ef4429 100644
--- a/src/core/hle/service/nim_aoc.cpp
+++ b/src/core/hle/service/nim_aoc.cpp
@@ -25,7 +25,7 @@ const Interface::FunctionInfo FunctionTable[] = {
25// Interface class 25// Interface class
26 26
27Interface::Interface() { 27Interface::Interface() {
28 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 28 Register(FunctionTable);
29} 29}
30 30
31} // namespace 31} // namespace
diff --git a/src/core/hle/service/ns_s.cpp b/src/core/hle/service/ns_s.cpp
index b9aca4257..5cf3e2039 100644
--- a/src/core/hle/service/ns_s.cpp
+++ b/src/core/hle/service/ns_s.cpp
@@ -21,7 +21,7 @@ const Interface::FunctionInfo FunctionTable[] = {
21// Interface class 21// Interface class
22 22
23Interface::Interface() { 23Interface::Interface() {
24 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 24 Register(FunctionTable);
25} 25}
26 26
27} // namespace 27} // namespace
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index ce456a966..61fcb54ce 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = {
26// Interface class 26// Interface class
27 27
28Interface::Interface() { 28Interface::Interface() {
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 29 Register(FunctionTable);
30} 30}
31 31
32} // namespace 32} // namespace
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp
index 529dccafb..d61eaf80f 100644
--- a/src/core/hle/service/pm_app.cpp
+++ b/src/core/hle/service/pm_app.cpp
@@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = {
26// Interface class 26// Interface class
27 27
28Interface::Interface() { 28Interface::Interface() {
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 29 Register(FunctionTable);
30} 30}
31 31
32} // namespace 32} // namespace
diff --git a/src/core/hle/service/ptm_play.cpp b/src/core/hle/service/ptm_play.cpp
index ae9e2925c..b357057fd 100644
--- a/src/core/hle/service/ptm_play.cpp
+++ b/src/core/hle/service/ptm_play.cpp
@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
22// Interface class 22// Interface class
23 23
24Interface::Interface() { 24Interface::Interface() {
25 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 25 Register(FunctionTable);
26} 26}
27 27
28} // namespace 28} // namespace
diff --git a/src/core/hle/service/ptm_sysm.cpp b/src/core/hle/service/ptm_sysm.cpp
index 4b5f86a47..b6f688de3 100644
--- a/src/core/hle/service/ptm_sysm.cpp
+++ b/src/core/hle/service/ptm_sysm.cpp
@@ -50,7 +50,7 @@ const Interface::FunctionInfo FunctionTable[] = {
50// Interface class 50// Interface class
51 51
52Interface::Interface() { 52Interface::Interface() {
53 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 53 Register(FunctionTable);
54} 54}
55 55
56} // namespace 56} // namespace
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp
index 753180add..7c8d9ce8c 100644
--- a/src/core/hle/service/ptm_u.cpp
+++ b/src/core/hle/service/ptm_u.cpp
@@ -4,8 +4,9 @@
4 4
5#include "common/log.h" 5#include "common/log.h"
6#include "common/make_unique.h" 6#include "common/make_unique.h"
7#include "core/file_sys/archive_extsavedata.h" 7
8#include "core/hle/hle.h" 8#include "core/hle/hle.h"
9#include "core/hle/service/fs/archive.h"
9#include "core/hle/service/ptm_u.h" 10#include "core/hle/service/ptm_u.h"
10 11
11//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -28,7 +29,6 @@ struct GameCoin {
28 u8 day; 29 u8 day;
29}; 30};
30static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; 31static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 };
31static std::unique_ptr<FileSys::Archive_ExtSaveData> ptm_shared_extsavedata;
32static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; 32static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0};
33 33
34/// Charge levels used by PTM functions 34/// Charge levels used by PTM functions
@@ -137,32 +137,29 @@ const Interface::FunctionInfo FunctionTable[] = {
137// Interface class 137// Interface class
138 138
139Interface::Interface() { 139Interface::Interface() {
140 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 140 Register(FunctionTable);
141 // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file 141
142 // TODO(Subv): In the future we should use the FS service to query this archive 142 // Open the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file
143 std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
144 ptm_shared_extsavedata = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true);
145 if (!ptm_shared_extsavedata->Initialize()) {
146 LOG_CRITICAL(Service_PTM, "Could not initialize SharedExtSaveData archive for the PTM:U service");
147 return;
148 }
149 FileSys::Path archive_path(ptm_shared_extdata_id); 143 FileSys::Path archive_path(ptm_shared_extdata_id);
150 ResultCode result = ptm_shared_extsavedata->Open(archive_path); 144 auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
151 // If the archive didn't exist, create the files inside 145 // If the archive didn't exist, create the files inside
152 if (result.description == ErrorDescription::FS_NotFormatted) { 146 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) {
153 // Format the archive to clear the directories 147 // Format the archive to create the directories
154 ptm_shared_extsavedata->Format(archive_path); 148 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
155 // Open it again to get a valid archive now that the folder exists 149 // Open it again to get a valid archive now that the folder exists
156 ptm_shared_extsavedata->Open(archive_path); 150 archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
151 _assert_msg_(Service_PTM, archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!");
152
157 FileSys::Path gamecoin_path("gamecoin.dat"); 153 FileSys::Path gamecoin_path("gamecoin.dat");
158 FileSys::Mode open_mode = {}; 154 FileSys::Mode open_mode = {};
159 open_mode.write_flag = 1; 155 open_mode.write_flag = 1;
160 open_mode.create_flag = 1; 156 open_mode.create_flag = 1;
161 // Open the file and write the default gamecoin information 157 // Open the file and write the default gamecoin information
162 auto gamecoin = ptm_shared_extsavedata->OpenFile(gamecoin_path, open_mode); 158 auto gamecoin_result = Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode);
163 if (gamecoin != nullptr) { 159 if (gamecoin_result.Succeeded()) {
164 gamecoin->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); 160 auto gamecoin = gamecoin_result.MoveFrom();
165 gamecoin->Close(); 161 gamecoin->backend->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin));
162 gamecoin->backend->Close();
166 } 163 }
167 } 164 }
168} 165}
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 355196fd3..e0979ea5d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -54,96 +54,76 @@
54 54
55namespace Service { 55namespace Service {
56 56
57Manager* g_manager = nullptr; ///< Service manager 57std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
58std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
58 59
59//////////////////////////////////////////////////////////////////////////////////////////////////// 60////////////////////////////////////////////////////////////////////////////////////////////////////
60// Service Manager class 61// Module interface
61
62void Manager::AddService(Interface* service) {
63 // TOOD(yuriks): Fix error reporting
64 m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE);
65 m_services.push_back(service);
66}
67
68void Manager::DeleteService(const std::string& port_name) {
69 Interface* service = FetchFromPortName(port_name);
70 m_services.erase(std::remove(m_services.begin(), m_services.end(), service), m_services.end());
71 m_port_map.erase(port_name);
72}
73 62
74Interface* Manager::FetchFromHandle(Handle handle) { 63static void AddNamedPort(Interface* interface) {
75 // TODO(yuriks): This function is very suspicious and should probably be exterminated. 64 g_kernel_named_ports.emplace(interface->GetPortName(), interface);
76 return Kernel::g_handle_table.Get<Interface>(handle).get();
77} 65}
78 66
79Interface* Manager::FetchFromPortName(const std::string& port_name) { 67static void AddService(Interface* interface) {
80 auto itr = m_port_map.find(port_name); 68 g_srv_services.emplace(interface->GetPortName(), interface);
81 if (itr == m_port_map.end()) {
82 return nullptr;
83 }
84 return FetchFromHandle(itr->second);
85} 69}
86 70
87
88////////////////////////////////////////////////////////////////////////////////////////////////////
89// Module interface
90
91/// Initialize ServiceManager 71/// Initialize ServiceManager
92void Init() { 72void Init() {
93 g_manager = new Manager; 73 AddNamedPort(new SRV::Interface);
94 74
95 g_manager->AddService(new SRV::Interface); 75 AddService(new AC_U::Interface);
96 g_manager->AddService(new AC_U::Interface); 76 AddService(new ACT_U::Interface);
97 g_manager->AddService(new ACT_U::Interface); 77 AddService(new AM_APP::Interface);
98 g_manager->AddService(new AM_APP::Interface); 78 AddService(new AM_NET::Interface);
99 g_manager->AddService(new AM_NET::Interface); 79 AddService(new AM_SYS::Interface);
100 g_manager->AddService(new AM_SYS::Interface); 80 AddService(new APT_A::Interface);
101 g_manager->AddService(new APT_A::Interface); 81 AddService(new APT_S::Interface);
102 g_manager->AddService(new APT_S::Interface); 82 AddService(new APT_U::Interface);
103 g_manager->AddService(new APT_U::Interface); 83 AddService(new BOSS_P::Interface);
104 g_manager->AddService(new BOSS_P::Interface); 84 AddService(new BOSS_U::Interface);
105 g_manager->AddService(new BOSS_U::Interface); 85 AddService(new CAM_U::Interface);
106 g_manager->AddService(new CAM_U::Interface); 86 AddService(new CECD_S::Interface);
107 g_manager->AddService(new CECD_S::Interface); 87 AddService(new CECD_U::Interface);
108 g_manager->AddService(new CECD_U::Interface); 88 AddService(new CFG_I::Interface);
109 g_manager->AddService(new CFG_I::Interface); 89 AddService(new CFG_S::Interface);
110 g_manager->AddService(new CFG_S::Interface); 90 AddService(new CFG_U::Interface);
111 g_manager->AddService(new CFG_U::Interface); 91 AddService(new CSND_SND::Interface);
112 g_manager->AddService(new CSND_SND::Interface); 92 AddService(new DSP_DSP::Interface);
113 g_manager->AddService(new DSP_DSP::Interface); 93 AddService(new ERR_F::Interface);
114 g_manager->AddService(new ERR_F::Interface); 94 AddService(new FRD_A::Interface);
115 g_manager->AddService(new FRD_A::Interface); 95 AddService(new FRD_U::Interface);
116 g_manager->AddService(new FRD_U::Interface); 96 AddService(new FS::FSUserInterface);
117 g_manager->AddService(new FS::FSUserInterface); 97 AddService(new GSP_GPU::Interface);
118 g_manager->AddService(new GSP_GPU::Interface); 98 AddService(new GSP_LCD::Interface);
119 g_manager->AddService(new GSP_LCD::Interface); 99 AddService(new HID_User::Interface);
120 g_manager->AddService(new HID_User::Interface); 100 AddService(new HID_SPVR::Interface);
121 g_manager->AddService(new HID_SPVR::Interface); 101 AddService(new HTTP_C::Interface);
122 g_manager->AddService(new HTTP_C::Interface); 102 AddService(new IR_RST::Interface);
123 g_manager->AddService(new IR_RST::Interface); 103 AddService(new IR_U::Interface);
124 g_manager->AddService(new IR_U::Interface); 104 AddService(new LDR_RO::Interface);
125 g_manager->AddService(new LDR_RO::Interface); 105 AddService(new MIC_U::Interface);
126 g_manager->AddService(new MIC_U::Interface); 106 AddService(new NDM_U::Interface);
127 g_manager->AddService(new NDM_U::Interface); 107 AddService(new NEWS_S::Interface);
128 g_manager->AddService(new NEWS_S::Interface); 108 AddService(new NEWS_U::Interface);
129 g_manager->AddService(new NEWS_U::Interface); 109 AddService(new NIM_AOC::Interface);
130 g_manager->AddService(new NIM_AOC::Interface); 110 AddService(new NS_S::Interface);
131 g_manager->AddService(new NS_S::Interface); 111 AddService(new NWM_UDS::Interface);
132 g_manager->AddService(new NWM_UDS::Interface); 112 AddService(new PM_APP::Interface);
133 g_manager->AddService(new PM_APP::Interface); 113 AddService(new PTM_PLAY::Interface);
134 g_manager->AddService(new PTM_PLAY::Interface); 114 AddService(new PTM_U::Interface);
135 g_manager->AddService(new PTM_U::Interface); 115 AddService(new PTM_SYSM::Interface);
136 g_manager->AddService(new PTM_SYSM::Interface); 116 AddService(new SOC_U::Interface);
137 g_manager->AddService(new SOC_U::Interface); 117 AddService(new SSL_C::Interface);
138 g_manager->AddService(new SSL_C::Interface); 118 AddService(new Y2R_U::Interface);
139 g_manager->AddService(new Y2R_U::Interface);
140 119
141 LOG_DEBUG(Service, "initialized OK"); 120 LOG_DEBUG(Service, "initialized OK");
142} 121}
143 122
144/// Shutdown ServiceManager 123/// Shutdown ServiceManager
145void Shutdown() { 124void Shutdown() {
146 delete g_manager; 125 g_srv_services.clear();
126 g_kernel_named_ports.clear();
147 LOG_DEBUG(Service, "shutdown OK"); 127 LOG_DEBUG(Service, "shutdown OK");
148} 128}
149 129
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index e75d5008b..3370f9f9b 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -5,9 +5,11 @@
5#pragma once 5#pragma once
6 6
7#include <algorithm> 7#include <algorithm>
8#include <vector>
9#include <map>
10#include <string> 8#include <string>
9#include <unordered_map>
10#include <vector>
11
12#include <boost/container/flat_map.hpp>
11 13
12#include "common/common.h" 14#include "common/common.h"
13#include "common/string_util.h" 15#include "common/string_util.h"
@@ -27,7 +29,7 @@ static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 character
27class Manager; 29class Manager;
28 30
29/// Interface to a CTROS service 31/// Interface to a CTROS service
30class Interface : public Kernel::Session { 32class Interface : public Kernel::Session {
31 // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be 33 // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be
32 // just something that encapsulates a session and acts as a helper to implement service 34 // just something that encapsulates a session and acts as a helper to implement service
33 // processes. 35 // processes.
@@ -38,11 +40,11 @@ class Interface : public Kernel::Session {
38 * Creates a function string for logging, complete with the name (or header code, depending 40 * Creates a function string for logging, complete with the name (or header code, depending
39 * on what's passed in) the port name, and all the cmd_buff arguments. 41 * on what's passed in) the port name, and all the cmd_buff arguments.
40 */ 42 */
41 std::string MakeFunctionString(const std::string& name, const std::string& port_name, const u32* cmd_buff) { 43 std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) {
42 // Number of params == bits 0-5 + bits 6-11 44 // Number of params == bits 0-5 + bits 6-11
43 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); 45 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
44 46
45 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name.c_str(), port_name.c_str()); 47 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name);
46 for (int i = 1; i <= num_params; ++i) { 48 for (int i = 1; i <= num_params; ++i) {
47 function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]); 49 function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
48 } 50 }
@@ -57,7 +59,7 @@ public:
57 struct FunctionInfo { 59 struct FunctionInfo {
58 u32 id; 60 u32 id;
59 Function func; 61 Function func;
60 std::string name; 62 const char* name;
61 }; 63 };
62 64
63 /** 65 /**
@@ -68,34 +70,19 @@ public:
68 return "[UNKNOWN SERVICE PORT]"; 70 return "[UNKNOWN SERVICE PORT]";
69 } 71 }
70 72
71 /// Allocates a new handle for the service
72 Handle CreateHandle(Kernel::Object *obj) {
73 // TODO(yuriks): Fix error reporting
74 Handle handle = Kernel::g_handle_table.Create(obj).ValueOr(INVALID_HANDLE);
75 m_handles.push_back(handle);
76 return handle;
77 }
78
79 /// Frees a handle from the service
80 template <class T>
81 void DeleteHandle(const Handle handle) {
82 Kernel::g_handle_table.Close(handle);
83 m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
84 }
85
86 ResultVal<bool> SyncRequest() override { 73 ResultVal<bool> SyncRequest() override {
87 u32* cmd_buff = Kernel::GetCommandBuffer(); 74 u32* cmd_buff = Kernel::GetCommandBuffer();
88 auto itr = m_functions.find(cmd_buff[0]); 75 auto itr = m_functions.find(cmd_buff[0]);
89 76
90 if (itr == m_functions.end() || itr->second.func == nullptr) { 77 if (itr == m_functions.end() || itr->second.func == nullptr) {
91 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; 78 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
92 LOG_ERROR(Service, "%s %s", "unknown/unimplemented", MakeFunctionString(function_name, GetPortName(), cmd_buff).c_str()); 79 LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
93 80
94 // TODO(bunnei): Hack - ignore error 81 // TODO(bunnei): Hack - ignore error
95 cmd_buff[1] = 0; 82 cmd_buff[1] = 0;
96 return MakeResult<bool>(false); 83 return MakeResult<bool>(false);
97 } else { 84 } else {
98 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName(), cmd_buff).c_str()); 85 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
99 } 86 }
100 87
101 itr->second.func(this); 88 itr->second.func(this);
@@ -108,37 +95,18 @@ protected:
108 /** 95 /**
109 * Registers the functions in the service 96 * Registers the functions in the service
110 */ 97 */
111 void Register(const FunctionInfo* functions, int len) { 98 template <size_t N>
112 for (int i = 0; i < len; i++) { 99 void Register(const FunctionInfo (&functions)[N]) {
113 m_functions[functions[i].id] = functions[i]; 100 m_functions.reserve(N);
101 for (auto& fn : functions) {
102 // Usually this array is sorted by id already, so hint to instead at the end
103 m_functions.emplace_hint(m_functions.cend(), fn.id, fn);
114 } 104 }
115 } 105 }
116 106
117private: 107private:
108 boost::container::flat_map<u32, FunctionInfo> m_functions;
118 109
119 std::vector<Handle> m_handles;
120 std::map<u32, FunctionInfo> m_functions;
121
122};
123
124/// Simple class to manage accessing services from ports and UID handles
125class Manager {
126public:
127 /// Add a service to the manager
128 void AddService(Interface* service);
129
130 /// Removes a service from the manager
131 void DeleteService(const std::string& port_name);
132
133 /// Get a Service Interface from its Handle
134 Interface* FetchFromHandle(Handle handle);
135
136 /// Get a Service Interface from its port
137 Interface* FetchFromPortName(const std::string& port_name);
138
139private:
140 std::vector<Interface*> m_services;
141 std::map<std::string, u32> m_port_map;
142}; 110};
143 111
144/// Initialize ServiceManager 112/// Initialize ServiceManager
@@ -147,8 +115,9 @@ void Init();
147/// Shutdown ServiceManager 115/// Shutdown ServiceManager
148void Shutdown(); 116void Shutdown();
149 117
150 118/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC.
151extern Manager* g_manager; ///< Service manager 119extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
152 120/// Map of services registered with the "srv:" service, retrieved using GetServiceHandle.
121extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
153 122
154} // namespace 123} // namespace
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index bb8ee86be..414c53c54 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -734,7 +734,7 @@ const Interface::FunctionInfo FunctionTable[] = {
734// Interface class 734// Interface class
735 735
736Interface::Interface() { 736Interface::Interface() {
737 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 737 Register(FunctionTable);
738} 738}
739 739
740Interface::~Interface() { 740Interface::~Interface() {
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index aa0aac3bb..cc59a03ce 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -23,7 +23,7 @@ static void GetProcSemaphore(Service::Interface* self) {
23 u32* cmd_buff = Kernel::GetCommandBuffer(); 23 u32* cmd_buff = Kernel::GetCommandBuffer();
24 24
25 // TODO(bunnei): Change to a semaphore once these have been implemented 25 // TODO(bunnei): Change to a semaphore once these have been implemented
26 event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event").MoveFrom(); 26 event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event");
27 event_handle->Clear(); 27 event_handle->Clear();
28 28
29 cmd_buff[1] = 0; // No error 29 cmd_buff[1] = 0; // No error
@@ -35,10 +35,10 @@ static void GetServiceHandle(Service::Interface* self) {
35 u32* cmd_buff = Kernel::GetCommandBuffer(); 35 u32* cmd_buff = Kernel::GetCommandBuffer();
36 36
37 std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); 37 std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
38 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); 38 auto it = Service::g_srv_services.find(port_name);
39 39
40 if (nullptr != service) { 40 if (it != Service::g_srv_services.end()) {
41 cmd_buff[3] = service->GetHandle(); 41 cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom();
42 LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); 42 LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]);
43 } else { 43 } else {
44 LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); 44 LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str());
@@ -63,7 +63,7 @@ const Interface::FunctionInfo FunctionTable[] = {
63// Interface class 63// Interface class
64 64
65Interface::Interface() { 65Interface::Interface() {
66 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 66 Register(FunctionTable);
67} 67}
68 68
69} // namespace 69} // namespace
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index 360516cdf..3f49c1c97 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
22// Interface class 22// Interface class
23 23
24Interface::Interface() { 24Interface::Interface() {
25 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 25 Register(FunctionTable);
26} 26}
27 27
28} // namespace 28} // namespace
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index b3d873ef0..fc76d2721 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -54,7 +54,7 @@ const Interface::FunctionInfo FunctionTable[] = {
54// Interface class 54// Interface class
55 55
56Interface::Interface() { 56Interface::Interface() {
57 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 57 Register(FunctionTable);
58} 58}
59 59
60} // namespace 60} // namespace
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 88813c2ce..96da29923 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -30,6 +30,11 @@ using Kernel::ERR_INVALID_HANDLE;
30 30
31namespace SVC { 31namespace SVC {
32 32
33const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
34 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
35const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
36 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E
37
33/// An invalid result code that is meant to be overwritten when a thread resumes from waiting 38/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
34const ResultCode RESULT_INVALID(0xDEADC0DE); 39const ResultCode RESULT_INVALID(0xDEADC0DE);
35 40
@@ -94,14 +99,21 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
94} 99}
95 100
96/// Connect to an OS service given the port name, returns the handle to the port to out 101/// Connect to an OS service given the port name, returns the handle to the port to out
97static ResultCode ConnectToPort(Handle* out, const char* port_name) { 102static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) {
98 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); 103 if (port_name == nullptr)
104 return ERR_NOT_FOUND;
105 if (std::strlen(port_name) > 11)
106 return ERR_PORT_NAME_TOO_LONG;
99 107
100 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); 108 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name);
101 _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!");
102 109
103 *out = service->GetHandle(); 110 auto it = Service::g_kernel_named_ports.find(port_name);
111 if (it == Service::g_kernel_named_ports.end()) {
112 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name);
113 return ERR_NOT_FOUND;
114 }
104 115
116 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(it->second));
105 return RESULT_SUCCESS; 117 return RESULT_SUCCESS;
106} 118}
107 119
@@ -119,9 +131,8 @@ static ResultCode SendSyncRequest(Handle handle) {
119 131
120/// Close a handle 132/// Close a handle
121static ResultCode CloseHandle(Handle handle) { 133static ResultCode CloseHandle(Handle handle) {
122 // ImplementMe 134 LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle);
123 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); 135 return Kernel::g_handle_table.Close(handle);
124 return RESULT_SUCCESS;
125} 136}
126 137
127/// Wait for a handle to synchronize, timeout after the specified nanoseconds 138/// Wait for a handle to synchronize, timeout after the specified nanoseconds
@@ -133,16 +144,16 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
133 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, 144 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
134 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); 145 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
135 146
147 HLE::Reschedule(__func__);
148
136 // Check for next thread to schedule 149 // Check for next thread to schedule
137 if (object->ShouldWait()) { 150 if (object->ShouldWait()) {
138 151
139 object->AddWaitingThread(Kernel::GetCurrentThread()); 152 object->AddWaitingThread(Kernel::GetCurrentThread());
140 Kernel::WaitCurrentThread_WaitSynchronization(object, false, false); 153 Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false);
141 154
142 // Create an event to wake the thread up after the specified nanosecond delay has passed 155 // Create an event to wake the thread up after the specified nanosecond delay has passed
143 Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); 156 Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds);
144
145 HLE::Reschedule(__func__);
146 157
147 // NOTE: output of this SVC will be set later depending on how the thread resumes 158 // NOTE: output of this SVC will be set later depending on how the thread resumes
148 return RESULT_INVALID; 159 return RESULT_INVALID;
@@ -201,24 +212,28 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
201 // NOTE: This should deadlock the current thread if no timeout was specified 212 // NOTE: This should deadlock the current thread if no timeout was specified
202 if (!wait_all) { 213 if (!wait_all) {
203 wait_thread = true; 214 wait_thread = true;
204 Kernel::WaitCurrentThread_WaitSynchronization(nullptr, true, wait_all);
205 } 215 }
206 } 216 }
207 217
218 HLE::Reschedule(__func__);
219
208 // If thread should wait, then set its state to waiting and then reschedule... 220 // If thread should wait, then set its state to waiting and then reschedule...
209 if (wait_thread) { 221 if (wait_thread) {
210 222
211 // Actually wait the current thread on each object if we decided to wait... 223 // Actually wait the current thread on each object if we decided to wait...
224 std::vector<SharedPtr<Kernel::WaitObject>> wait_objects;
225 wait_objects.reserve(handle_count);
226
212 for (int i = 0; i < handle_count; ++i) { 227 for (int i = 0; i < handle_count; ++i) {
213 auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); 228 auto object = Kernel::g_handle_table.GetWaitObject(handles[i]);
214 object->AddWaitingThread(Kernel::GetCurrentThread()); 229 object->AddWaitingThread(Kernel::GetCurrentThread());
215 Kernel::WaitCurrentThread_WaitSynchronization(object, true, wait_all); 230 wait_objects.push_back(object);
216 } 231 }
217 232
218 // Create an event to wake the thread up after the specified nanosecond delay has passed 233 Kernel::WaitCurrentThread_WaitSynchronization(std::move(wait_objects), true, wait_all);
219 Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds);
220 234
221 HLE::Reschedule(__func__); 235 // Create an event to wake the thread up after the specified nanosecond delay has passed
236 Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds);
222 237
223 // NOTE: output of this SVC will be set later depending on how the thread resumes 238 // NOTE: output of this SVC will be set later depending on how the thread resumes
224 return RESULT_INVALID; 239 return RESULT_INVALID;
@@ -250,7 +265,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
250static ResultCode CreateAddressArbiter(Handle* out_handle) { 265static ResultCode CreateAddressArbiter(Handle* out_handle) {
251 using Kernel::AddressArbiter; 266 using Kernel::AddressArbiter;
252 267
253 CASCADE_RESULT(SharedPtr<AddressArbiter> arbiter, AddressArbiter::Create()); 268 SharedPtr<AddressArbiter> arbiter = AddressArbiter::Create();
254 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter))); 269 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter)));
255 LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle); 270 LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle);
256 return RESULT_SUCCESS; 271 return RESULT_SUCCESS;
@@ -308,7 +323,7 @@ static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u
308 } 323 }
309 324
310 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( 325 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(
311 name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE)); 326 name, entry_point, priority, arg, processor_id, stack_top));
312 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); 327 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread)));
313 328
314 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 329 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
@@ -327,7 +342,7 @@ static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u
327static void ExitThread() { 342static void ExitThread() {
328 LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); 343 LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC());
329 344
330 Kernel::GetCurrentThread()->Stop(__func__); 345 Kernel::GetCurrentThread()->Stop();
331 HLE::Reschedule(__func__); 346 HLE::Reschedule(__func__);
332} 347}
333 348
@@ -355,7 +370,7 @@ static ResultCode SetThreadPriority(Handle handle, s32 priority) {
355static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { 370static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
356 using Kernel::Mutex; 371 using Kernel::Mutex;
357 372
358 CASCADE_RESULT(SharedPtr<Mutex> mutex, Mutex::Create(initial_locked != 0)); 373 SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0);
359 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); 374 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
360 375
361 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 376 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
@@ -423,7 +438,9 @@ static ResultCode QueryMemory(void* info, void* out, u32 addr) {
423 438
424/// Create an event 439/// Create an event
425static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { 440static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
426 CASCADE_RESULT(auto evt, Kernel::Event::Create(static_cast<ResetType>(reset_type))); 441 using Kernel::Event;
442
443 SharedPtr<Event> evt = Kernel::Event::Create(static_cast<ResetType>(reset_type));
427 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); 444 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
428 445
429 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 446 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
@@ -433,19 +450,17 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
433 450
434/// Duplicates a kernel handle 451/// Duplicates a kernel handle
435static ResultCode DuplicateHandle(Handle* out, Handle handle) { 452static ResultCode DuplicateHandle(Handle* out, Handle handle) {
436 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle); 453 CASCADE_RESULT(*out, Kernel::g_handle_table.Duplicate(handle));
437 if (out_h.Succeeded()) { 454 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
438 *out = *out_h; 455 return RESULT_SUCCESS;
439 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
440 }
441 return out_h.Code();
442} 456}
443 457
444/// Signals an event 458/// Signals an event
445static ResultCode SignalEvent(Handle handle) { 459static ResultCode SignalEvent(Handle handle) {
460 using Kernel::Event;
446 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); 461 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
447 462
448 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); 463 SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
449 if (evt == nullptr) 464 if (evt == nullptr)
450 return ERR_INVALID_HANDLE; 465 return ERR_INVALID_HANDLE;
451 466
@@ -456,9 +471,10 @@ static ResultCode SignalEvent(Handle handle) {
456 471
457/// Clears an event 472/// Clears an event
458static ResultCode ClearEvent(Handle handle) { 473static ResultCode ClearEvent(Handle handle) {
474 using Kernel::Event;
459 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); 475 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
460 476
461 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); 477 SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
462 if (evt == nullptr) 478 if (evt == nullptr)
463 return ERR_INVALID_HANDLE; 479 return ERR_INVALID_HANDLE;
464 480
@@ -470,7 +486,7 @@ static ResultCode ClearEvent(Handle handle) {
470static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { 486static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
471 using Kernel::Timer; 487 using Kernel::Timer;
472 488
473 CASCADE_RESULT(auto timer, Timer::Create(static_cast<ResetType>(reset_type))); 489 SharedPtr<Timer> timer = Timer::Create(static_cast<ResetType>(reset_type));
474 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); 490 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
475 491
476 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 492 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
@@ -528,7 +544,7 @@ static void SleepThread(s64 nanoseconds) {
528 Kernel::WaitCurrentThread_Sleep(); 544 Kernel::WaitCurrentThread_Sleep();
529 545
530 // Create an event to wake the thread up after the specified nanosecond delay has passed 546 // Create an event to wake the thread up after the specified nanosecond delay has passed
531 Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds); 547 Kernel::GetCurrentThread()->WakeAfterDelay(nanoseconds);
532 548
533 HLE::Reschedule(__func__); 549 HLE::Reschedule(__func__);
534} 550}
@@ -544,7 +560,7 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
544 using Kernel::SharedMemory; 560 using Kernel::SharedMemory;
545 // TODO(Subv): Implement this function 561 // TODO(Subv): Implement this function
546 562
547 CASCADE_RESULT(auto shared_memory, SharedMemory::Create()); 563 SharedPtr<SharedMemory> shared_memory = SharedMemory::Create();
548 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); 564 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
549 565
550 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); 566 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr);
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 58eec3005..aad0e5d0d 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -202,8 +202,6 @@ template void Write<u8>(u32 addr, const u8 data);
202 202
203/// Update hardware 203/// Update hardware
204static void VBlankCallback(u64 userdata, int cycles_late) { 204static void VBlankCallback(u64 userdata, int cycles_late) {
205 auto& framebuffer_top = g_regs.framebuffer_config[0];
206
207 frame_count++; 205 frame_count++;
208 last_skip_frame = g_skip_frame; 206 last_skip_frame = g_skip_frame;
209 g_skip_frame = (frame_count & Settings::values.frame_skip) != 0; 207 g_skip_frame = (frame_count & Settings::values.frame_skip) != 0;
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index e7e5df408..773eaf771 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -212,7 +212,7 @@ public:
212 return GetPtr(segments[segment].p_offset); 212 return GetPtr(segments[segment].p_offset);
213 } 213 }
214 u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; } 214 u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; }
215 int GetSectionSize(SectionID section) const { return sections[section].sh_size; } 215 unsigned int GetSectionSize(SectionID section) const { return sections[section].sh_size; }
216 SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found 216 SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found
217 217
218 bool DidRelocate() const { 218 bool DidRelocate() const {
@@ -298,7 +298,7 @@ bool ElfReader::LoadSymbols() {
298 298
299 //We have a symbol table! 299 //We have a symbol table!
300 Elf32_Sym* symtab = (Elf32_Sym *)(GetSectionDataPtr(sec)); 300 Elf32_Sym* symtab = (Elf32_Sym *)(GetSectionDataPtr(sec));
301 int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); 301 unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
302 for (unsigned sym = 0; sym < numSymbols; sym++) { 302 for (unsigned sym = 0; sym < numSymbols; sym++) {
303 int size = symtab[sym].st_size; 303 int size = symtab[sym].st_size;
304 if (size == 0) 304 if (size == 0)
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 52730a7b4..94dcc50f9 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -127,7 +127,7 @@ ResultStatus LoadFile(const std::string& filename) {
127 // Load application and RomFS 127 // Load application and RomFS
128 if (ResultStatus::Success == app_loader.Load()) { 128 if (ResultStatus::Success == app_loader.Load()) {
129 Kernel::g_program_id = app_loader.GetProgramId(); 129 Kernel::g_program_id = app_loader.GetProgramId();
130 Service::FS::CreateArchive(Common::make_unique<FileSys::Archive_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS); 130 Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
131 return ResultStatus::Success; 131 return ResultStatus::Success;
132 } 132 }
133 break; 133 break;
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 7456b019b..3510c6b28 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -38,7 +38,7 @@ enum class ResultStatus {
38 ErrorMemoryAllocationFailed, 38 ErrorMemoryAllocationFailed,
39}; 39};
40 40
41static u32 MakeMagic(char a, char b, char c, char d) { 41static inline u32 MakeMagic(char a, char b, char c, char d) {
42 return a | b << 8 | c << 16 | d << 24; 42 return a | b << 8 | c << 16 | d << 24;
43} 43}
44 44
diff --git a/src/core/settings.h b/src/core/settings.h
index 9b52be259..e62dd4358 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -29,7 +29,6 @@ struct Values {
29 int pad_sright_key; 29 int pad_sright_key;
30 30
31 // Core 31 // Core
32 int cpu_core;
33 int gpu_refresh_rate; 32 int gpu_refresh_rate;
34 int frame_skip; 33 int frame_skip;
35 34
diff --git a/src/video_core/math.h b/src/video_core/math.h
index 9622e7614..c176b225a 100644
--- a/src/video_core/math.h
+++ b/src/video_core/math.h
@@ -457,27 +457,41 @@ public:
457 const T& b() const { return z; } 457 const T& b() const { return z; }
458 const T& a() const { return w; } 458 const T& a() const { return w; }
459 459
460 // swizzlers - create a subvector of specific components 460 // Swizzlers - Create a subvector of specific components
461 // e.g. Vec2 uv() { return Vec2(x,y); } 461 // e.g. Vec2 uv() { return Vec2(x,y); }
462 // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all component names (x<->r) and permutations (xy<->yx) 462
463 // _DEFINE_SWIZZLER2 defines a single such function
464 // DEFINE_SWIZZLER2_COMP1 defines one-component functions for all component names (x<->r)
465 // DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and permutations (xy<->yx)
463#define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); } 466#define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); }
464#define DEFINE_SWIZZLER2(a, b, a2, b2) \ 467#define DEFINE_SWIZZLER2_COMP1(a, a2) \
468 _DEFINE_SWIZZLER2(a, a, a##a); \
469 _DEFINE_SWIZZLER2(a, a, a2##a2)
470#define DEFINE_SWIZZLER2_COMP2(a, b, a2, b2) \
465 _DEFINE_SWIZZLER2(a, b, a##b); \ 471 _DEFINE_SWIZZLER2(a, b, a##b); \
466 _DEFINE_SWIZZLER2(a, b, a2##b2); \ 472 _DEFINE_SWIZZLER2(a, b, a2##b2); \
467 _DEFINE_SWIZZLER2(b, a, b##a); \ 473 _DEFINE_SWIZZLER2(b, a, b##a); \
468 _DEFINE_SWIZZLER2(b, a, b2##a2) 474 _DEFINE_SWIZZLER2(b, a, b2##a2)
469 475
470 DEFINE_SWIZZLER2(x, y, r, g); 476 DEFINE_SWIZZLER2_COMP2(x, y, r, g);
471 DEFINE_SWIZZLER2(x, z, r, b); 477 DEFINE_SWIZZLER2_COMP2(x, z, r, b);
472 DEFINE_SWIZZLER2(x, w, r, a); 478 DEFINE_SWIZZLER2_COMP2(x, w, r, a);
473 DEFINE_SWIZZLER2(y, z, g, b); 479 DEFINE_SWIZZLER2_COMP2(y, z, g, b);
474 DEFINE_SWIZZLER2(y, w, g, a); 480 DEFINE_SWIZZLER2_COMP2(y, w, g, a);
475 DEFINE_SWIZZLER2(z, w, b, a); 481 DEFINE_SWIZZLER2_COMP2(z, w, b, a);
476#undef DEFINE_SWIZZLER2 482 DEFINE_SWIZZLER2_COMP1(x, r);
483 DEFINE_SWIZZLER2_COMP1(y, g);
484 DEFINE_SWIZZLER2_COMP1(z, b);
485 DEFINE_SWIZZLER2_COMP1(w, a);
486#undef DEFINE_SWIZZLER2_COMP1
487#undef DEFINE_SWIZZLER2_COMP2
477#undef _DEFINE_SWIZZLER2 488#undef _DEFINE_SWIZZLER2
478 489
479#define _DEFINE_SWIZZLER3(a, b, c, name) const Vec3<T> name() const { return Vec3<T>(a, b, c); } 490#define _DEFINE_SWIZZLER3(a, b, c, name) const Vec3<T> name() const { return Vec3<T>(a, b, c); }
480#define DEFINE_SWIZZLER3(a, b, c, a2, b2, c2) \ 491#define DEFINE_SWIZZLER3_COMP1(a, a2) \
492 _DEFINE_SWIZZLER3(a, a, a, a##a##a); \
493 _DEFINE_SWIZZLER3(a, a, a, a2##a2##a2)
494#define DEFINE_SWIZZLER3_COMP3(a, b, c, a2, b2, c2) \
481 _DEFINE_SWIZZLER3(a, b, c, a##b##c); \ 495 _DEFINE_SWIZZLER3(a, b, c, a##b##c); \
482 _DEFINE_SWIZZLER3(a, c, b, a##c##b); \ 496 _DEFINE_SWIZZLER3(a, c, b, a##c##b); \
483 _DEFINE_SWIZZLER3(b, a, c, b##a##c); \ 497 _DEFINE_SWIZZLER3(b, a, c, b##a##c); \
@@ -491,11 +505,16 @@ public:
491 _DEFINE_SWIZZLER3(c, a, b, c2##a2##b2); \ 505 _DEFINE_SWIZZLER3(c, a, b, c2##a2##b2); \
492 _DEFINE_SWIZZLER3(c, b, a, c2##b2##a2) 506 _DEFINE_SWIZZLER3(c, b, a, c2##b2##a2)
493 507
494 DEFINE_SWIZZLER3(x, y, z, r, g, b); 508 DEFINE_SWIZZLER3_COMP3(x, y, z, r, g, b);
495 DEFINE_SWIZZLER3(x, y, w, r, g, a); 509 DEFINE_SWIZZLER3_COMP3(x, y, w, r, g, a);
496 DEFINE_SWIZZLER3(x, z, w, r, b, a); 510 DEFINE_SWIZZLER3_COMP3(x, z, w, r, b, a);
497 DEFINE_SWIZZLER3(y, z, w, g, b, a); 511 DEFINE_SWIZZLER3_COMP3(y, z, w, g, b, a);
498#undef DEFINE_SWIZZLER3 512 DEFINE_SWIZZLER3_COMP1(x, r);
513 DEFINE_SWIZZLER3_COMP1(y, g);
514 DEFINE_SWIZZLER3_COMP1(z, b);
515 DEFINE_SWIZZLER3_COMP1(w, a);
516#undef DEFINE_SWIZZLER3_COMP1
517#undef DEFINE_SWIZZLER3_COMP3
499#undef _DEFINE_SWIZZLER3 518#undef _DEFINE_SWIZZLER3
500}; 519};
501 520
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 78603ebdf..9c1a12dc8 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -233,19 +233,29 @@ struct Regs {
233 }; 233 };
234 234
235 enum class ColorModifier : u32 { 235 enum class ColorModifier : u32 {
236 SourceColor = 0, 236 SourceColor = 0x0,
237 OneMinusSourceColor = 1, 237 OneMinusSourceColor = 0x1,
238 SourceAlpha = 2, 238 SourceAlpha = 0x2,
239 OneMinusSourceAlpha = 3, 239 OneMinusSourceAlpha = 0x3,
240 240 SourceRed = 0x4,
241 // Other values seem to be non-standard extensions 241 OneMinusSourceRed = 0x5,
242
243 SourceGreen = 0x8,
244 OneMinusSourceGreen = 0x9,
245
246 SourceBlue = 0xc,
247 OneMinusSourceBlue = 0xd,
242 }; 248 };
243 249
244 enum class AlphaModifier : u32 { 250 enum class AlphaModifier : u32 {
245 SourceAlpha = 0, 251 SourceAlpha = 0x0,
246 OneMinusSourceAlpha = 1, 252 OneMinusSourceAlpha = 0x1,
247 253 SourceRed = 0x2,
248 // Other values seem to be non-standard extensions 254 OneMinusSourceRed = 0x3,
255 SourceGreen = 0x4,
256 OneMinusSourceGreen = 0x5,
257 SourceBlue = 0x6,
258 OneMinusSourceBlue = 0x7,
249 }; 259 };
250 260
251 enum class Operation : u32 { 261 enum class Operation : u32 {
@@ -328,15 +338,29 @@ struct Regs {
328 338
329 union { 339 union {
330 enum BlendEquation : u32 { 340 enum BlendEquation : u32 {
331 Add = 0, 341 Add = 0,
342 Subtract = 1,
343 ReverseSubtract = 2,
344 Min = 3,
345 Max = 4
332 }; 346 };
333 347
334 enum BlendFactor : u32 { 348 enum BlendFactor : u32 {
335 Zero = 0, 349 Zero = 0,
336 One = 1, 350 One = 1,
337 351 SourceColor = 2,
338 SourceAlpha = 6, 352 OneMinusSourceColor = 3,
339 OneMinusSourceAlpha = 7, 353 DestColor = 4,
354 OneMinusDestColor = 5,
355 SourceAlpha = 6,
356 OneMinusSourceAlpha = 7,
357 DestAlpha = 8,
358 OneMinusDestAlpha = 9,
359 ConstantColor = 10,
360 OneMinusConstantColor = 11,
361 ConstantAlpha = 12,
362 OneMinusConstantAlpha = 13,
363 SourceAlphaSaturate = 14
340 }; 364 };
341 365
342 BitField< 0, 8, BlendEquation> blend_equation_rgb; 366 BitField< 0, 8, BlendEquation> blend_equation_rgb;
@@ -357,7 +381,12 @@ struct Regs {
357 BitField<0, 4, Op> op; 381 BitField<0, 4, Op> op;
358 } logic_op; 382 } logic_op;
359 383
360 INSERT_PADDING_WORDS(0x1); 384 union {
385 BitField< 0, 8, u32> r;
386 BitField< 8, 8, u32> g;
387 BitField<16, 8, u32> b;
388 BitField<24, 8, u32> a;
389 } blend_const;
361 390
362 union { 391 union {
363 BitField< 0, 1, u32> enable; 392 BitField< 0, 1, u32> enable;
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 7f66c6d42..06fd8d140 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -260,7 +260,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
260 using AlphaModifier = Regs::TevStageConfig::AlphaModifier; 260 using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
261 using Operation = Regs::TevStageConfig::Operation; 261 using Operation = Regs::TevStageConfig::Operation;
262 262
263 auto GetColorSource = [&](Source source) -> Math::Vec4<u8> { 263 auto GetSource = [&](Source source) -> Math::Vec4<u8> {
264 switch (source) { 264 switch (source) {
265 case Source::PrimaryColor: 265 case Source::PrimaryColor:
266 return primary_color; 266 return primary_color;
@@ -287,36 +287,8 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
287 } 287 }
288 }; 288 };
289 289
290 auto GetAlphaSource = [&](Source source) -> u8 {
291 switch (source) {
292 case Source::PrimaryColor:
293 return primary_color.a();
294
295 case Source::Texture0:
296 return texture_color[0].a();
297
298 case Source::Texture1:
299 return texture_color[1].a();
300
301 case Source::Texture2:
302 return texture_color[2].a();
303
304 case Source::Constant:
305 return tev_stage.const_a;
306
307 case Source::Previous:
308 return combiner_output.a();
309
310 default:
311 LOG_ERROR(HW_GPU, "Unknown alpha combiner source %d\n", (int)source);
312 _dbg_assert_(HW_GPU, 0);
313 return 0;
314 }
315 };
316
317 static auto GetColorModifier = [](ColorModifier factor, const Math::Vec4<u8>& values) -> Math::Vec3<u8> { 290 static auto GetColorModifier = [](ColorModifier factor, const Math::Vec4<u8>& values) -> Math::Vec3<u8> {
318 switch (factor) 291 switch (factor) {
319 {
320 case ColorModifier::SourceColor: 292 case ColorModifier::SourceColor:
321 return values.rgb(); 293 return values.rgb();
322 294
@@ -324,27 +296,56 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
324 return (Math::Vec3<u8>(255, 255, 255) - values.rgb()).Cast<u8>(); 296 return (Math::Vec3<u8>(255, 255, 255) - values.rgb()).Cast<u8>();
325 297
326 case ColorModifier::SourceAlpha: 298 case ColorModifier::SourceAlpha:
327 return { values.a(), values.a(), values.a() }; 299 return values.aaa();
328 300
329 default: 301 case ColorModifier::OneMinusSourceAlpha:
330 LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor); 302 return (Math::Vec3<u8>(255, 255, 255) - values.aaa()).Cast<u8>();
331 _dbg_assert_(HW_GPU, 0); 303
332 return {}; 304 case ColorModifier::SourceRed:
305 return values.rrr();
306
307 case ColorModifier::OneMinusSourceRed:
308 return (Math::Vec3<u8>(255, 255, 255) - values.rrr()).Cast<u8>();
309
310 case ColorModifier::SourceGreen:
311 return values.ggg();
312
313 case ColorModifier::OneMinusSourceGreen:
314 return (Math::Vec3<u8>(255, 255, 255) - values.ggg()).Cast<u8>();
315
316 case ColorModifier::SourceBlue:
317 return values.bbb();
318
319 case ColorModifier::OneMinusSourceBlue:
320 return (Math::Vec3<u8>(255, 255, 255) - values.bbb()).Cast<u8>();
333 } 321 }
334 }; 322 };
335 323
336 static auto GetAlphaModifier = [](AlphaModifier factor, u8 value) -> u8 { 324 static auto GetAlphaModifier = [](AlphaModifier factor, const Math::Vec4<u8>& values) -> u8 {
337 switch (factor) { 325 switch (factor) {
338 case AlphaModifier::SourceAlpha: 326 case AlphaModifier::SourceAlpha:
339 return value; 327 return values.a();
340 328
341 case AlphaModifier::OneMinusSourceAlpha: 329 case AlphaModifier::OneMinusSourceAlpha:
342 return 255 - value; 330 return 255 - values.a();
343 331
344 default: 332 case AlphaModifier::SourceRed:
345 LOG_ERROR(HW_GPU, "Unknown alpha factor %d\n", (int)factor); 333 return values.r();
346 _dbg_assert_(HW_GPU, 0); 334
347 return 0; 335 case AlphaModifier::OneMinusSourceRed:
336 return 255 - values.r();
337
338 case AlphaModifier::SourceGreen:
339 return values.g();
340
341 case AlphaModifier::OneMinusSourceGreen:
342 return 255 - values.g();
343
344 case AlphaModifier::SourceBlue:
345 return values.b();
346
347 case AlphaModifier::OneMinusSourceBlue:
348 return 255 - values.b();
348 } 349 }
349 }; 350 };
350 351
@@ -414,17 +415,17 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
414 // combiner_output.rgb(), but instead store it in a temporary variable until 415 // combiner_output.rgb(), but instead store it in a temporary variable until
415 // alpha combining has been done. 416 // alpha combining has been done.
416 Math::Vec3<u8> color_result[3] = { 417 Math::Vec3<u8> color_result[3] = {
417 GetColorModifier(tev_stage.color_modifier1, GetColorSource(tev_stage.color_source1)), 418 GetColorModifier(tev_stage.color_modifier1, GetSource(tev_stage.color_source1)),
418 GetColorModifier(tev_stage.color_modifier2, GetColorSource(tev_stage.color_source2)), 419 GetColorModifier(tev_stage.color_modifier2, GetSource(tev_stage.color_source2)),
419 GetColorModifier(tev_stage.color_modifier3, GetColorSource(tev_stage.color_source3)) 420 GetColorModifier(tev_stage.color_modifier3, GetSource(tev_stage.color_source3))
420 }; 421 };
421 auto color_output = ColorCombine(tev_stage.color_op, color_result); 422 auto color_output = ColorCombine(tev_stage.color_op, color_result);
422 423
423 // alpha combiner 424 // alpha combiner
424 std::array<u8,3> alpha_result = { 425 std::array<u8,3> alpha_result = {
425 GetAlphaModifier(tev_stage.alpha_modifier1, GetAlphaSource(tev_stage.alpha_source1)), 426 GetAlphaModifier(tev_stage.alpha_modifier1, GetSource(tev_stage.alpha_source1)),
426 GetAlphaModifier(tev_stage.alpha_modifier2, GetAlphaSource(tev_stage.alpha_source2)), 427 GetAlphaModifier(tev_stage.alpha_modifier2, GetSource(tev_stage.alpha_source2)),
427 GetAlphaModifier(tev_stage.alpha_modifier3, GetAlphaSource(tev_stage.alpha_source3)) 428 GetAlphaModifier(tev_stage.alpha_modifier3, GetSource(tev_stage.alpha_source3))
428 }; 429 };
429 auto alpha_output = AlphaCombine(tev_stage.alpha_op, alpha_result); 430 auto alpha_output = AlphaCombine(tev_stage.alpha_op, alpha_result);
430 431
@@ -528,18 +529,48 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
528 auto params = registers.output_merger.alpha_blending; 529 auto params = registers.output_merger.alpha_blending;
529 530
530 auto LookupFactorRGB = [&](decltype(params)::BlendFactor factor) -> Math::Vec3<u8> { 531 auto LookupFactorRGB = [&](decltype(params)::BlendFactor factor) -> Math::Vec3<u8> {
531 switch(factor) { 532 switch (factor) {
532 case params.Zero: 533 case params.Zero:
533 return Math::Vec3<u8>(0, 0, 0); 534 return Math::Vec3<u8>(0, 0, 0);
534 535
535 case params.One: 536 case params.One:
536 return Math::Vec3<u8>(255, 255, 255); 537 return Math::Vec3<u8>(255, 255, 255);
537 538
539 case params.SourceColor:
540 return combiner_output.rgb();
541
542 case params.OneMinusSourceColor:
543 return Math::Vec3<u8>(255 - combiner_output.r(), 255 - combiner_output.g(), 255 - combiner_output.b());
544
545 case params.DestColor:
546 return dest.rgb();
547
548 case params.OneMinusDestColor:
549 return Math::Vec3<u8>(255 - dest.r(), 255 - dest.g(), 255 - dest.b());
550
538 case params.SourceAlpha: 551 case params.SourceAlpha:
539 return Math::MakeVec(combiner_output.a(), combiner_output.a(), combiner_output.a()); 552 return Math::Vec3<u8>(combiner_output.a(), combiner_output.a(), combiner_output.a());
540 553
541 case params.OneMinusSourceAlpha: 554 case params.OneMinusSourceAlpha:
542 return Math::Vec3<u8>(255-combiner_output.a(), 255-combiner_output.a(), 255-combiner_output.a()); 555 return Math::Vec3<u8>(255 - combiner_output.a(), 255 - combiner_output.a(), 255 - combiner_output.a());
556
557 case params.DestAlpha:
558 return Math::Vec3<u8>(dest.a(), dest.a(), dest.a());
559
560 case params.OneMinusDestAlpha:
561 return Math::Vec3<u8>(255 - dest.a(), 255 - dest.a(), 255 - dest.a());
562
563 case params.ConstantColor:
564 return Math::Vec3<u8>(registers.output_merger.blend_const.r, registers.output_merger.blend_const.g, registers.output_merger.blend_const.b);
565
566 case params.OneMinusConstantColor:
567 return Math::Vec3<u8>(255 - registers.output_merger.blend_const.r, 255 - registers.output_merger.blend_const.g, 255 - registers.output_merger.blend_const.b);
568
569 case params.ConstantAlpha:
570 return Math::Vec3<u8>(registers.output_merger.blend_const.a, registers.output_merger.blend_const.a, registers.output_merger.blend_const.a);
571
572 case params.OneMinusConstantAlpha:
573 return Math::Vec3<u8>(255 - registers.output_merger.blend_const.a, 255 - registers.output_merger.blend_const.a, 255 - registers.output_merger.blend_const.a);
543 574
544 default: 575 default:
545 LOG_CRITICAL(HW_GPU, "Unknown color blend factor %x", factor); 576 LOG_CRITICAL(HW_GPU, "Unknown color blend factor %x", factor);
@@ -549,7 +580,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
549 }; 580 };
550 581
551 auto LookupFactorA = [&](decltype(params)::BlendFactor factor) -> u8 { 582 auto LookupFactorA = [&](decltype(params)::BlendFactor factor) -> u8 {
552 switch(factor) { 583 switch (factor) {
553 case params.Zero: 584 case params.Zero:
554 return 0; 585 return 0;
555 586
@@ -562,6 +593,18 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
562 case params.OneMinusSourceAlpha: 593 case params.OneMinusSourceAlpha:
563 return 255 - combiner_output.a(); 594 return 255 - combiner_output.a();
564 595
596 case params.DestAlpha:
597 return dest.a();
598
599 case params.OneMinusDestAlpha:
600 return 255 - dest.a();
601
602 case params.ConstantAlpha:
603 return registers.output_merger.blend_const.a;
604
605 case params.OneMinusConstantAlpha:
606 return 255 - registers.output_merger.blend_const.a;
607
565 default: 608 default:
566 LOG_CRITICAL(HW_GPU, "Unknown alpha blend factor %x", factor); 609 LOG_CRITICAL(HW_GPU, "Unknown alpha blend factor %x", factor);
567 exit(0); 610 exit(0);
@@ -573,17 +616,60 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
573 LookupFactorA(params.factor_source_a)); 616 LookupFactorA(params.factor_source_a));
574 auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb), 617 auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb),
575 LookupFactorA(params.factor_dest_a)); 618 LookupFactorA(params.factor_dest_a));
619
620 auto src_result = (combiner_output * srcfactor).Cast<int>();
621 auto dst_result = (dest * dstfactor).Cast<int>();
576 622
577 switch (params.blend_equation_rgb) { 623 switch (params.blend_equation_rgb) {
578 case params.Add: 624 case params.Add:
579 { 625 {
580 auto result = (combiner_output * srcfactor + dest * dstfactor) / 255; 626 auto result = (src_result + dst_result) / 255;
581 result.r() = std::min(255, result.r()); 627 result.r() = std::min(255, result.r());
582 result.g() = std::min(255, result.g()); 628 result.g() = std::min(255, result.g());
583 result.b() = std::min(255, result.b()); 629 result.b() = std::min(255, result.b());
584 combiner_output = result.Cast<u8>(); 630 combiner_output = result.Cast<u8>();
585 break; 631 break;
586 } 632 }
633
634 case params.Subtract:
635 {
636 auto result = (src_result - dst_result) / 255;
637 result.r() = std::max(0, result.r());
638 result.g() = std::max(0, result.g());
639 result.b() = std::max(0, result.b());
640 combiner_output = result.Cast<u8>();
641 break;
642 }
643
644 case params.ReverseSubtract:
645 {
646 auto result = (dst_result - src_result) / 255;
647 result.r() = std::max(0, result.r());
648 result.g() = std::max(0, result.g());
649 result.b() = std::max(0, result.b());
650 combiner_output = result.Cast<u8>();
651 break;
652 }
653
654 case params.Min:
655 {
656 Math::Vec4<int> result;
657 result.r() = std::min(src_result.r(),dst_result.r());
658 result.g() = std::min(src_result.g(),dst_result.g());
659 result.b() = std::min(src_result.b(),dst_result.b());
660 combiner_output = result.Cast<u8>();
661 break;
662 }
663
664 case params.Max:
665 {
666 Math::Vec4<int> result;
667 result.r() = std::max(src_result.r(),dst_result.r());
668 result.g() = std::max(src_result.g(),dst_result.g());
669 result.b() = std::max(src_result.b(),dst_result.b());
670 combiner_output = result.Cast<u8>();
671 break;
672 }
587 673
588 default: 674 default:
589 LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", params.blend_equation_rgb.Value()); 675 LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", params.blend_equation_rgb.Value());