From 96140b0d163d18c0158f29b2063307efad918e18 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Mon, 30 Jan 2023 11:25:36 -0400 Subject: Global: Add necessary files to test linking --- include/NMWException.h | 26 ++++++++++++++++++ obj_files.mk | 3 ++ src/Runtime/Gecko_ExceptionPPC.cpp | 42 ++++++++++++++++++++++++++++ src/Runtime/__init_cpp_exceptions.cpp | 52 +++++++++++++++++++++++++++++++++++ src/Runtime/global_destructor_chain.c | 2 +- 5 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 include/NMWException.h create mode 100644 src/Runtime/Gecko_ExceptionPPC.cpp create mode 100644 src/Runtime/__init_cpp_exceptions.cpp diff --git a/include/NMWException.h b/include/NMWException.h new file mode 100644 index 0000000..9cf7e48 --- /dev/null +++ b/include/NMWException.h @@ -0,0 +1,26 @@ +#ifndef NMWEXCEPTION_H +#define NMWEXCEPTION_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (dtor_func)(void *object, int free_object); +typedef struct destructor_chain dtor_chain; + +struct destructor_chain { + dtor_chain *next; + dtor_func *destructor; + void *object; +}; + +void __unregister_fragment(int fragmentID); +int __register_fragment(struct __eti_init_info *info, char *TOC); +void *__register_global_object(void *object, dtor_func *destructor, dtor_chain *regmem); +void __destroy_global_chain(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/obj_files.mk b/obj_files.mk index 2e65fa0..4677312 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -2,5 +2,8 @@ O_FILES := $(BUILD_DIR)/src/main.o \ $(BUILD_DIR)/src/pso/TMainTask.o \ $(BUILD_DIR)/src/pso/TObject.o \ $(BUILD_DIR)/src/Runtime/global_destructor_chain.o \ + $(BUILD_DIR)/src/Runtime/Gecko_ExceptionPPC.o \ + $(BUILD_DIR)/src/Runtime/__init_cpp_exceptions.o \ + $(BUILD_DIR)/src/Runtime/abort_exit.o \ $(BUILD_DIR)/src/Dolphin/os/__start.o \ $(BUILD_DIR)/src/Dolphin/os/__ppc_eabi_init.o 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; -- cgit v1.2.3-13-gbd6f