diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 24 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc/svc_thread.cpp | 3 | 
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,      context.cpu_registers[0] = arg;      context.cpu_registers[15] = entry_point;      context.cpu_registers[13] = stack_top; +    context.fpscr = 0;  }  static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top, @@ -58,8 +59,8 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,      context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;      context.pc = entry_point;      context.sp = stack_top; -    // TODO(merry): Perform a hardware test to determine the below value.      context.fpcr = 0; +    context.fpsr = 0;  }  } // namespace @@ -815,6 +816,27 @@ void KThread::Continue() {      KScheduler::OnThreadStateChanged(kernel, this, old_state);  } +void KThread::CloneFpuStatus() { +    // We shouldn't reach here when starting kernel threads. +    ASSERT(this->GetOwnerProcess() != nullptr); +    ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(kernel)); + +    if (this->GetOwnerProcess()->Is64BitProcess()) { +        // Clone FPSR and FPCR. +        ThreadContext64 cur_ctx{}; +        kernel.System().CurrentArmInterface().SaveContext(cur_ctx); + +        this->GetContext64().fpcr = cur_ctx.fpcr; +        this->GetContext64().fpsr = cur_ctx.fpsr; +    } else { +        // Clone FPSCR. +        ThreadContext32 cur_ctx{}; +        kernel.System().CurrentArmInterface().SaveContext(cur_ctx); + +        this->GetContext32().fpscr = cur_ctx.fpscr; +    } +} +  Result KThread::SetActivity(Svc::ThreadActivity activity) {      // Lock ourselves.      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:          thread_context_32.tpidr = static_cast<u32>(value);      } +    void CloneFpuStatus(); +      [[nodiscard]] ThreadContext32& GetContext32() {          return thread_context_32;      } 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,      // Commit the thread reservation.      thread_reservation.Commit(); +    // Clone the current fpu status to the new thread. +    thread->CloneFpuStatus(); +      // Register the new thread.      KThread::Register(kernel, thread);  | 
