Steal MSL runtime from sms & mkdd

This commit is contained in:
Roman Sandu
2025-06-23 21:23:21 +03:00
parent d338d491ba
commit b7f95f2000
15 changed files with 1265 additions and 110 deletions
+7 -7
View File
@@ -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"),
],
},
{
+37
View File
@@ -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
+41
View File
@@ -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
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef _MEM_H
#define _MEM_H
#include "types.h"
#include "stddef.h"
#ifdef __cplusplus
extern "C" {
+1 -1
View File
@@ -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))))
+1 -1
View File
@@ -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__
@@ -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;
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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;
+77 -79
View File
@@ -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;
}
+42
View File
@@ -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;
}
@@ -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;
+50
View File
@@ -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
}
+875
View File
@@ -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
}