diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Runtime/Gecko_ExceptionPPC.cpp | 42 | ||||
-rw-r--r-- | src/Runtime/__init_cpp_exceptions.cpp | 52 | ||||
-rw-r--r-- | src/Runtime/global_destructor_chain.c | 2 |
3 files changed, 95 insertions, 1 deletions
diff --git a/src/Runtime/Gecko_ExceptionPPC.cpp b/src/Runtime/Gecko_ExceptionPPC.cpp new file mode 100644 index 0000000..693aa25 --- /dev/null +++ b/src/Runtime/Gecko_ExceptionPPC.cpp @@ -0,0 +1,42 @@ +// This file was taken from the Metroid Prime decompilation project. +// https://github.com/PrimeDecomp/prime/blob/main/src/Runtime/Gecko_ExceptionPPC.cpp +#include "__ppc_eabi_linker.h" +#include "NMWException.h" + +#if __MWERKS__ +#pragma exceptions on +#endif + +typedef struct ProcessInfo { + __eti_init_info* exception_info; + char* TOC; + int active; +} ProcessInfo; + +static ProcessInfo fragmentinfo[1]; + +int __register_fragment(struct __eti_init_info* info, char* TOC) { + ProcessInfo* f; + int i; + + for (i = 0, f = fragmentinfo; i < 1; ++i, ++f) { + if (f->active == 0) { + f->exception_info = info; + f->TOC = TOC; + f->active = 1; + return (i); + } + } + + return (-1); +} + +void __unregister_fragment(int fragmentId) { + ProcessInfo* f; + if (fragmentId >= 0 && fragmentId < 1) { + f = &fragmentinfo[fragmentId]; + f->exception_info = 0; + f->TOC = 0; + f->active = 0; + } +} diff --git a/src/Runtime/__init_cpp_exceptions.cpp b/src/Runtime/__init_cpp_exceptions.cpp new file mode 100644 index 0000000..937cc79 --- /dev/null +++ b/src/Runtime/__init_cpp_exceptions.cpp @@ -0,0 +1,52 @@ +// This file was taken from the Metroid Prime decompilation project. +// https://github.com/PrimeDecomp/prime/blob/main/src/Runtime/__init_cpp_exceptions.cpp +#include "NMWException.h" +#include "__ppc_eabi_linker.h" + +static int fragmentID = -2; + +#ifdef __cplusplus +extern "C" { +#endif + +extern void __init_cpp_exceptions(void); +extern void __fini_cpp_exceptions(void); +extern void suspend(void); + +#ifdef __cplusplus +} +#endif + +/* clang-format off */ +static asm char* GetR2() { + nofralloc; + mr r3, r2 + blr +} +/* clang-format on */ + +extern void __init_cpp_exceptions(void) { + char* R2; + if (fragmentID == -2) { + + R2 = GetR2(); + + /* HACK: TODO: _eti_init_info should be _eti_init_info, we can't use the appropriate name yet due to the + * linker not being able to generate it*/ + fragmentID = __register_fragment(_eti_init_info, R2); + } +} + +extern void __fini_cpp_exceptions(void) { + if (fragmentID != -2) { + __unregister_fragment(fragmentID); + fragmentID = -2; + } +} + +__declspec(section + ".ctors") static void* const __init_cpp_exceptions_reference = __init_cpp_exceptions; +__declspec(section + ".dtors") static void* const __destroy_global_chain_reference = __destroy_global_chain; +__declspec(section + ".dtors") static void* const __fini_cpp_exceptions_reference = __fini_cpp_exceptions; diff --git a/src/Runtime/global_destructor_chain.c b/src/Runtime/global_destructor_chain.c index b96c8f3..1f3790d 100644 --- a/src/Runtime/global_destructor_chain.c +++ b/src/Runtime/global_destructor_chain.c @@ -10,7 +10,7 @@ extern void *__register_global_object(void *object, dtor_func *destructor, dtor_ return object; } -extern void __destroy_global_chain() { +void __destroy_global_chain() { dtor_chain *iter = __global_destructor_chain; while (__global_destructor_chain != 0) { iter = __global_destructor_chain; |