diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 965fff7..ed9ff57 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,7 @@ This will also generate `.s` (assembly) files inside the `build/[GAME ID]/asm` f - Write C++ code that creates matching assembly code - Use the following string as the build flags - Compiler `4.3 build 188 (Wii MW 1.5)` - - `-O2,p -lang=c++ -RTTI off -enum int -fp hard -enc SJIS -fp_contract on -str reuse -inline auto -use_lmw_stmw on` + - `-O4,s -lang=c++ -RTTI off -enum int -fp hard -enc SJIS -fp_contract on -str reuse -inline auto -use_lmw_stmw on` - When placing the function or variable into this repository, mark in a comment the address of the symbol - For example `// symbol 0x80395304` diff --git a/README.md b/README.md index 21c693b..682fb2b 100644 --- a/README.md +++ b/README.md @@ -109,4 +109,4 @@ Select an object from the left sidebar to begin diffing. Changes to the project ## References - [Decomp Toolkit](https://github.com/encounter/dtk-template) (repo template) - [Dolphin 2001 SDK](https://github.com/doldecomp/dolsdk2001) -- [MSL Runtime](https://github.com/projectPiki/pikmin2/blob/main/src/Dolphin/Runtime) (From Pikmin 2 Decomp) + - Alice uses Revolution SDK of a currently unknown version or release, however, dolsdk can be used as a basis diff --git a/config/SALP4Q/splits.txt b/config/SALP4Q/splits.txt index d0f99f8..b66afda 100644 --- a/config/SALP4Q/splits.txt +++ b/config/SALP4Q/splits.txt @@ -13,51 +13,54 @@ Sections: .sdata2 type:rodata align:16 .sbss2 type:bss align:32 -PowerPC_EABI_Support/Runtime/global_destructor_chain.c: - .text start:0x80368C58 end:0x80394124 +Revolution/OS/__start.c: + .init start:0x80004000 end:0x80006618 -PowerPC_EABI_Support/Runtime/__init_cpp_exceptions.cpp: - .text start:0x80395304 end:0x80395374 - .ctors start:0x804D3540 end:0x804D3544 rename:.ctors$10 - .dtors start:0x804D41E0 end:0x804D41E4 rename:.dtors$10 - .dtors start:0x804D41E4 end:0x804D41E8 rename:.dtors$15 - .sdata start:0x805F3828 end:0x805F3830 +Alice/Objects/Groups/CKGrpAliceHero.cpp: + .text start:0x8000DBF0 end:0x8000E264 -PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.cpp: - .text start:0x80395374 end:0x80395480 +Alice/Objects/Hooks/CKHkAliceHero.cpp: + .text start:0x8001D894 end:0x8001E9E8 -Alice/Objects/0Managers/CKSoundManager.cpp: - .text start:0x802BA0DC end:0x802BAEA0 +Alice/Objects/Components/CKAliceHeroConfig.cpp: + .text start:0x800539D4 end:0x80055528 -Alice/Objects/1Services/CKSrvTrigger.cpp: - .text start:0x8022CE90 end:0x8022D744 +Alice/Objects/Logic/CKAliceGameSpawnPoint.cpp: + .text start:0x800EEFBC end:0x800EF814 -Alice/Objects/2Hooks/CKHkAliceHero.cpp: - .text start:0x8001D894 end:0x8001E9E8 +Alice/Objects/Geometries/CSkinGeometry.cpp: + .text start:0x801DB1A8 end:0x801DB6D8 -Alice/Objects/4Groups/CKGrpAliceHero.cpp: - .text start:0x8000DBF0 end:0x8000E264 +Alice/Objects/Graphics/CLightManager.cpp: + .text start:0x801E3D88 end:0x801E76B4 -Alice/Objects/6Components/CKAliceHeroConfig.cpp: - .text start:0x800539D4 end:0x80055528 +Alice/Objects/Nodes/CSpawnNode.cpp: + .text start:0x80211C1C end:0x80212060 -Alice/Objects/7Camera/CKCameraFixTrack.cpp: - .text start:0x80238574 end:0x802388B4 +Alice/Objects/Services/CKSrvTrigger.cpp: + .text start:0x8022CE90 end:0x8022D744 -Alice/Objects/8Cinematics/CKStartDoor.cpp: - .text start:0x80266000 end:0x802662AC +Alice/Objects/Camera/CKCameraFixTrack.cpp: + .text start:0x80238574 end:0x802388B4 -Alice/Objects/9Dictionaries/CKSoundDictionary.cpp: - .text start:0x802B9360 end:0x802B9A70 +Alice/Objects/Cinematics/CKStartDoor.cpp: + .text start:0x80266000 end:0x802662AC -Alice/Objects/10Geometries/CSkinGeometry.cpp: - .text start:0x801DB1A8 end:0x801DB6D8 +Alice/Objects/Dictionaries/CKSoundDictionary.cpp: + .text start:0x802B9360 end:0x802B9A70 -Alice/Objects/11Nodes/CSpawnNode.cpp: - .text start:0x80211C1C end:0x80212060 +Alice/Objects/Managers/CKSoundManager.cpp: + .text start:0x802BA0DC end:0x802BAEA0 -Alice/Objects/12Logic/CKAliceGameSpawnPoint.cpp: - .text start:0x800EEFBC end:0x800EF814 +PowerPC_EABI_Support/Runtime/global_destructor_chain.c: + .text start:0x80368C58 end:0x80394124 + +PowerPC_EABI_Support/Runtime/__init_cpp_exceptions.cpp: + .text start:0x80395304 end:0x80395374 + .ctors start:0x804D3540 end:0x804D3544 rename:.ctors$10 + .dtors start:0x804D41E0 end:0x804D41E4 rename:.dtors$10 + .dtors start:0x804D41E4 end:0x804D41E8 rename:.dtors$15 + .sdata start:0x805F3828 end:0x805F3830 -Alice/Objects/13Graphics/CLightManager.cpp: - .text start:0x801E3D88 end:0x801E76B4 +PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.cpp: + .text start:0x80395374 end:0x80395480 diff --git a/configure.py b/configure.py index ca27779..5b2c228 100644 --- a/configure.py +++ b/configure.py @@ -184,7 +184,7 @@ "-fp hardware", "-Cpp_exceptions off", # "-W all", - "-O4,p", + "-O4,s", "-inline auto", '-pragma "cats off"', '-pragma "warn_notinlined off"', @@ -244,7 +244,7 @@ def MatchingFor(*versions): config.warn_missing_source = False config.libs = [ { - "lib": "PowerPC_EABI_Support", + "lib": "PowerPC_EABI_Support/Runtime", "mw_version": config.linker_version, "cflags": cflags_runtime, "host": False, @@ -255,6 +255,22 @@ def MatchingFor(*versions): Object(MatchingFor(), "PowerPC_EABI_Support/Runtime/global_destructor_chain.c") ], }, + { + "lib": "PowerPC_EABI_Support/MSL", + "mw_version": config.linker_version, + "cflags": cflags_runtime, + "host": False, + "progress_category": "sdk", # str | List[str] + "objects": [], + }, + { + "lib": "PowerPC_EABI_Support/MetroTRK", + "mw_version": config.linker_version, + "cflags": cflags_runtime, + "host": False, + "progress_category": "sdk", # str | List[str] + "objects": [], + }, { "lib": "Revolution", "mw_version": config.linker_version, @@ -268,10 +284,23 @@ def MatchingFor(*versions): { "lib": "Alice", "mw_version": config.linker_version, - "cflags": cflags_runtime, + "cflags": cflags_base, "host": False, "progress_category": "game", # str | List[str] - "objects": [], + "objects": [ + Object(MatchingFor(), "Alice/Objects/Managers/CKSoundManager.cpp"), + Object(MatchingFor(), "Alice/Objects/Services/CKSrvTrigger.cpp"), + Object(MatchingFor(), "Alice/Objects/Hooks/CKHkAliceHero.cpp"), + Object(MatchingFor(), "Alice/Objects/Groups/CKGrpAliceHero.cpp"), + Object(MatchingFor(), "Alice/Objects/Components/CKAliceHeroConfig.cpp"), + Object(MatchingFor(), "Alice/Objects/Camera/CKCameraFixTrack.cpp"), + Object(MatchingFor(), "Alice/Objects/Cinematics/CKStartDoor.cpp"), + Object(MatchingFor(), "Alice/Objects/Dictionaries/CKSoundDictionary.cpp"), + Object(MatchingFor(), "Alice/Objects/Geometries/CSkinGeometry.cpp"), + Object(MatchingFor(), "Alice/Objects/Nodes/CSpawnNode.cpp"), + Object(MatchingFor(), "Alice/Objects/Logic/CKAliceGameSpawnPoint.cpp"), + Object(MatchingFor(), "Alice/Objects/Graphics/CLightManager.cpp") + ], } ] diff --git a/include/PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.h b/include/PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.h index 0cf3b41..adb1733 100644 --- a/include/PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.h +++ b/include/PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.h @@ -3,7 +3,7 @@ #include "types.h" #include "PowerPC_EABI_Support/Runtime/__ppc_eabi_linker.h" - #define MAXFRAGMENTS 1 + #define MAXFRAGMENTS 0x1F typedef struct ExceptionTableIndex { u32 functionoffset; @@ -25,11 +25,11 @@ typedef struct ProcessInfo { __eti_init_info* exception_info; char* TOC; - s32 active; + u32 active; } ProcessInfo; - s32 __register_fragment(struct __eti_init_info*, char*); - void __unregister_fragment(s32); + u32 __register_fragment(struct __eti_init_info*, char*); + void __unregister_fragment(u32); s32 ExPPC_FindExceptionFragment(char*, FragmentInfo*); #endif diff --git a/include/Revolution/OS/__ppc_eabi_init.h b/include/Revolution/OS/__ppc_eabi_init.h new file mode 100644 index 0000000..723ca62 --- /dev/null +++ b/include/Revolution/OS/__ppc_eabi_init.h @@ -0,0 +1,89 @@ +#ifndef RVL_SDK_OS_PPC_EABI_INIT_H + #define RVL_SDK_OS_PPC_EABI_INIT_H + #include "global.h" + #ifdef __cplusplus + extern "C" { + #endif + + #pragma section ".init" + DECL_SECTION(".init") void __init_hardware(void); + // DECL_SECTION(".init") void __flush_cache(void*, size_t); + + s32 main(s32 argc, char** argv); + void __init_user(void); + void __init_cpp(void); + void __fini_cpp(void); + DECL_WEAK void exit(void); + void _ExitProcess(void); + + // Declare linker symbols for a section in the ROM + #define DECL_ROM_SECTION(x) \ + extern u8 _f##x[]; \ + extern u8 _f##x##_rom[]; \ + extern u8 _e##x[]; + + // Declare linker symbols for a BSS section + #define DECL_BSS_SECTION(x) \ + extern u8 _f##x[]; \ + extern u8 _e##x[]; + + // Debugger stack + extern u8 _db_stack_addr[]; + extern u8 _db_stack_end[]; + + // Program arena + extern u8 __ArenaLo[]; + extern u8 __ArenaHi[]; + + // Program stack + extern u8 _stack_addr[]; + extern u8 _stack_end[]; + + // Small data bases + extern u8 _SDA_BASE_[]; + extern u8 _SDA2_BASE_[]; + + // ROM sections + DECL_ROM_SECTION(_init); + DECL_ROM_SECTION(extab); + DECL_ROM_SECTION(extabindex); + DECL_ROM_SECTION(_text); + DECL_ROM_SECTION(_ctors); + DECL_ROM_SECTION(_dtors); + DECL_ROM_SECTION(_rodata); + DECL_ROM_SECTION(_data); + DECL_ROM_SECTION(_sdata); + DECL_ROM_SECTION(_sdata2); + DECL_ROM_SECTION(_stack); + + // BSS sections + DECL_BSS_SECTION(_bss); + DECL_BSS_SECTION(_sbss); + DECL_BSS_SECTION(_sbss2); + + // typedef struct RomSection { + // void* phys; // at 0x4 + // void* virt; // at 0x0 + // size_t size; // at 0x8 + // } RomSection; + + // typedef struct BssSection { + // void* virt; // at 0x0 + // size_t size; // at 0x8 + // } BssSection; + + typedef struct ExtabIndexInfo { + void* section; // at 0x0 + struct ExtabIndexInfo* extab; // at 0x4 + void* codeStart; // at 0x8 + u32 codeSize; // at 0xC + } ExtabIndexInfo; + + // DECL_SECTION(".init") extern const RomSection _rom_copy_info[]; + // DECL_SECTION(".init") extern const BssSection _bss_init_info[]; + DECL_SECTION(".init") extern const ExtabIndexInfo _eti_init_info[]; + + #ifdef __cplusplus + } + #endif +#endif diff --git a/src/PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.cpp b/src/PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.cpp index 0457e9b..46e09fb 100644 --- a/src/PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.cpp +++ b/src/PowerPC_EABI_Support/Runtime/Gecko_ExceptionPPC.cpp @@ -3,12 +3,11 @@ extern ProcessInfo fragment_info[MAXFRAGMENTS]; -s32 __register_fragment(struct __eti_init_info* info, char* TOC) +#pragma schedule once +u32 __register_fragment(struct __eti_init_info* info, char* TOC) { ProcessInfo* f = fragment_info; - s32 i; - - for (i = 0; i < MAXFRAGMENTS; i++, f++) { + for (u32 i = 0; i < MAXFRAGMENTS+1; i++, f++) { if (f->active == 0) { f->exception_info = info; f->TOC = TOC; @@ -16,14 +15,14 @@ s32 __register_fragment(struct __eti_init_info* info, char* TOC) return i; } } - return -1; } +#pragma schedule twice -void __unregister_fragment(s32 fragmentID) +void __unregister_fragment(u32 fragmentID) { ProcessInfo* f; - if (fragmentID >= 0 && fragmentID < MAXFRAGMENTS) { + if (fragmentID >= 0 && fragmentID <= MAXFRAGMENTS) { f = &fragment_info[fragmentID]; f->exception_info = 0; f->TOC = 0; @@ -37,7 +36,7 @@ s32 ExPPC_FindExceptionFragment(char* returnaddr, FragmentInfo* frag) s32 i; __eti_init_info* eti_info; - for (i = 0, f = fragment_info; i < MAXFRAGMENTS; ++i, ++f) { + for (i = 0, f = fragment_info; i < MAXFRAGMENTS+1; ++i, ++f) { if (f->active) { eti_info = f->exception_info; while (1) { @@ -58,6 +57,5 @@ s32 ExPPC_FindExceptionFragment(char* returnaddr, FragmentInfo* frag) } } } - return 0; } diff --git a/src/Revolution/OS/__start.c b/src/Revolution/OS/__start.c index e69de29..e5b5965 100644 --- a/src/Revolution/OS/__start.c +++ b/src/Revolution/OS/__start.c @@ -0,0 +1,346 @@ +#include "global.h" +// #include "Revolution/OS/__ppc_eabi_init.h" + +static u8 Debug_BBA; + +// SECTION_INIT static void __check_pad3(void) { +// if ((OS_GC_PAD_3_BTN & 0x0EEF) == 0x0EEF) { +// OSResetSystem(0, 0, 0); +// } +// } + +SECTION_INIT static void __set_debug_bba(void) { + Debug_BBA = TRUE; +} + +SECTION_INIT static BOOL __get_debug_bba(void) { + return Debug_BBA; +} + +// SECTION_INIT DECL_WEAK asm void __start(void) { +// // clang-format off +// nofralloc + +// // Setup hardware +// bl __init_registers +// bl __init_hardware + +// // Create first stack frame +// li r0, -1 +// // Parameter save +// stwu r1, -8(r1) +// // LR save (-1 to signify first frame) +// stw r0, 4(r1) +// // Back chain (-1 to signify first frame) +// stw r0, 0(r1) + +// // Setup ROM/BSS +// bl __init_data + +// // Clear debugger exception mask +// li r0, 0 +// lis r6, (OS_DEBUG_INTERFACE + OSDebugInterface.exceptionMask)@ha +// addi r6, r6, (OS_DEBUG_INTERFACE + OSDebugInterface.exceptionMask)@l +// stw r0, 0(r6) + +// /** +// * Check the BI2 debug flag to determine how to call InitMetroTRK. +// * +// * This can be done by either checking the value from the DVD +// * (OSBI2.debugFlag), or by checking the global OS_BI2_DEBUG_FLAG. +// * +// * If the DVD BI2 is available, it is prioritized over the global value. +// */ +// lis r6, OS_DVD_BI2@ha +// addi r6, r6, OS_DVD_BI2@l +// lwz r6, 0(r6) +// cmplwi r6, 0 +// beq _no_dvd_bi2 // <- NULL BI2, try the OS global + +// // Use the DVD's flag +// lwz r7, OSBI2.debugFlag(r6) +// b _handle_bi2_debug_flag + +// /** +// * At this point, we do one last check to decide whether we want to +// * setup the TRK debugger. +// * +// * If the OS boot info specifies an arena hi, we grab the BI2 debug +// * flag using the global OS_BI2_DEBUG_FLAG. +// * +// * (This must be some heuristic, but I don't understand it) +// */ +// _no_dvd_bi2: +// lis r5, (OS_BOOT_INFO + OSBootInfo.arenaHi)@ha +// addi r5, r5, (OS_BOOT_INFO + OSBootInfo.arenaHi)@l +// lwz r5, 0(r5) +// cmplwi r5, 0 +// beq _check_for_exec_args // <- NULL arena hi, don't setup the debugger + +// // Grab the global BI2 debug flag +// lis r7, OS_BI2_DEBUG_FLAG@ha +// addi r7, r7, OS_BI2_DEBUG_FLAG@l +// lwz r7, 0(r7) + +// /** +// * The BI2 debug flag/level decides how to set up TRK. +// * +// * Most importantly, it decides how InitMetroTRKCommTable is called, by +// * specifying a type of hardware. +// * +// * ID 1: NDEV hardware +// * ID 2: BBA hardware +// * Anything else: "Unknown" to TRK, defaults to GDEV hardware +// * +// * BI2 debug level maps to TRK comm hardware ID as follows: +// * - BI2 Level 2 -> ID 0 (GDEV) +// * - BI2 Level 3 -> ID 1 (NDEV) +// * - BI2 Level 4 -> ID 2 (BBA) +// */ +// _handle_bi2_debug_flag: +// // BI2 Debug Level 3: Init TRK as GDEV hardware +// li r5, 0 +// cmplwi r7, 2 +// beq _call_init_metro_trk + +// // BI2 Debug Level 2: Init TRK as NDEV hardware +// cmplwi r7, 3 +// li r5, 1 +// beq _call_init_metro_trk + +// // BI2 Debug Level 4: Init TRK as BBA hardware +// // *Any other debug level is ignored* +// cmplwi r7, 4 +// bne _check_for_exec_args // <- Ignore debug level, goto next step +// /** +// * I think at one point this used to call InitMetroTRK as they set +// * r5 here; however, in this version it goes unused. +// * +// * What currently happens is __set_debug_bba sets Debug_BBA, which +// * will result in a call to InitMetroTRK_BBA after the OS is +// * initialized. +// * +// * Maybe this is a leftover from how things worked before +// * InitMetroTRK_BBA was written? +// */ +// li r5, 2 +// bl __set_debug_bba +// b _check_for_exec_args + +// /** +// * Call InitMetroTRK +// * The MetroTRK hardware ID is specified in r5 +// */ +// _call_init_metro_trk: +// lis r6, InitMetroTRK@ha +// addi r6, r6, InitMetroTRK@l +// mtlr r6 +// blrl + +// /** +// * After setting up the hardware and the debugger, we next setup +// * the program arguments. This label checks whether any arguments +// * exist. +// * +// * BI2 contains an offset from itself to the argument data, which +// * is formatted as follows: +// * +// * typedef struct BI2Args { +// * int argc; +// * union { +// * char* argument; +// * u32 offset; +// * } argv[]; +// * } BI2Args; +// */ +// _check_for_exec_args: +// lis r6, OS_DVD_BI2@ha +// addi r6, r6, OS_DVD_BI2@l +// lwz r5, 0(r6) +// cmplwi r5, 0 +// beq+ _no_args // <- No BI2 to get args from + +// lwz r6, OSBI2.argumentOfs(r5) +// cmplwi r6, 0 +// beq+ _no_args // <- Invalid argument offset in BI2 + +// // Calculate pointer to argument data +// add r6, r5, r6 +// // First integer value is the argument count +// lwz r14, 0(r6) +// cmplwi r14, 0 +// beq _no_args // <- Argument count is zero + +// // BI2 args + 0x8, used to adjust MEM1 later +// addi r15, r6, 4 +// // Move argc to the counter to prepare the loop +// mtctr r14 + +// /** +// * This loop unpacks the arguments by converting them from offsets +// * to pointers, in-place. +// * +// * The offsets are relative to the start of the BI2, so we just +// * add the offset to the BI2 pointer and write it back. +// */ +// _unpack_args_loop: +// // Skip over argc +// addi r6, r6, 4 +// // Load argument offset +// lwz r7, 0(r6) +// // Convert offset to pointer +// add r7, r7, r5 +// // Store pointer +// stw r7, 0(r6) +// bdnz _unpack_args_loop + +// /** +// * Both the MEM1 arena hi and the MEM1 limit are adjusted to +// * preserve the BI2 args. +// * +// * They are set to eight bytes into the BI2 arguments, +// * rounded down to the nearest 32 bytes. +// */ +// lis r5, (OS_BOOT_INFO + OSBootInfo.arenaHi)@ha +// addi r5, r5, (OS_BOOT_INFO + OSBootInfo.arenaHi)@l +// clrrwi r7, r15, 5 +// stw r7, 0(r5) + +// lis r5, OS_USABLE_MEM1_END@ha +// addi r5, r5, OS_USABLE_MEM1_END@l +// clrrwi r7, r15, 5 +// stw r7, 0(r5) +// b _init_os + +// /** +// * Either there was no BI2 available, or it did not contain any arguments +// */ +// _no_args: +// li r14, 0 // argc = 0 +// li r15, 0 // argv = NULL + +// /** +// * Here, the OS and its debug monitor are initialized, and +// * then we check if we should call __check_pad3. +// * +// * __check_pad3 is called before future initialization if the disk +// * drive device code is 0x0001, or if the OS' inquiry fails (emulation +// * or some debug hardware?) +// * +// * The apploader reads the button state of the fourth GCN controller +// * and writes it to GC_PAD_3_BTN (zero-indexed), which is used in +// * __check_pad3. WiiBrew states that this is for GameCube NR disc +// * support, so that could explain the unusual DVD device code address. +// */ +// _init_os: +// // Initialize the OS and its debug monitor +// bl DBInit +// bl OSInit + +// // Load DVD device code address +// lis r4, OS_DVD_DEVICE_CODE@ha +// addi r4, r4, OS_DVD_DEVICE_CODE@l +// lhz r3, 0(r4) +// // Check whether OS inquiry failed +// andi. r5, r3, DVD_DEVICE_CODE_READ +// beq _call_check_pad3 // <- Bit 0 is NOT set (fail) +// // 0x0001 may be a real ID or a failsafe (see OS.c:InquiryCallback) +// andi. r3, r3, (~DVD_DEVICE_CODE_READ) & 0xFFFF +// cmplwi r3, 0x0001 +// bne _check_debug_bba // <- NOT 0x0001 device code address +// _call_check_pad3: +// bl __check_pad3 + +// /** +// * If the BI2 debug level from earlier was set to four, we need to +// * initialize the debugger for BBA hardware. +// */ +// _check_debug_bba: +// bl __get_debug_bba +// cmplwi r3, 1 +// bne _after_init_metro_trk_bba // <- Debug_BBA == false +// bl InitMetroTRK_BBA + +// /** +// * 1. Initialize C++ runtime +// * 2. Call main(argc, argv) +// * 3. Teardown C++ runtime +// */ +// _after_init_metro_trk_bba: +// bl __init_user +// mr r3, r14 +// mr r4, r15 +// bl main +// b exit // <- Will halt CPU +// // clang-format on +// } + +// DECL_SECTION(".init") static asm void __init_registers(void) { +// // clang-format off +// nofralloc + +// li r0, 0 +// li r3, 0 +// li r4, 0 +// li r5, 0 +// li r6, 0 +// li r7, 0 +// li r8, 0 +// li r9, 0 +// li r10, 0 +// li r11, 0 +// li r12, 0 +// li r14, 0 +// li r15, 0 +// li r16, 0 +// li r17, 0 +// li r18, 0 +// li r19, 0 +// li r20, 0 +// li r21, 0 +// li r22, 0 +// li r23, 0 +// li r24, 0 +// li r25, 0 +// li r26, 0 +// li r27, 0 +// li r28, 0 +// li r29, 0 +// li r30, 0 +// li r31, 0 + +// lis r1, _stack_addr@h +// ori r1, r1, _stack_addr@l +// lis r2, _SDA2_BASE_@h +// ori r2, r2, _SDA2_BASE_@l +// lis r13, _SDA_BASE_@h +// ori r13, r13, _SDA_BASE_@l + +// blr +// // clang-format on +// } + +// SECTION_INIT static void __init_data(void) { +// const RomSection* rs; +// const BssSection* bs; + +// rs = _rom_copy_info; +// while (TRUE) { +// if (rs->size == 0) { +// break; +// } + +// __copy_rom_section(rs->virt, rs->phys, rs->size); +// rs++; +// } + +// bs = _bss_init_info; +// while (TRUE) { +// if (bs->size == 0) { +// break; +// } + +// __init_bss_section(bs->virt, bs->size); +// bs++; +// } +// }