summaryrefslogtreecommitdiff
path: root/src/Runtime
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2023-02-02 17:29:19 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2023-02-03 13:27:06 -0400
commitf2eabdb6257c09cf2890dac5e9737912728542af (patch)
tree3b46f6787185d65605651a0f48776dc9779ce648 /src/Runtime
parenteef1dd840b7cecac28c2e6b0574707b90a37d4e7 (diff)
global: Add rest of Dolphin SDK proper, add MSL, and MetroTRK
Finally, it links properly.
Diffstat (limited to 'src/Runtime')
-rw-r--r--src/Runtime/NMWException.cpp49
-rw-r--r--src/Runtime/NMWException.h16
-rw-r--r--src/Runtime/__mem.c85
-rw-r--r--src/Runtime/__va_arg.c57
-rw-r--r--src/Runtime/abort_exit.c17
-rw-r--r--src/Runtime/global_destructor_chain.c36
-rw-r--r--src/Runtime/ptmf.c45
-rw-r--r--src/Runtime/runtime.c842
8 files changed, 1098 insertions, 49 deletions
diff --git a/src/Runtime/NMWException.cpp b/src/Runtime/NMWException.cpp
new file mode 100644
index 0000000..1ccbad1
--- /dev/null
+++ b/src/Runtime/NMWException.cpp
@@ -0,0 +1,49 @@
+#include <NMWException.h>
+#pragma exceptions on
+
+class __partial_array_destructor {
+private:
+ void* p;
+ size_t size;
+ size_t n;
+ void* dtor;
+
+public:
+ size_t i;
+
+ __partial_array_destructor(void* array, size_t elementsize, size_t nelements, void* 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 "C" void __construct_array(void* ptr, void* ctor, void* 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 "C" void __destroy_arr(void* block, void* 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/Runtime/NMWException.h b/src/Runtime/NMWException.h
deleted file mode 100644
index 49b623e..0000000
--- a/src/Runtime/NMWException.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef NMWEXCEPTION_H
-#define NMWEXCEPTION_H
-
-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 *__register_global_object(void *object, dtor_func *destructor, dtor_chain *regmem);
-void __destroy_global_chain();
-
-#endif
diff --git a/src/Runtime/__mem.c b/src/Runtime/__mem.c
new file mode 100644
index 0000000..a5ef6c1
--- /dev/null
+++ b/src/Runtime/__mem.c
@@ -0,0 +1,85 @@
+#include "string.h"
+
+void* memcpy(void* dst, const void* src, size_t n) {
+ const char* p;
+ char* q;
+ int rev = ((unsigned long)src < (unsigned long)dst);
+
+ if (!rev) {
+
+ for (p = (const char*)src - 1, q = (char*)dst - 1, n++; --n;)
+ *++q = *++p;
+
+ } else {
+ for (p = (const char*)src + n, q = (char*)dst + n, n++; --n;)
+ *--q = *--p;
+ }
+ return (dst);
+}
+
+#define cps ((unsigned char*)src)
+#define cpd ((unsigned char*)dst)
+#define lps ((unsigned long*)src)
+#define lpd ((unsigned long*)dst)
+#define deref_auto_inc(p) *++(p)
+
+void __fill_mem(void* dst, int val, size_t n) {
+ unsigned long v = (unsigned char)val;
+ unsigned long i;
+
+ cpd = ((unsigned char*)dst) - 1;
+
+ if (n >= 32) {
+ i = (~(unsigned long)dst) & 3;
+
+ if (i) {
+ n -= i;
+
+ do
+ deref_auto_inc(cpd) = v;
+ while (--i);
+ }
+
+ if (v)
+ v |= v << 24 | v << 16 | v << 8;
+
+ lpd = ((unsigned long*)(cpd + 1)) - 1;
+
+ i = n >> 5;
+
+ if (i)
+ do {
+ deref_auto_inc(lpd) = v;
+ deref_auto_inc(lpd) = v;
+ deref_auto_inc(lpd) = v;
+ deref_auto_inc(lpd) = v;
+ deref_auto_inc(lpd) = v;
+ deref_auto_inc(lpd) = v;
+ deref_auto_inc(lpd) = v;
+ deref_auto_inc(lpd) = v;
+ } while (--i);
+
+ i = (n & 31) >> 2;
+
+ if (i)
+ do
+ deref_auto_inc(lpd) = v;
+ while (--i);
+
+ cpd = ((unsigned char*)(lpd + 1)) - 1;
+
+ n &= 3;
+ }
+
+ if (n)
+ do
+ deref_auto_inc(cpd) = v;
+ while (--n);
+
+ return;
+}
+
+void* memset(void* str, int c, size_t n) {
+ __fill_mem(str, c, n);
+ return str;
+}
diff --git a/src/Runtime/__va_arg.c b/src/Runtime/__va_arg.c
new file mode 100644
index 0000000..fd0e182
--- /dev/null
+++ b/src/Runtime/__va_arg.c
@@ -0,0 +1,57 @@
+typedef struct {
+ char gpr;
+ char fpr;
+ char reserved[2];
+ char* input_arg_area;
+ char* reg_save_area;
+} va_list[1];
+
+typedef enum {
+ ARGPOINTER,
+ WORD,
+ DOUBLEWORD,
+ REAL,
+} _va_arg_type;
+
+#define ALIGN(addr, amount) (((unsigned int)(addr) + ((amount)-1)) & ~((amount)-1))
+
+void* __va_arg(va_list ap, _va_arg_type type) {
+ char* addr;
+ char* curGprPtr = &(ap->gpr);
+ int curGpr = ap->gpr;
+ int max = 8;
+ int size = 4;
+ int inc = 1;
+ int even = 0;
+ int fprOffset = 0;
+ int regSize = 4;
+
+ if (type == 3) {
+ curGprPtr = &(ap->fpr);
+ curGpr = ap->fpr;
+ size = 8;
+ fprOffset = 8 * 4;
+ regSize = 8;
+ }
+ if (type == 2) {
+ size = 8;
+ max = max - 1;
+ if (curGpr & 1)
+ even = 1;
+ inc = 2;
+ }
+ if (curGpr < max) {
+ curGpr += even;
+ addr = ap->reg_save_area + fprOffset + (curGpr * regSize);
+ *curGprPtr = curGpr + inc;
+ } else {
+ *curGprPtr = 8;
+ addr = ap->input_arg_area;
+ addr = (char*)ALIGN(addr, size);
+ ap->input_arg_area = addr + size;
+ }
+ if (type == ARGPOINTER)
+ addr = *((char**)addr);
+
+ return addr;
+}
diff --git a/src/Runtime/abort_exit.c b/src/Runtime/abort_exit.c
deleted file mode 100644
index 43b1a0c..0000000
--- a/src/Runtime/abort_exit.c
+++ /dev/null
@@ -1,17 +0,0 @@
-void __destroy_global_chain();
-
-extern void (*_dtors[])(void);
-
-int __aborting;
-
-
-void exit(int state) {
- void (**dtor)(void);
- if (!__aborting) {
- dtor = _dtors;
- while (*dtor != 0) {
- (*dtor)();
- dtor++;
- }
- }
-}
diff --git a/src/Runtime/global_destructor_chain.c b/src/Runtime/global_destructor_chain.c
index 1f3790d..7c24b76 100644
--- a/src/Runtime/global_destructor_chain.c
+++ b/src/Runtime/global_destructor_chain.c
@@ -1,22 +1,26 @@
#include "NMWException.h"
-dtor_chain *__global_destructor_chain;
-
-extern void *__register_global_object(void *object, dtor_func *destructor, dtor_chain *regmem) {
- regmem->next = __global_destructor_chain;
- regmem->destructor = destructor;
- regmem->object = object;
- __global_destructor_chain = regmem;
- return object;
+
+
+DestructorChain* __global_destructor_chain;
+
+extern void* __register_global_object(void* object, void* destructor, void* regmem) {
+ ((DestructorChain*)regmem)->next = __global_destructor_chain;
+ ((DestructorChain*)regmem)->destructor = destructor;
+ ((DestructorChain*)regmem)->object = object;
+ __global_destructor_chain = (DestructorChain*)regmem;
+
+ return object;
}
-void __destroy_global_chain() {
- dtor_chain *iter = __global_destructor_chain;
- while (__global_destructor_chain != 0) {
- iter = __global_destructor_chain;
- __global_destructor_chain = __global_destructor_chain->next;
- iter->destructor(iter->object, -1);
- }
+void __destroy_global_chain(void) {
+ DestructorChain* iter;
+
+ while ((iter=__global_destructor_chain) != 0) {
+ __global_destructor_chain = iter->next;
+ DTORCALL_COMPLETE(iter->destructor, iter->object);
+ }
}
-__declspec(section ".dtors") static void* const __destroy_global_chain_reference = __destroy_global_chain;
+__declspec(section
+ ".dtors") static void* const __destroy_global_chain_reference = __destroy_global_chain;
diff --git a/src/Runtime/ptmf.c b/src/Runtime/ptmf.c
new file mode 100644
index 0000000..b9e8a90
--- /dev/null
+++ b/src/Runtime/ptmf.c
@@ -0,0 +1,45 @@
+
+typedef struct PTMF {
+ long this_delta; // delta to this pointer
+ long vtbl_offset; // offset in vtable (-1: not a virtual function)
+ union {
+ void* func_addr; //nonvirtual function address
+ long ventry_offset; // of virtual function entry in vtable
+ } func_data;
+} PTMF;
+
+const PTMF __ptmf_null = {0, 0, 0};
+
+/* clang-format off */
+asm void __ptmf_test(register PTMF* ptmf) {
+ nofralloc
+
+ lwz r5, PTMF.this_delta(ptmf)
+ lwz r6, PTMF.vtbl_offset(ptmf)
+ lwz r7, PTMF.func_data(ptmf)
+ li r3, 1
+ cmpwi cr0, r5, 0
+ cmpwi cr6, r6, 0
+ cmpwi cr7, r7, 0
+ bnelr cr0
+ bnelr cr6
+ bnelr cr7
+ li r3, 0
+ blr
+}
+
+asm void __ptmf_scall(...) {
+ nofralloc
+ lwz r0, PTMF.this_delta(r12)
+ lwz r11, PTMF.vtbl_offset(r12)
+ lwz r12, PTMF.func_data(r12)
+ add r3, r3, r0
+ cmpwi r11, 0
+ blt @1
+ lwzx r12, r3, r12
+ lwzx r12, r12, r11
+@1
+ mtctr r12
+ bctr
+}
+/* clang-format - on*/
diff --git a/src/Runtime/runtime.c b/src/Runtime/runtime.c
new file mode 100644
index 0000000..16fd6ed
--- /dev/null
+++ b/src/Runtime/runtime.c
@@ -0,0 +1,842 @@
+/* clang-format off */
+#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)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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 long long __constants[] = {
+ 0x0000000000000000, // 0.0
+ 0x41F0000000000000, // 2**32
+ 0x41E0000000000000, // 2**31
+};
+
+
+asm unsigned long __cvt_fp2unsigned(register double d) {
+ nofralloc
+ stwu r1, -0x10(r1)
+ lis r4, __constants@h
+ ori r4, r4, __constants@l
+ li r3, 0
+ lfd f0, 0(r4)
+ lfd f3, 8(r4)
+ lfd f4, 0x10(r4)
+ fcmpu cr0, f1, f0
+ fcmpu cr6, f1, f3
+ blt lbl_803899A8
+ addi r3, r3, -1
+ bge cr6, lbl_803899A8
+ fcmpu cr7, f1, f4
+ fmr f2, f1
+ blt cr7, lbl_80389994
+ fsub f2, f1, f4
+lbl_80389994:
+ fctiwz f2, f2
+ stfd f2, 8(r1)
+ lwz r3, 0xc(r1)
+ blt cr7, lbl_803899A8
+ addis r3, r3, 0x8000
+lbl_803899A8:
+ addi r1, r1, 0x10
+ blr
+}
+
+
+asm void __save_fpr() {
+ ENTRY_SAVE_FPR(14)
+ ENTRY_SAVE_FPR2(14)
+ stfd fp14,-144 (r11)
+ ENTRY_SAVE_FPR(15)
+ ENTRY_SAVE_FPR2(15)
+ stfd fp15,-136 (r11)
+ ENTRY_SAVE_FPR(16)
+ ENTRY_SAVE_FPR2(16)
+ stfd fp16,-128 (r11)
+ ENTRY_SAVE_FPR(17)
+ ENTRY_SAVE_FPR2(17)
+ stfd fp17,-120 (r11)
+ ENTRY_SAVE_FPR(18)
+ ENTRY_SAVE_FPR2(18)
+ stfd fp18,-112 (r11)
+ ENTRY_SAVE_FPR(19)
+ ENTRY_SAVE_FPR2(19)
+ stfd fp19,-104 (r11)
+ ENTRY_SAVE_FPR(20)
+ ENTRY_SAVE_FPR2(20)
+ stfd fp20,-96 (r11)
+ ENTRY_SAVE_FPR(21)
+ ENTRY_SAVE_FPR2(21)
+ stfd fp21,-88 (r11)
+ ENTRY_SAVE_FPR(22)
+ ENTRY_SAVE_FPR2(22)
+ stfd fp22,-80(r11)
+ ENTRY_SAVE_FPR(23)
+ ENTRY_SAVE_FPR2(23)
+ stfd fp23,-72(r11)
+ ENTRY_SAVE_FPR(24)
+ ENTRY_SAVE_FPR2(24)
+ stfd fp24,-64(r11)
+ ENTRY_SAVE_FPR(25)
+ ENTRY_SAVE_FPR2(25)
+ stfd fp25,-56(r11)
+ ENTRY_SAVE_FPR(26)
+ ENTRY_SAVE_FPR2(26)
+ stfd fp26,-48(r11)
+ ENTRY_SAVE_FPR(27)
+ ENTRY_SAVE_FPR2(27)
+ stfd fp27,-40(r11)
+ ENTRY_SAVE_FPR(28)
+ ENTRY_SAVE_FPR2(28)
+ stfd fp28,-32(r11)
+ ENTRY_SAVE_FPR(29)
+ ENTRY_SAVE_FPR2(29)
+ stfd fp29,-24(r11)
+ ENTRY_SAVE_FPR(30)
+ ENTRY_SAVE_FPR2(30)
+ stfd fp30,-16(r11)
+ ENTRY_SAVE_FPR(31)
+ ENTRY_SAVE_FPR2(31)
+ stfd fp31,-8(r11)
+ blr
+}
+
+asm void __restore_fpr(void) {
+ nofralloc
+ ENTRY_RESTORE_FPR(14)
+ ENTRY_RESTORE_FPR2(14)
+ lfd fp14,-144(r11)
+ ENTRY_RESTORE_FPR(15)
+ ENTRY_RESTORE_FPR2(15)
+ lfd fp15,-136(r11)
+ ENTRY_RESTORE_FPR(16)
+ ENTRY_RESTORE_FPR2(16)
+ lfd fp16,-128(r11)
+ ENTRY_RESTORE_FPR(17)
+ ENTRY_RESTORE_FPR2(17)
+ lfd fp17,-120(r11)
+ ENTRY_RESTORE_FPR(18)
+ ENTRY_RESTORE_FPR2(18)
+ lfd fp18,-112(r11)
+ ENTRY_RESTORE_FPR(19)
+ ENTRY_RESTORE_FPR2(19)
+ lfd fp19,-104(r11)
+ ENTRY_RESTORE_FPR(20)
+ ENTRY_RESTORE_FPR2(20)
+ lfd fp20,-96(r11)
+ ENTRY_RESTORE_FPR(21)
+ ENTRY_RESTORE_FPR2(21)
+ lfd fp21,-88(r11)
+ ENTRY_RESTORE_FPR(22)
+ ENTRY_RESTORE_FPR2(22)
+ lfd fp22,-80(r11)
+ ENTRY_RESTORE_FPR(23)
+ ENTRY_RESTORE_FPR2(23)
+ lfd fp23,-72(r11)
+ ENTRY_RESTORE_FPR(24)
+ ENTRY_RESTORE_FPR2(24)
+ lfd fp24,-64(r11)
+ ENTRY_RESTORE_FPR(25)
+ ENTRY_RESTORE_FPR2(25)
+ lfd fp25,-56(r11)
+ ENTRY_RESTORE_FPR(26)
+ ENTRY_RESTORE_FPR2(26)
+ lfd fp26,-48(r11)
+ ENTRY_RESTORE_FPR(27)
+ ENTRY_RESTORE_FPR2(27)
+ lfd fp27,-40(r11)
+ ENTRY_RESTORE_FPR(28)
+ ENTRY_RESTORE_FPR2(28)
+ lfd fp28,-32(r11)
+ ENTRY_RESTORE_FPR(29)
+ ENTRY_RESTORE_FPR2(29)
+ lfd fp29,-24(r11)
+ ENTRY_RESTORE_FPR(30)
+ ENTRY_RESTORE_FPR2(30)
+ lfd fp30,-16(r11)
+ ENTRY_RESTORE_FPR(31)
+ ENTRY_RESTORE_FPR2(31)
+ lfd fp31,-8(r11)
+ blr
+}
+
+asm void __save_gpr(void) {
+ nofralloc
+ ENTRY_SAVE_GPR(14)
+ stw r14,-72(r11)
+ ENTRY_SAVE_GPR(15)
+ stw r15,-68(r11)
+ ENTRY_SAVE_GPR(16)
+ stw r16,-64(r11)
+ ENTRY_SAVE_GPR(17)
+ stw r17,-60(r11)
+ ENTRY_SAVE_GPR(18)
+ stw r18,-56(r11)
+ ENTRY_SAVE_GPR(19)
+ stw r19,-52(r11)
+ ENTRY_SAVE_GPR(20)
+ stw r20,-48(r11)
+ ENTRY_SAVE_GPR(21)
+ stw r21,-44(r11)
+ ENTRY_SAVE_GPR(22)
+ stw r22,-40(r11)
+ ENTRY_SAVE_GPR(23)
+ stw r23,-36(r11)
+ ENTRY_SAVE_GPR(24)
+ stw r24,-32(r11)
+ ENTRY_SAVE_GPR(25)
+ stw r25,-28(r11)
+ ENTRY_SAVE_GPR(26)
+ stw r26,-24(r11)
+ ENTRY_SAVE_GPR(27)
+ stw r27,-20(r11)
+ ENTRY_SAVE_GPR(28)
+ stw r28,-16(r11)
+ ENTRY_SAVE_GPR(29)
+ stw r29,-12(r11)
+ ENTRY_SAVE_GPR(30)
+ stw r30,-8(r11)
+ ENTRY_SAVE_GPR(31)
+ stw r31,-4(r11)
+ blr
+}
+
+asm void __restore_gpr(void) {
+ nofralloc
+ ENTRY_RESTORE_GPR(14)
+ lwz r14,-72(r11)
+ ENTRY_RESTORE_GPR(15)
+ lwz r15,-68(r11)
+ ENTRY_RESTORE_GPR(16)
+ lwz r16,-64(r11)
+ ENTRY_RESTORE_GPR(17)
+ lwz r17,-60(r11)
+ ENTRY_RESTORE_GPR(18)
+ lwz r18,-56(r11)
+ ENTRY_RESTORE_GPR(19)
+ lwz r19,-52(r11)
+ ENTRY_RESTORE_GPR(20)
+ lwz r20,-48(r11)
+ ENTRY_RESTORE_GPR(21)
+ lwz r21,-44(r11)
+ ENTRY_RESTORE_GPR(22)
+ lwz r22,-40(r11)
+ ENTRY_RESTORE_GPR(23)
+ lwz r23,-36(r11)
+ ENTRY_RESTORE_GPR(24)
+ lwz r24,-32(r11)
+ ENTRY_RESTORE_GPR(25)
+ lwz r25,-28(r11)
+ ENTRY_RESTORE_GPR(26)
+ lwz r26,-24(r11)
+ ENTRY_RESTORE_GPR(27)
+ lwz r27,-20(r11)
+ ENTRY_RESTORE_GPR(28)
+ lwz r28,-16(r11)
+ ENTRY_RESTORE_GPR(29)
+ lwz r29,-12(r11)
+ ENTRY_RESTORE_GPR(30)
+ lwz r30,-8(r11)
+ ENTRY_RESTORE_GPR(31)
+ lwz r31,-4(r11)
+ blr
+}
+
+asm void __div2u(void) {
+ nofralloc
+ cmpwi r3, 0
+ cntlzw r0, r3
+ cntlzw r9, r4
+ bne lbl_80389AF4
+ addi r0, r9, 0x20
+lbl_80389AF4:
+ cmpwi r5, 0
+ cntlzw r9, r5
+ cntlzw r10, r6
+ bne lbl_80389B08
+ addi r9, r10, 0x20
+lbl_80389B08:
+ cmpw r0, r9
+ subfic r10, r0, 0x40
+ bgt lbl_80389BC0
+ addi r9, r9, 1
+ subfic r9, r9, 0x40
+ add r0, r0, r9
+ subf r9, r9, r10
+ mtctr r9
+ cmpwi r9, 0x20
+ addi r7, r9, -32
+ blt lbl_80389B40
+ srw r8, r3, r7
+ li r7, 0
+ b lbl_80389B54
+lbl_80389B40:
+ srw r8, r4, r9
+ subfic r7, r9, 0x20
+ slw r7, r3, r7
+ or r8, r8, r7
+ srw r7, r3, r9
+lbl_80389B54:
+ cmpwi r0, 0x20
+ addic r9, r0, -32
+ blt lbl_80389B6C
+ slw r3, r4, r9
+ li r4, 0
+ b lbl_80389B80
+lbl_80389B6C:
+ slw r3, r3, r0
+ subfic r9, r0, 0x20
+ srw r9, r4, r9
+ or r3, r3, r9
+ slw r4, r4, r0
+lbl_80389B80:
+ li r10, -1
+ addic r7, r7, 0
+lbl_80389B88:
+ 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 lbl_80389BB0
+ mr r8, r0
+ mr r7, r9
+ addic r0, r10, 1
+lbl_80389BB0:
+ bdnz lbl_80389B88
+ adde r4, r4, r4
+ adde r3, r3, r3
+ blr
+lbl_80389BC0:
+ li r4, 0
+ li r3, 0
+ blr
+}
+
+asm void __div2i(void) {
+ nofralloc
+ stwu r1, -0x10(r1)
+ rlwinm. r9, r3, 0, 0, 0
+ beq lbl_80389BE0
+ subfic r4, r4, 0
+ subfze r3, r3
+lbl_80389BE0:
+ stw r9, 8(r1)
+ rlwinm. r10, r5, 0, 0, 0
+ beq lbl_80389BF4
+ subfic r6, r6, 0
+ subfze r5, r5
+lbl_80389BF4:
+ stw r10, 0xc(r1)
+ cmpwi r3, 0
+ cntlzw r0, r3
+ cntlzw r9, r4
+ bne lbl_80389C0C
+ addi r0, r9, 0x20
+lbl_80389C0C:
+ cmpwi r5, 0
+ cntlzw r9, r5
+ cntlzw r10, r6
+ bne lbl_80389C20
+ addi r9, r10, 0x20
+lbl_80389C20:
+ cmpw r0, r9
+ subfic r10, r0, 0x40
+ bgt lbl_80389CF4
+ addi r9, r9, 1
+ subfic r9, r9, 0x40
+ add r0, r0, r9
+ subf r9, r9, r10
+ mtctr r9
+ cmpwi r9, 0x20
+ addi r7, r9, -32
+ blt lbl_80389C58
+ srw r8, r3, r7
+ li r7, 0
+ b lbl_80389C6C
+lbl_80389C58:
+ srw r8, r4, r9
+ subfic r7, r9, 0x20
+ slw r7, r3, r7
+ or r8, r8, r7
+ srw r7, r3, r9
+lbl_80389C6C:
+ cmpwi r0, 0x20
+ addic r9, r0, -32
+ blt lbl_80389C84
+ slw r3, r4, r9
+ li r4, 0
+ b lbl_80389C98
+lbl_80389C84:
+ slw r3, r3, r0
+ subfic r9, r0, 0x20
+ srw r9, r4, r9
+ or r3, r3, r9
+ slw r4, r4, r0
+lbl_80389C98:
+ li r10, -1
+ addic r7, r7, 0
+lbl_80389CA0:
+ 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 lbl_80389CC8
+ mr r8, r0
+ mr r7, r9
+ addic r0, r10, 1
+lbl_80389CC8:
+ bdnz lbl_80389CA0
+ adde r4, r4, r4
+ adde r3, r3, r3
+ lwz r9, 8(r1)
+ lwz r10, 0xc(r1)
+ xor. r7, r9, r10
+ beq lbl_80389CFC
+ cmpwi r9, 0
+ subfic r4, r4, 0
+ subfze r3, r3
+ b lbl_80389CFC
+lbl_80389CF4:
+ li r4, 0
+ li r3, 0
+lbl_80389CFC:
+ addi r1, r1, 0x10
+ blr
+}
+
+asm void __mod2u() {
+ nofralloc
+ cmpwi r3, 0
+ cntlzw r0, r3
+ cntlzw r9, r4
+ bne lbl_80389D18
+ addi r0, r9, 0x20
+lbl_80389D18:
+ cmpwi r5, 0
+ cntlzw r9, r5
+ cntlzw r10, r6
+ bne lbl_80389D2C
+ addi r9, r10, 0x20
+lbl_80389D2C:
+ cmpw r0, r9
+ subfic r10, r0, 0x40
+ bgtlr
+ addi r9, r9, 1
+ subfic r9, r9, 0x40
+ add r0, r0, r9
+ subf r9, r9, r10
+ mtctr r9
+ cmpwi r9, 0x20
+ addi r7, r9, -32
+ blt lbl_80389D64
+ srw r8, r3, r7
+ li r7, 0
+ b lbl_80389D78
+lbl_80389D64:
+ srw r8, r4, r9
+ subfic r7, r9, 0x20
+ slw r7, r3, r7
+ or r8, r8, r7
+ srw r7, r3, r9
+lbl_80389D78:
+ cmpwi r0, 0x20
+ addic r9, r0, -32
+ blt lbl_80389D90
+ slw r3, r4, r9
+ li r4, 0
+ b lbl_80389DA4
+lbl_80389D90:
+ slw r3, r3, r0
+ subfic r9, r0, 0x20
+ srw r9, r4, r9
+ or r3, r3, r9
+ slw r4, r4, r0
+lbl_80389DA4:
+ li r10, -1
+ addic r7, r7, 0
+lbl_80389DAC:
+ 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 lbl_80389DD4
+ mr r8, r0
+ mr r7, r9
+ addic r0, r10, 1
+lbl_80389DD4:
+ bdnz lbl_80389DAC
+ mr r4, r8
+ mr r3, r7
+ blr
+ blr
+}
+
+asm void __mod2i(void) {
+ nofralloc
+ cmpwi cr7, r3, 0
+ bge cr7, lbl_80389DF8
+ subfic r4, r4, 0
+ subfze r3, r3
+lbl_80389DF8:
+ cmpwi r5, 0
+ bge lbl_80389E08
+ subfic r6, r6, 0
+ subfze r5, r5
+lbl_80389E08:
+ cmpwi r3, 0
+ cntlzw r0, r3
+ cntlzw r9, r4
+ bne lbl_80389E1C
+ addi r0, r9, 0x20
+lbl_80389E1C:
+ cmpwi r5, 0
+ cntlzw r9, r5
+ cntlzw r10, r6
+ bne lbl_80389E30
+ addi r9, r10, 0x20
+lbl_80389E30:
+ cmpw r0, r9
+ subfic r10, r0, 0x40
+ bgt lbl_80389EE4
+ addi r9, r9, 1
+ subfic r9, r9, 0x40
+ add r0, r0, r9
+ subf r9, r9, r10
+ mtctr r9
+ cmpwi r9, 0x20
+ addi r7, r9, -32
+ blt lbl_80389E68
+ srw r8, r3, r7
+ li r7, 0
+ b lbl_80389E7C
+lbl_80389E68:
+ srw r8, r4, r9
+ subfic r7, r9, 0x20
+ slw r7, r3, r7
+ or r8, r8, r7
+ srw r7, r3, r9
+lbl_80389E7C:
+ cmpwi r0, 0x20
+ addic r9, r0, -32
+ blt lbl_80389E94
+ slw r3, r4, r9
+ li r4, 0
+ b lbl_80389EA8
+lbl_80389E94:
+ slw r3, r3, r0
+ subfic r9, r0, 0x20
+ srw r9, r4, r9
+ or r3, r3, r9
+ slw r4, r4, r0
+lbl_80389EA8:
+ li r10, -1
+ addic r7, r7, 0
+lbl_80389EB0:
+ 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 lbl_80389ED8
+ mr r8, r0
+ mr r7, r9
+ addic r0, r10, 1
+lbl_80389ED8:
+ bdnz lbl_80389EB0
+ mr r4, r8
+ mr r3, r7
+lbl_80389EE4:
+ bgelr cr7
+ subfic r4, r4, 0
+ subfze r3, r3
+ blr
+}
+
+asm void __shl2i() {
+ nofralloc
+ subfic r8, r5, 0x20
+ addic 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
+}
+
+asm void __shr2u() {
+ nofralloc
+ subfic r8, r5, 0x20
+ addic 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
+}
+
+asm void __shr2i() {
+ nofralloc
+ subfic r8, r5, 0x20
+ addic. r9, r5, -32
+ srw r4, r4, r5
+ slw r10, r3, r8
+ or r4, r4, r10
+ sraw r10, r3, r9
+ ble lbl_80389F5C
+ or r4, r4, r10
+lbl_80389F5C:
+ sraw r3, r3, r5
+ blr
+}
+
+asm void __cvt_sll_flt(void) {
+ nofralloc
+ stwu r1, -0x10(r1)
+ rlwinm. r5, r3, 0, 0, 0
+ beq lbl_80389F78
+ subfic r4, r4, 0
+ subfze r3, r3
+lbl_80389F78:
+ or. r7, r3, r4
+ li r6, 0
+ beq lbl_8038A000
+ cntlzw r7, r3
+ cntlzw r8, r4
+ rlwinm r9, r7, 0x1a, 0, 4
+ srawi r9, r9, 0x1f
+ and r9, r9, r8
+ add r7, r7, r9
+ subfic r8, r7, 0x20
+ addic r9, r7, -32
+ 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, 0x15
+ cmpwi r7, 0x400
+ addi r6, r6, 0x43e
+ blt lbl_80389FE8
+ bgt lbl_80389FDC
+ rlwinm. r7, r4, 0, 0x14, 0x14
+ beq lbl_80389FE8
+lbl_80389FDC:
+ addic r4, r4, 0x800
+ addze r3, r3
+ addze r6, r6
+lbl_80389FE8:
+ rotlwi r4, r4, 0x15
+ rlwimi r4, r3, 0x15, 0, 0xa
+ rlwinm r3, r3, 0x15, 0xc, 0x1f
+ slwi r6, r6, 0x14
+ or r3, r6, r3
+ or r3, r5, r3
+lbl_8038A000:
+ stw r3, 8(r1)
+ stw r4, 0xc(r1)
+ lfd f1, 8(r1)
+ frsp f1, f1
+ addi r1, r1, 0x10
+ blr
+}
+
+asm unsigned long __cvt_dbl_usll(register double d) {
+ nofralloc
+ stwu r1, -0x10(r1)
+ stfd f1, 8(r1)
+ lwz r3, 8(r1)
+ lwz r4, 0xc(r1)
+ rlwinm r5, r3, 0xc, 0x15, 0x1f
+ cmplwi r5, 0x3ff
+ bge lbl_8038A040
+ li r3, 0
+ li r4, 0
+ b lbl_8038A0DC
+lbl_8038A040:
+ mr r6, r3
+ clrlwi r3, r3, 0xc
+ oris r3, r3, 0x10
+ addi r5, r5, -1075
+ cmpwi r5, 0
+ bge lbl_8038A080
+ neg r5, r5
+ subfic r8, r5, 0x20
+ addic 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 lbl_8038A0CC
+lbl_8038A080:
+ cmpwi r5, 0xa
+ ble+ lbl_8038A0AC
+ rlwinm. r6, r6, 0, 0, 0
+ beq lbl_8038A09C
+ lis r3, 0x8000
+ li r4, 0
+ b lbl_8038A0DC
+lbl_8038A09C:
+ lis r3, 0x7FFFFFFF@h
+ ori r3, r3, 0x7FFFFFFF@l
+ li r4, -1
+ b lbl_8038A0DC
+lbl_8038A0AC:
+ subfic r8, r5, 0x20
+ addic 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
+lbl_8038A0CC:
+ rlwinm. r6, r6, 0, 0, 0
+ beq lbl_8038A0DC
+ subfic r4, r4, 0
+ subfze r3, r3
+lbl_8038A0DC:
+ addi r1, r1, 0x10
+ blr
+}
+
+#ifdef __cplusplus
+}
+#endif