mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	core/arm: Backend-specific context implementations
This commit is contained in:
		
							parent
							
								
									7d5c3b00a8
								
							
						
					
					
						commit
						fb2d34997e
					
				
					 9 changed files with 212 additions and 73 deletions
				
			
		|  | @ -172,8 +172,8 @@ QString WaitTreeThread::GetText() const { | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     QString pc_info = tr(" PC = 0x%1 LR = 0x%2") |     QString pc_info = tr(" PC = 0x%1 LR = 0x%2") | ||||||
|                           .arg(thread.context.pc, 8, 16, QLatin1Char('0')) |                           .arg(thread.context->GetProgramCounter(), 8, 16, QLatin1Char('0')) | ||||||
|                           .arg(thread.context.lr, 8, 16, QLatin1Char('0')); |                           .arg(thread.context->GetLinkRegister(), 8, 16, QLatin1Char('0')); | ||||||
|     return WaitTreeWaitObject::GetText() + pc_info + " (" + status + ") "; |     return WaitTreeWaitObject::GetText() + pc_info + " (" + status + ") "; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
|  | #include <memory> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/arm/skyeye_common/arm_regformat.h" | #include "core/arm/skyeye_common/arm_regformat.h" | ||||||
| #include "core/arm/skyeye_common/vfp/asm_vfp.h" | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | ||||||
|  | @ -14,15 +15,42 @@ class ARM_Interface : NonCopyable { | ||||||
| public: | public: | ||||||
|     virtual ~ARM_Interface() {} |     virtual ~ARM_Interface() {} | ||||||
| 
 | 
 | ||||||
|     struct ThreadContext { |     class ThreadContext { | ||||||
|         u32 cpu_registers[13]; |     public: | ||||||
|         u32 sp; |         virtual ~ThreadContext() = default; | ||||||
|         u32 lr; | 
 | ||||||
|         u32 pc; |         virtual void Reset() = 0; | ||||||
|         u32 cpsr; |         virtual u32 GetCpuRegister(size_t index) const = 0; | ||||||
|         u32 fpu_registers[64]; |         virtual void SetCpuRegister(size_t index, u32 value) = 0; | ||||||
|         u32 fpscr; |         virtual u32 GetCpsr() const = 0; | ||||||
|         u32 fpexc; |         virtual void SetCpsr(u32 value) = 0; | ||||||
|  |         virtual u32 GetFpuRegister(size_t index) const = 0; | ||||||
|  |         virtual void SetFpuRegister(size_t index, u32 value) = 0; | ||||||
|  |         virtual u32 GetFpscr() const = 0; | ||||||
|  |         virtual void SetFpscr(u32 value) = 0; | ||||||
|  |         virtual u32 GetFpexc() const = 0; | ||||||
|  |         virtual void SetFpexc(u32 value) = 0; | ||||||
|  | 
 | ||||||
|  |         u32 GetStackPointer() const { | ||||||
|  |             return GetCpuRegister(13); | ||||||
|  |         } | ||||||
|  |         void SetStackPointer(u32 value) { | ||||||
|  |             return SetCpuRegister(13, value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         u32 GetLinkRegister() const { | ||||||
|  |             return GetCpuRegister(14); | ||||||
|  |         } | ||||||
|  |         void SetLinkRegister(u32 value) { | ||||||
|  |             return SetCpuRegister(14, value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         u32 GetProgramCounter() const { | ||||||
|  |             return GetCpuRegister(15); | ||||||
|  |         } | ||||||
|  |         void SetProgramCounter(u32 value) { | ||||||
|  |             return SetCpuRegister(15, value); | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /// Runs the CPU until an event happens
 |     /// Runs the CPU until an event happens
 | ||||||
|  | @ -124,17 +152,23 @@ public: | ||||||
|      */ |      */ | ||||||
|     virtual void SetCP15Register(CP15Register reg, u32 value) = 0; |     virtual void SetCP15Register(CP15Register reg, u32 value) = 0; | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Creates a CPU context | ||||||
|  |      * @note The created context may only be used with this instance. | ||||||
|  |      */ | ||||||
|  |     virtual std::unique_ptr<ThreadContext> NewContext() const = 0; | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Saves the current CPU context |      * Saves the current CPU context | ||||||
|      * @param ctx Thread context to save |      * @param ctx Thread context to save | ||||||
|      */ |      */ | ||||||
|     virtual void SaveContext(ThreadContext& ctx) = 0; |     virtual void SaveContext(const std::unique_ptr<ThreadContext>& ctx) = 0; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Loads a CPU context |      * Loads a CPU context | ||||||
|      * @param ctx Thread context to load |      * @param ctx Thread context to load | ||||||
|      */ |      */ | ||||||
|     virtual void LoadContext(const ThreadContext& ctx) = 0; |     virtual void LoadContext(const std::unique_ptr<ThreadContext>& ctx) = 0; | ||||||
| 
 | 
 | ||||||
|     /// Prepare core for thread reschedule (if needed to correctly handle state)
 |     /// Prepare core for thread reschedule (if needed to correctly handle state)
 | ||||||
|     virtual void PrepareReschedule() = 0; |     virtual void PrepareReschedule() = 0; | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  | #include <dynarmic/context.h> | ||||||
| #include <dynarmic/dynarmic.h> | #include <dynarmic/dynarmic.h> | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
|  | @ -14,6 +15,59 @@ | ||||||
| #include "core/hle/kernel/svc.h" | #include "core/hle/kernel/svc.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| 
 | 
 | ||||||
|  | class DynarmicThreadContext final : public ARM_Interface::ThreadContext { | ||||||
|  | public: | ||||||
|  |     DynarmicThreadContext() { | ||||||
|  |         Reset(); | ||||||
|  |     } | ||||||
|  |     ~DynarmicThreadContext() override = default; | ||||||
|  | 
 | ||||||
|  |     void Reset() override { | ||||||
|  |         ctx.Regs() = {}; | ||||||
|  |         ctx.SetCpsr(0); | ||||||
|  |         ctx.ExtRegs() = {}; | ||||||
|  |         ctx.SetFpscr(0); | ||||||
|  |         fpexc = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     u32 GetCpuRegister(size_t index) const override { | ||||||
|  |         return ctx.Regs()[index]; | ||||||
|  |     } | ||||||
|  |     void SetCpuRegister(size_t index, u32 value) override { | ||||||
|  |         ctx.Regs()[index] = value; | ||||||
|  |     } | ||||||
|  |     u32 GetCpsr() const override { | ||||||
|  |         return ctx.Cpsr(); | ||||||
|  |     } | ||||||
|  |     void SetCpsr(u32 value) override { | ||||||
|  |         ctx.SetCpsr(value); | ||||||
|  |     } | ||||||
|  |     u32 GetFpuRegister(size_t index) const override { | ||||||
|  |         return ctx.ExtRegs()[index]; | ||||||
|  |     } | ||||||
|  |     void SetFpuRegister(size_t index, u32 value) override { | ||||||
|  |         ctx.ExtRegs()[index] = value; | ||||||
|  |     } | ||||||
|  |     u32 GetFpscr() const override { | ||||||
|  |         return ctx.Fpscr(); | ||||||
|  |     } | ||||||
|  |     void SetFpscr(u32 value) override { | ||||||
|  |         ctx.SetFpscr(value); | ||||||
|  |     } | ||||||
|  |     u32 GetFpexc() const override { | ||||||
|  |         return fpexc; | ||||||
|  |     } | ||||||
|  |     void SetFpexc(u32 value) override { | ||||||
|  |         fpexc = value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     friend class ARM_Dynarmic; | ||||||
|  | 
 | ||||||
|  |     Dynarmic::Context ctx; | ||||||
|  |     u32 fpexc; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void* user_arg) { | static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void* user_arg) { | ||||||
|     ARMul_State* state = static_cast<ARMul_State*>(user_arg); |     ARMul_State* state = static_cast<ARMul_State*>(user_arg); | ||||||
| 
 | 
 | ||||||
|  | @ -148,30 +202,24 @@ void ARM_Dynarmic::SetCP15Register(CP15Register reg, u32 value) { | ||||||
|     interpreter_state->CP15[reg] = value; |     interpreter_state->CP15[reg] = value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) { | std::unique_ptr<ARM_Interface::ThreadContext> ARM_Dynarmic::NewContext() const { | ||||||
|     memcpy(ctx.cpu_registers, jit->Regs().data(), sizeof(ctx.cpu_registers)); |     return std::make_unique<DynarmicThreadContext>(); | ||||||
|     memcpy(ctx.fpu_registers, jit->ExtRegs().data(), sizeof(ctx.fpu_registers)); |  | ||||||
| 
 |  | ||||||
|     ctx.sp = jit->Regs()[13]; |  | ||||||
|     ctx.lr = jit->Regs()[14]; |  | ||||||
|     ctx.pc = jit->Regs()[15]; |  | ||||||
|     ctx.cpsr = jit->Cpsr(); |  | ||||||
| 
 |  | ||||||
|     ctx.fpscr = jit->Fpscr(); |  | ||||||
|     ctx.fpexc = interpreter_state->VFP[VFP_FPEXC]; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) { | void ARM_Dynarmic::SaveContext(const std::unique_ptr<ThreadContext>& arg) { | ||||||
|     memcpy(jit->Regs().data(), ctx.cpu_registers, sizeof(ctx.cpu_registers)); |     DynarmicThreadContext* ctx = dynamic_cast<DynarmicThreadContext*>(arg.get()); | ||||||
|     memcpy(jit->ExtRegs().data(), ctx.fpu_registers, sizeof(ctx.fpu_registers)); |     ASSERT(ctx); | ||||||
| 
 | 
 | ||||||
|     jit->Regs()[13] = ctx.sp; |     jit->SaveContext(ctx->ctx); | ||||||
|     jit->Regs()[14] = ctx.lr; |     ctx->fpexc = interpreter_state->VFP[VFP_FPEXC]; | ||||||
|     jit->Regs()[15] = ctx.pc; | } | ||||||
|     jit->SetCpsr(ctx.cpsr); |  | ||||||
| 
 | 
 | ||||||
|     jit->SetFpscr(ctx.fpscr); | void ARM_Dynarmic::LoadContext(const std::unique_ptr<ThreadContext>& arg) { | ||||||
|     interpreter_state->VFP[VFP_FPEXC] = ctx.fpexc; |     const DynarmicThreadContext* ctx = dynamic_cast<DynarmicThreadContext*>(arg.get()); | ||||||
|  |     ASSERT(ctx); | ||||||
|  | 
 | ||||||
|  |     jit->LoadContext(ctx->ctx); | ||||||
|  |     interpreter_state->VFP[VFP_FPEXC] = ctx->fpexc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ARM_Dynarmic::PrepareReschedule() { | void ARM_Dynarmic::PrepareReschedule() { | ||||||
|  |  | ||||||
|  | @ -35,8 +35,9 @@ public: | ||||||
|     u32 GetCP15Register(CP15Register reg) override; |     u32 GetCP15Register(CP15Register reg) override; | ||||||
|     void SetCP15Register(CP15Register reg, u32 value) override; |     void SetCP15Register(CP15Register reg, u32 value) override; | ||||||
| 
 | 
 | ||||||
|     void SaveContext(ThreadContext& ctx) override; |     std::unique_ptr<ThreadContext> NewContext() const override; | ||||||
|     void LoadContext(const ThreadContext& ctx) override; |     void SaveContext(const std::unique_ptr<ThreadContext>& arg) override; | ||||||
|  |     void LoadContext(const std::unique_ptr<ThreadContext>& arg) override; | ||||||
| 
 | 
 | ||||||
|     void PrepareReschedule() override; |     void PrepareReschedule() override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,6 +12,62 @@ | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| 
 | 
 | ||||||
|  | class DynComThreadContext final : public ARM_Interface::ThreadContext { | ||||||
|  | public: | ||||||
|  |     DynComThreadContext() { | ||||||
|  |         Reset(); | ||||||
|  |     } | ||||||
|  |     ~DynComThreadContext() override = default; | ||||||
|  | 
 | ||||||
|  |     void Reset() override { | ||||||
|  |         cpu_registers = {}; | ||||||
|  |         cpsr = 0; | ||||||
|  |         fpu_registers = {}; | ||||||
|  |         fpscr = 0; | ||||||
|  |         fpexc = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     u32 GetCpuRegister(size_t index) const override { | ||||||
|  |         return cpu_registers[index]; | ||||||
|  |     } | ||||||
|  |     void SetCpuRegister(size_t index, u32 value) override { | ||||||
|  |         cpu_registers[index] = value; | ||||||
|  |     } | ||||||
|  |     u32 GetCpsr() const override { | ||||||
|  |         return cpsr; | ||||||
|  |     } | ||||||
|  |     void SetCpsr(u32 value) override { | ||||||
|  |         cpsr = value; | ||||||
|  |     } | ||||||
|  |     u32 GetFpuRegister(size_t index) const override { | ||||||
|  |         return fpu_registers[index]; | ||||||
|  |     } | ||||||
|  |     void SetFpuRegister(size_t index, u32 value) override { | ||||||
|  |         fpu_registers[index] = value; | ||||||
|  |     } | ||||||
|  |     u32 GetFpscr() const override { | ||||||
|  |         return fpscr; | ||||||
|  |     } | ||||||
|  |     void SetFpscr(u32 value) override { | ||||||
|  |         fpscr = value; | ||||||
|  |     } | ||||||
|  |     u32 GetFpexc() const override { | ||||||
|  |         return fpexc; | ||||||
|  |     } | ||||||
|  |     void SetFpexc(u32 value) override { | ||||||
|  |         fpexc = value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     friend class ARM_DynCom; | ||||||
|  | 
 | ||||||
|  |     std::array<u32, 16> cpu_registers; | ||||||
|  |     u32 cpsr; | ||||||
|  |     std::array<u32, 64> fpu_registers; | ||||||
|  |     u32 fpscr; | ||||||
|  |     u32 fpexc; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { | ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { | ||||||
|     state = std::make_unique<ARMul_State>(initial_mode); |     state = std::make_unique<ARMul_State>(initial_mode); | ||||||
| } | } | ||||||
|  | @ -93,30 +149,30 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) { | ||||||
|     CoreTiming::AddTicks(ticks_executed); |     CoreTiming::AddTicks(ticks_executed); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ARM_DynCom::SaveContext(ThreadContext& ctx) { | std::unique_ptr<ARM_Interface::ThreadContext> ARM_DynCom::NewContext() const { | ||||||
|     memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers)); |     return std::make_unique<DynComThreadContext>(); | ||||||
|     memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers)); |  | ||||||
| 
 |  | ||||||
|     ctx.sp = state->Reg[13]; |  | ||||||
|     ctx.lr = state->Reg[14]; |  | ||||||
|     ctx.pc = state->Reg[15]; |  | ||||||
|     ctx.cpsr = state->Cpsr; |  | ||||||
| 
 |  | ||||||
|     ctx.fpscr = state->VFP[VFP_FPSCR]; |  | ||||||
|     ctx.fpexc = state->VFP[VFP_FPEXC]; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ARM_DynCom::LoadContext(const ThreadContext& ctx) { | void ARM_DynCom::SaveContext(const std::unique_ptr<ThreadContext>& arg) { | ||||||
|     memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers)); |     DynComThreadContext* ctx = dynamic_cast<DynComThreadContext*>(arg.get()); | ||||||
|     memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers)); |     ASSERT(ctx); | ||||||
| 
 | 
 | ||||||
|     state->Reg[13] = ctx.sp; |     ctx->cpu_registers = state->Reg; | ||||||
|     state->Reg[14] = ctx.lr; |     ctx->cpsr = state->Cpsr; | ||||||
|     state->Reg[15] = ctx.pc; |     ctx->fpu_registers = state->ExtReg; | ||||||
|     state->Cpsr = ctx.cpsr; |     ctx->fpscr = state->VFP[VFP_FPSCR]; | ||||||
|  |     ctx->fpexc = state->VFP[VFP_FPEXC]; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     state->VFP[VFP_FPSCR] = ctx.fpscr; | void ARM_DynCom::LoadContext(const std::unique_ptr<ThreadContext>& arg) { | ||||||
|     state->VFP[VFP_FPEXC] = ctx.fpexc; |     DynComThreadContext* ctx = dynamic_cast<DynComThreadContext*>(arg.get()); | ||||||
|  |     ASSERT(ctx); | ||||||
|  | 
 | ||||||
|  |     state->Reg = ctx->cpu_registers; | ||||||
|  |     state->Cpsr = ctx->cpsr; | ||||||
|  |     state->ExtReg = ctx->fpu_registers; | ||||||
|  |     state->VFP[VFP_FPSCR] = ctx->fpscr; | ||||||
|  |     state->VFP[VFP_FPEXC] = ctx->fpexc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ARM_DynCom::PrepareReschedule() { | void ARM_DynCom::PrepareReschedule() { | ||||||
|  |  | ||||||
|  | @ -35,8 +35,9 @@ public: | ||||||
|     u32 GetCP15Register(CP15Register reg) override; |     u32 GetCP15Register(CP15Register reg) override; | ||||||
|     void SetCP15Register(CP15Register reg, u32 value) override; |     void SetCP15Register(CP15Register reg, u32 value) override; | ||||||
| 
 | 
 | ||||||
|     void SaveContext(ThreadContext& ctx) override; |     std::unique_ptr<ThreadContext> NewContext() const override; | ||||||
|     void LoadContext(const ThreadContext& ctx) override; |     void SaveContext(const std::unique_ptr<ThreadContext>& arg) override; | ||||||
|  |     void LoadContext(const std::unique_ptr<ThreadContext>& arg) override; | ||||||
| 
 | 
 | ||||||
|     void PrepareReschedule() override; |     void PrepareReschedule() override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -733,8 +733,8 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point | ||||||
|                    Thread::Create(name, entry_point, priority, arg, processor_id, stack_top, |                    Thread::Create(name, entry_point, priority, arg, processor_id, stack_top, | ||||||
|                                   g_current_process)); |                                   g_current_process)); | ||||||
| 
 | 
 | ||||||
|     thread->context.fpscr = |     thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | | ||||||
|         FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000
 |                               FPSCR_ROUND_TOZERO); // 0x03C00000
 | ||||||
| 
 | 
 | ||||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(thread))); |     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(thread))); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -60,7 +60,7 @@ inline static u32 const NewThreadId() { | ||||||
|     return next_thread_id++; |     return next_thread_id++; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Thread::Thread() {} | Thread::Thread() : context(Core::CPU().NewContext()) {} | ||||||
| Thread::~Thread() {} | Thread::~Thread() {} | ||||||
| 
 | 
 | ||||||
| Thread* GetCurrentThread() { | Thread* GetCurrentThread() { | ||||||
|  | @ -309,14 +309,13 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t | ||||||
|  * @param entry_point Address of entry point for execution |  * @param entry_point Address of entry point for execution | ||||||
|  * @param arg User argument for thread |  * @param arg User argument for thread | ||||||
|  */ |  */ | ||||||
| static void ResetThreadContext(ARM_Interface::ThreadContext& context, u32 stack_top, | static void ResetThreadContext(const std::unique_ptr<ARM_Interface::ThreadContext>& context, | ||||||
|                                u32 entry_point, u32 arg) { |                                u32 stack_top, u32 entry_point, u32 arg) { | ||||||
|     memset(&context, 0, sizeof(ARM_Interface::ThreadContext)); |     context->Reset(); | ||||||
| 
 |     context->SetCpuRegister(0, arg); | ||||||
|     context.cpu_registers[0] = arg; |     context->SetProgramCounter(entry_point); | ||||||
|     context.pc = entry_point; |     context->SetStackPointer(stack_top); | ||||||
|     context.sp = stack_top; |     context->SetCpsr(USER32MODE | ((entry_point & 1) << 5)); // Usermode and THUMB mode
 | ||||||
|     context.cpsr = USER32MODE | ((entry_point & 1) << 5); // Usermode and THUMB mode
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, u32 priority, | ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, u32 priority, | ||||||
|  | @ -453,8 +452,8 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, u32 priority, SharedPtr<Proce | ||||||
| 
 | 
 | ||||||
|     SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); |     SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); | ||||||
| 
 | 
 | ||||||
|     thread->context.fpscr = |     thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | | ||||||
|         FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010
 |                               FPSCR_IXC); // 0x03C00010
 | ||||||
| 
 | 
 | ||||||
|     // Note: The newly created thread will be run when the scheduler fires.
 |     // Note: The newly created thread will be run when the scheduler fires.
 | ||||||
|     return thread; |     return thread; | ||||||
|  | @ -480,11 +479,11 @@ void Reschedule() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Thread::SetWaitSynchronizationResult(ResultCode result) { | void Thread::SetWaitSynchronizationResult(ResultCode result) { | ||||||
|     context.cpu_registers[0] = result.raw; |     context->SetCpuRegister(0, result.raw); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Thread::SetWaitSynchronizationOutput(s32 output) { | void Thread::SetWaitSynchronizationOutput(s32 output) { | ||||||
|     context.cpu_registers[1] = output; |     context->SetCpuRegister(1, output); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| s32 Thread::GetWaitObjectIndex(WaitObject* object) const { | s32 Thread::GetWaitObjectIndex(WaitObject* object) const { | ||||||
|  |  | ||||||
|  | @ -181,7 +181,7 @@ public: | ||||||
|         return status == THREADSTATUS_WAIT_SYNCH_ALL; |         return status == THREADSTATUS_WAIT_SYNCH_ALL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ARM_Interface::ThreadContext context; |     std::unique_ptr<ARM_Interface::ThreadContext> context; | ||||||
| 
 | 
 | ||||||
|     u32 thread_id; |     u32 thread_id; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue