diff options
-rw-r--r-- | arm9/asm/NNS_FND_expheap_s.s | 111 | ||||
-rw-r--r-- | arm9/lib/libnns/include/NNS_FND_heapcommon.h | 8 | ||||
-rw-r--r-- | arm9/lib/libnns/src/NNS_FND_expheap.c | 65 |
3 files changed, 75 insertions, 109 deletions
diff --git a/arm9/asm/NNS_FND_expheap_s.s b/arm9/asm/NNS_FND_expheap_s.s index 494e3c21..d173bef0 100644 --- a/arm9/asm/NNS_FND_expheap_s.s +++ b/arm9/asm/NNS_FND_expheap_s.s @@ -8,6 +8,8 @@ .extern InitMBlock .extern InitExpHeap .extern AllocUsedBlockFromFreeBlock + .extern AllocFromHead + .extern AllocFromTail .text arm_func_start NNS_FndGetSizeForMBlockExpHeap @@ -274,112 +276,3 @@ _020AE0D4: .balign 4 _020AE118: .word 0x00004652 arm_func_end RecycleRegion - - local_arm_func_start AllocFromTail -AllocFromTail: ; 0x020AE11C - stmdb sp!, {r4-r9,lr} - sub sp, sp, #0x4 - add r0, r0, #0x24 - ldrh r4, [r0, #0x12] - mov r3, r1 - mvn lr, #0x0 - and r1, r4, #0x1 - mov r1, r1, lsl #0x10 - movs r1, r1, lsr #0x10 - moveq r5, #0x1 - mov r1, #0x0 - ldr r4, [r0, #0x4] - movne r5, #0x0 - mov r12, r1 - cmp r4, #0x0 - beq _020AE1B0 - sub r2, r2, #0x1 - mvn r2, r2 -_020AE164: - ldr r8, [r4, #0x4] - add r9, r4, #0x10 - add r6, r8, r9 - sub r6, r6, r3 - and r7, r2, r6 - subs r6, r7, r9 - bmi _020AE1A4 - cmp lr, r8 - bls _020AE1A4 - mov r1, r4 - mov lr, r8 - mov r12, r7 - cmp r5, #0x0 - bne _020AE1B0 - cmp r8, r3 - beq _020AE1B0 -_020AE1A4: - ldr r4, [r4, #0x8] - cmp r4, #0x0 - bne _020AE164 -_020AE1B0: - cmp r1, #0x0 - addeq sp, sp, #0x4 - moveq r0, #0x0 - ldmeqia sp!, {r4-r9,pc} - mov r4, #0x1 - mov r2, r12 - str r4, [sp, #0x0] - bl AllocUsedBlockFromFreeBlock - add sp, sp, #0x4 - ldmia sp!, {r4-r9,pc} - arm_func_end AllocFromTail - - local_arm_func_start AllocFromHead -AllocFromHead: ; 0x020AE1D8 - stmdb sp!, {r4-r9,lr} - sub sp, sp, #0x4 - add r0, r0, #0x24 - ldrh r4, [r0, #0x12] - mov r3, r1 - ldr r5, [r0, #0x0] - and r1, r4, #0x1 - mov r1, r1, lsl #0x10 - movs r1, r1, lsr #0x10 - moveq r6, #0x1 - mov r1, #0x0 - movne r6, #0x0 - mov lr, r1 - cmp r5, #0x0 - mvn r4, #0x0 - beq _020AE270 - sub r12, r2, #0x1 - mvn r2, r12 -_020AE220: - add r8, r5, #0x10 - add r7, r12, r8 - and r9, r2, r7 - sub r7, r9, r8 - ldr r8, [r5, #0x4] - add r7, r3, r7 - cmp r8, r7 - blo _020AE264 - cmp r4, r8 - bls _020AE264 - mov r1, r5 - mov r4, r8 - mov lr, r9 - cmp r6, #0x0 - bne _020AE270 - cmp r8, r3 - beq _020AE270 -_020AE264: - ldr r5, [r5, #0xc] - cmp r5, #0x0 - bne _020AE220 -_020AE270: - cmp r1, #0x0 - addeq sp, sp, #0x4 - moveq r0, #0x0 - ldmeqia sp!, {r4-r9,pc} - mov r4, #0x0 - mov r2, lr - str r4, [sp, #0x0] - bl AllocUsedBlockFromFreeBlock - add sp, sp, #0x4 - ldmia sp!, {r4-r9,pc} - arm_func_end AllocFromHead diff --git a/arm9/lib/libnns/include/NNS_FND_heapcommon.h b/arm9/lib/libnns/include/NNS_FND_heapcommon.h index 77473efe..f35bf097 100644 --- a/arm9/lib/libnns/include/NNS_FND_heapcommon.h +++ b/arm9/lib/libnns/include/NNS_FND_heapcommon.h @@ -98,4 +98,12 @@ static inline void FillAllocMemory(NNSiFndHeapHead* pHeapHd, void* address, u32 void NNSi_FndInitHeapHead(NNSiFndHeapHead *pHead, u32 signature, void* heapStart, void* heapEnd, u16 optionFlag); +#define NNSi_FndRoundUp(value, alignment) (((value) + (alignment - 1)) & ~(alignment - 1)) + +#define NNSi_FndRoundUpPtr(ptr, alignment) ((void*)NNSi_FndRoundUp(NNSiGetUIntPtr(ptr), alignment)) + +#define NNSi_FndRoundDown(value, alignment) ((value) & ~(alignment - 1)) + +#define NNSi_FndRoundDownPtr(ptr, alignment) ((void*)NNSi_FndRoundDown(NNSiGetUIntPtr(ptr), alignment)) + #endif //GUARD_NNS_FND_HEAPCOMMON_H diff --git a/arm9/lib/libnns/src/NNS_FND_expheap.c b/arm9/lib/libnns/src/NNS_FND_expheap.c index f5a74dc4..31ea5fbe 100644 --- a/arm9/lib/libnns/src/NNS_FND_expheap.c +++ b/arm9/lib/libnns/src/NNS_FND_expheap.c @@ -36,6 +36,11 @@ static inline void* GetMBlockEndAddr(NNSiFndExpHeapMBlockHead* block) return AddU32ToPtr(GetMemPtrForMBlock(block), block->blockSize);
}
+static inline u16 GetAllocMode(NNSiFndExpHeapHead* pExHeapHd)
+{
+ return NNSi_FndGetBitValue(pExHeapHd->feature, 0, 1);
+}
+
static inline void SetAllocMode(NNSiFndExpHeapHead* pExHeapHd, u16 mode)
{
NNSi_FndSetBitValue(pExHeapHd->feature, 0, 1, mode);
@@ -202,3 +207,63 @@ void* AllocUsedBlockFromFreeBlock(NNSiFndExpHeapHead* pEHHead, NNSiFndExpHeapMBl return mblock;
}
+
+void* AllocFromHead(NNSiFndHeapHead* pHeapHd, u32 size, int alignment)
+{
+ NNSiFndExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd);
+ const BOOL bAllocFirst = GetAllocMode(pExpHeapHd) == 0;
+ NNSiFndExpHeapMBlockHead* pMBlkHd = NULL;
+ NNSiFndExpHeapMBlockHead* pMBlkHdFound = NULL;
+ u32 foundSize = 0xFFFFFFFF;
+ void* foundMBlock = NULL;
+
+ for (pMBlkHd = pExpHeapHd->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext)
+ {
+ void *const mblock = GetMemPtrForMBlock(pMBlkHd);
+ void *const reqMBlock = NNSi_FndRoundUpPtr(mblock, alignment);
+ const u32 offset = GetOffsetFromPtr(mblock, reqMBlock);
+ if (pMBlkHd->blockSize >= size + offset && foundSize > pMBlkHd->blockSize)
+ {
+ pMBlkHdFound = pMBlkHd;
+ foundSize = pMBlkHd->blockSize;
+ foundMBlock = reqMBlock;
+ if (bAllocFirst || foundSize == size)
+ break;
+ }
+ }
+
+ if (!pMBlkHdFound)
+ return NULL;
+
+ return AllocUsedBlockFromFreeBlock(pExpHeapHd, pMBlkHdFound, foundMBlock, size, 0);
+}
+
+void* AllocFromTail(NNSiFndHeapHead* pHeapHd, u32 size, int alignment)
+{
+ NNSiFndExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd);
+ const BOOL bAllocFirst = GetAllocMode(pExpHeapHd) == 0;
+ NNSiFndExpHeapMBlockHead* pMBlkHd = NULL;
+ NNSiFndExpHeapMBlockHead* pMBlkHdFound = NULL;
+ u32 foundSize = 0xFFFFFFFF;
+ void* foundMBlock = NULL;
+
+ for (pMBlkHd = pExpHeapHd->mbFreeList.tail; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadPrev)
+ {
+ void *const mblock = GetMemPtrForMBlock(pMBlkHd);
+ void *const mBlockEnd = AddU32ToPtr(mblock, pMBlkHd->blockSize);
+ void *const reqMBlock = NNSi_FndRoundDownPtr(SubU32ToPtr(mBlockEnd, size), alignment);
+ if (ComparePtr(reqMBlock, mblock) >= 0 && foundSize > pMBlkHd->blockSize)
+ {
+ pMBlkHdFound = pMBlkHd;
+ foundSize = pMBlkHd->blockSize;
+ foundMBlock = reqMBlock;
+ if (bAllocFirst || foundSize == size)
+ break;
+ }
+ }
+
+ if (!pMBlkHdFound)
+ return NULL;
+
+ return AllocUsedBlockFromFreeBlock(pExpHeapHd, pMBlkHdFound, foundMBlock, size, 1);
+}
|