OSFreeToHeap matching besides SDA offset, OSAllocFromHeap almost matching besides register swap

This commit is contained in:
Max
2020-09-14 22:13:52 -04:00
parent 0d864ef8a9
commit 1847436ad5
3 changed files with 148 additions and 112 deletions
-112
View File
@@ -2,115 +2,3 @@
.section .text, "ax" # 0x80006980 - 0x803E1E60
.global OSAllocFromHeap
OSAllocFromHeap:
/* 80269F5C 00265BBC 1C 63 00 0C */ mulli r3, r3, 0xc
/* 80269F60 00265BC0 80 AD A7 B8 */ lwz r5, lbl_8063FA78-_SDA_BASE_(r13)
/* 80269F64 00265BC4 38 04 00 3F */ addi r0, r4, 0x3f
/* 80269F68 00265BC8 7C A5 1A 14 */ add r5, r5, r3
/* 80269F6C 00265BCC 54 04 00 34 */ rlwinm r4, r0, 0, 0, 0x1a
/* 80269F70 00265BD0 80 65 00 04 */ lwz r3, 4(r5)
/* 80269F74 00265BD4 7C 66 1B 78 */ mr r6, r3
/* 80269F78 00265BD8 48 00 00 14 */ b lbl_80269F8C
lbl_80269F7C:
/* 80269F7C 00265BDC 80 06 00 08 */ lwz r0, 8(r6)
/* 80269F80 00265BE0 7C 04 00 00 */ cmpw r4, r0
/* 80269F84 00265BE4 40 81 00 10 */ ble lbl_80269F94
/* 80269F88 00265BE8 80 C6 00 04 */ lwz r6, 4(r6)
lbl_80269F8C:
/* 80269F8C 00265BEC 2C 06 00 00 */ cmpwi r6, 0
/* 80269F90 00265BF0 40 82 FF EC */ bne lbl_80269F7C
lbl_80269F94:
/* 80269F94 00265BF4 2C 06 00 00 */ cmpwi r6, 0
/* 80269F98 00265BF8 40 82 00 0C */ bne lbl_80269FA4
/* 80269F9C 00265BFC 38 60 00 00 */ li r3, 0
/* 80269FA0 00265C00 4E 80 00 20 */ blr
lbl_80269FA4:
/* 80269FA4 00265C04 80 06 00 08 */ lwz r0, 8(r6)
/* 80269FA8 00265C08 7C 04 00 50 */ subf r0, r4, r0
/* 80269FAC 00265C0C 28 00 00 40 */ cmplwi r0, 0x40
/* 80269FB0 00265C10 40 80 00 3C */ bge lbl_80269FEC
/* 80269FB4 00265C14 80 86 00 04 */ lwz r4, 4(r6)
/* 80269FB8 00265C18 2C 04 00 00 */ cmpwi r4, 0
/* 80269FBC 00265C1C 41 82 00 0C */ beq lbl_80269FC8
/* 80269FC0 00265C20 80 06 00 00 */ lwz r0, 0(r6)
/* 80269FC4 00265C24 90 04 00 00 */ stw r0, 0(r4)
lbl_80269FC8:
/* 80269FC8 00265C28 80 86 00 00 */ lwz r4, 0(r6)
/* 80269FCC 00265C2C 2C 04 00 00 */ cmpwi r4, 0
/* 80269FD0 00265C30 40 82 00 0C */ bne lbl_80269FDC
/* 80269FD4 00265C34 80 66 00 04 */ lwz r3, 4(r6)
/* 80269FD8 00265C38 48 00 00 0C */ b lbl_80269FE4
lbl_80269FDC:
/* 80269FDC 00265C3C 80 06 00 04 */ lwz r0, 4(r6)
/* 80269FE0 00265C40 90 04 00 04 */ stw r0, 4(r4)
lbl_80269FE4:
/* 80269FE4 00265C44 90 65 00 04 */ stw r3, 4(r5)
/* 80269FE8 00265C48 48 00 00 44 */ b lbl_8026A02C
lbl_80269FEC:
/* 80269FEC 00265C4C 90 86 00 08 */ stw r4, 8(r6)
/* 80269FF0 00265C50 7C 86 22 14 */ add r4, r6, r4
/* 80269FF4 00265C54 90 04 00 08 */ stw r0, 8(r4)
/* 80269FF8 00265C58 80 06 00 00 */ lwz r0, 0(r6)
/* 80269FFC 00265C5C 90 04 00 00 */ stw r0, 0(r4)
/* 8026A000 00265C60 80 66 00 04 */ lwz r3, 4(r6)
/* 8026A004 00265C64 2C 03 00 00 */ cmpwi r3, 0
/* 8026A008 00265C68 90 64 00 04 */ stw r3, 4(r4)
/* 8026A00C 00265C6C 41 82 00 08 */ beq lbl_8026A014
/* 8026A010 00265C70 90 83 00 00 */ stw r4, 0(r3)
lbl_8026A014:
/* 8026A014 00265C74 80 64 00 00 */ lwz r3, 0(r4)
/* 8026A018 00265C78 2C 03 00 00 */ cmpwi r3, 0
/* 8026A01C 00265C7C 41 82 00 0C */ beq lbl_8026A028
/* 8026A020 00265C80 90 83 00 04 */ stw r4, 4(r3)
/* 8026A024 00265C84 48 00 00 08 */ b lbl_8026A02C
lbl_8026A028:
/* 8026A028 00265C88 90 85 00 04 */ stw r4, 4(r5)
lbl_8026A02C:
/* 8026A02C 00265C8C 80 65 00 08 */ lwz r3, 8(r5)
/* 8026A030 00265C90 38 00 00 00 */ li r0, 0
/* 8026A034 00265C94 90 66 00 04 */ stw r3, 4(r6)
/* 8026A038 00265C98 2C 03 00 00 */ cmpwi r3, 0
/* 8026A03C 00265C9C 90 06 00 00 */ stw r0, 0(r6)
/* 8026A040 00265CA0 41 82 00 08 */ beq lbl_8026A048
/* 8026A044 00265CA4 90 C3 00 00 */ stw r6, 0(r3)
lbl_8026A048:
/* 8026A048 00265CA8 90 C5 00 08 */ stw r6, 8(r5)
/* 8026A04C 00265CAC 38 66 00 20 */ addi r3, r6, 0x20
/* 8026A050 00265CB0 4E 80 00 20 */ blr
.global OSFreeToHeap
OSFreeToHeap:
/* 8026A054 00265CB4 94 21 FF F0 */ stwu r1, -0x10(r1)
/* 8026A058 00265CB8 7C 08 02 A6 */ mflr r0
/* 8026A05C 00265CBC 38 84 FF E0 */ addi r4, r4, -32
/* 8026A060 00265CC0 90 01 00 14 */ stw r0, 0x14(r1)
/* 8026A064 00265CC4 1C 03 00 0C */ mulli r0, r3, 0xc
/* 8026A068 00265CC8 93 E1 00 0C */ stw r31, 0xc(r1)
/* 8026A06C 00265CCC 80 AD A7 B8 */ lwz r5, lbl_8063FA78-_SDA_BASE_(r13)
/* 8026A070 00265CD0 80 C4 00 04 */ lwz r6, 4(r4)
/* 8026A074 00265CD4 7F E5 02 14 */ add r31, r5, r0
/* 8026A078 00265CD8 2C 06 00 00 */ cmpwi r6, 0
/* 8026A07C 00265CDC 80 7F 00 08 */ lwz r3, 8(r31)
/* 8026A080 00265CE0 41 82 00 0C */ beq lbl_8026A08C
/* 8026A084 00265CE4 80 04 00 00 */ lwz r0, 0(r4)
/* 8026A088 00265CE8 90 06 00 00 */ stw r0, 0(r6)
lbl_8026A08C:
/* 8026A08C 00265CEC 80 A4 00 00 */ lwz r5, 0(r4)
/* 8026A090 00265CF0 2C 05 00 00 */ cmpwi r5, 0
/* 8026A094 00265CF4 40 82 00 0C */ bne lbl_8026A0A0
/* 8026A098 00265CF8 80 64 00 04 */ lwz r3, 4(r4)
/* 8026A09C 00265CFC 48 00 00 0C */ b lbl_8026A0A8
lbl_8026A0A0:
/* 8026A0A0 00265D00 80 04 00 04 */ lwz r0, 4(r4)
/* 8026A0A4 00265D04 90 05 00 04 */ stw r0, 4(r5)
lbl_8026A0A8:
/* 8026A0A8 00265D08 90 7F 00 08 */ stw r3, 8(r31)
/* 8026A0AC 00265D0C 80 7F 00 04 */ lwz r3, 4(r31)
/* 8026A0B0 00265D10 4B FF FE 01 */ bl DLInsert
/* 8026A0B4 00265D14 90 7F 00 04 */ stw r3, 4(r31)
/* 8026A0B8 00265D18 83 E1 00 0C */ lwz r31, 0xc(r1)
/* 8026A0BC 00265D1C 80 01 00 14 */ lwz r0, 0x14(r1)
/* 8026A0C0 00265D20 7C 08 03 A6 */ mtlr r0
/* 8026A0C4 00265D24 38 21 00 10 */ addi r1, r1, 0x10
/* 8026A0C8 00265D28 4E 80 00 20 */ blr
+7
View File
@@ -6,6 +6,11 @@ extern "C" {
#endif
typedef struct Cell Cell;
typedef int OSHeapHandle;
#if 0
extern volatile OSHeapHandle __OSCurrHeap; // used in OSInitAlloc
#endif
struct Cell {
Cell* prev;
@@ -14,6 +19,8 @@ struct Cell {
};
Cell *DLInsert(Cell *original, Cell *inserted);
void *OSAllocFromHeap(OSHeapHandle heap, u32 size);
void OSFreeToHeap(OSHeapHandle heap, void *ptr);
#ifdef __cplusplus
}
+141
View File
@@ -47,3 +47,144 @@ Cell *DLInsert(Cell *original, Cell *inserted)
return inserted;
}
// sizeof unkStruct == 12
// element of a "heap array"
typedef struct unkStruct {
s32 heapSize; // initialized to -1 in OSInitAlloc, set to heap size in OSCreateHeap
Cell *start; // set to start param of OSCreateHeap
Cell *freeList; // initialized to NULL in OSInitAlloc along with start
// head of a linked list of allocated blocks (the free list)
} unkStruct;
// arenaStart param of OSInitAlloc, points to array of maxHeap unkStructs, 68c
static unkStruct *gUnk8063fa78;
#if 0 // not found in DOL
static u32 gUnk8063fa6c; // aligned arenaEnd, 680
// returned by OSInitAlloc, "base address of the new arena,"
// pointer to the beginning of the real data after the heap array header, 684
static void *gUnk8063fa70;
// Table of heaps
static int gUnk8063fa74; // maxHeaps param of OSInitAlloc, 688
volatile OSHeapHandle __OSCurrHeap = -1;
void *OSInitAlloc(void *arenaStart, void *arenaEnd, int maxHeaps)
{
gUnk8063fa78 = (unkStruct *)arenaStart;
gUnk8063fa74 = maxHeaps;
for (int i = 0; i < gUnk8063fa74; i++) {
gUnk8063fa78[i].heapSize = -1; // -1 indicates this heap is unused
gUnk8063fa78[i].start = NULL;
gUnk8063fa78[i].freeList = NULL;
}
gUnk8063fa6c = (u32)arenaEnd & ~0x1f;
__OSCurrHeap = -1;
gUnk8063fa70 = (void *)(((u32)&gUnk8063fa78[maxHeaps] + 0x1f) & ~0x1f);
return gUnk8063fa70;
}
OSHeapHandle OSCreateHeap(void *start, void *end)
{
start = (void *)((u32)start + 0x1f & ~0x1f);
end = (void *)((u32)end & ~0x1f);
for (int i = 0; i < gUnk8063fa74; i++) {
if (gUnk8063fa78[i].heapSize < 0) {
gUnk8063fa78[i].heapSize = end - start;
((Cell *)start)->prev = NULL;
((Cell *)start)->next = NULL;
((Cell *)start)->size = gUnk8063fa78[i].heapSize;
gUnk8063fa78[i].start = (Cell *)start;
gUnk8063fa78[i].freeList = NULL;
return i;
}
}
return -1;
}
#endif
// NOTE: matches except for r4/r5 reg swap
void *OSAllocFromHeap(OSHeapHandle heap, u32 size)
{
// r4, add 32 bytes to requested size (for the header), then round up
// to the next multiple of 32 (for alignment)
//s32 sizeWithHeader = size + 32;
unkStruct *r5 = &gUnk8063fa78[heap]; // r5, start parameter from OSInitAlloc
Cell *r3 = r5->start;
s32 totalSize = ((size + 63) & ~0x1f); // r4
Cell *r6;
for (r6 = r3; r6; r6 = r6->next) {
if (totalSize <= r6->size) break;
}
if (!r6) return NULL;
// r6 has enough space to satisfy the request
u32 difference = r6->size - totalSize; // r0
if (difference < 0x40) {
// this heap has reached its memory limit, so
// remove r6 node from doubly linked list
Cell *nextCell = r6->next;
if (nextCell)
nextCell->prev = r6->prev;
Cell *prevCell = r6->prev;
if (!prevCell)
r3 = r6->next;
else
prevCell->next = r6->next;
r5->start = r3;
} else {
// REPLACE r6 node with r6SizeShifted node in the
// linked list. Set the new node's size to be the
// amount of bytes remaining
r6->size = totalSize;
Cell *r6SizeShifted = (Cell *)((u32)r6 + totalSize); // r4
r6SizeShifted->size = difference;
r6SizeShifted->prev = r6->prev;
Cell *r6Next = r6->next;
r6SizeShifted->next = r6Next;
if (r6Next) {
r6Next->prev = r6SizeShifted;
}
// connect doubly linked list
if (r6SizeShifted->prev)
r6SizeShifted->prev->next = r6SizeShifted;
else
r5->start = r6SizeShifted;
}
// Make the r6 node the new head of another linked list
// headed by r5->freeList
Cell *fList = r5->freeList;
r6->next = fList;
r6->prev = NULL;
if (fList) {
fList->prev = r6;
}
r5->freeList = r6;
return (void*)((u32)r6 + 32);
}
void OSFreeToHeap(OSHeapHandle heap, void *ptr)
{
// heap block has a 32-byte header preceding the real data
Cell *node = (Cell *)((u32)ptr - 32); // r4
unkStruct *r31 = &gUnk8063fa78[heap];
Cell *r3 = r31->freeList;
// removing node from freeList
Cell *r6 = node->next;
if (r6) {
r6->prev = node->prev;
}
Cell *r5 = node->prev;
if (!r5) {
r3 = node->next;
} else {
r5->next = node->next;
}
r31->freeList = r3; // new head
r31->start = DLInsert(r31->start, node);
}