diff --git a/src/lib/heap.s b/src/lib/heap.s index 62e7be8..e62c779 100644 --- a/src/lib/heap.s +++ b/src/lib/heap.s @@ -2,6 +2,32 @@ # It's slow / unoptimized, and only for # learning how to set up a basic heap +# It's also very messy due to trying to +# avoiding the usage of s registers; +# the point is to improve performance, +# because you don't need extra read & writes, +# which is pretty pointless because this +# is not optimized to be scalable anyways. +# This makes debugging it very fun :) + +# If I were to write this in a sane way, +# I would break up certain parts into functions. +# For example, free would create a new block +# from the old block first, then merge with +# either side using functions. + +# Unfortunately, I am not sane. + +# Also, I tried to allow for memory up to +# 0xffffffffffffffff at some points, +# which of course won't happen anyways +# because of the stack and the fact that +# that address probably won't even exist +# in virtual memory, but not at other points, +# so if you happen to not have a stack and +# the heap gets there, things are prolly +# gonna break due to unsigned comparisons :) + # mask and imask are used to floor & ceil # to get correct bounds .equ align_imask, 0b111 @@ -34,9 +60,14 @@ heap_oom: .string "Heap ran out of memory!\n" 0: +.word 0f - heap_neg_size +heap_neg_size: + .string "Negative size given to alloc!\n" +0: + .section .data -.align 4 +.align 3 .global heap_info # global for testing only .equ heap_last_used, 0 # is the last block used; # matches binfo @@ -78,9 +109,11 @@ heap_init: li a0, 0 jal brk andi a0, a0, align_mask + blt a0, t1, 1f sub t2, a0, t1 # size = end - start (t2) li t3, sizeof_fb bgeu t2, t3, 0f # check if enough mem to start +1: move a1, a0 add a0, t1, t3 @@ -104,6 +137,10 @@ heap_init: addi sp, sp, +8 ret +# TODO: this shouldn't panic if it fails; +# instead return null I guess +# or maybe return status in a1? + # args: # a0 - size # @@ -114,6 +151,12 @@ heap_alloc: addi sp, sp, -8 sd ra, 0(sp) + bgez a0, 0f # panic if negative size + la a0, heap_neg_size + lw a1, -4(a0) + j panic +0: + # align size properly (t0) move t0, a0 @@ -121,6 +164,13 @@ heap_alloc: addi t0, t0, align_imask andi t0, t0, align_mask + # increase size if smaller than free block + + li t1, sizeof_fb + bge t0, t1, 0f + move t0, t1 +0: + # step 1: # get a free block that will fit (t1) # and its free space (t2) @@ -252,11 +302,11 @@ heap_free: # merge with next if possible add t2, a0, t0 # t2 = next block - bge t2, t4, 0f # skip if end + bgeu t2, t4, 0f # skip if end ld t1, binfo(t2) andi t1, t1, size_mask # t1 = next size add t6, t2, t1 # t6 = next next block - blt t6, t4, 1f # if end: + bltu t6, t4, 1f # if end: ld t6, binfo(t3) # t6 = last block is used bnez t6, 0f # skip if used j 2f # if end free, we can use diff --git a/src/test/heap.s b/src/test/heap.s index 21d2f76..3dbadf7 100644 --- a/src/test/heap.s +++ b/src/test/heap.s @@ -27,7 +27,7 @@ hexstr: .global heap_test heap_test: - addi sp, sp, -(7*8) + addi sp, sp, -(8*8) sd ra, 0(sp) sd s0, 8(sp) sd s1, 16(sp) @@ -35,6 +35,7 @@ heap_test: sd s3, 32(sp) sd s4, 40(sp) sd s5, 48(sp) + sd s6, 56(sp) # empty heap @@ -43,7 +44,7 @@ heap_test: # put stuff on heap - li a0, 8*9 + li a0, 8*1 jal heap_alloc move s2, a0 @@ -60,7 +61,7 @@ heap_test: # put array of stuff on heap - li s0, 0x0a + li s0, 0x04 0: bltz s0, 0f @@ -92,6 +93,8 @@ heap_test: move a0, s2 jal heap_free + jal print_heap + jal printnl move a0, s3 jal heap_free move a0, s4 @@ -104,11 +107,12 @@ heap_test: ld ra, 0(sp) ld s0, 8(sp) ld s1, 16(sp) - sd s2, 24(sp) - sd s3, 32(sp) - sd s4, 40(sp) - sd s5, 48(sp) - addi sp, sp, +(7*8) + ld s2, 24(sp) + ld s3, 32(sp) + ld s4, 40(sp) + ld s5, 48(sp) + ld s6, 56(sp) + addi sp, sp, +(8*8) ret print_heap: