diff --git a/configure.py b/configure.py index 76d4dc09..47b8ff67 100644 --- a/configure.py +++ b/configure.py @@ -861,19 +861,19 @@ config.libs = [ { "lib": "Runtime.PPCEABI.H", "mw_version": config.linker_version, - "cflags": cflags_runtime, + "cflags": [*cflags_runtime, "-inline auto,deferred", "-use_lmw_stmw on", "-char signed", "-fp_contract on"], "progress_category": "sdk", "src_dir": "src/static", "objects": [ Object(Matching, "Runtime.PPCEABI.H/__init_cpp_exceptions.cpp"), Object(Matching, "Runtime.PPCEABI.H/__mem.c"), - Object(NonMatching, "Runtime.PPCEABI.H/__va_arg.c"), - Object(NonMatching, "Runtime.PPCEABI.H/CPlusLibPPC.cp"), - Object(NonMatching, "Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp"), + Object(Matching, "Runtime.PPCEABI.H/__va_arg.c"), + Object(Matching, "Runtime.PPCEABI.H/CPlusLibPPC.cp"), + Object(Matching, "Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp"), Object(Matching, "Runtime.PPCEABI.H/global_destructor_chain.c"), - Object(NonMatching, "Runtime.PPCEABI.H/NMWException.cp"), - Object(NonMatching, "Runtime.PPCEABI.H/ptmf.c"), - Object(NonMatching, "Runtime.PPCEABI.H/runtime.c"), + Object(Matching, "Runtime.PPCEABI.H/NMWException.cp"), + Object(Matching, "Runtime.PPCEABI.H/ptmf.c"), + Object(Matching, "Runtime.PPCEABI.H/runtime.c"), ], }, { diff --git a/include/Runtime.PPCEABI.H/MWCPlusLib.h b/include/Runtime.PPCEABI.H/MWCPlusLib.h new file mode 100644 index 00000000..67a0fb36 --- /dev/null +++ b/include/Runtime.PPCEABI.H/MWCPlusLib.h @@ -0,0 +1,37 @@ +#ifndef _RUNTIME_MWCPLUSLIB_H +#define _RUNTIME_MWCPLUSLIB_H + +#include "stddef.h" + +#define CTORARG_TYPE int +#define CTORARG_PARTIAL (0) +#define CTORARG_COMPLETE (1) + +#define CTORCALL_COMPLETE(ctor, objptr) (((void (*)(void*, CTORARG_TYPE))ctor)(objptr, CTORARG_COMPLETE)) + +#define DTORARG_TYPE int + +#define DTORCALL_COMPLETE(dtor, objptr) (((void (*)(void*, DTORARG_TYPE))dtor)(objptr, -1)) +#define DTORCALL_PARTIAL(dtor, objptr) (((void (*)(void*, DTORARG_TYPE))dtor)(objptr, 0)) + +typedef void* ConstructorDestructor; + +#ifdef __cplusplus +extern "C" { +#endif + +extern void* __copy(char* to, char* from, size_t size); + +extern void __construct_array(void* ptr, ConstructorDestructor ctor, ConstructorDestructor dtor, size_t size, size_t n); +extern void __destroy_arr(void* block, ConstructorDestructor* dtor, size_t size, size_t n); +extern void* __construct_new_array(void* block, ConstructorDestructor ctor, ConstructorDestructor dtor_arg, size_t size, + size_t n); +extern void __destroy_new_array(void* block, ConstructorDestructor dtor); +extern void __destroy_new_array2(); +extern void __destroy_new_array3(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/Runtime.PPCEABI.H/NMWException.h b/include/Runtime.PPCEABI.H/NMWException.h new file mode 100644 index 00000000..0716d301 --- /dev/null +++ b/include/Runtime.PPCEABI.H/NMWException.h @@ -0,0 +1,41 @@ +#ifndef _NMWEXCEPTION +#define _NMWEXCEPTION + +typedef short vbase_ctor_arg_type; +typedef char local_cond_type; + +typedef struct CatchInfo { + void* location; + void* typeinfo; + void* dtor; + void* sublocation; + long pointercopy; + void* stacktop; +} CatchInfo; + +typedef struct DestructorChain { + struct DestructorChain* next; + void* destructor; + void* object; +} DestructorChain; + +#ifdef __cplusplus +extern "C" { +#endif + +extern void* __register_global_object(void* object, void* destructor, void* registration); +extern void __destroy_global_chain(void); + +extern void __end__catch(CatchInfo* catchinfo); +extern void __throw(char* throwtype, void* location, void* dtor); +extern char __throw_catch_compare(const char* throwtype, const char* catchtype, long* offset_result); +extern void __unexpected(CatchInfo* catchinfo); + +extern int __register_fragment(struct __eti_init_info* info, char* TOC); +extern void __unregister_fragment(int fragmentID); + +#ifdef __cplusplus +} +#endif + +#endif // _NMWEXCEPTION diff --git a/include/_mem.h b/include/_mem.h index 46cc8408..f61c5b4b 100644 --- a/include/_mem.h +++ b/include/_mem.h @@ -1,7 +1,7 @@ #ifndef _MEM_H #define _MEM_H -#include "types.h" +#include "stddef.h" #ifdef __cplusplus extern "C" { diff --git a/include/libc/stdarg.h b/include/libc/stdarg.h index 8834b297..aa32c7be 100644 --- a/include/libc/stdarg.h +++ b/include/libc/stdarg.h @@ -19,7 +19,7 @@ typedef __va_list va_list; extern void __builtin_va_info(va_list*); #endif -void* __va_arg(va_list v_list, unsigned char type); +void* __va_arg(va_list v_list, int type); #define va_start(ap, fmt) ((void)fmt, __builtin_va_info(&ap)) #define va_arg(ap, t) (*((t*)__va_arg(ap, _var_arg_typeof(t)))) diff --git a/include/va_args.h b/include/va_args.h index 536fcb08..5813f177 100644 --- a/include/va_args.h +++ b/include/va_args.h @@ -17,7 +17,7 @@ typedef struct __va_list_struct { typedef _va_list_struct __va_list[1]; -void* __va_arg(_va_list_struct* list, int type); +void* __va_arg(_va_list_struct* list, long type); #define __va_start(list, fmt) __builtin_va_info(&list) #ifdef __MWERKS__ diff --git a/src/static/Runtime.PPCEABI.H/CPlusLibPPC.cp b/src/static/Runtime.PPCEABI.H/CPlusLibPPC.cp new file mode 100644 index 00000000..26a3fd1f --- /dev/null +++ b/src/static/Runtime.PPCEABI.H/CPlusLibPPC.cp @@ -0,0 +1,11 @@ +extern "C" char* __copy(char* r3, char* r4, unsigned long r5) { + if (!r3) + return r3; + if (!r5) + return r3; + char* d = (char*)r3; + do { + *d++ = *r4++; + } while (--r5); + return r3; +} diff --git a/src/static/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp b/src/static/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp new file mode 100644 index 00000000..9773db37 --- /dev/null +++ b/src/static/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp @@ -0,0 +1,45 @@ +#include "Runtime.PPCEABI.H/NMWException.h" + +// NOTE: there is a bug in mwcc where any pure-asm function +// disables this optimization but doesn't reset it to be on +// original probably had an asm function in one of the headers +// above, but no idea which for now +#pragma peephole off + +typedef struct ProcessInfo { + __eti_init_info* exception_info; + char* TOC; + int active; +} ProcessInfo; + +#define MAXFRAGMENTS 1 +static ProcessInfo fragmentinfo[MAXFRAGMENTS]; + +int __register_fragment(struct __eti_init_info* info, char* TOC) +{ + ProcessInfo* f = fragmentinfo; + int i; + + for (i = 0; i < MAXFRAGMENTS; 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 < MAXFRAGMENTS) { + f = &fragmentinfo[fragmentID]; + f->exception_info = 0; + f->TOC = 0; + f->active = 0; + } +} diff --git a/src/static/Runtime.PPCEABI.H/NMWException.cp b/src/static/Runtime.PPCEABI.H/NMWException.cp new file mode 100644 index 00000000..b146e72d --- /dev/null +++ b/src/static/Runtime.PPCEABI.H/NMWException.cp @@ -0,0 +1,55 @@ +#include "Runtime.PPCEABI.H/NMWException.h" +#include "Runtime.PPCEABI.H/MWCPlusLib.h" + +#pragma exceptions on + +#define ARRAY_HEADER_SIZE 8 + +class __partial_array_destructor { + private: + void* p; + size_t size; + size_t n; + ConstructorDestructor dtor; + + public: + size_t i; + + __partial_array_destructor(void* array, size_t elementsize, size_t nelements, ConstructorDestructor destructor) { + p = array; + size = elementsize; + n = nelements; + dtor = destructor; + i = n; + } + + ~__partial_array_destructor() { + char* ptr; + + if (i < n && dtor) { + for (ptr = (char*)p + size * i; i > 0; i--) { + ptr -= size; + DTORCALL_COMPLETE(dtor, ptr); + } + } + } +}; + +extern void __construct_array(void* ptr, ConstructorDestructor ctor, ConstructorDestructor dtor, size_t size, + size_t n) { + __partial_array_destructor pad(ptr, size, n, dtor); + char* p; + + for (pad.i = 0, p = (char*)ptr; pad.i < n; pad.i++, p += size) { + CTORCALL_COMPLETE(ctor, p); + } +} + +extern void __destroy_arr(void* block, ConstructorDestructor* dtor, size_t size, size_t n) { + char* p; + + for (p = (char*)block + size * n; n > 0; n--) { + p -= size; + DTORCALL_COMPLETE(dtor, p); + } +} diff --git a/src/static/Runtime.PPCEABI.H/__init_cpp_exceptions.cpp b/src/static/Runtime.PPCEABI.H/__init_cpp_exceptions.cpp index 15235157..12555571 100644 --- a/src/static/Runtime.PPCEABI.H/__init_cpp_exceptions.cpp +++ b/src/static/Runtime.PPCEABI.H/__init_cpp_exceptions.cpp @@ -1,5 +1,7 @@ static int fragmentID = -2; +extern char* GetR2(void); + #ifdef __cplusplus extern "C" { #endif @@ -24,12 +26,10 @@ extern void __destroy_global_chain(void); } #endif -asm char* GetR2(void) { - // clang-format off - nofralloc - mr r3, r2 - blr - // clang-format on +extern void __init_cpp_exceptions(void) { + if (fragmentID == -2) { + fragmentID = __register_fragment(&_eti_init_info, GetR2()); + } } extern void __fini_cpp_exceptions(void) { @@ -39,10 +39,12 @@ extern void __fini_cpp_exceptions(void) { } } -extern void __init_cpp_exceptions(void) { - if (fragmentID == -2) { - fragmentID = __register_fragment(&_eti_init_info, GetR2()); - } +asm char* GetR2(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + mr r3, r2 + blr +#endif // clang-format on } __declspec(section ".ctors") extern void* const __init_cpp_exceptions_reference = __init_cpp_exceptions; diff --git a/src/static/Runtime.PPCEABI.H/__mem.c b/src/static/Runtime.PPCEABI.H/__mem.c index a082bc60..68b6c7eb 100644 --- a/src/static/Runtime.PPCEABI.H/__mem.c +++ b/src/static/Runtime.PPCEABI.H/__mem.c @@ -1,89 +1,87 @@ #include "_mem.h" -__declspec(section ".init") void* memset(void* dst, int val, size_t size){ - __fill_mem(dst,val, size); +__declspec(section ".init") void* memcpy(void* dst, const void* src, size_t size) { + const unsigned char* s; + unsigned char* d; + if ((unsigned long)src >= (unsigned long)dst) { + s = (const unsigned char*)src - 1; + d = (unsigned char*)dst - 1; + size++; + while (--size != 0) { + *++d = *++s; + } + } else { + s = (const unsigned char*)src + size; + d = (unsigned char*)dst + size; + size++; + while (--size != 0) { + *--d = *--s; + } + } return dst; } -__declspec(section ".init") void __fill_mem(void* dst, int val, size_t n){ - u32 v = (u8) val; - u32 i; - - ((u8 *) dst) = ((u8 *) dst) - 1; - - if (n >= 32) - { - i = (~ (u32) dst) & 3; +__declspec(section ".init") void __fill_mem(void* dst, int val, size_t n) { + unsigned long v = (unsigned char)val; + unsigned long i; - if (i) { - n -= i; - - do { - *++(((u8 *) dst)) = v; - } while (--i); - } - - if (v) - v |= v << 24 | v << 16 | v << 8; - - ((u32 *) dst) = ((u32 *) (((u8 *) dst) + 1)) - 1; - - i = n >> 5; - - if (i) { - do { - *++((u32 *) dst) = v; - *++((u32 *) dst) = v; - *++((u32 *) dst) = v; - *++((u32 *) dst) = v; - *++((u32 *) dst) = v; - *++((u32 *) dst) = v; - *++((u32 *) dst) = v; - *++((u32 *) dst) = v; - } while (--i); - } - - i = (n & 31) >> 2; - - if (i) { - do { - *++((u32 *) dst) = v; - } while (--i); - } - - ((u8 *) dst) = ((u8 *) (((u32 *) dst) + 1)) - 1; - - n &= 3; - } - - if (n) - do { - *++((u8 *) dst) = v; - } while (--n); - - return; + ((unsigned char*)dst) = ((unsigned char*)dst) - 1; + + if (n >= 32) { + i = (~(unsigned long)dst) & 3; + + if (i) { + n -= i; + + do { + *++(((unsigned char*)dst)) = v; + } while (--i); + } + + if (v) + v |= v << 24 | v << 16 | v << 8; + + ((unsigned long*)dst) = ((unsigned long*)(((unsigned char*)dst) + 1)) - 1; + + i = n >> 5; + + if (i) { + do { + *++((unsigned long*)dst) = v; + *++((unsigned long*)dst) = v; + *++((unsigned long*)dst) = v; + *++((unsigned long*)dst) = v; + *++((unsigned long*)dst) = v; + *++((unsigned long*)dst) = v; + *++((unsigned long*)dst) = v; + *++((unsigned long*)dst) = v; + } while (--i); + } + + i = (n & 31) >> 2; + + if (i) { + do { + *++((unsigned long*)dst) = v; + } while (--i); + } + + ((unsigned char*)dst) = ((unsigned char*)(((unsigned long*)dst) + 1)) - 1; + + n &= 3; + } + + if (n) + do { + *++((unsigned char*)dst) = v; + } while (--n); + + return; } -__declspec(section ".init") void* memcpy(void* dst, const void* src, size_t size){ - const u8* s; - u8* d; +__declspec(section ".init") void* memset(void* dst, int val, size_t size) { + __fill_mem(dst, val, size); - if((u32)src >= (u32)dst){ - s = (const u8*)src -1; - d = (u8*)dst -1; - size++; - while (--size !=0){ - *++d = *++s; - } - } - else{ - s = (const u8*)src + size; - d = (u8*)dst + size; - size++; - while (--size != 0){ - *--d = *--s; - } - } - return dst; - } + return dst; +} diff --git a/src/static/Runtime.PPCEABI.H/__va_arg.c b/src/static/Runtime.PPCEABI.H/__va_arg.c new file mode 100644 index 00000000..2a3ef9ab --- /dev/null +++ b/src/static/Runtime.PPCEABI.H/__va_arg.c @@ -0,0 +1,42 @@ +#include "stdarg.h" + +void* __va_arg(va_list v_list, int type) { + char* addr; + char* reg = &(v_list->gpr); + long g_reg = v_list->gpr; + long maxsize = 8; + long size = 4; + long increment = 1; + long even = 0; + long fpr_offset = 0; + long regsize = 4; + + if (type == 3) { + reg = &(v_list->fpr); + g_reg = v_list->fpr; + size = 8; + fpr_offset = 32; + regsize = 8; + } + if (type == 2) { + size = 8; + maxsize--; + if (g_reg & 1) + even = 1; + increment = 2; + } + if (g_reg < maxsize) { + g_reg += even; + addr = v_list->reg_save_area + fpr_offset + (g_reg * regsize); + *reg = g_reg + increment; + } else { + *reg = 8; + addr = v_list->input_arg_area; + addr = (char*)(((unsigned long)(addr) + ((size)-1)) & ~((size)-1)); + v_list->input_arg_area = addr + size; + } + if (type == 0) + addr = *((char**)addr); + + return addr; +} diff --git a/src/static/Runtime.PPCEABI.H/global_destructor_chain.c b/src/static/Runtime.PPCEABI.H/global_destructor_chain.c index a93e742f..2691ecae 100644 --- a/src/static/Runtime.PPCEABI.H/global_destructor_chain.c +++ b/src/static/Runtime.PPCEABI.H/global_destructor_chain.c @@ -6,15 +6,6 @@ typedef struct DestructorChain { DestructorChain* __global_destructor_chain; -void __destroy_global_chain(void) { - DestructorChain* gdc; - - while ((gdc = __global_destructor_chain) != 0) { - __global_destructor_chain = gdc->next; - ((void (*)(void*, short))gdc->destructor)(gdc->object, -1); - } -} - void* __register_global_object(void* object, void* destructor, void* regmem) { ((DestructorChain*)regmem)->next = __global_destructor_chain; ((DestructorChain*)regmem)->destructor = destructor; @@ -24,5 +15,13 @@ void* __register_global_object(void* object, void* destructor, void* regmem) { return object; } -__declspec(section ".dtors") static void* const __destroy_global_chain_reference = - __destroy_global_chain; +void __destroy_global_chain(void) { + DestructorChain* gdc; + + while ((gdc = __global_destructor_chain) != 0) { + __global_destructor_chain = gdc->next; + ((void (*)(void*, short))gdc->destructor)(gdc->object, -1); + } +} + +__declspec(section ".dtors") static void* const __destroy_global_chain_reference = __destroy_global_chain; diff --git a/src/static/Runtime.PPCEABI.H/ptmf.c b/src/static/Runtime.PPCEABI.H/ptmf.c new file mode 100644 index 00000000..0998fd0b --- /dev/null +++ b/src/static/Runtime.PPCEABI.H/ptmf.c @@ -0,0 +1,50 @@ +// presumably, ptmf = pointer to member function + +typedef struct PTMF { + long this_delta; // self-explanatory + long v_offset; // vtable offset + union { + void* f_addr; // function address + long ve_offset; // virtual function entry offset (of vtable) + } f_data; +} PTMF; + +long __ptmf_test(PTMF* ptmf); +void __ptmf_scall(...); + +asm long __ptmf_test(register PTMF* ptmf) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + lwz r5, PTMF.this_delta(r3) + lwz r6, PTMF.v_offset(r3) + lwz r7, PTMF.f_data(r3) + li r3, 0x1 + cmpwi r5, 0 + cmpwi cr6, r6, 0 + cmpwi cr7, r7, 0 + bnelr- + bnelr- cr6 + bnelr- cr7 + li r3, 0 + blr +#endif // clang-format on +} + +asm void __ptmf_scall(...) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + lwz r0, PTMF.this_delta(r12) + lwz r11, PTMF.v_offset(r12) + lwz r12, PTMF.f_data(r12) + add r3, r3, r0 + cmpwi r11, 0 + blt- cr0, loc_0x20 + lwzx r12, r3, r12 + lwzx r12, r12, r11 + loc_0x20: + mtctr r12 + bctr +#endif // clang-format on +} diff --git a/src/static/Runtime.PPCEABI.H/runtime.c b/src/static/Runtime.PPCEABI.H/runtime.c new file mode 100644 index 00000000..35f651a2 --- /dev/null +++ b/src/static/Runtime.PPCEABI.H/runtime.c @@ -0,0 +1,875 @@ +#pragma ANSI_strict off +#pragma tvectors off +#pragma internal on + +#define SAVE_FPR(reg) _savefpr_##reg +#define RESTORE_FPR(reg) _restfpr_##reg +#define SAVE_GPR(reg) _savegpr_##reg +#define RESTORE_GPR(reg) _restgpr_##reg +#define ENTRY_SAVE_FPR(reg) entry SAVE_FPR(reg) +#define ENTRY_RESTORE_FPR(reg) entry RESTORE_FPR(reg) +#define ENTRY_SAVE_GPR(reg) entry SAVE_GPR(reg) +#define ENTRY_RESTORE_GPR(reg) entry RESTORE_GPR(reg) +#define SAVE_FPR2(reg) _savef##reg +#define RESTORE_FPR2(reg) _restf##reg +#define ENTRY_SAVE_FPR2(reg) +#define ENTRY_RESTORE_FPR2(reg) + +#define save_restore_reg r11 + +asm void __div2u(void); +asm void __div2i(void); +asm void __mod2u(void); +asm void __mod2i(void); +asm void __shl2i(void); +asm void __shr2u(void); +asm void __shr2i(void); +asm void __cvt_sll_flt(void); +asm void __cvt_dbl_usll(void); + +void SAVE_FPR(14)(void); +void SAVE_FPR(15)(void); +void SAVE_FPR(16)(void); +void SAVE_FPR(17)(void); +void SAVE_FPR(18)(void); +void SAVE_FPR(19)(void); +void SAVE_FPR(20)(void); +void SAVE_FPR(21)(void); +void SAVE_FPR(22)(void); +void SAVE_FPR(23)(void); +void SAVE_FPR(24)(void); +void SAVE_FPR(25)(void); +void SAVE_FPR(26)(void); +void SAVE_FPR(27)(void); +void SAVE_FPR(28)(void); +void SAVE_FPR(29)(void); +void SAVE_FPR(30)(void); +void SAVE_FPR(31)(void); +void SAVE_FPR2(14)(void); +void SAVE_FPR2(15)(void); +void SAVE_FPR2(16)(void); +void SAVE_FPR2(17)(void); +void SAVE_FPR2(18)(void); +void SAVE_FPR2(19)(void); +void SAVE_FPR2(20)(void); +void SAVE_FPR2(21)(void); +void SAVE_FPR2(22)(void); +void SAVE_FPR2(23)(void); +void SAVE_FPR2(24)(void); +void SAVE_FPR2(25)(void); +void SAVE_FPR2(26)(void); +void SAVE_FPR2(27)(void); +void SAVE_FPR2(28)(void); +void SAVE_FPR2(29)(void); +void SAVE_FPR2(30)(void); +void SAVE_FPR2(31)(void); +void RESTORE_FPR(14)(void); +void RESTORE_FPR(15)(void); +void RESTORE_FPR(16)(void); +void RESTORE_FPR(17)(void); +void RESTORE_FPR(18)(void); +void RESTORE_FPR(19)(void); +void RESTORE_FPR(20)(void); +void RESTORE_FPR(21)(void); +void RESTORE_FPR(22)(void); +void RESTORE_FPR(23)(void); +void RESTORE_FPR(24)(void); +void RESTORE_FPR(25)(void); +void RESTORE_FPR(26)(void); +void RESTORE_FPR(27)(void); +void RESTORE_FPR(28)(void); +void RESTORE_FPR(29)(void); +void RESTORE_FPR(30)(void); +void RESTORE_FPR(31)(void); +void RESTORE_FPR2(14)(void); +void RESTORE_FPR2(15)(void); +void RESTORE_FPR2(16)(void); +void RESTORE_FPR2(17)(void); +void RESTORE_FPR2(18)(void); +void RESTORE_FPR2(19)(void); +void RESTORE_FPR2(20)(void); +void RESTORE_FPR2(21)(void); +void RESTORE_FPR2(22)(void); +void RESTORE_FPR2(23)(void); +void RESTORE_FPR2(24)(void); +void RESTORE_FPR2(25)(void); +void RESTORE_FPR2(26)(void); +void RESTORE_FPR2(27)(void); +void RESTORE_FPR2(28)(void); +void RESTORE_FPR2(29)(void); +void RESTORE_FPR2(30)(void); +void RESTORE_FPR2(31)(void); +void SAVE_GPR(14)(void); +void SAVE_GPR(15)(void); +void SAVE_GPR(16)(void); +void SAVE_GPR(17)(void); +void SAVE_GPR(18)(void); +void SAVE_GPR(19)(void); +void SAVE_GPR(20)(void); +void SAVE_GPR(21)(void); +void SAVE_GPR(22)(void); +void SAVE_GPR(23)(void); +void SAVE_GPR(24)(void); +void SAVE_GPR(25)(void); +void SAVE_GPR(26)(void); +void SAVE_GPR(27)(void); +void SAVE_GPR(28)(void); +void SAVE_GPR(29)(void); +void SAVE_GPR(30)(void); +void SAVE_GPR(31)(void); +void RESTORE_GPR(14)(void); +void RESTORE_GPR(15)(void); +void RESTORE_GPR(16)(void); +void RESTORE_GPR(17)(void); +void RESTORE_GPR(18)(void); +void RESTORE_GPR(19)(void); +void RESTORE_GPR(20)(void); +void RESTORE_GPR(21)(void); +void RESTORE_GPR(22)(void); +void RESTORE_GPR(23)(void); +void RESTORE_GPR(24)(void); +void RESTORE_GPR(25)(void); +void RESTORE_GPR(26)(void); +void RESTORE_GPR(27)(void); +void RESTORE_GPR(28)(void); +void RESTORE_GPR(29)(void); +void RESTORE_GPR(30)(void); +void RESTORE_GPR(31)(void); + +static const unsigned __constants[] = { + 0x00000000, 0x00000000, // 0.0 + 0x41F00000, 0x00000000, // 2**32 + 0x41E00000, 0x00000000, // 2**31 +}; + +asm unsigned __cvt_fp2unsigned(register double d) { +#ifdef __MWERKS__ // clang-format off + nofralloc + stwu r1,-16(r1) + lis r4, __constants@h + ori r4, r4, __constants@l + li r3,0 + lfd fp0,0(r4) + lfd fp3,8(r4) + lfd fp4,16(r4) + fcmpu cr0,fp1,fp0 + fcmpu cr6,fp1,fp3 + blt cr0, @exit + addi r3,r3,-1 + bge cr6,@exit + fcmpu cr7,fp1,fp4 + fmr fp2,fp1 + blt cr7,@1 + fsub fp2,fp1,fp4 +@1 fctiwz fp2,fp2 + stfd fp2,8(r1) + lwz r3,12(r1) + blt cr7,@exit + addis r3,r3,-0x8000 +@exit: + addi r1,r1,16 + blr +#endif // clang-format on +} + +static asm void __save_fpr(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + ENTRY_SAVE_FPR(14) + ENTRY_SAVE_FPR2(14) + stfd fp14,-144(save_restore_reg) + ENTRY_SAVE_FPR(15) + ENTRY_SAVE_FPR2(15) + stfd fp15,-136(save_restore_reg) + ENTRY_SAVE_FPR(16) + ENTRY_SAVE_FPR2(16) + stfd fp16,-128(save_restore_reg) + ENTRY_SAVE_FPR(17) + ENTRY_SAVE_FPR2(17) + stfd fp17,-120(save_restore_reg) + ENTRY_SAVE_FPR(18) + ENTRY_SAVE_FPR2(18) + stfd fp18,-112(save_restore_reg) + ENTRY_SAVE_FPR(19) + ENTRY_SAVE_FPR2(19) + stfd fp19,-104(save_restore_reg) + ENTRY_SAVE_FPR(20) + ENTRY_SAVE_FPR2(20) + stfd fp20,-96(save_restore_reg) + ENTRY_SAVE_FPR(21) + ENTRY_SAVE_FPR2(21) + stfd fp21,-88(save_restore_reg) + ENTRY_SAVE_FPR(22) + ENTRY_SAVE_FPR2(22) + stfd fp22,-80(save_restore_reg) + ENTRY_SAVE_FPR(23) + ENTRY_SAVE_FPR2(23) + stfd fp23,-72(save_restore_reg) + ENTRY_SAVE_FPR(24) + ENTRY_SAVE_FPR2(24) + stfd fp24,-64(save_restore_reg) + ENTRY_SAVE_FPR(25) + ENTRY_SAVE_FPR2(25) + stfd fp25,-56(save_restore_reg) + ENTRY_SAVE_FPR(26) + ENTRY_SAVE_FPR2(26) + stfd fp26,-48(save_restore_reg) + ENTRY_SAVE_FPR(27) + ENTRY_SAVE_FPR2(27) + stfd fp27,-40(save_restore_reg) + ENTRY_SAVE_FPR(28) + ENTRY_SAVE_FPR2(28) + stfd fp28,-32(save_restore_reg) + ENTRY_SAVE_FPR(29) + ENTRY_SAVE_FPR2(29) + stfd fp29,-24(save_restore_reg) + ENTRY_SAVE_FPR(30) + ENTRY_SAVE_FPR2(30) + stfd fp30,-16(save_restore_reg) + ENTRY_SAVE_FPR(31) + ENTRY_SAVE_FPR2(31) + stfd fp31,-8(save_restore_reg) + blr +#endif // clang-format on +} + +static asm void __restore_fpr(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + ENTRY_RESTORE_FPR(14) + ENTRY_RESTORE_FPR2(14) + lfd fp14,-144(save_restore_reg) + ENTRY_RESTORE_FPR(15) + ENTRY_RESTORE_FPR2(15) + lfd fp15,-136(save_restore_reg) + ENTRY_RESTORE_FPR(16) + ENTRY_RESTORE_FPR2(16) + lfd fp16,-128(save_restore_reg) + ENTRY_RESTORE_FPR(17) + ENTRY_RESTORE_FPR2(17) + lfd fp17,-120(save_restore_reg) + ENTRY_RESTORE_FPR(18) + ENTRY_RESTORE_FPR2(18) + lfd fp18,-112(save_restore_reg) + ENTRY_RESTORE_FPR(19) + ENTRY_RESTORE_FPR2(19) + lfd fp19,-104(save_restore_reg) + ENTRY_RESTORE_FPR(20) + ENTRY_RESTORE_FPR2(20) + lfd fp20,-96(save_restore_reg) + ENTRY_RESTORE_FPR(21) + ENTRY_RESTORE_FPR2(21) + lfd fp21,-88(save_restore_reg) + ENTRY_RESTORE_FPR(22) + ENTRY_RESTORE_FPR2(22) + lfd fp22,-80(save_restore_reg) + ENTRY_RESTORE_FPR(23) + ENTRY_RESTORE_FPR2(23) + lfd fp23,-72(save_restore_reg) + ENTRY_RESTORE_FPR(24) + ENTRY_RESTORE_FPR2(24) + lfd fp24,-64(save_restore_reg) + ENTRY_RESTORE_FPR(25) + ENTRY_RESTORE_FPR2(25) + lfd fp25,-56(save_restore_reg) + ENTRY_RESTORE_FPR(26) + ENTRY_RESTORE_FPR2(26) + lfd fp26,-48(save_restore_reg) + ENTRY_RESTORE_FPR(27) + ENTRY_RESTORE_FPR2(27) + lfd fp27,-40(save_restore_reg) + ENTRY_RESTORE_FPR(28) + ENTRY_RESTORE_FPR2(28) + lfd fp28,-32(save_restore_reg) + ENTRY_RESTORE_FPR(29) + ENTRY_RESTORE_FPR2(29) + lfd fp29,-24(save_restore_reg) + ENTRY_RESTORE_FPR(30) + ENTRY_RESTORE_FPR2(30) + lfd fp30,-16(save_restore_reg) + ENTRY_RESTORE_FPR(31) + ENTRY_RESTORE_FPR2(31) + lfd fp31,-8(save_restore_reg) + blr +#endif // clang-format on +} + +static asm void __save_gpr(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + ENTRY_SAVE_GPR(14) + stw r14,-72(save_restore_reg) + ENTRY_SAVE_GPR(15) + stw r15,-68(save_restore_reg) + ENTRY_SAVE_GPR(16) + stw r16,-64(save_restore_reg) + ENTRY_SAVE_GPR(17) + stw r17,-60(save_restore_reg) + ENTRY_SAVE_GPR(18) + stw r18,-56(save_restore_reg) + ENTRY_SAVE_GPR(19) + stw r19,-52(save_restore_reg) + ENTRY_SAVE_GPR(20) + stw r20,-48(save_restore_reg) + ENTRY_SAVE_GPR(21) + stw r21,-44(save_restore_reg) + ENTRY_SAVE_GPR(22) + stw r22,-40(save_restore_reg) + ENTRY_SAVE_GPR(23) + stw r23,-36(save_restore_reg) + ENTRY_SAVE_GPR(24) + stw r24,-32(save_restore_reg) + ENTRY_SAVE_GPR(25) + stw r25,-28(save_restore_reg) + ENTRY_SAVE_GPR(26) + stw r26,-24(save_restore_reg) + ENTRY_SAVE_GPR(27) + stw r27,-20(save_restore_reg) + ENTRY_SAVE_GPR(28) + stw r28,-16(save_restore_reg) + ENTRY_SAVE_GPR(29) + stw r29,-12(save_restore_reg) + ENTRY_SAVE_GPR(30) + stw r30,-8(save_restore_reg) + ENTRY_SAVE_GPR(31) + stw r31,-4(save_restore_reg) + blr +#endif // clang-format on +} + +static asm void __restore_gpr(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + ENTRY_RESTORE_GPR(14) + lwz r14,-72(save_restore_reg) + ENTRY_RESTORE_GPR(15) + lwz r15,-68(save_restore_reg) + ENTRY_RESTORE_GPR(16) + lwz r16,-64(save_restore_reg) + ENTRY_RESTORE_GPR(17) + lwz r17,-60(save_restore_reg) + ENTRY_RESTORE_GPR(18) + lwz r18,-56(save_restore_reg) + ENTRY_RESTORE_GPR(19) + lwz r19,-52(save_restore_reg) + ENTRY_RESTORE_GPR(20) + lwz r20,-48(save_restore_reg) + ENTRY_RESTORE_GPR(21) + lwz r21,-44(save_restore_reg) + ENTRY_RESTORE_GPR(22) + lwz r22,-40(save_restore_reg) + ENTRY_RESTORE_GPR(23) + lwz r23,-36(save_restore_reg) + ENTRY_RESTORE_GPR(24) + lwz r24,-32(save_restore_reg) + ENTRY_RESTORE_GPR(25) + lwz r25,-28(save_restore_reg) + ENTRY_RESTORE_GPR(26) + lwz r26,-24(save_restore_reg) + ENTRY_RESTORE_GPR(27) + lwz r27,-20(save_restore_reg) + ENTRY_RESTORE_GPR(28) + lwz r28,-16(save_restore_reg) + ENTRY_RESTORE_GPR(29) + lwz r29,-12(save_restore_reg) + ENTRY_RESTORE_GPR(30) + lwz r30,-8(save_restore_reg) + ENTRY_RESTORE_GPR(31) + lwz r31,-4(save_restore_reg) + blr +#endif // clang-format on +} + +asm void __div2u(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + cmpwi cr0,r3,0 + cntlzw r0,r3 + cntlzw r9,r4 + bne cr0,lab1 + addi r0,r9,32 +lab1: + cmpwi cr0,r5,0 + cntlzw r9,r5 + cntlzw r10,r6 + bne cr0,lab2 + addi r9,r10,32 +lab2: + cmpw cr0,r0,r9 + subfic r10,r0,64 + bgt cr0,lab9 + addi r9,r9,1 + subfic r9,r9,64 + add r0,r0,r9 + subf r9,r9,r10 + mtctr r9 + cmpwi cr0,r9,32 + addi r7,r9,-32 + blt cr0,lab3 + srw r8,r3,r7 + li r7,0 + b lab4 +lab3: + srw r8,r4,r9 + subfic r7,r9,32 + slw r7,r3,r7 + or r8,r8,r7 + srw r7,r3,r9 +lab4: + cmpwi cr0,r0,32 + addic r9,r0,-32 + blt cr0,lab5 + slw r3,r4,r9 + li r4,0 + b lab6 +lab5: + slw r3,r3,r0 + subfic r9,r0,32 + srw r9,r4,r9 + or r3,r3,r9 + slw r4,r4,r0 +lab6: + li r10,-1 + addic r7,r7,0 +lab7: + adde r4,r4,r4 + adde r3,r3,r3 + adde r8,r8,r8 + adde r7,r7,r7 + subfc r0,r6,r8 + subfe. r9,r5,r7 + blt cr0,lab8 + mr r8,r0 + mr r7,r9 + addic r0,r10,1 +lab8: + bdnz lab7 + adde r4,r4,r4 + adde r3,r3,r3 + blr +lab9: + li r4,0 + li r3,0 + blr +#endif // clang-format on +} + +asm void __div2i(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + stwu r1,-16(r1) + rlwinm. r9,r3,0,0,0 + beq cr0,positive1 + subfic r4,r4,0 + subfze r3,r3 +positive1: + stw r9,8(r1) + rlwinm. r10,r5,0,0,0 + beq cr0,positive2 + subfic r6,r6,0 + subfze r5,r5 +positive2: + stw r10,12(r1) + cmpwi cr0,r3,0 + cntlzw r0,r3 + cntlzw r9,r4 + bne cr0,lab1 + addi r0,r9,32 +lab1: + cmpwi cr0,r5,0 + cntlzw r9,r5 + cntlzw r10,r6 + bne cr0,lab2 + addi r9,r10,32 +lab2: + cmpw cr0,r0,r9 + subfic r10,r0,64 + bgt cr0,lab9 + addi r9,r9,1 + subfic r9,r9,64 + add r0,r0,r9 + subf r9,r9,r10 + mtctr r9 + cmpwi cr0,r9,32 + addi r7,r9,-32 + blt cr0,lab3 + srw r8,r3,r7 + li r7,0 + b lab4 +lab3: + srw r8,r4,r9 + subfic r7,r9,32 + slw r7,r3,r7 + or r8,r8,r7 + srw r7,r3,r9 +lab4: + cmpwi cr0,r0,32 + addic r9,r0,-32 + blt cr0,lab5 + slw r3,r4,r9 + li r4,0 + b lab6 +lab5: + slw r3,r3,r0 + subfic r9,r0,32 + srw r9,r4,r9 + or r3,r3,r9 + slw r4,r4,r0 +lab6: + li r10,-1 + addic r7,r7,0 +lab7: + adde r4,r4,r4 + adde r3,r3,r3 + adde r8,r8,r8 + adde r7,r7,r7 + subfc r0,r6,r8 + subfe. r9,r5,r7 + blt cr0,lab8 + mr r8,r0 + mr r7,r9 + addic r0,r10,1 +lab8: + bdnz lab7 + adde r4,r4,r4 + adde r3,r3,r3 + lwz r9,8(r1) + lwz r10,12(r1) + xor. r7,r9,r10 + beq cr0,no_adjust + cmpwi cr0,r9,0 + subfic r4,r4,0 + subfze r3,r3 + +no_adjust: + b func_end + +lab9: + li r4,0 + li r3,0 +func_end: + addi r1,r1,16 + blr +#endif // clang-format on +} + +// Modulo for 64-bit ints +// uses funky 2-register passing ABI +// r3,r4 = r3,r4 % r5,r6 +asm void __mod2u(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + cmpwi cr0,r3,0 + cntlzw r0,r3 + cntlzw r9,r4 + bne cr0,lab1 + addi r0,r9,32 +lab1: + cmpwi cr0,r5,0 + cntlzw r9,r5 + cntlzw r10,r6 + bne cr0,lab2 + addi r9,r10,32 +lab2: + cmpw cr0,r0,r9 + subfic r10,r0,64 + bgt cr0,lab9 + addi r9,r9,1 + subfic r9,r9,64 + add r0,r0,r9 + subf r9,r9,r10 + mtctr r9 + cmpwi cr0,r9,32 + addi r7,r9,-32 + blt cr0,lab3 + srw r8,r3,r7 + li r7,0 + b lab4 +lab3: + srw r8,r4,r9 + subfic r7,r9,32 + slw r7,r3,r7 + or r8,r8,r7 + srw r7,r3,r9 +lab4: + cmpwi cr0,r0,32 + addic r9,r0,-32 + blt cr0,lab5 + slw r3,r4,r9 + li r4,0 + b lab6 +lab5: + slw r3,r3,r0 + subfic r9,r0,32 + srw r9,r4,r9 + or r3,r3,r9 + slw r4,r4,r0 +lab6: + li r10,-1 + addic r7,r7,0 +lab7: + adde r4,r4,r4 + adde r3,r3,r3 + adde r8,r8,r8 + adde r7,r7,r7 + subfc r0,r6,r8 + subfe. r9,r5,r7 + blt cr0,lab8 + mr r8,r0 + mr r7,r9 + addic r0,r10,1 +lab8: + bdnz lab7 + mr r4,r8 + mr r3,r7 + blr +lab9: + blr +#endif // clang-format on +} + +asm void __mod2i(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + + cmpwi cr7,r3,0 + bge cr7,positive1 + subfic r4,r4,0 + subfze r3,r3 +positive1: + cmpwi cr0,r5,0 + bge cr0,positive2 + subfic r6,r6,0 + subfze r5,r5 +positive2: + cmpwi cr0,r3,0 + cntlzw r0,r3 + cntlzw r9,r4 + bne cr0,lab1 + addi r0,r9,32 +lab1: + cmpwi cr0,r5,0 + cntlzw r9,r5 + cntlzw r10,r6 + bne cr0,lab2 + addi r9,r10,32 +lab2: + cmpw cr0,r0,r9 + subfic r10,r0,64 + bgt cr0,lab9 + addi r9,r9,1 + subfic r9,r9,64 + add r0,r0,r9 + subf r9,r9,r10 + mtctr r9 + cmpwi cr0,r9,32 + addi r7,r9,-32 + blt cr0,lab3 + srw r8,r3,r7 + li r7,0 + b lab4 +lab3: + srw r8,r4,r9 + subfic r7,r9,32 + slw r7,r3,r7 + or r8,r8,r7 + srw r7,r3,r9 +lab4: + cmpwi cr0,r0,32 + addic r9,r0,-32 + blt cr0,lab5 + slw r3,r4,r9 + li r4,0 + b lab6 +lab5: + slw r3,r3,r0 + subfic r9,r0,32 + srw r9,r4,r9 + or r3,r3,r9 + slw r4,r4,r0 +lab6: + li r10,-1 + addic r7,r7,0 +lab7: + adde r4,r4,r4 + adde r3,r3,r3 + adde r8,r8,r8 + adde r7,r7,r7 + subfc r0,r6,r8 + subfe. r9,r5,r7 + blt cr0,lab8 + mr r8,r0 + mr r7,r9 + addic r0,r10,1 +lab8: + bdnz lab7 + mr r4,r8 + mr r3,r7 +lab9: + bge cr7,no_adjust + subfic r4,r4,0 + subfze r3,r3 +no_adjust: + blr +#endif // clang-format on +} + +asm void __shl2i(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + subfic r8,r5,32 + subic r9,r5,32 + slw r3,r3,r5 + srw r10,r4,r8 + or r3,r3,r10 + slw r10,r4,r9 + or r3,r3,r10 + slw r4,r4,r5 + blr +#endif // clang-format on +} + +asm void __shr2u(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + subfic r8,r5,32 + subic r9,r5,32 + srw r4,r4,r5 + slw r10,r3,r8 + or r4,r4,r10 + srw r10,r3,r9 + or r4,r4,r10 + srw r3,r3,r5 + blr +#endif // clang-format on +} + +asm void __shr2i(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + subfic r8, r5, 0x20 + addic. r9, r5, -0x20 + srw r4, r4, r5 + slw r10, r3, r8 + or r4, r4, r10 + sraw r10, r3, r9 + ble around + or r4, r4, r10 +around: + sraw r3, r3, r5 + blr +#endif // clang-format on +} + +asm void __cvt_ull_flt(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + stwu r1, -0x10(r1) + or. r7, r3, r4 + li r6, 0x0 + beq zero + cntlzw r7, r3 + cntlzw r8, r4 + extlwi r9, r7, 5, 26 + srawi r9, r9, 31 + and r9, r9, r8 + add r7, r7, r9 + subfic r8, r7, 0x20 + addic r9, r7, -0x20 + slw r3, r3, r7 + srw r10, r4, r8 + or r3, r3, r10 + slw r10, r4, r9 + or r3, r3, r10 + slw r4, r4, r7 + subf r6, r7, r6 + clrlwi r7, r4, 21 + cmpwi r7, 0x400 + addi r6, r6, 0x43e + blt noround + bgt round + rlwinm. r7, r4, 0, 20, 20 + beq noround +round: + addic r4, r4, 0x800 + addze r3, r3 + addze r6, r6 +noround: + rotrwi r4, r4, 11 + rlwimi r4, r3, 21, 0, 10 + extrwi r3, r3, 20, 1 + slwi r6, r6, 20 + or r3, r6, r3 +zero: + stw r3, 0x8(r1) + stw r4, 0xc(r1) + lfd f1, 0x8(r1) + frsp f1, f1 + addi r1, r1, 0x10 + blr +#endif // clang-format on +} + +asm void __cvt_dbl_usll(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + stwu r1,-16(r1) + stfd f1,8(r1) + lwz r3,8(r1) + lwz r4,12(r1) + rlwinm r5,r3,12,21,31 + cmpli cr0,0,r5,1023 + bge cr0,not_fraction + li r3,0 + li r4,0 + b func_end +not_fraction: + mr r6,r3 + rlwinm r3,r3,0,12,31 + oris r3,r3,0x0010 + addi r5,r5,-1075 + cmpwi cr0,r5,0 + bge cr0,left + neg r5,r5 + subfic r8,r5,32 + subic r9,r5,32 + srw r4,r4,r5 + slw r10,r3,r8 + or r4,r4,r10 + srw r10,r3,r9 + or r4,r4,r10 + srw r3,r3,r5 + b around +left: + cmpwi cr0,r5,10 + ble+ no_overflow + rlwinm. r6,r6,0,0,0 + beq cr0,max_positive + lis r3,0x8000 + li r4,0 + b func_end +max_positive: + lis r3,0x7FFF + ori r3,r3,0xFFFF + li r4,-1 + b func_end +no_overflow: + subfic r8,r5,32 + subic r9,r5,32 + slw r3,r3,r5 + srw r10,r4,r8 + or r3,r3,r10 + slw r10,r4,r9 + or r3,r3,r10 + slw r4,r4,r5 +around: + rlwinm. r6,r6,0,0,0 + beq cr0,positive + subfic r4,r4,0 + subfze r3,r3 +positive: +func_end: + addi r1,r1,16 + blr +#endif // clang-format on +}