summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/k_thread.cpp24
-rw-r--r--src/core/hle/kernel/k_thread.h2
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp3
3 files changed, 28 insertions, 1 deletions
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 8c403f5fd..15ae652f9 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -49,6 +49,7 @@ static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context,
49 context.cpu_registers[0] = arg; 49 context.cpu_registers[0] = arg;
50 context.cpu_registers[15] = entry_point; 50 context.cpu_registers[15] = entry_point;
51 context.cpu_registers[13] = stack_top; 51 context.cpu_registers[13] = stack_top;
52 context.fpscr = 0;
52} 53}
53 54
54static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top, 55static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top,
@@ -58,8 +59,8 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
58 context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1; 59 context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
59 context.pc = entry_point; 60 context.pc = entry_point;
60 context.sp = stack_top; 61 context.sp = stack_top;
61 // TODO(merry): Perform a hardware test to determine the below value.
62 context.fpcr = 0; 62 context.fpcr = 0;
63 context.fpsr = 0;
63} 64}
64} // namespace 65} // namespace
65 66
@@ -815,6 +816,27 @@ void KThread::Continue() {
815 KScheduler::OnThreadStateChanged(kernel, this, old_state); 816 KScheduler::OnThreadStateChanged(kernel, this, old_state);
816} 817}
817 818
819void KThread::CloneFpuStatus() {
820 // We shouldn't reach here when starting kernel threads.
821 ASSERT(this->GetOwnerProcess() != nullptr);
822 ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(kernel));
823
824 if (this->GetOwnerProcess()->Is64BitProcess()) {
825 // Clone FPSR and FPCR.
826 ThreadContext64 cur_ctx{};
827 kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
828
829 this->GetContext64().fpcr = cur_ctx.fpcr;
830 this->GetContext64().fpsr = cur_ctx.fpsr;
831 } else {
832 // Clone FPSCR.
833 ThreadContext32 cur_ctx{};
834 kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
835
836 this->GetContext32().fpscr = cur_ctx.fpscr;
837 }
838}
839
818Result KThread::SetActivity(Svc::ThreadActivity activity) { 840Result KThread::SetActivity(Svc::ThreadActivity activity) {
819 // Lock ourselves. 841 // Lock ourselves.
820 KScopedLightLock lk(activity_pause_lock); 842 KScopedLightLock lk(activity_pause_lock);
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index bd125f5f1..9423f08ca 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -254,6 +254,8 @@ public:
254 thread_context_32.tpidr = static_cast<u32>(value); 254 thread_context_32.tpidr = static_cast<u32>(value);
255 } 255 }
256 256
257 void CloneFpuStatus();
258
257 [[nodiscard]] ThreadContext32& GetContext32() { 259 [[nodiscard]] ThreadContext32& GetContext32() {
258 return thread_context_32; 260 return thread_context_32;
259 } 261 }
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index b39807841..9bc1ebe74 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -82,6 +82,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
82 // Commit the thread reservation. 82 // Commit the thread reservation.
83 thread_reservation.Commit(); 83 thread_reservation.Commit();
84 84
85 // Clone the current fpu status to the new thread.
86 thread->CloneFpuStatus();
87
85 // Register the new thread. 88 // Register the new thread.
86 KThread::Register(kernel, thread); 89 KThread::Register(kernel, thread);
87 90