chiark / gitweb /
Initial revision
[ssr] / StraySrc / Dynamite / dynamite / s / dynArea
1 ;
2 ; dynArea.s
3 ;
4 ; The handling of the dynamic area itself
5 ;
6 ; © 1994-1998 Straylight
7 ;
8 ;----- Licensing note -------------------------------------------------------
9 ;
10 ; This file is part of Straylight's Dynamite
11 ;
12 ; Dynamite is free software; you can redistribute it and/or modify
13 ; it under the terms of the GNU General Public License as published by
14 ; the Free Software Foundation; either version 2, or (at your option)
15 ; any later version.
16 ;
17 ; Dynamite is distributed in the hope that it will be useful,
18 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ; GNU General Public License for more details.
21 ;
22 ; You should have received a copy of the GNU General Public License
23 ; along with Dynamite.  If not, write to the Free Software Foundation,
24 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26
27 ;----- Standard header ------------------------------------------------------
28
29                 GET     libs:header
30                 GET     libs:swis
31
32                 GET     libs:stream
33
34 ;----- External dependencies ------------------------------------------------
35
36                 GET     sh.wSpace
37
38 ;----- Main code ------------------------------------------------------------
39
40                 AREA    |Dynamite$$Code|,CODE,READONLY
41
42 ; --- da_findPage ---
43 ;
44 ; On entry:     R2 == address of the page
45 ;
46 ; On exit:      R0 == page number
47 ;
48 ; Use:          Finds the page number of the page with the address given.
49
50                 EXPORT  da_findPage
51 da_findPage     ROUT
52
53                 STMFD   R13!,{R1,R7-R9,R14}     ;Stack the link
54                 LDR     R14,dyn_machine         ;Load the machine type
55                 CMP     R14,#&A3                ;RISC OS 3?
56                 BCS     %10da_findPage          ;Yes -- jump ahead then
57
58                 LDR     R9,dyn_pageCount        ;Load number of pages-1
59                 MOV     R14,#&164               ;Find CAM map (RO 2 and 3!)
60                 ADD     R9,R14,R9,LSL #2        ;Last valid entry
61                 MOV     R8,R2,LSL #4            ;The address of interest << 4
62                 SUB     R7,R14,#4               ;We're pre-indexing
63 00da_findPage   CMP     R7,R9                   ;Have we finished?
64                 LDRNE   R1,[R7,#4]!             ;Load out the entry
65                 TEQNE   R8,R1,LSL #4            ;Is this a match?
66                 BNE     %00da_findPage          ;No -- keep on looking
67                 TEQ     R8,R1,LSL #4            ;Was that a match?
68                 SUBEQ   R7,R7,R14               ;Yes -- get offset from base
69                 MOVEQ   R0,R7,LSR #2            ;And turn into page number
70                 MOVNE   R0,#-1                  ;Otherwise return -1
71                 LDMFD   R13!,{R1,R7-R9,PC}^     ;Return to caller
72
73                 ; --- We are on RISC OS 3 ---
74
75 10da_findPage   MOV     R1,#0                   ;Start at this page
76                 MOV     R14,#-1                 ;Get a terminator
77                 STMDB   R13!,{R1,R2,R3,R14}     ;Store that in block
78                 MOV     R0,R13                  ;Point to the block
79                 SWI     OS_FindMemMapEntries    ;Find the page number
80                 LDR     R0,[R13],#16            ;Load the page number
81                 LDMFD   R13!,{R1,R7-R9,PC}^     ;Return to caller
82
83                 LTORG
84
85 ; --- da_addPages ---
86 ;
87 ; On entry:     R0 == number of pages to add
88 ;               R12 == workspace address
89 ;
90 ; On exit:      Possible error returned
91 ;
92 ; Use:          Increases the size of the dynamic area by the number of
93 ;               pages given in R0
94
95                 EXPORT  da_addPages
96 da_addPages     ROUT
97
98                 STMFD   R13!,{R0-R9,R14}        ;Save some registers
99
100                 LDR     R9,dyn_machine          ;What machine are we on?
101                 CMP     R9,#&A5                 ;Is it a RISC PC?
102                 BGE     %50da_addPages          ;Yes -- do things differently
103
104                 MOVS    R9,R0                   ;Remember this value
105                 BEQ     %10da_addPages          ;Nothing to do -- return
106                 LDR     R14,dyn_sprSize         ;Get address of spr area size
107                 LDR     R14,[R14]               ;Get the size out
108                 LDR     R1,dyn_areaSize         ;Find our area size
109                 SUB     R4,R14,R1               ;Find top of system sprites
110                 ADD     R2,R4,#&01400000        ;Top of sprite area
111
112                 LDR     R3,dyn_log2PageSize     ;Find page size of machine
113                 MOV     R5,R9,LSL R3            ;Find size in bytes
114                 LDR     R3,dyn_pageSize         ;Find real page size
115                 MOV     R1,R5                   ;We want this in R1 too
116                 MOV     R0,#3                   ;Change sprite area size
117                 SWI     XOS_ChangeDynamicArea   ;Yes... do it now!
118                 BVS     %99da_addPages          ;Error -- return
119
120                 ; --- Make sure system sprite size remains the same ---
121
122                 MOV     R14,#&01400000          ;Get address of sprite area
123                 STR     R4,[R14,#0]             ;Get system sprite size
124
125                 ; --- Work out how big dynamite area is now ---
126
127                 LDR     R14,dyn_areaSize        ;Get the previous size
128                 RSB     R8,R14,#&01800000       ;Put new blocks here
129                 ADD     R14,R14,R5              ;The new size
130                 STR     R14,dyn_areaSize        ;Save this size back
131
132                 ; --- Now we need to map up the area ---
133
134                 SUB     R13,R13,#16             ;Get me a mem map block
135                 MOV     R14,#0                  ;A nice 0 thing
136                 STR     R14,[R13,#8]            ;Protection level
137                 MOV     R14,#-1                 ;The terminator
138                 STR     R14,[R13,#12]           ;Put that in the block
139 00da_addPages   SUB     R8,R8,R3                ;Next page goes here
140                 BL      da_findPage             ;Find page number of R2
141                 STR     R0,[R13,#0]             ;Store the page number
142                 STR     R8,[R13,#4]             ;Put that page here please
143                 MOV     R0,R13                  ;Point to the block
144                 SWI     XOS_SetMemMapEntries    ;Set mem map entries
145                 SUBS    R9,R9,#1                ;Reduce page count
146                 ADD     R2,R2,R3                ;Now move next page
147                 BGT     %00da_addPages          ;Keep doing that then
148                 ADD     R13,R13,#16             ;Get the block back
149
150                 ; --- Phew! -- almost there ---
151
152                 CMP     R4,#0                   ;Is there a sprite area?
153                 MOVNE   R4,#&01400000           ;Yes -- get its address
154                 MOV     R14,#&1000              ;VDU driver workspace
155                 STR     R4,[R14,#1364]          ;And store as sprite area ptr
156
157 10da_addPages   LDMFD   R13!,{R0-R9,PC}^        ;Return to caller
158
159                 ; --- We are on a RISC PC ---
160
161 50da_addPages   LDR     R1,dyn_log2PageSize     ;Get the log 2 page size
162                 MOV     R1,R0,LSL R1            ;Work out increment
163                 LDR     R0,dyn_areaHandle       ;Load the area handle
164                 SWI     XOS_ChangeDynamicArea   ;And increase appropriately
165                 LDRVC   R14,dyn_areaSize        ;Load the old area size
166                 ADDVC   R14,R14,R1              ;Apply our increment to it
167                 STRVC   R14,dyn_areaSize        ;And save it back again
168                 LDMVCFD R13!,{R0-R9,PC}^        ;Return to caller
169
170 99da_addPages   LDMFD   R13!,{R0-R9,R14}        ;Load back registers
171                 ADR     R0,da__noMem            ;Point to error
172                 ORRS    PC,R14,#V_flag          ;Return with error
173
174 da__noMem       DCD     1
175                 DCB     "No pages left",0
176
177 ; --- da_removePages ---
178 ;
179 ; On entry:     R0 == number of pages to remove
180 ;
181 ; On exit:      --
182 ;
183 ; Use:          Removes the given number of pages from the dynamite
184 ;               area. If the number of pages to remove is greater than
185 ;               the actual number of pages allocated, as many as possible
186 ;               are removed
187
188                 EXPORT  da_removePages
189 da_removePages  ROUT
190
191                 STMFD   R13!,{R0-R10,R14}       ;Stack some registers
192
193                 LDR     R9,dyn_machine          ;What machine are we on?
194                 CMP     R9,#&A5                 ;Is it a RISC PC?
195                 BGE     %50da_removePages       ;Yes -- do things differently
196
197                 MOV     R9,R0                   ;Remember this value
198                 LDR     R8,dyn_areaSize         ;Get my area size
199                 RSB     R2,R8,#&01800000        ;The lowest page
200
201                 LDR     R5,dyn_log2PageSize     ;Get the page size
202                 MOV     R7,R8,LSR R5            ;Number of dynamite pages
203                 CMP     R9,R7                   ;Are we in range?
204                 MOVGT   R9,R7                   ;No -- we are now
205                 CMP     R9,#0                   ;Are we removing 0 pages?
206                 BEQ     %99da_removePages       ;Yes -- return now
207
208                 LDR     R14,dyn_sprSize         ;Get address of spr area size
209                 LDR     R14,[R14]               ;Get the size out
210                 LDR     R1,dyn_areaSize         ;Find our area size
211                 SUB     R10,R14,R1              ;Find top of system sprites
212                 ADD     R6,R10,#&01400000       ;Top of sprite area
213
214                 SUB     R14,R8,R9,LSL R5        ;The new dynamite size
215                 STR     R14,dyn_areaSize        ;Store this away nicely
216
217                 ; --- Now we need to map down the area ---
218
219                 LDR     R3,dyn_pageSize         ;Get the page size
220                 MOV     R4,R9                   ;Look after the page count
221                 SUB     R13,R13,#16             ;Get me a mem map block
222                 MOV     R14,#0                  ;A nice 0 thing
223                 STR     R14,[R13,#8]            ;Protection level
224                 MOV     R14,#-1                 ;The terminator
225                 STR     R14,[R13,#12]           ;Put that in the block
226 00              BL      da_findPage             ;Find page number of R2
227                 STR     R0,[R13,#0]             ;Store the page number
228                 STR     R6,[R13,#4]             ;Put that page here please
229                 MOV     R0,R13                  ;Point to the block
230                 SWI     XOS_SetMemMapEntries    ;Set mem map entries
231                 ADD     R2,R2,R3                ;Now move next page
232                 ADD     R6,R6,R3                ;Put the next one here
233                 SUBS    R9,R9,#1                ;Reduce page count
234                 BGT     %00da_removePages       ;Keep doing that then
235                 ADD     R13,R13,#16             ;Get the block back
236
237                 CMP     R10,#0                  ;Was there an area before
238                 BNE     %10da_removePages       ;Yes -- all ok then
239                 LDR     R6,dyn_sprSize          ;Get address of spr area size
240                 LDR     R6,[R6]                 ;Get the size out
241                 MOV     R7,#0                   ;Sprite area header
242                 MOV     R8,#16
243                 MOV     R9,#16
244                 MOV     R2,#&1400000            ;Point to sprite area
245                 STMIA   R2,{R6-R9}              ;Store the header
246
247 10              MOV     R1,R4,LSL R5            ;We reduce by this amount
248                 RSB     R1,R1,#0                ;Make it negative
249                 MOV     R0,#3                   ;Change sprite area size
250                 SWI     XOS_ChangeDynamicArea   ;Remove those damn pages
251                 B       %99da_removePages       ;Return to caller
252
253                 ; --- We're on a RISC PC ---
254
255 50              LDR     R1,dyn_log2PageSize     ;Get the log 2 page size
256                 MOV     R1,R0,LSL R1            ;Work out increment
257                 RSB     R1,R1,#0                ;Negate it nicely
258                 LDR     R0,dyn_areaHandle       ;Load the area handle
259                 SWI     XOS_ChangeDynamicArea   ;And increase appropriately
260                 LDR     R14,dyn_areaSize        ;Load the current size
261                 SUB     R14,R14,R1              ;How much was it altered by?
262                 STR     R14,dyn_areaSize        ;And save that back
263
264 99              LDMFD   R13!,{R0-R10,PC}^       ;Return to caller
265
266                 LTORG
267
268
269 ; --- da_readSize ---
270 ;
271 ; On entry:     --
272 ;
273 ; On exit:      R0 == size of area
274 ;
275 ; Use:          Returns the size of the sprite area (including the
276 ;               dynamite area).
277
278                 EXPORT  da_readSize
279 da_readSize     ROUT
280
281                 LDR     R0,dyn_machine          ;What machine are we on?
282                 CMP     R0,#&A5                 ;Is it a RISC PC?
283                 BGE     %50da_readSize          ;Yes -- do other things
284
285                 LDR     R0,dyn_sprSize          ;Get spr area size pointer
286                 LDR     R0,[R0,#0]              ;Load out the size
287                 MOVS    PC,R14                  ;And return to caller
288
289                 ; --- We're on a RISC PC ---
290
291 50da_readSize   STMFD   R13!,{R1,R14}           ;Stack some registers
292                 MOV     R0,#3                   ;Read size of sprite area
293                 SWI     XOS_ReadDynamicArea     ;Read things out then
294                 MOV     R0,R1                   ;Put size in R0
295                 LDMFD   R13!,{R1,PC}^           ;Return to caller
296
297                 LTORG
298
299 ; --- da_describe ---
300 ;
301 ; On entry:     --
302 ;
303 ; On exit:      R0 == dynamic area number (3 == sprite area)
304 ;               R1 == size of area
305 ;               R2 == total free in area
306 ;
307 ; Use:          Gives back som information on the dynamite area.
308
309                 EXPORT  da_describe
310 da_describe     ROUT
311
312                 LDR     R0,dyn_machine          ;Load out the machine type
313                 CMP     R0,#&A5                 ;Is it a RISC PC?
314                 LDRGE   R0,dyn_areaHandle       ;Yes -- load dynamic area hnd
315                 MOVLT   R0,#-1                  ;No -- return a silly value
316                 LDR     R1,dyn_areaSize         ;Put area size in R1
317                 LDR     R2,dyn_heapSize         ;And heap size in R2
318                 SUB     R2,R1,R2                ;Get size of unused area
319                 MOVS    PC,R14                  ;Return to caller
320
321                 LTORG
322
323 ;----- That's all, folks ----------------------------------------------------
324
325                 END