summaryrefslogtreecommitdiff
path: root/programs/sub-suite/free-old.s
blob: 7f75edd6b8b0b2e7dfa8201617b4f9f3ad013037 (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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
.include "declare.s"

.org 0

; free: Free allocated memory.
; Input: A = Pointer to allocated memory.
; Output: none.
; Caller preserved registers: none.
; Callie preserved registers: A, B, Y.

free:
	pha.q		; Preserve A.
	phb.q		; Preserve B.
	phy.q		; Preserve Y.
	pha.q		; Push the pointer argument to the stack.
	and #0		; Reset A.
	tay		; Reset Y.
	sbs #$18	; Allocate 3 local variables onto the stack.
	lda.q sp+25	; Get the passed pointer.
	ora.d sp+29	; Is the passed pointer NULL?
	bne @getrealblk	; No, so get the real block.
	bra @end	; Yes, so we're done.
@getrealblk:
	lda.q sp+25	; Get the passed pointer.
	sec		; Prepare for a non borrowing subtract.
	sbc #8		; Move the passed pointer back by one.
	sta.q sp+25	; Set the first local variable to the start of the used block.
	lda.q (sp+25)	; Get the real block address.
	sta.q sp+25	; Set the passed pointer to the start of the real block.
	ldy #ublk.size	; Get the size of the real block.
	lda.q (sp+25), y;
	sta.q sp+17	; Save the size of the real block.
	clc		; Prepare for a non carrying add.
	adc.q sp+25	; Add the size of the real block with the start of the real block.
	cmp.q heapptr	; Is this block on top of the heap?
	bne @heapadd	; No, so add it to the free block list.
@dectop:
	lda.q sp+25	; Get the block.
	sta.q heapptr	; Set the top of the heap to it.
@chklastblk:
	lda.q heapl	; Get the last free list entry.
	sta.q sp+17	; Copy it into the second local variable.
	ora.d sp+21	; Is the free list empty?
	beq @end	; Yes, so we're done.
	lda.q sp+17	; No, so Get the last free list entry.
	ldy #fblk.size	; Get the size of the block.
	lda.q (sp+17), y;
	clc		; Prepare for a non carrying add.
	adc.q sp+17	; Add the size of the block, with the address of the block entry.
	cmp.q heapptr	; Is the last block on top of the heap?
	bne @end	; No, so we're done.
@delblk:
	lda.q sp+17	; Yes, so remove the last block.
	sta.q heapptr	;
@correctblk:
	ldy #fblk.prev	; Get the previous block.
	lda.q (sp+17), y;
	sta.q sp+25	; Save the previous block for now.
	sta.q heapl	; Set the last block to the previous block.
	ora.d sp+29	; Is the previous block non NULL?
	bne @delnxtblk	; Yes, so delete the next block.
	sta.q heapf	; No, so empty the free list.
	bra @end	; We are done.
@delnxtblk:
	and #0		; Reset A.
	ldy #fblk.next	; Delete the next block.
	sta.q (sp+25), y;
@end:
	ads #$20	; Clean up the stack frame.
	ply.q		; Restore Y.
	plb.q		; Restore B.
	pla.q		; Restore A.
	rts		; End of free.


@heapadd:
	lda.q heapf	; Get the first block.
	sta.q sp+9	; Copy it into the third local variable.
	ora.d sp+13	; Is the free list empty?
	bne @srchflst	; No, so start searching the free list.
@empty:
	ldy #fblk.next	; Clear the next block.
	sta.q (sp+25), y;
	ldy #fblk.prev	; Clear the previous block.
	sta.q (sp+25), y;
	lda.q sp+25	; Reset A.
	sta.q heapf	; Clear the first block entry.
	sta.q heapf	; Clear the last block entry.
	bra @end	; We are done.
@srchflst:
	and #0		; Reset A.
	sta.q sp+1	; Reset the left pointer.
	ldy #fblk.next	; Setup for the loop.
@loop:
	lda.q sp+9	; Get the right pointer.
	cmp.q sp+25	; Is the right pointer at, or below the current block?
	beq @nextright	; Yes, so get the next right pointer.
	bcs @chkrmerge	; No, so do the right block merge.
@nextright:
	sta.q sp+1	; Set the left pointer, to the right pointer.
	lda.q (sp+9), y	; Get the next right pointer.
	sta.q sp+9	; Set the current right pointer to the next right pointer.
	ora.d sp+13	; Is the next right pointer NULL?
	bne @loop	; No, so keep looping.
@st_lmerge2:
	sta.q (sp+25), y; Clear the next block.
	lda.q sp+25	; Get the current block.
	sta.q heapl	; Set the last free block entry to it.
	bra @chklmerge2	; Do the left block merge.
@chkrmerge:
	lda.q sp+25	; Get the current block.
	clc		; Prepare for a non carrying add.
	adc.q sp+17	; Add the size of the current block, to the current block.
	cmp.q sp+9	; Is the right pointer NULL?
	bne @normerge	; No, so don't merge the right block.
@rmerge:
	ldy #fblk.size	; Get the size of the right pointer.
	lda.q sp+17	; Get the size of the current block.
	clc		; Prepare for a non carrying add.
	adc.q (sp+9), y	; Add the size of the current block, with the size of the right pointer.
	sta.q (sp+25), y; Set the size of the current block, to the new size.
@rmerge2:
	ldy #fblk.next	; Get the next right pointer.
	lda.q (sp+9), y	;
	sta.q (sp+25), y; Set the next block, to the next right pointer.
	sta.q sp+17	; Save the next block in the second local variable.
	ora.d sp+21	; Is the next block NULL?
	beq @setheapl	; Yes, so set the last block.
@setprev:
	lda.q sp+25	; Get the current block.
	ldy #fblk.prev	; Set the previous block to the current block.
	sta.q (sp+17), y;
	bra @chklmerge	; Do the left block merge.
@setheapl:
	lda.q sp+25	; Get the current block.
	sta.q heapl	; Set the last block to the current block.
	bra @chklmerge	; Do the left block merge.
@normerge:
	lda.q sp+9	; Get the right pointer.
	ldy #fblk.next	; Set the next block to the right pointer.
	sta.q (sp+25), y;
	lda.q sp+25	; Get the current block.
	ldy #fblk.prev	; Set the previous right pointer to the current block.
	lda.q (sp+9), y	;
@chklmerge:
	lda.q sp+1	; Get the left pointer.
	ora.d sp+5	; Is the left pointer NULL?
	bne @chklmerge2	; No, so keep checking.
@newstart:
	ldy #fblk.prev	; Clear the previous block.
	sta.q (sp+25), y;
	lda.q sp+25	; Get the current block.
	sta.q heapf	; Set the first block, to the current block.
	bra @end2	; We are done.
@chklmerge2:
	ldy #fblk.size	; Get the size of the left block.
	lda.q (sp+1), y	;
	clc		; Prepare for a non carrying add.
	adc.q sp+1	; Add the size of the left block, to the left pointer.
	cmp.q sp+25	; Is the left block adjacent?
	bne @nolmerge	; No, so don't merge the left block.
@lmerge:
	lda.q (sp+1), y	; Get the size of the left block.
	clc		; Prepare for a non carrying add.
	ldb.q (sp+25), y; Get the size of the current block.
	adc b		; Add the size of the left block, with the size of the current block.
	sta.q (sp+1), y	; Set the size of the left block to the new size.
@lmerge2:
	ldy #fblk.next	; Get the next block.
	lda.q (sp+25), y;
	sta.q (sp+1), y	; Set the next left pointer, to the next block.
	sta.q sp+17	; Set the second local variable to the next block.
	ora.d sp+21	; Is the next left pointer NULL?
	beq @newlast	; Yes, so set the last block.
@lprev:
	lda.q sp+1	; Get the left pointer.
	ldy #fblk.prev	; Set the next left pointer's previous pointer to the left pointer.
	sta.q (sp+17), y;
	bra @end2	; We are done.
@newlast:
	lda.q sp+1	; Get the left pointer.
	sta.q heapl	; Set the last block, to the left pointer.
	bra @end2	; We are done.
@nolmerge:
	lda.q sp+25	; Get the current block.
	ldy #fblk.next	; Set the next left pointer, to the current block.
	sta.q (sp+1), y	;
@nolmerge2:
	lda.q sp+1	; Get the left pointer.
	ldy #fblk.prev	; Set the previous block, to the left pointer.
	sta.q (sp+25), y;
@end2:
	ads #$20	; Clean up the stack frame.
	ply.q		; Restore Y.
	plb.q		; Restore B.
	pla.q		; Restore A.
	rts		; End of free.

a
q