Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

168 lines (137 sloc) 3.799 kb
;; Memory allocation.
;; by José Manuel Díez (jdiez)
;; licensed under MIT.
;;
;; http://u.jdiez.me/0x42c/kernel.html#x01e-kern-malloc
;; http://u.jdiez.me/0x42c/kernel.html#x022-kern-free
;; declares: malloc, free
:mem_start dat 0x6000 ; adjust these to your liking.
:mem_end dat 0x7fff
:alloc_init
set a, [mem_start]
set b, [mem_end]
jsr set_initial_blocks
set pc, pop
; void* malloc(int owner, int words)
:malloc
set push, i
set i, [mem_start]
:malloc_loop
ife [i], 0xffff
set pc, malloc_found_free
add i, 1
add i, [i]
add i, 2
set pc, malloc_loop
:malloc_found_free
ife i, [mem_start] ; beginning
set pc, malloc_allocate
add i, 1
ife [i], a
set pc, malloc_prepare
ifg [i], a
set pc, malloc_check_overhead
add i, 1
add i, [i] ; size of block
set pc, malloc_loop
:malloc_check_overhead
set push, b
set b, [i]
sub b, a
ifg b, 3 ; plenty of space for overhead
set pc, malloc_check_end
sub i, 1
set b, pop
set [i], b ; it isn't worth dividing the space
set push, i
set pc, malloc_end
:malloc_check_end
set b, pop
set pc, malloc_prepare
:malloc_prepare
sub i, 1
set pc, malloc_allocate
:malloc_allocate
set push, i
set push, i
set [i], b
add i, 1
set [i], a
add i, 1
add i, a
set b, pop
set [i], b ; header pointer
add i, 1
set a, i
set b, [mem_end]
jsr set_initial_blocks
set pc, malloc_end
:malloc_end
set a, pop
add a, 2 ; real start of memory
set i, pop
set pc, pop
; void free(void* addr)
:free
sub a, 2 ; user gives the first allocated word, header is two words back
set [a], 0xffff ; free memory
set push, a
:free_check_forward
add a, 1
set b, [a]
add a, b
add a, 2 ; next header
ife [a], 0xffff
set pc, free_merge_forward
:free_check_backwards
set a, peek
sub a, 1
ifg a, [mem_start]
set pc free_check_backwards_continue
set pc, free_end
:free_check_backwards_continue
ife [a], 0x0 ; if previous footer is empty
set pc, free_end
set b, [a]
set a, b
ifn [a], 0xffff
set pc, free_end
set peek, a ; the previous push is unnecesary
add a, 1
set b, [a]
add a, b
add a, 2
set pc, free_merge_forward ; no need to check since we already know there's a blob of free memory there
:free_merge_forward
set [a], 0x0
add a, 1
set b, [a]
set c, b ; previous block length
set [a], 0x0
add a, b
ifn a, [mem_end]
add a, 1 ; footer of this block
set b, pop
set push, b ; we'll need it at the end
set [a], b
set a, b
add a, 1
set b, [a]
add b, c
add b, 3 ; considering overhead
set [a], b
set pc, free_end
:free_end
set a, pop
set pc, pop
; void set_initial_blocks(void memstart, void memend)
:set_initial_blocks
set push, b
set [a], 0xffff ; owner of free mem
add a, 1
sub b, a
set [a], b ; space available
set b, pop
sub a, 1
set [b], a
set pc, pop
Jump to Line
Something went wrong with that request. Please try again.