4 ; Handling of requests for small link blocks (MDW)
6 ; © 1994-1998 Straylight
9 ;----- Licensing note -------------------------------------------------------
11 ; This file is part of Straylight's Sapphire library.
13 ; Sapphire is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
18 ; Sapphire is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ; GNU General Public License for more details.
23 ; You should have received a copy of the GNU General Public License
24 ; along with Sapphire. If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 ;----- Standard header ------------------------------------------------------
32 ;----- External dependencies ------------------------------------------------
38 ;----- Word to the wise -----------------------------------------------------
40 ; Various bits of Sapphire require lots of small blocks for linked lists and
41 ; things. To avoid mangling the heap, we allocate very big blocks and then
42 ; split them up into littler ones. These big blocks just contain lots of
45 ; The data blocks are allocated such that they are just big enough for the
46 ; data -- the caller must specify the actual size of the block when freeing.
47 ; Completely free big blocks just stay in the heap ready to be allocated
48 ; again by this system. They are not returned to the heap.
50 ; We keep a table of pointers to the big block lists for each supported
51 ; block size. This is rather like the `bins' idea in the C library malloc
54 ;----- Main code ------------------------------------------------------------
56 AREA |Sapphire$$Code|,CODE,READONLY
60 ; On entry: R0 == size of block to allocate
62 ; On exit: R0 == pointer to block allocated
65 ; Use: Allocates a block of the size specified, typically very
68 ; If the size is not one of those supported (currently
69 ; supported sizes are 8-40 inclusive in 4 byte increments),
70 ; the behaviour is undefined (but very predictable).
75 STMFD R13!,{R1-R3,R12,R14}
77 ; --- Find the correct table entry ---
79 WSPACE sub__wSpace ;Find my workspace
80 ADD R1,R12,R0 ;Find the entry in the table
82 ; --- Are there any free blocks? ---
84 LDR R2,[R1] ;Get the free list offset
85 CMP R2,#0 ;Are there any free blocks?
86 BEQ %20sub_alloc ;No -- better allocate some
88 ; --- Mess about with the free list and return ---
90 10sub_alloc LDR R0,[R2] ;Get next pointer from block
91 STR R0,[R1] ;This is now first free block
92 MOV R0,R2 ;Return the old free block
93 LDMFD R13!,{R1-R3,R12,R14} ;Restore registers and return
94 BICS PC,R14,#V_flag ;Clear error as we leave
96 ; --- Create a big block ---
98 ; We're now using alloc for this. To avoid extra memory
99 ; usage, we nobble alloc's `extra' word which allows it
100 ; to find the free routine, because we'll never free it
103 20sub_alloc MOV R2,R0 ;Keep the size safe
104 MOV R0,R0,LSL #3 ;Find the chunk size
105 SUB R0,R0,#4 ;This is evil. I don't care
106 BL alloc ;Allocate some memory
107 BCS %90sub_alloc ;If failed, report error
108 SUB R0,R0,#4 ;Gobble alloc's overhead
110 ; --- Now set up the links for the free list ---
112 MOV R14,#0 ;Next free pointer start at 0
113 MOV R3,#8 ;We have 8 blocks to do
114 00 STR R14,[R0],R2 ;Store in next field
115 SUB R14,R0,R2 ;Remember old block pointer
116 SUBS R3,R3,#1 ;Point to previous block
117 BGT %b00 ;If more to do, continue...
119 ; --- The links are set up -- now take off a block ---
121 MOV R2,R14 ;Use last block allocated
122 B %10sub_alloc ;Then allocate as normal
124 ; --- Handle an error ---
126 90 BL alloc_error ;Find the error message
127 LDMFD R13!,{R1-R3,R12,R14} ;Restore registers
128 ORRS PC,R14,#V_flag ;And return the error
134 ; On entry: R0 == pointer to block
135 ; R1 == size of the block
139 ; Use: Frees a block allocated using sub_alloc.
144 STMFD R13!,{R0,R1,R12,R14} ;Preserve registers
146 ; --- Find the correct table entry ---
148 WSPACE sub__wSpace ;Find my workspace
149 ADD R1,R12,R1 ;Find the entry in the table
151 ; --- Mess about with the list ---
153 LDR R14,[R1] ;Get current first block
154 STR R14,[R0] ;Store in newly freed block
155 STR R0,[R1] ;And insert new block in list
156 LDMFD R13!,{R0,R1,R12,PC}^ ;Oh, and return to caller
166 ; Use: Initialises the suballocation system for use.
171 STMFD R13!,{R0-R2,R12,R14} ;Save some registers
172 WSPACE sub__wSpace ;Find my workspace
174 ; --- Am I initialised? ---
176 LDR R14,sub__flags ;Get my flags word
177 TST R14,#sub__INITED ;Test the flag
178 LDMNEFD R13!,{R0-R2,R12,PC}^ ;Yes -- return to caller
180 ; --- Set up the workspace properly ---
182 ORR R14,R14,#sub__INITED ;We are now initialised
183 STR R14,sub__flags ;Store it in the flags
184 ADD R0,R12,#4 ;Point to the table
185 MOV R1,#10*4 ;Number of entries supported
186 MOV R2,#0 ;Zero them all
187 BL mem_set ;Zero-initialise my workspace
188 BL alloc_init ;Make sure alloc is awake
189 LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller
195 ;----- Workspace ------------------------------------------------------------
200 sub__flags # 0 ;Various interesting flags
202 sub__INITED EQU (1<<0) ;Am I initialised?
204 sub__table # 4*10 ;The suballoc root table
206 sub__wSize EQU {VAR}-sub__wStart
208 AREA |Sapphire$$LibData|,CODE,READONLY
215 ;----- That's all folks -----------------------------------------------------