mirror of
https://github.com/decaf-emu/decaf-emu.git
synced 2026-10-14 09:38:28 +00:00
coreinit: Add coroutine functions.
This commit is contained in:
@@ -41,6 +41,7 @@ Module::RegisterFunctions()
|
||||
registerAllocatorFunctions();
|
||||
registerAtomic64Functions();
|
||||
registerCoreFunctions();
|
||||
registerCoroutineFunctions();
|
||||
registerCacheFunctions();
|
||||
registerDebugFunctions();
|
||||
registerDeviceFunctions();
|
||||
|
||||
@@ -47,6 +47,7 @@ private:
|
||||
static void registerAllocatorFunctions();
|
||||
static void registerAtomic64Functions();
|
||||
static void registerCoreFunctions();
|
||||
static void registerCoroutineFunctions();
|
||||
static void registerCacheFunctions();
|
||||
static void registerDebugFunctions();
|
||||
static void registerDeviceFunctions();
|
||||
|
||||
57
src/libdecaf/src/modules/coreinit/coreinit_coroutine.cpp
Normal file
57
src/libdecaf/src/modules/coreinit/coreinit_coroutine.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "coreinit.h"
|
||||
#include "coreinit_coroutine.h"
|
||||
#include "coreinit_thread.h"
|
||||
|
||||
namespace coreinit
|
||||
{
|
||||
|
||||
void
|
||||
OSInitCoroutine(OSCoroutine *context, uint32_t entry, uint32_t stack)
|
||||
{
|
||||
context->nia = entry;
|
||||
context->gpr1 = stack;
|
||||
}
|
||||
|
||||
void
|
||||
OSSwitchCoroutine(OSCoroutine *from, OSCoroutine *to)
|
||||
{
|
||||
OSThread *thread = OSGetCurrentThread();
|
||||
|
||||
// Save current coroutine state
|
||||
from->nia = thread->context.lr;
|
||||
from->cr = thread->context.cr;
|
||||
from->gpr5 = thread->context.gpr[5];
|
||||
from->gpr1 = thread->context.gpr[1];
|
||||
from->gpr2 = thread->context.gpr[2];
|
||||
for (int i = 13; i < 32; i++) {
|
||||
thread->context.gpr[i] = to->gpr13_31[i-13];
|
||||
}
|
||||
for (int i = 14; i < 32; i++) {
|
||||
thread->context.fpr[i] = to->fpr14_31[i-14];
|
||||
}
|
||||
|
||||
// Switch to new coroutine state
|
||||
thread->context.lr = to->nia;
|
||||
thread->context.cr = to->cr;
|
||||
thread->context.gpr[0] = from->nia; // Probably just coincidence
|
||||
thread->context.gpr[1] = to->gpr1;
|
||||
thread->context.gpr[2] = to->gpr2;
|
||||
thread->context.gpr[3] = 1;
|
||||
thread->context.gpr[4] = 1;
|
||||
thread->context.gpr[5] = to->gpr5;
|
||||
for (int i = 13; i < 32; i++) {
|
||||
thread->context.gpr[i] = to->gpr13_31[i-13];
|
||||
}
|
||||
for (int i = 14; i < 32; i++) {
|
||||
thread->context.fpr[i] = to->fpr14_31[i-14];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Module::registerCoroutineFunctions()
|
||||
{
|
||||
RegisterKernelFunction(OSInitCoroutine);
|
||||
RegisterKernelFunction(OSSwitchCoroutine);
|
||||
}
|
||||
|
||||
} // namespace coreinit
|
||||
29
src/libdecaf/src/modules/coreinit/coreinit_coroutine.h
Normal file
29
src/libdecaf/src/modules/coreinit/coreinit_coroutine.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "common/types.h"
|
||||
#include "common/be_val.h"
|
||||
#include "common/structsize.h"
|
||||
|
||||
namespace coreinit
|
||||
{
|
||||
|
||||
struct OSCoroutine
|
||||
{
|
||||
be_val<uint32_t> nia;
|
||||
be_val<uint32_t> cr;
|
||||
be_val<uint32_t> gpr5;
|
||||
be_val<uint32_t> gpr1;
|
||||
be_val<uint32_t> gpr2;
|
||||
be_val<uint32_t> gpr13_31[19];
|
||||
be_val<double> fpr14_31[18];
|
||||
UNKNOWN(0x90);
|
||||
};
|
||||
CHECK_OFFSET(OSCoroutine, 0x000, nia);
|
||||
CHECK_OFFSET(OSCoroutine, 0x004, cr);
|
||||
CHECK_OFFSET(OSCoroutine, 0x008, gpr5);
|
||||
CHECK_OFFSET(OSCoroutine, 0x00C, gpr1);
|
||||
CHECK_OFFSET(OSCoroutine, 0x010, gpr2);
|
||||
CHECK_OFFSET(OSCoroutine, 0x014, gpr13_31);
|
||||
CHECK_OFFSET(OSCoroutine, 0x060, fpr14_31);
|
||||
CHECK_SIZE(OSCoroutine, 0x180);
|
||||
|
||||
} // namespace coreinit
|
||||
Reference in New Issue
Block a user