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…
Reference in a new issue