blob: 1d87435c2ea1f6346ce7032beed77d3c8df03529 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
; Heap bump allocator implementation
;
; Just below the MMIO segment, which starts at 0xE7F0, is the heap segment. The heap area
; grows down from 0xE7EF until it overlaps with the stack, which grows up from 0x8000.
;
; The stack pointer is stored in register SP, which is the general use register RH by spec.
;
; The interface consists of two functions, bump_alloc and bump_reset.
; The bump_alloc function allocates a block of memory from the heap,
; returning the lowest address of the allocated block.
; The bump_reset function resets the heap to its initial state, freeing all allocated blocks.
;
; To initialize the bump allocator, call bump_reset.
;
; The bump allocator cannot free individual blocks, only reset the entire heap.
;
; The memory layout is as follows:
; 0xE7EF (heap_segment) alloc_next value
; 0xE7EE downwards allocated blocks
;
; The alloc_next value is a pointer to the next free word in the heap.
; It is stored in the first word of the heap.
@label bump_next_p
heap_segment
@label bump_arena_start
${heap_segment - 1}
@label bump_reset
; reset the heap to its initial state (zero allocated blocks)
; can be used to initialize the bump allocator
; parameters: none
; return: void
stack_stash RA RB
ldi bump_arena_start RA ; RA := bump_arena_start pointer
ldr RA RA ; RA := bump_arena_start
ldi bump_next_p RB ; RB := bump_next_p pointer
ldr RB RB ; RB := bump_next_p
str RA RB ; *bump_next_p = bump_arena_start
stack_restore RA RB
return
@label bump_alloc
; allocate a block of memory from the heap, checking for overlap with the stack
; parameters: RA = n of words to allocate
; return: RG = address of allocated block or 0 if allocation failed
stack_stash RB RC
ldi bump_next_p RB ; RB := bump_next_p pointer
ldr RB RB ; RB := bump_next_p
ldr RB RG ; RG := *bump_next_p (address of next free word)
sub RG RA RG ; RG := RG - RA (new alloc_next value)
; check that the new alloc_next value does not overlap with the stack
sub RG SP RC ; RC := RG - SP
bri sign bump_alloc_overlap ; if RC < 0, bump_alloc_overlap
; otherwise allocation ok
@label bump_alloc_ok
str RG RB ; *bump_next_p = RG
inc RG ; RG := RG + 1 (lowest address of allocated block)
jpi bump_alloc_return
@label bump_alloc_overlap
; allocation failed, return 0
ldi 0 RG
@label bump_alloc_return
stack_restore RB RC
return
|