coreinit: Add coroutine functions.

This commit is contained in:
Andrew Church
2016-07-06 19:52:57 +09:00
parent 8178fde45c
commit 04c7504e48
4 changed files with 88 additions and 0 deletions

View File

@@ -41,6 +41,7 @@ Module::RegisterFunctions()
registerAllocatorFunctions();
registerAtomic64Functions();
registerCoreFunctions();
registerCoroutineFunctions();
registerCacheFunctions();
registerDebugFunctions();
registerDeviceFunctions();

View File

@@ -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();

View 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

View 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