summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints_p.h2
-rw-r--r--src/citra_qt/debugger/profiler.cpp4
-rw-r--r--src/citra_qt/debugger/profiler.h2
-rw-r--r--src/citra_qt/util/spinbox.cpp3
-rw-r--r--src/common/thread.h81
-rw-r--r--src/common/thread_queue_list.h18
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp6
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h2
-rw-r--r--src/core/arm/interpreter/armcopro.cpp142
-rw-r--r--src/core/arm/interpreter/arminit.cpp37
-rw-r--r--src/core/arm/skyeye_common/armdefs.h79
-rw-r--r--src/core/arm/skyeye_common/armemu.h21
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp621
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h22
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h3
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp72
-rw-r--r--src/core/core.h3
-rw-r--r--src/core/file_sys/disk_archive.h2
-rw-r--r--src/core/hle/function_wrappers.h7
-rw-r--r--src/core/hle/hle.cpp1
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp4
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/mutex.cpp10
-rw-r--r--src/core/hle/kernel/shared_memory.cpp1
-rw-r--r--src/core/hle/kernel/thread.cpp50
-rw-r--r--src/core/hle/kernel/thread.h32
-rw-r--r--src/core/hle/kernel/timer.cpp2
-rw-r--r--src/core/hle/service/apt/apt.cpp13
-rw-r--r--src/core/hle/service/ptm/ptm_sysm.cpp2
-rw-r--r--src/core/hle/service/service.cpp43
-rw-r--r--src/core/hle/service/service.h55
-rw-r--r--src/core/hle/svc.cpp52
-rw-r--r--src/video_core/rasterizer.cpp4
34 files changed, 276 insertions, 1123 deletions
diff --git a/src/citra_qt/debugger/graphics_breakpoints_p.h b/src/citra_qt/debugger/graphics_breakpoints_p.h
index 232bfc863..34e72e859 100644
--- a/src/citra_qt/debugger/graphics_breakpoints_p.h
+++ b/src/citra_qt/debugger/graphics_breakpoints_p.h
@@ -25,7 +25,7 @@ public:
25 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; 25 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
26 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 26 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
27 27
28 bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); 28 bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
29 29
30public slots: 30public slots:
31 void OnBreakPointHit(Pica::DebugContext::Event event); 31 void OnBreakPointHit(Pica::DebugContext::Event event);
diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp
index ae0568b6a..2ac1748b7 100644
--- a/src/citra_qt/debugger/profiler.cpp
+++ b/src/citra_qt/debugger/profiler.cpp
@@ -26,7 +26,7 @@ static QVariant GetDataForColumn(int col, const AggregatedDuration& duration)
26static const TimingCategoryInfo* GetCategoryInfo(int id) 26static const TimingCategoryInfo* GetCategoryInfo(int id)
27{ 27{
28 const auto& categories = GetProfilingManager().GetTimingCategoriesInfo(); 28 const auto& categories = GetProfilingManager().GetTimingCategoriesInfo();
29 if (id >= categories.size()) { 29 if ((size_t)id >= categories.size()) {
30 return nullptr; 30 return nullptr;
31 } else { 31 } else {
32 return &categories[id]; 32 return &categories[id];
@@ -98,7 +98,7 @@ QVariant ProfilerModel::data(const QModelIndex& index, int role) const
98 const TimingCategoryInfo* info = GetCategoryInfo(index.row() - 2); 98 const TimingCategoryInfo* info = GetCategoryInfo(index.row() - 2);
99 return info != nullptr ? QString(info->name) : QVariant(); 99 return info != nullptr ? QString(info->name) : QVariant();
100 } else { 100 } else {
101 if (index.row() - 2 < results.time_per_category.size()) { 101 if (index.row() - 2 < (int)results.time_per_category.size()) {
102 return GetDataForColumn(index.column(), results.time_per_category[index.row() - 2]); 102 return GetDataForColumn(index.column(), results.time_per_category[index.row() - 2]);
103 } else { 103 } else {
104 return QVariant(); 104 return QVariant();
diff --git a/src/citra_qt/debugger/profiler.h b/src/citra_qt/debugger/profiler.h
index a6d87aa0f..fabf279b8 100644
--- a/src/citra_qt/debugger/profiler.h
+++ b/src/citra_qt/debugger/profiler.h
@@ -18,7 +18,7 @@ class ProfilerModel : public QAbstractItemModel
18public: 18public:
19 ProfilerModel(QObject* parent); 19 ProfilerModel(QObject* parent);
20 20
21 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 21 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
22 QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; 22 QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
23 QModelIndex parent(const QModelIndex& child) const override; 23 QModelIndex parent(const QModelIndex& child) const override;
24 int columnCount(const QModelIndex& parent = QModelIndex()) const override; 24 int columnCount(const QModelIndex& parent = QModelIndex()) const override;
diff --git a/src/citra_qt/util/spinbox.cpp b/src/citra_qt/util/spinbox.cpp
index 2e2076a27..de4060116 100644
--- a/src/citra_qt/util/spinbox.cpp
+++ b/src/citra_qt/util/spinbox.cpp
@@ -29,6 +29,7 @@
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 31
32#include <cstdlib>
32#include <QLineEdit> 33#include <QLineEdit>
33#include <QRegExpValidator> 34#include <QRegExpValidator>
34 35
@@ -206,7 +207,7 @@ QString CSpinBox::TextFromValue()
206{ 207{
207 return prefix 208 return prefix
208 + QString(HasSign() ? ((value < 0) ? "-" : "+") : "") 209 + QString(HasSign() ? ((value < 0) ? "-" : "+") : "")
209 + QString("%1").arg(abs(value), num_digits, base, QLatin1Char('0')).toUpper() 210 + QString("%1").arg(std::abs(value), num_digits, base, QLatin1Char('0')).toUpper()
210 + suffix; 211 + suffix;
211} 212}
212 213
diff --git a/src/common/thread.h b/src/common/thread.h
index a45728e1e..5fdb6baeb 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -51,109 +51,60 @@ int CurrentThreadId();
51void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); 51void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
52void SetCurrentThreadAffinity(u32 mask); 52void SetCurrentThreadAffinity(u32 mask);
53 53
54class Event 54class Event {
55{
56public: 55public:
57 Event() 56 Event() : is_set(false) {}
58 : is_set(false)
59 {}
60 57
61 void Set() 58 void Set() {
62 {
63 std::lock_guard<std::mutex> lk(m_mutex); 59 std::lock_guard<std::mutex> lk(m_mutex);
64 if (!is_set) 60 if (!is_set) {
65 {
66 is_set = true; 61 is_set = true;
67 m_condvar.notify_one(); 62 m_condvar.notify_one();
68 } 63 }
69 } 64 }
70 65
71 void Wait() 66 void Wait() {
72 {
73 std::unique_lock<std::mutex> lk(m_mutex); 67 std::unique_lock<std::mutex> lk(m_mutex);
74 m_condvar.wait(lk, IsSet(this)); 68 m_condvar.wait(lk, [&]{ return is_set; });
75 is_set = false; 69 is_set = false;
76 } 70 }
77 71
78 void Reset() 72 void Reset() {
79 {
80 std::unique_lock<std::mutex> lk(m_mutex); 73 std::unique_lock<std::mutex> lk(m_mutex);
81 // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration 74 // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
82 is_set = false; 75 is_set = false;
83 } 76 }
84 77
85private: 78private:
86 class IsSet 79 bool is_set;
87 {
88 public:
89 IsSet(const Event* ev)
90 : m_event(ev)
91 {}
92
93 bool operator()()
94 {
95 return m_event->is_set;
96 }
97
98 private:
99 const Event* const m_event;
100 };
101
102 volatile bool is_set;
103 std::condition_variable m_condvar; 80 std::condition_variable m_condvar;
104 std::mutex m_mutex; 81 std::mutex m_mutex;
105}; 82};
106 83
107// TODO: doesn't work on windows with (count > 2) 84class Barrier {
108class Barrier
109{
110public: 85public:
111 Barrier(size_t count) 86 Barrier(size_t count) : m_count(count), m_waiting(0) {}
112 : m_count(count), m_waiting(0)
113 {}
114 87
115 // block until "count" threads call Sync() 88 /// Blocks until all "count" threads have called Sync()
116 bool Sync() 89 void Sync() {
117 {
118 std::unique_lock<std::mutex> lk(m_mutex); 90 std::unique_lock<std::mutex> lk(m_mutex);
119 91
120 // TODO: broken when next round of Sync()s 92 // TODO: broken when next round of Sync()s
121 // is entered before all waiting threads return from the notify_all 93 // is entered before all waiting threads return from the notify_all
122 94
123 if (m_count == ++m_waiting) 95 if (++m_waiting == m_count) {
124 {
125 m_waiting = 0; 96 m_waiting = 0;
126 m_condvar.notify_all(); 97 m_condvar.notify_all();
127 return true; 98 } else {
128 } 99 m_condvar.wait(lk, [&]{ return m_waiting == 0; });
129 else
130 {
131 m_condvar.wait(lk, IsDoneWating(this));
132 return false;
133 } 100 }
134 } 101 }
135 102
136private: 103private:
137 class IsDoneWating
138 {
139 public:
140 IsDoneWating(const Barrier* bar)
141 : m_bar(bar)
142 {}
143
144 bool operator()()
145 {
146 return (0 == m_bar->m_waiting);
147 }
148
149 private:
150 const Barrier* const m_bar;
151 };
152
153 std::condition_variable m_condvar; 104 std::condition_variable m_condvar;
154 std::mutex m_mutex; 105 std::mutex m_mutex;
155 const size_t m_count; 106 const size_t m_count;
156 volatile size_t m_waiting; 107 size_t m_waiting;
157}; 108};
158 109
159void SleepCurrentThread(int ms); 110void SleepCurrentThread(int ms);
diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h
index 444abf115..4f27fc899 100644
--- a/src/common/thread_queue_list.h
+++ b/src/common/thread_queue_list.h
@@ -40,6 +40,18 @@ struct ThreadQueueList {
40 return -1; 40 return -1;
41 } 41 }
42 42
43 T get_first() {
44 Queue *cur = first;
45 while (cur != nullptr) {
46 if (!cur->data.empty()) {
47 return cur->data.front();
48 }
49 cur = cur->next_nonempty;
50 }
51
52 return T();
53 }
54
43 T pop_first() { 55 T pop_first() {
44 Queue *cur = first; 56 Queue *cur = first;
45 while (cur != nullptr) { 57 while (cur != nullptr) {
@@ -79,6 +91,12 @@ struct ThreadQueueList {
79 cur->data.push_back(thread_id); 91 cur->data.push_back(thread_id);
80 } 92 }
81 93
94 void move(const T& thread_id, Priority old_priority, Priority new_priority) {
95 remove(old_priority, thread_id);
96 prepare(new_priority);
97 push_back(new_priority, thread_id);
98 }
99
82 void remove(Priority priority, const T& thread_id) { 100 void remove(Priority priority, const T& thread_id) {
83 Queue *cur = &queues[priority]; 101 Queue *cur = &queues[priority];
84 boost::remove_erase(cur->data, thread_id); 102 boost::remove_erase(cur->data, thread_id);
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 0528175ba..42733b95e 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -6,7 +6,6 @@ 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/armcopro.cpp
10 arm/interpreter/arminit.cpp 9 arm/interpreter/arminit.cpp
11 arm/interpreter/armsupp.cpp 10 arm/interpreter/armsupp.cpp
12 arm/skyeye_common/vfp/vfp.cpp 11 arm/skyeye_common/vfp/vfp.cpp
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 1b1d01420..bc1e969e4 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -31,7 +31,6 @@ ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) {
31 31
32 // Reset the core to initial state 32 // Reset the core to initial state
33 ARMul_Reset(state.get()); 33 ARMul_Reset(state.get());
34 state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
35 state->Emulate = RUN; 34 state->Emulate = RUN;
36 35
37 // Switch to the desired privilege mode. 36 // Switch to the desired privilege mode.
@@ -99,7 +98,6 @@ void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 e
99 context.pc = entry_point; 98 context.pc = entry_point;
100 context.sp = stack_top; 99 context.sp = stack_top;
101 context.cpsr = 0x1F; // Usermode 100 context.cpsr = 0x1F; // Usermode
102 context.mode = 8; // Instructs dyncom CPU core to start execution as if it's "resuming" a thread.
103} 101}
104 102
105void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { 103void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
@@ -113,8 +111,6 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
113 111
114 ctx.fpscr = state->VFP[1]; 112 ctx.fpscr = state->VFP[1];
115 ctx.fpexc = state->VFP[2]; 113 ctx.fpexc = state->VFP[2];
116
117 ctx.mode = state->NextInstr;
118} 114}
119 115
120void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { 116void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
@@ -128,8 +124,6 @@ void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
128 124
129 state->VFP[1] = ctx.fpscr; 125 state->VFP[1] = ctx.fpscr;
130 state->VFP[2] = ctx.fpexc; 126 state->VFP[2] = ctx.fpexc;
131
132 state->NextInstr = ctx.mode;
133} 127}
134 128
135void ARM_DynCom::PrepareReschedule() { 129void ARM_DynCom::PrepareReschedule() {
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 822b3bbb9..2488c879c 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -27,7 +27,7 @@ public:
27 27
28 void AddTicks(u64 ticks) override; 28 void AddTicks(u64 ticks) override;
29 29
30 void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg); 30 void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) override;
31 void SaveContext(Core::ThreadContext& ctx) override; 31 void SaveContext(Core::ThreadContext& ctx) override;
32 void LoadContext(const Core::ThreadContext& ctx) override; 32 void LoadContext(const Core::ThreadContext& ctx) override;
33 33
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp
deleted file mode 100644
index 4ae0c52e4..000000000
--- a/src/core/arm/interpreter/armcopro.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
1/* armcopro.c -- co-processor interface: ARM6 Instruction Emulator.
2 Copyright (C) 1994, 2000 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#include "core/arm/skyeye_common/armdefs.h"
19#include "core/arm/skyeye_common/armemu.h"
20#include "core/arm/skyeye_common/vfp/vfp.h"
21
22// Dummy Co-processors.
23
24static unsigned int NoCoPro3R(ARMul_State* state, unsigned int a, ARMword b)
25{
26 return ARMul_CANT;
27}
28
29static unsigned int NoCoPro4R(ARMul_State* state, unsigned int a, ARMword b, ARMword c)
30{
31 return ARMul_CANT;
32}
33
34static unsigned int NoCoPro4W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c)
35{
36 return ARMul_CANT;
37}
38
39static unsigned int NoCoPro5R(ARMul_State* state, unsigned int a, ARMword b, ARMword c, ARMword d)
40{
41 return ARMul_CANT;
42}
43
44static unsigned int NoCoPro5W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c, ARMword* d)
45{
46 return ARMul_CANT;
47}
48
49// Install co-processor instruction handlers in this routine.
50void ARMul_CoProInit(ARMul_State* state)
51{
52 // Initialise tham all first.
53 for (unsigned int i = 0; i < 16; i++)
54 ARMul_CoProDetach(state, i);
55
56 // Install CoPro Instruction handlers here.
57 // The format is:
58 // ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
59 // LDC routine, STC routine, MRC routine, MCR routine,
60 // CDP routine, Read Reg routine, Write Reg routine).
61 if (state->is_v6) {
62 ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
63 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
64 ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
65 VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
66
67 /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
68 MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
69 }
70
71 // No handlers below here.
72
73 // Call all the initialisation routines.
74 for (unsigned int i = 0; i < 16; i++) {
75 if (state->CPInit[i])
76 (state->CPInit[i]) (state);
77 }
78}
79
80// Install co-processor finalisation routines in this routine.
81void ARMul_CoProExit(ARMul_State * state)
82{
83 for (unsigned int i = 0; i < 16; i++)
84 if (state->CPExit[i])
85 (state->CPExit[i]) (state);
86
87 // Detach all handlers.
88 for (unsigned int i = 0; i < 16; i++)
89 ARMul_CoProDetach(state, i);
90}
91
92// Routines to hook Co-processors into ARMulator.
93
94void
95ARMul_CoProAttach(ARMul_State* state,
96unsigned number,
97ARMul_CPInits* init,
98ARMul_CPExits* exit,
99ARMul_LDCs* ldc,
100ARMul_STCs* stc,
101ARMul_MRCs* mrc,
102ARMul_MCRs* mcr,
103ARMul_MRRCs* mrrc,
104ARMul_MCRRs* mcrr,
105ARMul_CDPs* cdp,
106ARMul_CPReads* read, ARMul_CPWrites* write)
107{
108 if (init != NULL)
109 state->CPInit[number] = init;
110 if (exit != NULL)
111 state->CPExit[number] = exit;
112 if (ldc != NULL)
113 state->LDC[number] = ldc;
114 if (stc != NULL)
115 state->STC[number] = stc;
116 if (mrc != NULL)
117 state->MRC[number] = mrc;
118 if (mcr != NULL)
119 state->MCR[number] = mcr;
120 if (mrrc != NULL)
121 state->MRRC[number] = mrrc;
122 if (mcrr != NULL)
123 state->MCRR[number] = mcrr;
124 if (cdp != NULL)
125 state->CDP[number] = cdp;
126 if (read != NULL)
127 state->CPRead[number] = read;
128 if (write != NULL)
129 state->CPWrite[number] = write;
130}
131
132void ARMul_CoProDetach(ARMul_State* state, unsigned number)
133{
134 ARMul_CoProAttach(state, number, NULL, NULL,
135 NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
136 NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
137
138 state->CPInit[number] = NULL;
139 state->CPExit[number] = NULL;
140 state->CPRead[number] = NULL;
141 state->CPWrite[number] = NULL;
142}
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index 1d732fe84..6ac45c396 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -19,6 +19,7 @@
19#include "core/mem_map.h" 19#include "core/mem_map.h"
20#include "core/arm/skyeye_common/armdefs.h" 20#include "core/arm/skyeye_common/armdefs.h"
21#include "core/arm/skyeye_common/armemu.h" 21#include "core/arm/skyeye_common/armemu.h"
22#include "core/arm/skyeye_common/vfp/vfp.h"
22 23
23/***************************************************************************\ 24/***************************************************************************\
24* Returns a new instantiation of the ARMulator's state * 25* Returns a new instantiation of the ARMulator's state *
@@ -28,22 +29,8 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
28 memset(state, 0, sizeof(ARMul_State)); 29 memset(state, 0, sizeof(ARMul_State));
29 30
30 state->Emulate = RUN; 31 state->Emulate = RUN;
31 for (unsigned int i = 0; i < 16; i++) {
32 state->Reg[i] = 0;
33 for (unsigned int j = 0; j < 7; j++)
34 state->RegBank[j][i] = 0;
35 }
36 for (unsigned int i = 0; i < 7; i++)
37 state->Spsr[i] = 0;
38
39 state->Mode = USER32MODE; 32 state->Mode = USER32MODE;
40 33
41 state->VectorCatch = 0;
42 state->Aborted = false;
43 state->Reseted = false;
44 state->Inted = 3;
45 state->LastInted = 3;
46
47 state->lateabtSig = HIGH; 34 state->lateabtSig = HIGH;
48 state->bigendSig = LOW; 35 state->bigendSig = LOW;
49 36
@@ -56,15 +43,11 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
56 43
57void ARMul_SelectProcessor(ARMul_State* state, unsigned properties) 44void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
58{ 45{
59 state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0; 46 state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
60 state->is_v5 = (properties & ARM_v5_Prop) != 0; 47 state->is_v5 = (properties & ARM_v5_Prop) != 0;
61 state->is_v5e = (properties & ARM_v5e_Prop) != 0; 48 state->is_v5e = (properties & ARM_v5e_Prop) != 0;
62 state->is_v6 = (properties & ARM_v6_Prop) != 0; 49 state->is_v6 = (properties & ARM_v6_Prop) != 0;
63 state->is_v7 = (properties & ARM_v7_Prop) != 0; 50 state->is_v7 = (properties & ARM_v7_Prop) != 0;
64
65 // Only initialse the coprocessor support once we
66 // know what kind of chip we are dealing with.
67 ARMul_CoProInit(state);
68} 51}
69 52
70// Resets certain MPCore CP15 values to their ARM-defined reset values. 53// Resets certain MPCore CP15 values to their ARM-defined reset values.
@@ -130,26 +113,20 @@ static void ResetMPCoreCP15Registers(ARMul_State* cpu)
130\***************************************************************************/ 113\***************************************************************************/
131void ARMul_Reset(ARMul_State* state) 114void ARMul_Reset(ARMul_State* state)
132{ 115{
133 state->NextInstr = 0; 116 VFPInit(state);
134 117
135 state->Reg[15] = 0; 118 state->Reg[15] = 0;
136 state->Cpsr = INTBITS | SVC32MODE; 119 state->Cpsr = INTBITS | SVC32MODE;
137 state->Mode = SVC32MODE; 120 state->Mode = SVC32MODE;
138
139 state->Bank = SVCBANK; 121 state->Bank = SVCBANK;
140 FLUSHPIPE;
141 122
142 ResetMPCoreCP15Registers(state); 123 ResetMPCoreCP15Registers(state);
143 124
144 state->EndCondition = 0;
145 state->ErrorCode = 0;
146
147 state->NresetSig = HIGH; 125 state->NresetSig = HIGH;
148 state->NfiqSig = HIGH; 126 state->NfiqSig = HIGH;
149 state->NirqSig = HIGH; 127 state->NirqSig = HIGH;
150 state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 128 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
151 state->abortSig = LOW; 129 state->abortSig = LOW;
152 state->AbortAddr = 1;
153 130
154 state->NumInstrs = 0; 131 state->NumInstrs = 0;
155} 132}
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 743e935f0..08da6d9eb 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -53,26 +53,11 @@ typedef u64 ARMdword; // must be 64 bits wide
53typedef u32 ARMword; // must be 32 bits wide 53typedef u32 ARMword; // must be 32 bits wide
54typedef u16 ARMhword; // must be 16 bits wide 54typedef u16 ARMhword; // must be 16 bits wide
55typedef u8 ARMbyte; // must be 8 bits wide 55typedef u8 ARMbyte; // must be 8 bits wide
56typedef struct ARMul_State ARMul_State;
57
58typedef unsigned ARMul_CPInits(ARMul_State* state);
59typedef unsigned ARMul_CPExits(ARMul_State* state);
60typedef unsigned ARMul_LDCs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
61typedef unsigned ARMul_STCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
62typedef unsigned ARMul_MRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
63typedef unsigned ARMul_MCRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
64typedef unsigned ARMul_MRRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
65typedef unsigned ARMul_MCRRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
66typedef unsigned ARMul_CDPs(ARMul_State* state, unsigned type, ARMword instr);
67typedef unsigned ARMul_CPReads(ARMul_State* state, unsigned reg, ARMword* value);
68typedef unsigned ARMul_CPWrites(ARMul_State* state, unsigned reg, ARMword value);
69 56
70#define VFP_REG_NUM 64 57#define VFP_REG_NUM 64
71struct ARMul_State 58struct ARMul_State
72{ 59{
73 ARMword Emulate; // To start and stop emulation 60 ARMword Emulate; // To start and stop emulation
74 unsigned EndCondition; // Reason for stopping
75 unsigned ErrorCode; // Type of illegal instruction
76 61
77 // Order of the following register should not be modified 62 // Order of the following register should not be modified
78 ARMword Reg[16]; // The current register file 63 ARMword Reg[16]; // The current register file
@@ -101,8 +86,6 @@ struct ARMul_State
101 ARMword ExtReg[VFP_REG_NUM]; 86 ARMword ExtReg[VFP_REG_NUM];
102 /* ---- End of the ordered registers ---- */ 87 /* ---- End of the ordered registers ---- */
103 88
104 ARMword RegBank[7][16]; // all the registers
105
106 ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed 89 ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
107 unsigned int shifter_carry_out; 90 unsigned int shifter_carry_out;
108 91
@@ -114,24 +97,7 @@ struct ARMul_State
114 unsigned long long NumInstrs; // The number of instructions executed 97 unsigned long long NumInstrs; // The number of instructions executed
115 unsigned NumInstrsToExecute; 98 unsigned NumInstrsToExecute;
116 99
117 unsigned NextInstr; 100 unsigned NresetSig; // Reset the processor
118 unsigned VectorCatch; // Caught exception mask
119
120 ARMul_CPInits* CPInit[16]; // Coprocessor initialisers
121 ARMul_CPExits* CPExit[16]; // Coprocessor finalisers
122 ARMul_LDCs* LDC[16]; // LDC instruction
123 ARMul_STCs* STC[16]; // STC instruction
124 ARMul_MRCs* MRC[16]; // MRC instruction
125 ARMul_MCRs* MCR[16]; // MCR instruction
126 ARMul_MRRCs* MRRC[16]; // MRRC instruction
127 ARMul_MCRRs* MCRR[16]; // MCRR instruction
128 ARMul_CDPs* CDP[16]; // CDP instruction
129 ARMul_CPReads* CPRead[16]; // Read CP register
130 ARMul_CPWrites* CPWrite[16]; // Write CP register
131 unsigned char* CPData[16]; // Coprocessor data
132 unsigned char const* CPRegWords[16]; // Map of coprocessor register sizes
133
134 unsigned NresetSig; // Reset the processor
135 unsigned NfiqSig; 101 unsigned NfiqSig;
136 unsigned NirqSig; 102 unsigned NirqSig;
137 103
@@ -173,13 +139,6 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
173*/ 139*/
174 unsigned lateabtSig; 140 unsigned lateabtSig;
175 141
176 bool Aborted; // Sticky flag for aborts
177 bool Reseted; // Sticky flag for Reset
178 ARMword Inted, LastInted; // Sticky flags for interrupts
179 ARMword Base; // Extra hand for base writeback
180 ARMword AbortAddr; // To keep track of Prefetch aborts
181 ARMword Vector; // Synthesize aborts in cycle modes
182
183 // For differentiating ARM core emulaiton. 142 // For differentiating ARM core emulaiton.
184 bool is_v4; // Are we emulating a v4 architecture (or higher)? 143 bool is_v4; // Are we emulating a v4 architecture (or higher)?
185 bool is_v5; // Are we emulating a v5 architecture? 144 bool is_v5; // Are we emulating a v5 architecture?
@@ -193,14 +152,6 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
193 152
194 // Added by ksh in 2005-10-1 153 // Added by ksh in 2005-10-1
195 cpu_config_t* cpu; 154 cpu_config_t* cpu;
196
197 u32 CurrInstr;
198 u32 last_pc; // The last PC executed
199 u32 last_instr; // The last instruction executed
200 u32 WriteAddr[17];
201 u32 WriteData[17];
202 u32 WritePc[17];
203 u32 CurrWrite;
204}; 155};
205 156
206/***************************************************************************\ 157/***************************************************************************\
@@ -286,34 +237,6 @@ enum {
286 ARMul_INC = 3 237 ARMul_INC = 3
287}; 238};
288 239
289enum {
290 ARMul_CP13_R0_FIQ = 0x1,
291 ARMul_CP13_R0_IRQ = 0x2,
292 ARMul_CP13_R8_PMUS = 0x1,
293
294 ARMul_CP14_R0_ENABLE = 0x0001,
295 ARMul_CP14_R0_CLKRST = 0x0004,
296 ARMul_CP14_R0_CCD = 0x0008,
297 ARMul_CP14_R0_INTEN0 = 0x0010,
298 ARMul_CP14_R0_INTEN1 = 0x0020,
299 ARMul_CP14_R0_INTEN2 = 0x0040,
300 ARMul_CP14_R0_FLAG0 = 0x0100,
301 ARMul_CP14_R0_FLAG1 = 0x0200,
302 ARMul_CP14_R0_FLAG2 = 0x0400,
303 ARMul_CP14_R10_MOE_IB = 0x0004,
304 ARMul_CP14_R10_MOE_DB = 0x0008,
305 ARMul_CP14_R10_MOE_BT = 0x000c,
306 ARMul_CP15_R1_ENDIAN = 0x0080,
307 ARMul_CP15_R1_ALIGN = 0x0002,
308 ARMul_CP15_R5_X = 0x0400,
309 ARMul_CP15_R5_ST_ALIGN = 0x0001,
310 ARMul_CP15_R5_IMPRE = 0x0406,
311 ARMul_CP15_R5_MMU_EXCPT = 0x0400,
312 ARMul_CP15_DBCON_M = 0x0100,
313 ARMul_CP15_DBCON_E1 = 0x000c,
314 ARMul_CP15_DBCON_E0 = 0x0003
315};
316
317/***************************************************************************\ 240/***************************************************************************\
318* Definitons of things in the host environment * 241* Definitons of things in the host environment *
319\***************************************************************************/ 242\***************************************************************************/
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index 2a1c50779..7e0965052 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -38,16 +38,6 @@ enum : u32 {
38 INTBITS = 0x1C0, 38 INTBITS = 0x1C0,
39}; 39};
40 40
41// Different ways to start the next instruction.
42enum {
43 SEQ = 0,
44 NONSEQ = 1,
45 PCINCEDSEQ = 2,
46 PCINCEDNONSEQ = 3,
47 PRIMEPIPE = 4,
48 RESUME = 8
49};
50
51// Values for Emulate. 41// Values for Emulate.
52enum { 42enum {
53 STOP = 0, // Stop 43 STOP = 0, // Stop
@@ -55,14 +45,3 @@ enum {
55 ONCE = 2, // Execute just one interation 45 ONCE = 2, // Execute just one interation
56 RUN = 3 // Continuous execution 46 RUN = 3 // Continuous execution
57}; 47};
58
59#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
60
61// Coprocessor support functions.
62extern void ARMul_CoProInit(ARMul_State*);
63extern void ARMul_CoProExit(ARMul_State*);
64extern void ARMul_CoProAttach(ARMul_State*, unsigned, ARMul_CPInits*,
65 ARMul_CPExits*, ARMul_LDCs*, ARMul_STCs*,
66 ARMul_MRCs*, ARMul_MCRs*, ARMul_MRRCs*, ARMul_MCRRs*,
67 ARMul_CDPs*, ARMul_CPReads*, ARMul_CPWrites*);
68extern void ARMul_CoProDetach(ARMul_State*, unsigned);
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index d793261fd..d0fa157a2 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -37,296 +37,18 @@ unsigned VFPInit(ARMul_State* state)
37 return 0; 37 return 0;
38} 38}
39 39
40unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value) 40void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
41{
42 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
43 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
44 int OPC_1 = BITS(instr, 21, 23);
45 int Rt = BITS(instr, 12, 15);
46 int CRn = BITS(instr, 16, 19);
47 int CRm = BITS(instr, 0, 3);
48 int OPC_2 = BITS(instr, 5, 7);
49
50 /* TODO check access permission */
51
52 /* CRn/opc1 CRm/opc2 */
53
54 if (CoProc == 10 || CoProc == 11)
55 {
56 if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
57 {
58 /* VMOV r to s */
59 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
60 VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, value);
61 return ARMul_DONE;
62 }
63
64 if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
65 {
66 VMRS(state, CRn, Rt, value);
67 return ARMul_DONE;
68 }
69 }
70 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
71 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
72
73 return ARMul_CANT;
74}
75
76unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
77{
78 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
79 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
80 int OPC_1 = BITS(instr, 21, 23);
81 int Rt = BITS(instr, 12, 15);
82 int CRn = BITS(instr, 16, 19);
83 int CRm = BITS(instr, 0, 3);
84 int OPC_2 = BITS(instr, 5, 7);
85
86 /* TODO check access permission */
87
88 /* CRn/opc1 CRm/opc2 */
89 if (CoProc == 10 || CoProc == 11)
90 {
91 if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
92 {
93 /* VMOV s to r */
94 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
95 VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, &value);
96 return ARMul_DONE;
97 }
98
99 if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
100 {
101 VMSR(state, CRn, Rt);
102 return ARMul_DONE;
103 }
104
105 if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0)
106 {
107 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
108 return ARMul_DONE;
109 }
110
111 if (CoProc == 11 && CRm == 0)
112 {
113 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
114 return ARMul_DONE;
115 }
116 }
117 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
118 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
119
120 return ARMul_CANT;
121}
122
123unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2)
124{
125 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
126 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
127 int OPC_1 = BITS(instr, 4, 7);
128 int Rt = BITS(instr, 12, 15);
129 int Rt2 = BITS(instr, 16, 19);
130 int CRm = BITS(instr, 0, 3);
131
132 if (CoProc == 10 || CoProc == 11)
133 {
134 if (CoProc == 10 && (OPC_1 & 0xD) == 1)
135 {
136 VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
137 return ARMul_DONE;
138 }
139
140 if (CoProc == 11 && (OPC_1 & 0xD) == 1)
141 {
142 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
143 VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
144 return ARMul_DONE;
145 }
146 }
147 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
148 instr, CoProc, OPC_1, Rt, Rt2, CRm);
149
150 return ARMul_CANT;
151}
152
153unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2)
154{
155 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
156 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
157 int OPC_1 = BITS(instr, 4, 7);
158 int Rt = BITS(instr, 12, 15);
159 int Rt2 = BITS(instr, 16, 19);
160 int CRm = BITS(instr, 0, 3);
161
162 /* TODO check access permission */
163
164 /* CRn/opc1 CRm/opc2 */
165
166 if (CoProc == 11 || CoProc == 10)
167 {
168 if (CoProc == 10 && (OPC_1 & 0xD) == 1)
169 {
170 VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
171 return ARMul_DONE;
172 }
173
174 if (CoProc == 11 && (OPC_1 & 0xD) == 1)
175 {
176 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
177 VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
178 return ARMul_DONE;
179 }
180 }
181 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
182 instr, CoProc, OPC_1, Rt, Rt2, CRm);
183
184 return ARMul_CANT;
185}
186
187unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
188{
189 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
190 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
191 int CRd = BITS(instr, 12, 15);
192 int Rn = BITS(instr, 16, 19);
193 int imm8 = BITS(instr, 0, 7);
194 int P = BIT(instr, 24);
195 int U = BIT(instr, 23);
196 int D = BIT(instr, 22);
197 int W = BIT(instr, 21);
198
199 /* TODO check access permission */
200
201 /* VSTM */
202 if ( (P|U|D|W) == 0 ) {
203 LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__);
204 exit(-1);
205 }
206 if (CoProc == 10 || CoProc == 11) {
207#if 1
208 if (P == 0 && U == 0 && W == 0) {
209 LOG_ERROR(Core_ARM11, "VSTM Related encodings\n");
210 exit(-1);
211 }
212 if (P == U && W == 1) {
213 LOG_ERROR(Core_ARM11, "UNDEFINED\n");
214 exit(-1);
215 }
216#endif
217
218 if (P == 1 && W == 0)
219 {
220 return VSTR(state, type, instr, value);
221 }
222
223 if (P == 1 && U == 0 && W == 1 && Rn == 0xD)
224 {
225 return VPUSH(state, type, instr, value);
226 }
227
228 return VSTM(state, type, instr, value);
229 }
230 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
231 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
232
233 return ARMul_CANT;
234}
235
236unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
237{ 41{
238 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ 42 if (reg == 1)
239 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
240 int CRd = BITS(instr, 12, 15);
241 int Rn = BITS(instr, 16, 19);
242 int imm8 = BITS(instr, 0, 7);
243 int P = BIT(instr, 24);
244 int U = BIT(instr, 23);
245 int D = BIT(instr, 22);
246 int W = BIT(instr, 21);
247
248 /* TODO check access permission */
249
250 if ( (P|U|D|W) == 0 ) {
251 LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__);
252 exit(-1);
253 }
254 if (CoProc == 10 || CoProc == 11)
255 { 43 {
256 if (P == 1 && W == 0) 44 state->VFP[VFP_FPSCR] = state->Reg[Rt];
257 {
258 return VLDR(state, type, instr, value);
259 }
260
261 if (P == 0 && U == 1 && W == 1 && Rn == 0xD)
262 {
263 return VPOP(state, type, instr, value);
264 }
265
266 return VLDM(state, type, instr, value);
267 } 45 }
268 LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", 46 else if (reg == 8)
269 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
270
271 return ARMul_CANT;
272}
273
274unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
275{
276 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
277 int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
278 int OPC_1 = BITS(instr, 20, 23);
279 int CRd = BITS(instr, 12, 15);
280 int CRn = BITS(instr, 16, 19);
281 int CRm = BITS(instr, 0, 3);
282 int OPC_2 = BITS(instr, 5, 7);
283
284 /* TODO check access permission */
285
286 /* CRn/opc1 CRm/opc2 */
287
288 if (CoProc == 10 || CoProc == 11)
289 { 47 {
290 if ((OPC_1 & 0xB) == 0xB && BITS(instr, 4, 7) == 0) 48 state->VFP[VFP_FPEXC] = state->Reg[Rt];
291 {
292 unsigned int single = BIT(instr, 8) == 0;
293 unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
294 unsigned int imm;
295 instr = BITS(instr, 16, 19) << 4 | BITS(instr, 0, 3); // FIXME dirty workaround to get a correct imm
296
297 if (single)
298 imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0x1f : 0)<<25 | BITS(instr, 0, 5)<<19;
299 else
300 imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0xff : 0)<<22 | BITS(instr, 0, 5)<<16;
301
302 VMOVI(state, single, d, imm);
303 return ARMul_DONE;
304 }
305
306 if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2)
307 {
308 unsigned int single = BIT(instr, 8) == 0;
309 unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
310 unsigned int m = (single ? BITS(instr, 0, 3)<<1 | BIT(instr, 5) : BITS(instr, 0, 3) | BIT(instr, 5)<<4);
311 VMOVR(state, single, d, m);
312 return ARMul_DONE;
313 }
314
315 int exceptions = 0;
316 if (CoProc == 10)
317 exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_FPSCR]);
318 else
319 exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_FPSCR]);
320
321 vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_FPSCR]);
322
323 return ARMul_DONE;
324 } 49 }
325 LOG_WARNING(Core_ARM11, "Can't identify %x\n", instr);
326 return ARMul_CANT;
327} 50}
328 51
329/* ----------- MRC ------------ */
330void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) 52void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value)
331{ 53{
332 if (to_arm) 54 if (to_arm)
@@ -338,43 +60,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword*
338 state->ExtReg[n] = *value; 60 state->ExtReg[n] = *value;
339 } 61 }
340} 62}
341void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value) 63
342{
343 if (reg == 1)
344 {
345 if (Rt != 15)
346 {
347 *value = state->VFP[VFP_FPSCR];
348 }
349 else
350 {
351 *value = state->VFP[VFP_FPSCR] ;
352 }
353 }
354 else
355 {
356 switch (reg)
357 {
358 case 0:
359 *value = state->VFP[VFP_FPSID];
360 break;
361 case 6:
362 /* MVFR1, VFPv3 only ? */
363 LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", Rt);
364 break;
365 case 7:
366 /* MVFR0, VFPv3 only? */
367 LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", Rt);
368 break;
369 case 8:
370 *value = state->VFP[VFP_FPEXC];
371 break;
372 default:
373 LOG_TRACE(Core_ARM11, "\tSUBARCHITECTURE DEFINED\n");
374 break;
375 }
376 }
377}
378void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) 64void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2)
379{ 65{
380 if (to_arm) 66 if (to_arm)
@@ -402,301 +88,6 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor
402 } 88 }
403} 89}
404 90
405/* ----------- MCR ------------ */
406void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
407{
408 if (reg == 1)
409 {
410 state->VFP[VFP_FPSCR] = state->Reg[Rt];
411 }
412 else if (reg == 8)
413 {
414 state->VFP[VFP_FPEXC] = state->Reg[Rt];
415 }
416}
417
418/* Memory operation are not inlined, as old Interpreter and Fast interpreter
419 don't have the same memory operation interface.
420 Old interpreter framework does one access to coprocessor per data, and
421 handles already data write, as well as address computation,
422 which is not the case for Fast interpreter. Therefore, implementation
423 of vfp instructions in old interpreter and fast interpreter are separate. */
424
425/* ----------- STC ------------ */
426int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
427{
428 static int i = 0;
429 static int single_reg, add, d, n, imm32, regs;
430 if (type == ARMul_FIRST)
431 {
432 single_reg = BIT(instr, 8) == 0; // Double precision
433 add = BIT(instr, 23);
434 imm32 = BITS(instr, 0,7)<<2; // may not be used
435 d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); /* Base register */
436 n = BITS(instr, 16, 19); // destination register
437
438 i = 0;
439 regs = 1;
440
441 return ARMul_DONE;
442 }
443 else if (type == ARMul_DATA)
444 {
445 if (single_reg)
446 {
447 *value = state->ExtReg[d+i];
448 i++;
449 if (i < regs)
450 return ARMul_INC;
451 else
452 return ARMul_DONE;
453 }
454 else
455 {
456 /* FIXME Careful of endianness, may need to rework this */
457 *value = state->ExtReg[d*2+i];
458 i++;
459 if (i < regs*2)
460 return ARMul_INC;
461 else
462 return ARMul_DONE;
463 }
464 }
465
466 return -1;
467}
468int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value)
469{
470 static int i = 0;
471 static int single_regs, d, imm32, regs;
472 if (type == ARMul_FIRST)
473 {
474 single_regs = BIT(instr, 8) == 0; // Single precision
475 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
476 imm32 = BITS(instr, 0,7)<<2; // may not be used
477 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FSTMX if regs is odd
478
479 state->Reg[R13] = state->Reg[R13] - imm32;
480
481 i = 0;
482
483 return ARMul_DONE;
484 }
485 else if (type == ARMul_DATA)
486 {
487 if (single_regs)
488 {
489 *value = state->ExtReg[d + i];
490 i++;
491 if (i < regs)
492 return ARMul_INC;
493 else
494 return ARMul_DONE;
495 }
496 else
497 {
498 /* FIXME Careful of endianness, may need to rework this */
499 *value = state->ExtReg[d*2 + i];
500 i++;
501 if (i < regs*2)
502 return ARMul_INC;
503 else
504 return ARMul_DONE;
505 }
506 }
507
508 return -1;
509}
510int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
511{
512 static int i = 0;
513 static int single_regs, add, wback, d, n, imm32, regs;
514 if (type == ARMul_FIRST)
515 {
516 single_regs = BIT(instr, 8) == 0; // Single precision
517 add = BIT(instr, 23);
518 wback = BIT(instr, 21); // write-back
519 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
520 n = BITS(instr, 16, 19); // destination register
521 imm32 = BITS(instr, 0,7) * 4; // may not be used
522 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FSTMX if regs is odd
523
524 if (wback) {
525 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
526 }
527
528 i = 0;
529
530 return ARMul_DONE;
531 }
532 else if (type == ARMul_DATA)
533 {
534 if (single_regs)
535 {
536 *value = state->ExtReg[d + i];
537 i++;
538 if (i < regs)
539 return ARMul_INC;
540 else
541 return ARMul_DONE;
542 }
543 else
544 {
545 /* FIXME Careful of endianness, may need to rework this */
546 *value = state->ExtReg[d*2 + i];
547 i++;
548 if (i < regs*2)
549 return ARMul_INC;
550 else
551 return ARMul_DONE;
552 }
553 }
554
555 return -1;
556}
557
558/* ----------- LDC ------------ */
559int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value)
560{
561 static int i = 0;
562 static int single_regs, d, imm32, regs;
563 if (type == ARMul_FIRST)
564 {
565 single_regs = BIT(instr, 8) == 0; // Single precision
566 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
567 imm32 = BITS(instr, 0, 7)<<2; // may not be used
568 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FLDMX if regs is odd
569
570 state->Reg[R13] = state->Reg[R13] + imm32;
571
572 i = 0;
573
574 return ARMul_DONE;
575 }
576 else if (type == ARMul_TRANSFER)
577 {
578 return ARMul_DONE;
579 }
580 else if (type == ARMul_DATA)
581 {
582 if (single_regs)
583 {
584 state->ExtReg[d + i] = value;
585 i++;
586 if (i < regs)
587 return ARMul_INC;
588 else
589 return ARMul_DONE;
590 }
591 else
592 {
593 /* FIXME Careful of endianness, may need to rework this */
594 state->ExtReg[d*2 + i] = value;
595 i++;
596 if (i < regs*2)
597 return ARMul_INC;
598 else
599 return ARMul_DONE;
600 }
601 }
602
603 return -1;
604}
605int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value)
606{
607 static int i = 0;
608 static int single_reg, add, d, n, imm32, regs;
609 if (type == ARMul_FIRST)
610 {
611 single_reg = BIT(instr, 8) == 0; // Double precision
612 add = BIT(instr, 23);
613 imm32 = BITS(instr, 0, 7)<<2; // may not be used
614 d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
615 n = BITS(instr, 16, 19); // destination register
616
617 i = 0;
618 regs = 1;
619
620 return ARMul_DONE;
621 }
622 else if (type == ARMul_TRANSFER)
623 {
624 return ARMul_DONE;
625 }
626 else if (type == ARMul_DATA)
627 {
628 if (single_reg)
629 {
630 state->ExtReg[d+i] = value;
631 i++;
632 if (i < regs)
633 return ARMul_INC;
634 else
635 return ARMul_DONE;
636 }
637 else
638 {
639 /* FIXME Careful of endianness, may need to rework this */
640 state->ExtReg[d*2+i] = value;
641 i++;
642 if (i < regs*2)
643 return ARMul_INC;
644 else
645 return ARMul_DONE;
646 }
647 }
648
649 return -1;
650}
651int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value)
652{
653 static int i = 0;
654 static int single_regs, add, wback, d, n, imm32, regs;
655 if (type == ARMul_FIRST)
656 {
657 single_regs = BIT(instr, 8) == 0; // Single precision
658 add = BIT(instr, 23);
659 wback = BIT(instr, 21); // write-back
660 d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
661 n = BITS(instr, 16, 19); // destination register
662 imm32 = BITS(instr, 0, 7) * 4; // may not be used
663 regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FLDMX if regs is odd
664
665 if (wback) {
666 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
667 }
668
669 i = 0;
670
671 return ARMul_DONE;
672 }
673 else if (type == ARMul_DATA)
674 {
675 if (single_regs)
676 {
677 state->ExtReg[d + i] = value;
678 i++;
679 if (i < regs)
680 return ARMul_INC;
681 else
682 return ARMul_DONE;
683 }
684 else
685 {
686 /* FIXME Careful of endianness, may need to rework this */
687 state->ExtReg[d*2 + i] = value;
688 i++;
689 if (i < regs*2)
690 return ARMul_INC;
691 else
692 return ARMul_DONE;
693 }
694 }
695
696 return -1;
697}
698
699/* ----------- CDP ------------ */
700void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) 91void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm)
701{ 92{
702 if (single) 93 if (single)
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index 1b72383e7..727350f14 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -28,13 +28,6 @@
28#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]); 28#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
29 29
30unsigned VFPInit(ARMul_State* state); 30unsigned VFPInit(ARMul_State* state);
31unsigned VFPMRC(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);
34unsigned VFPMCRR(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
35unsigned VFPSTC(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);
38 31
39s32 vfp_get_float(ARMul_State* state, u32 reg); 32s32 vfp_get_float(ARMul_State* state, u32 reg);
40void vfp_put_float(ARMul_State* state, s32 val, u32 reg); 33void vfp_put_float(ARMul_State* state, s32 val, u32 reg);
@@ -44,23 +37,10 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
44u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 37u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
45u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 38u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
46 39
47// MRC 40void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
48void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value);
49void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); 41void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value);
50void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); 42void VMOVBRRD(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); 43void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
52void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); 44void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
53void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); 45void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
54 46
55// MCR
56void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
57
58// STC
59int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value);
60int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value);
61int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value);
62
63// LDC
64int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value);
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 5d1b4e53f..6b3dae280 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -36,9 +36,6 @@
36#include "common/common_types.h" 36#include "common/common_types.h"
37#include "core/arm/skyeye_common/armdefs.h" 37#include "core/arm/skyeye_common/armdefs.h"
38 38
39#define pr_info //printf
40#define pr_debug //printf
41
42#define do_div(n, base) {n/=base;} 39#define do_div(n, base) {n/=base;}
43 40
44enum : u32 { 41enum : u32 {
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 8b2dfa388..a78bdc430 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -51,6 +51,8 @@
51 * =========================================================================== 51 * ===========================================================================
52 */ 52 */
53 53
54#include "common/logging/log.h"
55
54#include "core/arm/skyeye_common/vfp/vfp_helper.h" 56#include "core/arm/skyeye_common/vfp/vfp_helper.h"
55#include "core/arm/skyeye_common/vfp/asm_vfp.h" 57#include "core/arm/skyeye_common/vfp/asm_vfp.h"
56#include "core/arm/skyeye_common/vfp/vfp.h" 58#include "core/arm/skyeye_common/vfp/vfp.h"
@@ -63,8 +65,8 @@ static struct vfp_single vfp_single_default_qnan = {
63 65
64static void vfp_single_dump(const char *str, struct vfp_single *s) 66static void vfp_single_dump(const char *str, struct vfp_single *s)
65{ 67{
66 pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n", 68 LOG_DEBUG(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x",
67 str, s->sign != 0, s->exponent, s->significand); 69 str, s->sign != 0, s->exponent, s->significand);
68} 70}
69 71
70static void vfp_single_normalise_denormal(struct vfp_single *vs) 72static void vfp_single_normalise_denormal(struct vfp_single *vs)
@@ -154,7 +156,7 @@ u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs,
154 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0)) 156 } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0))
155 incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1; 157 incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1;
156 158
157 pr_debug("VFP: rounding increment = 0x%08x\n", incr); 159 LOG_DEBUG(Core_ARM11, "rounding increment = 0x%08x", incr);
158 160
159 /* 161 /*
160 * Is our rounding going to overflow? 162 * Is our rounding going to overflow?
@@ -209,10 +211,8 @@ pack:
209 vfp_single_dump("pack: final", vs); 211 vfp_single_dump("pack: final", vs);
210 { 212 {
211 s32 d = vfp_single_pack(vs); 213 s32 d = vfp_single_pack(vs);
212#if 1 214 LOG_DEBUG(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func,
213 pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func, 215 sd, d, exceptions);
214 sd, d, exceptions);
215#endif
216 vfp_put_float(state, d, sd); 216 vfp_put_float(state, d, sd);
217 } 217 }
218 218
@@ -302,7 +302,7 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
302 u32 z, a; 302 u32 z, a;
303 303
304 if ((significand & 0xc0000000) != 0x40000000) { 304 if ((significand & 0xc0000000) != 0x40000000) {
305 pr_debug("VFP: estimate_sqrt: invalid significand\n"); 305 LOG_DEBUG(Core_ARM11, "invalid significand");
306 } 306 }
307 307
308 a = significand << 1; 308 a = significand << 1;
@@ -392,7 +392,7 @@ sqrt_invalid:
392 term = (u64)vsd.significand * vsd.significand; 392 term = (u64)vsd.significand * vsd.significand;
393 rem = ((u64)vsm.significand << 32) - term; 393 rem = ((u64)vsm.significand << 32) - term;
394 394
395 pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem); 395 LOG_DEBUG(Core_ARM11, "term=%016lx rem=%016lx", term, rem);
396 396
397 while (rem < 0) { 397 while (rem < 0) {
398 vsd.significand -= 1; 398 vsd.significand -= 1;
@@ -624,7 +624,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
624 } 624 }
625 } 625 }
626 626
627 pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); 627 LOG_DEBUG(Core_ARM11, "ftoui: d(s%d)=%08x exceptions=%08x", sd, d, exceptions);
628 628
629 vfp_put_float(state, d, sd); 629 vfp_put_float(state, d, sd);
630 630
@@ -703,7 +703,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
703 } 703 }
704 } 704 }
705 705
706 pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); 706 LOG_DEBUG(Core_ARM11, "ftosi: d(s%d)=%08x exceptions=%08x", sd, d, exceptions);
707 707
708 vfp_put_float(state, (s32)d, sd); 708 vfp_put_float(state, (s32)d, sd);
709 709
@@ -800,7 +800,7 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
800 800
801 if (vsn->significand & 0x80000000 || 801 if (vsn->significand & 0x80000000 ||
802 vsm->significand & 0x80000000) { 802 vsm->significand & 0x80000000) {
803 pr_info("VFP: bad FP values in %s\n", __func__); 803 LOG_WARNING(Core_ARM11, "bad FP values");
804 vfp_single_dump("VSN", vsn); 804 vfp_single_dump("VSN", vsn);
805 vfp_single_dump("VSM", vsm); 805 vfp_single_dump("VSM", vsm);
806 } 806 }
@@ -871,7 +871,7 @@ vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_s
871 struct vfp_single *t = vsn; 871 struct vfp_single *t = vsn;
872 vsn = vsm; 872 vsn = vsm;
873 vsm = t; 873 vsm = t;
874 pr_debug("VFP: swapping M <-> N\n"); 874 LOG_DEBUG(Core_ARM11, "swapping M <-> N");
875 } 875 }
876 876
877 vsd->sign = vsn->sign ^ vsm->sign; 877 vsd->sign = vsn->sign ^ vsm->sign;
@@ -924,7 +924,7 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
924 s32 v; 924 s32 v;
925 925
926 v = vfp_get_float(state, sn); 926 v = vfp_get_float(state, sn);
927 pr_debug("VFP: s%u = %08x\n", sn, v); 927 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, v);
928 vfp_single_unpack(&vsn, v); 928 vfp_single_unpack(&vsn, v);
929 if (vsn.exponent == 0 && vsn.significand) 929 if (vsn.exponent == 0 && vsn.significand)
930 vfp_single_normalise_denormal(&vsn); 930 vfp_single_normalise_denormal(&vsn);
@@ -939,7 +939,7 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
939 vsp.sign = vfp_sign_negate(vsp.sign); 939 vsp.sign = vfp_sign_negate(vsp.sign);
940 940
941 v = vfp_get_float(state, sd); 941 v = vfp_get_float(state, sd);
942 pr_debug("VFP: s%u = %08x\n", sd, v); 942 LOG_DEBUG(Core_ARM11, "s%u = %08x", sd, v);
943 vfp_single_unpack(&vsn, v); 943 vfp_single_unpack(&vsn, v);
944 if (vsn.exponent == 0 && vsn.significand != 0) 944 if (vsn.exponent == 0 && vsn.significand != 0)
945 vfp_single_normalise_denormal(&vsn); 945 vfp_single_normalise_denormal(&vsn);
@@ -961,7 +961,7 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
961 */ 961 */
962static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 962static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
963{ 963{
964 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd); 964 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, sd);
965 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac"); 965 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac");
966} 966}
967 967
@@ -970,7 +970,8 @@ static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
970 */ 970 */
971static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 971static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
972{ 972{
973 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sd, sn); 973 // TODO: this one has its arguments inverted, investigate.
974 LOG_DEBUG(Core_ARM11, "s%u = %08x", sd, sn);
974 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac"); 975 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac");
975} 976}
976 977
@@ -979,7 +980,7 @@ static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
979 */ 980 */
980static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 981static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
981{ 982{
982 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd); 983 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, sd);
983 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc"); 984 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc");
984} 985}
985 986
@@ -988,7 +989,7 @@ static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
988 */ 989 */
989static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 990static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
990{ 991{
991 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd); 992 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, sd);
992 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); 993 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
993} 994}
994 995
@@ -1001,7 +1002,7 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1001 u32 exceptions; 1002 u32 exceptions;
1002 s32 n = vfp_get_float(state, sn); 1003 s32 n = vfp_get_float(state, sn);
1003 1004
1004 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, n); 1005 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
1005 1006
1006 vfp_single_unpack(&vsn, n); 1007 vfp_single_unpack(&vsn, n);
1007 if (vsn.exponent == 0 && vsn.significand) 1008 if (vsn.exponent == 0 && vsn.significand)
@@ -1024,7 +1025,7 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
1024 u32 exceptions; 1025 u32 exceptions;
1025 s32 n = vfp_get_float(state, sn); 1026 s32 n = vfp_get_float(state, sn);
1026 1027
1027 pr_debug("VFP: s%u = %08x\n", sn, n); 1028 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
1028 1029
1029 vfp_single_unpack(&vsn, n); 1030 vfp_single_unpack(&vsn, n);
1030 if (vsn.exponent == 0 && vsn.significand) 1031 if (vsn.exponent == 0 && vsn.significand)
@@ -1048,7 +1049,7 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1048 u32 exceptions; 1049 u32 exceptions;
1049 s32 n = vfp_get_float(state, sn); 1050 s32 n = vfp_get_float(state, sn);
1050 1051
1051 pr_debug("VFP: s%u = %08x\n", sn, n); 1052 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
1052 1053
1053 /* 1054 /*
1054 * Unpack and normalise denormals. 1055 * Unpack and normalise denormals.
@@ -1071,7 +1072,7 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1071 */ 1072 */
1072static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1073static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1073{ 1074{
1074 pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd); 1075 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, sd);
1075 /* 1076 /*
1076 * Subtraction is addition with one sign inverted. 1077 * Subtraction is addition with one sign inverted.
1077 */ 1078 */
@@ -1091,7 +1092,7 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1091 s32 n = vfp_get_float(state, sn); 1092 s32 n = vfp_get_float(state, sn);
1092 int tm, tn; 1093 int tm, tn;
1093 1094
1094 pr_debug("VFP: s%u = %08x\n", sn, n); 1095 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
1095 1096
1096 vfp_single_unpack(&vsn, n); 1097 vfp_single_unpack(&vsn, n);
1097 vfp_single_unpack(&vsm, m); 1098 vfp_single_unpack(&vsm, m);
@@ -1213,7 +1214,6 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1213 unsigned int sm = vfp_get_sm(inst); 1214 unsigned int sm = vfp_get_sm(inst);
1214 unsigned int vecitr, veclen, vecstride; 1215 unsigned int vecitr, veclen, vecstride;
1215 struct op *fop; 1216 struct op *fop;
1216 pr_debug("In %s\n", __FUNCTION__);
1217 1217
1218 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); 1218 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
1219 1219
@@ -1239,11 +1239,11 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1239 else 1239 else
1240 veclen = fpscr & FPSCR_LENGTH_MASK; 1240 veclen = fpscr & FPSCR_LENGTH_MASK;
1241 1241
1242 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, 1242 LOG_DEBUG(Core_ARM11, "vecstride=%u veclen=%u", vecstride,
1243 (veclen >> FPSCR_LENGTH_BIT) + 1); 1243 (veclen >> FPSCR_LENGTH_BIT) + 1);
1244 1244
1245 if (!fop->fn) { 1245 if (!fop->fn) {
1246 printf("VFP: could not find single op %d, inst=0x%x@0x%x\n", FEXT_TO_IDX(inst), inst, state->Reg[15]); 1246 LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst), inst, state->Reg[15]);
1247 exit(-1); 1247 exit(-1);
1248 goto invalid; 1248 goto invalid;
1249 } 1249 }
@@ -1255,17 +1255,17 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1255 1255
1256 type = (fop->flags & OP_DD) ? 'd' : 's'; 1256 type = (fop->flags & OP_DD) ? 'd' : 's';
1257 if (op == FOP_EXT) 1257 if (op == FOP_EXT)
1258 pr_debug("VFP: itr%d (%c%u) = op[%u] (s%u=%08x)\n", 1258 LOG_DEBUG(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)",
1259 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, 1259 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
1260 sm, m); 1260 sm, m);
1261 else 1261 else
1262 pr_debug("VFP: itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)\n", 1262 LOG_DEBUG(Core_ARM11, "itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)",
1263 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, 1263 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
1264 FOP_TO_IDX(op), sm, m); 1264 FOP_TO_IDX(op), sm, m);
1265 1265
1266 except = fop->fn(state, dest, sn, m, fpscr); 1266 except = fop->fn(state, dest, sn, m, fpscr);
1267 pr_debug("VFP: itr%d: exceptions=%08x\n", 1267 LOG_DEBUG(Core_ARM11, "itr%d: exceptions=%08x",
1268 vecitr >> FPSCR_LENGTH_BIT, except); 1268 vecitr >> FPSCR_LENGTH_BIT, except);
1269 1269
1270 exceptions |= except; 1270 exceptions |= except;
1271 1271
diff --git a/src/core/core.h b/src/core/core.h
index 5e132cb5a..278f0f1cc 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -21,9 +21,6 @@ struct ThreadContext {
21 u32 fpu_registers[32]; 21 u32 fpu_registers[32];
22 u32 fpscr; 22 u32 fpscr;
23 u32 fpexc; 23 u32 fpexc;
24
25 // These are not part of native ThreadContext, but needed by emu
26 u32 mode;
27}; 24};
28 25
29extern ARM_Interface* g_app_core; ///< ARM11 application core 26extern ARM_Interface* g_app_core; ///< ARM11 application core
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h
index dbbdced74..770bd715e 100644
--- a/src/core/file_sys/disk_archive.h
+++ b/src/core/file_sys/disk_archive.h
@@ -24,7 +24,7 @@ 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 { return "DiskArchive: " + mount_point; } 27 virtual std::string GetName() const override { return "DiskArchive: " + mount_point; }
28 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;
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 0b6b6f518..be2626eef 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -46,6 +46,13 @@ template<ResultCode func(u32*, u32, u32, u32, u32, u32)> void Wrap(){
46 FuncReturn(retval); 46 FuncReturn(retval);
47} 47}
48 48
49template<ResultCode func(u32*, s32, u32, u32, u32, s32)> void Wrap() {
50 u32 param_1 = 0;
51 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
52 Core::g_app_core->SetReg(1, param_1);
53 FuncReturn(retval);
54}
55
49template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() { 56template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() {
50 s32 param_1 = 0; 57 s32 param_1 = 0;
51 s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), 58 s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2),
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 1aaeaa9c9..c645d6563 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -13,6 +13,7 @@
13#include "core/hle/shared_page.h" 13#include "core/hle/shared_page.h"
14#include "core/hle/kernel/thread.h" 14#include "core/hle/kernel/thread.h"
15#include "core/hle/service/service.h" 15#include "core/hle/service/service.h"
16#include "core/hle/svc.h"
16 17
17//////////////////////////////////////////////////////////////////////////////////////////////////// 18////////////////////////////////////////////////////////////////////////////////////////////////////
18 19
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 42f8ce2d9..19135266c 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -46,14 +46,12 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
46 case ArbitrationType::WaitIfLessThan: 46 case ArbitrationType::WaitIfLessThan:
47 if ((s32)Memory::Read32(address) <= value) { 47 if ((s32)Memory::Read32(address) <= value) {
48 Kernel::WaitCurrentThread_ArbitrateAddress(address); 48 Kernel::WaitCurrentThread_ArbitrateAddress(address);
49 HLE::Reschedule(__func__);
50 } 49 }
51 break; 50 break;
52 case ArbitrationType::WaitIfLessThanWithTimeout: 51 case ArbitrationType::WaitIfLessThanWithTimeout:
53 if ((s32)Memory::Read32(address) <= value) { 52 if ((s32)Memory::Read32(address) <= value) {
54 Kernel::WaitCurrentThread_ArbitrateAddress(address); 53 Kernel::WaitCurrentThread_ArbitrateAddress(address);
55 GetCurrentThread()->WakeAfterDelay(nanoseconds); 54 GetCurrentThread()->WakeAfterDelay(nanoseconds);
56 HLE::Reschedule(__func__);
57 } 55 }
58 break; 56 break;
59 case ArbitrationType::DecrementAndWaitIfLessThan: 57 case ArbitrationType::DecrementAndWaitIfLessThan:
@@ -62,7 +60,6 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
62 Memory::Write32(address, memory_value); 60 Memory::Write32(address, memory_value);
63 if (memory_value <= value) { 61 if (memory_value <= value) {
64 Kernel::WaitCurrentThread_ArbitrateAddress(address); 62 Kernel::WaitCurrentThread_ArbitrateAddress(address);
65 HLE::Reschedule(__func__);
66 } 63 }
67 break; 64 break;
68 } 65 }
@@ -73,7 +70,6 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
73 if (memory_value <= value) { 70 if (memory_value <= value) {
74 Kernel::WaitCurrentThread_ArbitrateAddress(address); 71 Kernel::WaitCurrentThread_ArbitrateAddress(address);
75 GetCurrentThread()->WakeAfterDelay(nanoseconds); 72 GetCurrentThread()->WakeAfterDelay(nanoseconds);
76 HLE::Reschedule(__func__);
77 } 73 }
78 break; 74 break;
79 } 75 }
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 498b2ec98..6261b82b6 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -154,7 +154,7 @@ void Shutdown() {
154 */ 154 */
155bool LoadExec(u32 entry_point) { 155bool LoadExec(u32 entry_point) {
156 // 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
157 g_main_thread = Kernel::SetupMainThread(Kernel::DEFAULT_STACK_SIZE, entry_point, 0x30); 157 g_main_thread = Kernel::SetupMainThread(Kernel::DEFAULT_STACK_SIZE, entry_point, THREADPRIO_DEFAULT);
158 158
159 return true; 159 return true;
160} 160}
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index be2c49706..ebc9e79d7 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -56,7 +56,15 @@ SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
56} 56}
57 57
58bool Mutex::ShouldWait() { 58bool Mutex::ShouldWait() {
59 return lock_count > 0 && holding_thread != GetCurrentThread();; 59 auto thread = GetCurrentThread();
60 bool wait = lock_count > 0 && holding_thread != thread;
61
62 // If the holding thread of the mutex is lower priority than this thread, that thread should
63 // temporarily inherit this thread's priority
64 if (wait && thread->current_priority < holding_thread->current_priority)
65 holding_thread->BoostPriority(thread->current_priority);
66
67 return wait;
60} 68}
61 69
62void Mutex::Acquire() { 70void Mutex::Acquire() {
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 4211fcf04..9b2511b53 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -16,6 +16,7 @@ SharedPtr<SharedMemory> SharedMemory::Create(std::string name) {
16 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 16 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
17 17
18 shared_memory->name = std::move(name); 18 shared_memory->name = std::move(name);
19 shared_memory->base_address = 0x0;
19 20
20 return shared_memory; 21 return shared_memory;
21} 22}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index be1aed615..33d66b986 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -140,6 +140,28 @@ void ArbitrateAllThreads(u32 address) {
140 } 140 }
141} 141}
142 142
143/// Boost low priority threads (temporarily) that have been starved
144static void PriorityBoostStarvedThreads() {
145 u64 current_ticks = CoreTiming::GetTicks();
146
147 for (auto& thread : thread_list) {
148 // TODO(bunnei): Threads that have been waiting to be scheduled for `boost_ticks` (or
149 // longer) will have their priority temporarily adjusted to 1 higher than the highest
150 // priority thread to prevent thread starvation. This general behavior has been verified
151 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler
152 // should probably be reversed to verify this.
153
154 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long
155
156 u64 delta = current_ticks - thread->last_running_ticks;
157
158 if (thread->status == THREADSTATUS_READY && delta > boost_timeout && !thread->idle) {
159 const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0);
160 thread->BoostPriority(priority);
161 }
162 }
163}
164
143/** 165/**
144 * Switches the CPU's active thread context to that of the specified thread 166 * Switches the CPU's active thread context to that of the specified thread
145 * @param new_thread The thread to switch to 167 * @param new_thread The thread to switch to
@@ -151,6 +173,7 @@ static void SwitchContext(Thread* new_thread) {
151 173
152 // Save context for previous thread 174 // Save context for previous thread
153 if (previous_thread) { 175 if (previous_thread) {
176 previous_thread->last_running_ticks = CoreTiming::GetTicks();
154 Core::g_app_core->SaveContext(previous_thread->context); 177 Core::g_app_core->SaveContext(previous_thread->context);
155 178
156 if (previous_thread->status == THREADSTATUS_RUNNING) { 179 if (previous_thread->status == THREADSTATUS_RUNNING) {
@@ -168,6 +191,9 @@ static void SwitchContext(Thread* new_thread) {
168 ready_queue.remove(new_thread->current_priority, new_thread); 191 ready_queue.remove(new_thread->current_priority, new_thread);
169 new_thread->status = THREADSTATUS_RUNNING; 192 new_thread->status = THREADSTATUS_RUNNING;
170 193
194 // Restores thread to its nominal priority if it has been temporarily changed
195 new_thread->current_priority = new_thread->nominal_priority;
196
171 Core::g_app_core->LoadContext(new_thread->context); 197 Core::g_app_core->LoadContext(new_thread->context);
172 } else { 198 } else {
173 current_thread = nullptr; 199 current_thread = nullptr;
@@ -364,7 +390,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
364 thread->status = THREADSTATUS_DORMANT; 390 thread->status = THREADSTATUS_DORMANT;
365 thread->entry_point = entry_point; 391 thread->entry_point = entry_point;
366 thread->stack_top = stack_top; 392 thread->stack_top = stack_top;
367 thread->initial_priority = thread->current_priority = priority; 393 thread->nominal_priority = thread->current_priority = priority;
394 thread->last_running_ticks = CoreTiming::GetTicks();
368 thread->processor_id = processor_id; 395 thread->processor_id = processor_id;
369 thread->wait_set_output = false; 396 thread->wait_set_output = false;
370 thread->wait_all = false; 397 thread->wait_all = false;
@@ -400,17 +427,15 @@ static void ClampPriority(const Thread* thread, s32* priority) {
400void Thread::SetPriority(s32 priority) { 427void Thread::SetPriority(s32 priority) {
401 ClampPriority(this, &priority); 428 ClampPriority(this, &priority);
402 429
403 if (current_priority == priority) { 430 // If thread was ready, adjust queues
404 return; 431 if (status == THREADSTATUS_READY)
405 } 432 ready_queue.move(this, current_priority, priority);
406 433
407 if (status == THREADSTATUS_READY) { 434 nominal_priority = current_priority = priority;
408 // If thread was ready, adjust queues 435}
409 ready_queue.remove(current_priority, this); 436
410 ready_queue.prepare(priority); 437void Thread::BoostPriority(s32 priority) {
411 ready_queue.push_back(priority, this); 438 ready_queue.move(this, current_priority, priority);
412 }
413
414 current_priority = priority; 439 current_priority = priority;
415} 440}
416 441
@@ -440,6 +465,9 @@ SharedPtr<Thread> SetupMainThread(u32 stack_size, u32 entry_point, s32 priority)
440 465
441void Reschedule() { 466void Reschedule() {
442 Thread* prev = GetCurrentThread(); 467 Thread* prev = GetCurrentThread();
468
469 PriorityBoostStarvedThreads();
470
443 Thread* next = PopNextReadyThread(); 471 Thread* next = PopNextReadyThread();
444 HLE::g_reschedule = false; 472 HLE::g_reschedule = false;
445 473
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index cfd073a70..233bcbdbd 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -17,17 +17,19 @@
17#include "core/hle/kernel/kernel.h" 17#include "core/hle/kernel/kernel.h"
18#include "core/hle/result.h" 18#include "core/hle/result.h"
19 19
20enum ThreadPriority { 20enum ThreadPriority : s32{
21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority 21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority
22 THREADPRIO_DEFAULT = 16, ///< Default thread priority for userland apps 22 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
23 THREADPRIO_LOW = 31, ///< Low range of thread priority for userland apps 23 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps
24 THREADPRIO_LOWEST = 63, ///< Thread priority max checked by svcCreateThread 24 THREADPRIO_LOWEST = 63, ///< Lowest thread priority
25}; 25};
26 26
27enum ThreadProcessorId { 27enum ThreadProcessorId : s32 {
28 THREADPROCESSORID_0 = 0xFFFFFFFE, ///< Enables core appcode 28 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader
29 THREADPROCESSORID_1 = 0xFFFFFFFD, ///< Enables core syscore 29 THREADPROCESSORID_ALL = -1, ///< Run thread on either core
30 THREADPROCESSORID_ALL = 0xFFFFFFFC, ///< Enables both cores 30 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore)
31 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore)
32 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this
31}; 33};
32 34
33enum ThreadStatus { 35enum ThreadStatus {
@@ -88,6 +90,12 @@ public:
88 void SetPriority(s32 priority); 90 void SetPriority(s32 priority);
89 91
90 /** 92 /**
93 * Temporarily boosts the thread's priority until the next time it is scheduled
94 * @param priority The new priority
95 */
96 void BoostPriority(s32 priority);
97
98 /**
91 * Gets the thread's thread ID 99 * Gets the thread's thread ID
92 * @return The thread's ID 100 * @return The thread's ID
93 */ 101 */
@@ -135,8 +143,10 @@ public:
135 u32 entry_point; 143 u32 entry_point;
136 u32 stack_top; 144 u32 stack_top;
137 145
138 s32 initial_priority; 146 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application
139 s32 current_priority; 147 s32 current_priority; ///< Current thread priority, can be temporarily changed
148
149 u64 last_running_ticks; ///< CPU tick when thread was last running
140 150
141 s32 processor_id; 151 s32 processor_id;
142 152
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 610e26a3c..1ec2a4b10 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -66,7 +66,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
66 SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); 66 SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
67 67
68 if (timer == nullptr) { 68 if (timer == nullptr) {
69 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle); 69 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08lX", timer_handle);
70 return; 70 return;
71 } 71 }
72 72
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 4861d9e5f..190c5df7a 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -32,7 +32,8 @@ static Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem = nullptr;
32 32
33static Kernel::SharedPtr<Kernel::Mutex> lock = nullptr; 33static Kernel::SharedPtr<Kernel::Mutex> lock = nullptr;
34static Kernel::SharedPtr<Kernel::Event> notification_event = nullptr; ///< APT notification event 34static Kernel::SharedPtr<Kernel::Event> notification_event = nullptr; ///< APT notification event
35static Kernel::SharedPtr<Kernel::Event> pause_event = nullptr; ///< APT pause event 35static Kernel::SharedPtr<Kernel::Event> start_event = nullptr; ///< APT start event
36
36static std::vector<u8> shared_font; 37static std::vector<u8> shared_font;
37 38
38static u32 cpu_percent = 0; ///< CPU time available to the running application 39static u32 cpu_percent = 0; ///< CPU time available to the running application
@@ -44,11 +45,11 @@ void Initialize(Service::Interface* self) {
44 45
45 cmd_buff[2] = 0x04000000; // According to 3dbrew, this value should be 0x04000000 46 cmd_buff[2] = 0x04000000; // According to 3dbrew, this value should be 0x04000000
46 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); 47 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
47 cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom(); 48 cmd_buff[4] = Kernel::g_handle_table.Create(start_event).MoveFrom();
48 49
49 // TODO(bunnei): Check if these events are cleared/signaled every time Initialize is called. 50 // TODO(bunnei): Check if these events are cleared every time Initialize is called.
50 notification_event->Clear(); 51 notification_event->Clear();
51 pause_event->Signal(); // Fire start event 52 start_event->Clear();
52 53
53 ASSERT_MSG((nullptr != lock), "Cannot initialize without lock"); 54 ASSERT_MSG((nullptr != lock), "Cannot initialize without lock");
54 lock->Release(); 55 lock->Release();
@@ -81,7 +82,7 @@ void NotifyToWait(Service::Interface* self) {
81 u32* cmd_buff = Kernel::GetCommandBuffer(); 82 u32* cmd_buff = Kernel::GetCommandBuffer();
82 u32 app_id = cmd_buff[1]; 83 u32 app_id = cmd_buff[1];
83 // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further. 84 // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further.
84 pause_event->Signal(); 85 start_event->Signal();
85 86
86 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 87 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
87 LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); 88 LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id);
@@ -312,7 +313,7 @@ void Init() {
312 313
313 // TODO(bunnei): Check if these are created in Initialize or on APT process startup. 314 // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
314 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification"); 315 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification");
315 pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause"); 316 start_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Start");
316} 317}
317 318
318void Shutdown() { 319void Shutdown() {
diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp
index 2d841f69c..13322bdbb 100644
--- a/src/core/hle/service/ptm/ptm_sysm.cpp
+++ b/src/core/hle/service/ptm/ptm_sysm.cpp
@@ -16,7 +16,7 @@ namespace PTM {
16 * 1: Result code, 0 on success, otherwise error code 16 * 1: Result code, 0 on success, otherwise error code
17 * 2: Whether the system is going through a power off 17 * 2: Whether the system is going through a power off
18 */ 18 */
19void IsLegacyPowerOff(Service::Interface* self) { 19static void IsLegacyPowerOff(Service::Interface* self) {
20 u32* cmd_buff = Kernel::GetCommandBuffer(); 20 u32* cmd_buff = Kernel::GetCommandBuffer();
21 cmd_buff[1] = RESULT_SUCCESS.raw; 21 cmd_buff[1] = RESULT_SUCCESS.raw;
22 cmd_buff[2] = 0; 22 cmd_buff[2] = 0;
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 134ff1740..d50327cb9 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -51,6 +51,49 @@ namespace Service {
51std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports; 51std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
52std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; 52std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
53 53
54/**
55 * Creates a function string for logging, complete with the name (or header code, depending
56 * on what's passed in) the port name, and all the cmd_buff arguments.
57 */
58static std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) {
59 // Number of params == bits 0-5 + bits 6-11
60 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
61
62 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name);
63 for (int i = 1; i <= num_params; ++i) {
64 function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
65 }
66 return function_string;
67}
68
69ResultVal<bool> Interface::SyncRequest() {
70 u32* cmd_buff = Kernel::GetCommandBuffer();
71 auto itr = m_functions.find(cmd_buff[0]);
72
73 if (itr == m_functions.end() || itr->second.func == nullptr) {
74 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
75 LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
76
77 // TODO(bunnei): Hack - ignore error
78 cmd_buff[1] = 0;
79 return MakeResult<bool>(false);
80 } else {
81 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
82 }
83
84 itr->second.func(this);
85
86 return MakeResult<bool>(false); // TODO: Implement return from actual function
87}
88
89void Interface::Register(const FunctionInfo* functions, size_t n) {
90 m_functions.reserve(n);
91 for (size_t i = 0; i < n; ++i) {
92 // Usually this array is sorted by id already, so hint to instead at the end
93 m_functions.emplace_hint(m_functions.cend(), functions[i].id, functions[i]);
94 }
95}
96
54//////////////////////////////////////////////////////////////////////////////////////////////////// 97////////////////////////////////////////////////////////////////////////////////////////////////////
55// Module interface 98// Module interface
56 99
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index bfe16ebad..21ada67b5 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -4,20 +4,15 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <algorithm>
8#include <string> 7#include <string>
9#include <unordered_map> 8#include <unordered_map>
10#include <vector>
11 9
12#include <boost/container/flat_map.hpp> 10#include <boost/container/flat_map.hpp>
13 11
14#include "common/common.h" 12#include "common/common.h"
15#include "common/string_util.h"
16#include "core/mem_map.h"
17 13
18#include "core/hle/kernel/kernel.h" 14#include "core/hle/kernel/kernel.h"
19#include "core/hle/kernel/session.h" 15#include "core/hle/kernel/session.h"
20#include "core/hle/svc.h"
21 16
22//////////////////////////////////////////////////////////////////////////////////////////////////// 17////////////////////////////////////////////////////////////////////////////////////////////////////
23// Namespace Service 18// Namespace Service
@@ -26,31 +21,11 @@ namespace Service {
26 21
27static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) 22static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters)
28 23
29class Manager;
30
31/// Interface to a CTROS service 24/// Interface to a CTROS service
32class Interface : public Kernel::Session { 25class Interface : public Kernel::Session {
33 // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be 26 // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be
34 // just something that encapsulates a session and acts as a helper to implement service 27 // just something that encapsulates a session and acts as a helper to implement service
35 // processes. 28 // processes.
36
37 friend class Manager;
38
39 /**
40 * Creates a function string for logging, complete with the name (or header code, depending
41 * on what's passed in) the port name, and all the cmd_buff arguments.
42 */
43 std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) {
44 // Number of params == bits 0-5 + bits 6-11
45 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
46
47 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name);
48 for (int i = 1; i <= num_params; ++i) {
49 function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
50 }
51 return function_string;
52 }
53
54public: 29public:
55 std::string GetName() const override { return GetPortName(); } 30 std::string GetName() const override { return GetPortName(); }
56 31
@@ -70,25 +45,7 @@ public:
70 return "[UNKNOWN SERVICE PORT]"; 45 return "[UNKNOWN SERVICE PORT]";
71 } 46 }
72 47
73 ResultVal<bool> SyncRequest() override { 48 ResultVal<bool> SyncRequest() override;
74 u32* cmd_buff = Kernel::GetCommandBuffer();
75 auto itr = m_functions.find(cmd_buff[0]);
76
77 if (itr == m_functions.end() || itr->second.func == nullptr) {
78 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
79 LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
80
81 // TODO(bunnei): Hack - ignore error
82 cmd_buff[1] = 0;
83 return MakeResult<bool>(false);
84 } else {
85 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
86 }
87
88 itr->second.func(this);
89
90 return MakeResult<bool>(false); // TODO: Implement return from actual function
91 }
92 49
93protected: 50protected:
94 51
@@ -96,14 +53,12 @@ protected:
96 * Registers the functions in the service 53 * Registers the functions in the service
97 */ 54 */
98 template <size_t N> 55 template <size_t N>
99 void Register(const FunctionInfo (&functions)[N]) { 56 inline void Register(const FunctionInfo (&functions)[N]) {
100 m_functions.reserve(N); 57 Register(functions, 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);
104 }
105 } 58 }
106 59
60 void Register(const FunctionInfo* functions, size_t n);
61
107private: 62private:
108 boost::container::flat_map<u32, FunctionInfo> m_functions; 63 boost::container::flat_map<u32, FunctionInfo> m_functions;
109 64
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index bbb4eb9cd..76e9b171a 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -283,8 +283,13 @@ static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 val
283 if (arbiter == nullptr) 283 if (arbiter == nullptr)
284 return ERR_INVALID_HANDLE; 284 return ERR_INVALID_HANDLE;
285 285
286 return arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), 286 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type),
287 address, value, nanoseconds); 287 address, value, nanoseconds);
288
289 if (res == RESULT_SUCCESS)
290 HLE::Reschedule(__func__);
291
292 return res;
288} 293}
289 294
290/// Used to output a message on a debug hardware unit - does nothing on a retail unit 295/// Used to output a message on a debug hardware unit - does nothing on a retail unit
@@ -312,7 +317,7 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim
312} 317}
313 318
314/// Creates a new thread 319/// Creates a new thread
315static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { 320static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) {
316 using Kernel::Thread; 321 using Kernel::Thread;
317 322
318 std::string name; 323 std::string name;
@@ -323,6 +328,27 @@ static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u
323 name = Common::StringFromFormat("unknown-%08x", entry_point); 328 name = Common::StringFromFormat("unknown-%08x", entry_point);
324 } 329 }
325 330
331 // TODO(bunnei): Implement resource limits to return an error code instead of the below assert.
332 // The error code should be: Description::NotAuthorized, Module::OS, Summary::WrongArgument,
333 // Level::Permanent
334 ASSERT_MSG(priority >= THREADPRIO_USERLAND_MAX, "Unexpected thread priority!");
335
336 if (priority > THREADPRIO_LOWEST) {
337 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS,
338 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
339 }
340
341 switch (processor_id) {
342 case THREADPROCESSORID_DEFAULT:
343 case THREADPROCESSORID_0:
344 case THREADPROCESSORID_1:
345 break;
346 default:
347 // TODO(bunnei): Implement support for other processor IDs
348 ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id);
349 break;
350 }
351
326 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( 352 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(
327 name, entry_point, priority, arg, processor_id, stack_top)); 353 name, entry_point, priority, arg, processor_id, stack_top));
328 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); 354 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread)));
@@ -331,10 +357,7 @@ static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u
331 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, 357 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point,
332 name.c_str(), arg, stack_top, priority, processor_id, *out_handle); 358 name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
333 359
334 if (THREADPROCESSORID_1 == processor_id) { 360 HLE::Reschedule(__func__);
335 LOG_WARNING(Kernel_SVC,
336 "thread designated for system CPU core (UNIMPLEMENTED) will be run with app core scheduling");
337 }
338 361
339 return RESULT_SUCCESS; 362 return RESULT_SUCCESS;
340} 363}
@@ -374,8 +397,11 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
374 SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0); 397 SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0);
375 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); 398 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
376 399
400 HLE::Reschedule(__func__);
401
377 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 402 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
378 initial_locked ? "true" : "false", *out_handle); 403 initial_locked ? "true" : "false", *out_handle);
404
379 return RESULT_SUCCESS; 405 return RESULT_SUCCESS;
380} 406}
381 407
@@ -390,6 +416,9 @@ static ResultCode ReleaseMutex(Handle handle) {
390 return ERR_INVALID_HANDLE; 416 return ERR_INVALID_HANDLE;
391 417
392 mutex->Release(); 418 mutex->Release();
419
420 HLE::Reschedule(__func__);
421
393 return RESULT_SUCCESS; 422 return RESULT_SUCCESS;
394} 423}
395 424
@@ -428,6 +457,9 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
428 return ERR_INVALID_HANDLE; 457 return ERR_INVALID_HANDLE;
429 458
430 CASCADE_RESULT(*count, semaphore->Release(release_count)); 459 CASCADE_RESULT(*count, semaphore->Release(release_count));
460
461 HLE::Reschedule(__func__);
462
431 return RESULT_SUCCESS; 463 return RESULT_SUCCESS;
432} 464}
433 465
@@ -520,6 +552,9 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
520 return ERR_INVALID_HANDLE; 552 return ERR_INVALID_HANDLE;
521 553
522 timer->Set(initial, interval); 554 timer->Set(initial, interval);
555
556 HLE::Reschedule(__func__);
557
523 return RESULT_SUCCESS; 558 return RESULT_SUCCESS;
524} 559}
525 560
@@ -534,6 +569,9 @@ static ResultCode CancelTimer(Handle handle) {
534 return ERR_INVALID_HANDLE; 569 return ERR_INVALID_HANDLE;
535 570
536 timer->Cancel(); 571 timer->Cancel();
572
573 HLE::Reschedule(__func__);
574
537 return RESULT_SUCCESS; 575 return RESULT_SUCCESS;
538} 576}
539 577
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index dd46f0ec3..6ec253601 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -342,10 +342,10 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
342 342
343 case Regs::TextureConfig::MirroredRepeat: 343 case Regs::TextureConfig::MirroredRepeat:
344 { 344 {
345 int coord = (int)((unsigned)val % (2 * size)); 345 unsigned int coord = ((unsigned)val % (2 * size));
346 if (coord >= size) 346 if (coord >= size)
347 coord = 2 * size - 1 - coord; 347 coord = 2 * size - 1 - coord;
348 return coord; 348 return (int)coord;
349 } 349 }
350 350
351 default: 351 default: