chiark / gitweb /
JPEG support and other fixes from Nick Clark
[ssr] / StraySrc / Libraries / Sapphire / s / kernel
1 ;
2 ; kernel.s
3 ;
4 ; Sapphire library kernel
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Sapphire library.
12 ;
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)
16 ; any later version.
17 ;
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.
22 ;
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.
26
27 ;----- Standard header ------------------------------------------------------
28
29                 GET     libs:header
30                 GET     libs:swis
31
32                 GET     libs:stream
33
34 ;----- External dependencies ------------------------------------------------
35
36                 [       :LNOT::DEF: sapphire__dynaLink
37
38                 IMPORT  |Image$$RW$$Base|,WEAK
39                 IMPORT  |Image$$RW$$Limit|,WEAK
40                 IMPORT  |Sapphire$$ClientData$$Base|,WEAK
41                 IMPORT  |Sapphire$$ClientData$$Limit|,WEAK
42                 IMPORT  |Sapphire$$ExtTable$$Base|,WEAK
43                 IMPORT  |Sapphire$$ExtTable$$Limit|,WEAK
44
45                 ]
46
47                 IMPORT  |Sapphire$$LibData$$Base|,WEAK
48                 IMPORT  |Sapphire$$LibData$$Limit|,WEAK
49
50 ;----- Main code ------------------------------------------------------------
51
52                 AREA    |Sapphire$$Code|,CODE,READONLY
53
54                 [       :LNOT::DEF: sapphire__dynaLink
55
56 ; --- sapphire_init ---
57 ;
58 ; On entry:     R0 == pointer to application name
59 ;               R1 == application's workspace size
60 ;               R2 == size of stack required
61 ;
62 ; On exit:      R10 == pointer to heap base
63 ;               R11 == pointer to ScratchPad
64 ;               R12 == pointer to application workspace
65 ;               R13 == pointer to full descending stack
66 ;               Other registers are corrupted
67 ;
68 ; Use:          Initialises the Sapphire kernel, sets up the memory map,
69 ;               and allocates workspace for library and client units.  The
70 ;               initialisation performed is fairly minimal; in particular,
71 ;               the library units are not initialised -- you must call
72 ;               sapphire_libInit for this to take place.  This allows you
73 ;               to check command line arguments etc. before initialising
74 ;               the Wimp.
75
76                 EXPORT  sapphire_init
77 sapphire_init   ROUT
78
79                 ADR     R3,sapph__initTable     ;Point to initialisation tbl
80                 B       sapphire_doInit         ;Do main initialisation
81
82                 LTORG
83
84 ; --- sapphire_libInit ---
85 ;
86 ; On entry:     --
87 ;
88 ; On exit:      --
89 ;
90 ; Use:          Initialises the Sapphire library and client units.
91
92                 EXPORT  sapphire_libInit
93 sapphire_libInit ROUT
94
95                 STMFD   R13!,{R0,R14}           ;Save some registers
96                 ADR     R0,sapph__initTable     ;Point to initialisation tbl
97                 BL      sapphire_doLibInit      ;Do library initialisation
98                 LDMFD   R13!,{R0,PC}^           ;Return to caller
99
100                 LTORG
101
102 ; --- sapphire_disable ---
103 ;
104 ; On entry:     R0 == pointer to 0-terminated list of initialise routines
105 ;
106 ; On exit:      --
107 ;
108 ; Use:          Prevents the given initialisation routines from being called.
109 ;               This is mainly useful in the dynamic-linking environment,
110 ;               where all Sapphire units are normally active.  This routine
111 ;               allows you to inactivate units which for example do not
112 ;               have the resources they require, or use up unnecesary
113 ;               memory.
114
115                 EXPORT  sapphire_disable
116 sapphire_disable ROUT
117
118                 STMFD   R13!,{R1,R14}           ;Save some registers
119                 ADR     R1,sapph__initTable     ;Point to initialisation tbl
120                 BL      sapphire_doDisable      ;Do the disabling bits
121                 LDMFD   R13!,{R1,PC}^           ;Return to caller
122
123                 LTORG
124
125 sapph__initTable
126
127                 DCD     |Image$$RW$$Limit|
128                 DCD     |Sapphire$$ClientData$$Base|
129                 DCD     |Sapphire$$ClientData$$Limit|
130                 DCD     -1
131                 DCD     |Sapphire$$ExtTable$$Base|
132                 DCD     |Sapphire$$ExtTable$$Limit|
133
134                 ]
135
136 ; --- sapphire_doInit ---
137 ;
138 ; On entry:     R0 == pointer to application name
139 ;               R1 == client workspace size
140 ;               R2 == requested stack size
141 ;               R3 == pointer to initialisation table
142 ;
143 ; On exit:      R10 == base address of Sapphire heap
144 ;               R11 == pointer to scratchpad and global data
145 ;               R12 == pointer to client global workspace
146 ;               R13 == pointer to a full descendion stack
147 ;
148 ; Use:          Performs initialisation of the Sapphire library and the
149 ;               client's sections.  This is intended for use by the Sapphire
150 ;               stub, while initialising the dynamically linked version of
151 ;               Sapphire.
152
153                 EXPORT  sapphire_doInit
154 sapphire_doInit ROUT
155
156                 ; --- Stash arguments in high registers ---
157
158                 MOV     R6,R0                   ;Pointer to application name
159                 MOV     R5,R1                   ;Client's workspace size
160                 MOV     R7,R2                   ;Client's stack size
161                 MOV     R8,R3                   ;Pointer to intialise table
162
163                 ; --- Find the top of our memory area ---
164
165                 SWI     OS_GetEnv               ;Find the memory limit
166                 MOV     R13,R1                  ;This will do as a stack
167                 LDR     R12,[R8],#4             ;Load the application end
168
169                 ; --- Set up workspace allocation registers ---
170
171                 ADD     R9,R12,#sapph__wSize    ;Allocate my workspace
172                 ADD     R7,R7,#3                ;Make sure stack size...
173                 BIC     R7,R7,#3                ;... is word aligned
174                 CMP     R7,#sapph__minStack     ;Is his stack big enough?
175                 SUBCC   R10,R13,#sapph__minStack ;No -- allocate it big
176                 SUBCS   R10,R13,R7              ;Yes -- allocate his amount
177
178                 CMP     R9,R10                  ;Do we have enough memory?
179                 BCS     %90sapphire_doInit      ;No -- complain then
180
181                 ; --- Now find out how much we need ---
182
183                 STMFD   R13!,{R5,R6,R14}        ;Save some registers
184                 ADD     R5,R5,#3                ;Amount of workspace required
185                 BIC     R5,R5,#3                ;Make sure it's aligned
186                 MOV     R6,#20                  ;Space below R11 used so far
187                 MOV     R7,#256                 ;Force scratchpad to 256
188
189                 ADR     R4,sapph__ownTable      ;Point to the internal table
190                 LDMIA   R4,{R0,R1}              ;Load the base and limit
191                 BL      sapph__readSize         ;Work out sizes here
192
193                 MOV     R4,R8                   ;Point to init table
194 00              LDMIA   R4!,{R0,R1}             ;Load the base and limit
195                 CMP     R0,#-1                  ;Is it the end of the table?
196                 BLNE    sapph__readSize         ;No -- work out the sizes
197                 BNE     %00sapphire_doInit      ;And go back for more
198
199                 SUB     R4,R4,#4                ;We went a little too far
200                 LDMIA   R4,{R3,R4}              ;Load these values out
201 05              CMP     R3,R4                   ;Reached the end yet?
202                 BCS     %09sapphire_doInit      ;Yes -- skip onwards
203                 MOV     R14,PC                  ;Set up return address
204                 LDR     PC,[R3],#4              ;Get next return address
205                 CMP     R2,R6                   ;Need more space below R11?
206                 MOVHI   R6,R2                   ;Yes -- then increase size
207                 BL      sapph__readSize         ;Work out the sizes here
208                 B       %05sapphire_doInit      ;And go back for more
209
210                 ; --- Make initial allocations ---
211
212 09              SUB     R11,R10,R7              ;Allocate the scratchpad
213                 SUB     R10,R11,R6              ;And allocate workspace ptrs
214
215                 ADD     R1,R9,R5                ;Add on workspace reqments
216                 SUBS    R3,R10,R1               ;Do we have enough memory?
217                 BCC     %90sapphire_doInit      ;No -- make an error then
218
219                 ; --- Set up initial contents of magic area ---
220
221                 LDR     R0,[R13,#4]             ;Load application name ptr
222                 ADD     R7,R13,#12              ;Find stack base address
223                 STMDB   R11,{R0,R1,R7,R9}       ;Save values in the area
224
225                 ; --- Initialise the heap ---
226
227                 MOV     R0,#0                   ;Initialise a heap area
228                 SWI     OS_Heap                 ;Set it up then
229
230                 ; --- Set up kernel workspace ---
231
232                 MOV     R0,#0                   ;No global areas allocated
233                 STR     R0,sapph__globCnt       ;So clear the counter value
234
235                 ; --- Now start setting up workspace ---
236
237                 MOV     R7,#0                   ;Current workspace offset
238                 MOV     R2,#4                   ;Current R11 negative offset
239
240                 ADR     R6,sapph__ownTable      ;Point to internal table
241                 LDMIA   R6,{R0,R1}              ;Load the base and limit
242                 BL      sapph__setWSpace        ;Set up the workspace for it
243
244 10              LDMIA   R8!,{R0,R1}             ;Load the base and limit
245                 CMP     R0,#-1                  ;Is this the end yet?
246                 BLNE    sapph__setWSpace        ;No -- set up workspace
247                 BNE     %10sapphire_doInit      ;And go back round again
248
249                 ; --- Allocate the client's workspace ---
250
251                 ADD     R9,R9,R7                ;Find current workspace pos
252                 LDMIA   R13!,{R5,R6}            ;Load workspace size back
253                 STR     R9,sapph_clientWS       ;Save client workspace ptr
254                 ADD     R9,R9,R5                ;Move past client work size
255                 MOV     R7,#0                   ;Clear offset now
256
257                 ; --- Now allocate workspace for extensions ---
258
259                 SUB     R8,R8,#4                ;We overshot at the end
260                 LDMIA   R8,{R5,R6}              ;Load the values out
261 15              CMP     R5,R6                   ;Have we finished yet?
262                 BCS     %19sapphire_doInit      ;Yes -- skip out then
263                 MOV     R14,PC                  ;Set up return address
264                 LDR     PC,[R5],#4              ;Call the routine
265                 ADD     R9,R9,R7                ;Get updated workspace offset
266                 STR     R9,[R11,-R2]            ;Save in magic place
267                 MOV     R7,#0                   ;No offset set up yet
268                 BL      sapph__setWSpace        ;Set up its workspace
269                 B       %15sapphire_doInit      ;And go back round again
270
271                 ; --- That's it -- we're done ---
272
273 19              LDR     R12,sapph_clientWS      ;Load client's workspace
274                 LDR     R10,sapph_heapBase      ;Load the heap base too
275                 LDMFD   R13!,{PC}^              ;Return to caller
276
277                 ; --- Not enough memory to start up ---
278
279 90              ADR     R0,sapph__noMem         ;Point to the error message
280                 SWI     OS_GenerateError        ;Generate the error
281
282 sapph__ownTable DCD     |Sapphire$$LibData$$Base|
283                 DCD     |Sapphire$$LibData$$Limit|
284
285 sapph__noMem    DCD     0
286                 DCB     "Not enough memory to initialise",0
287
288                 LTORG
289
290 ; --- sapph__readSize ---
291 ;
292 ; On entry:     R0 == base of initialisation block
293 ;               R1 == limit of initialisation block
294 ;               R5 == amount of workspace required so far
295 ;               R7 == required size of scratchpad
296 ;
297 ; On exit:      R5, R7 updated as necessary
298 ;
299 ; Use:          Adjusts workspace parameters given an initialisation block.
300
301 sapph__readSize ROUT
302
303                 STMFD   R13!,{R0-R4,R14}        ;Save some registers
304 00              CMP     R0,R1                   ;Have we finished yet?
305                 LDMCSFD R13!,{R0-R4,PC}^        ;Yes -- then return
306                 LDMIA   R0!,{R2-R4,R14}         ;Load values from block
307                 ADD     R2,R2,#3                ;Make sure workspace is...
308                 BIC     R2,R2,#3                ;... word aligned
309                 ADD     R5,R5,R2                ;Incrment offset nicely
310                 CMP     R4,R7                   ;Is scratchpad big enough?
311                 MOVHI   R7,R4                   ;No -- make it bigger then
312                 B       %00sapph__readSize      ;And go back for the rest
313
314                 LTORG
315
316 ; --- sapph__setWSpace ---
317 ;
318 ; On entry:     R0 == base of initialisation block
319 ;               R1 == limit of initialisation block
320 ;               R7 == current workspace offset
321 ;               R9 == workspace chunk base address
322 ;
323 ; On exit:      R7 updated
324 ;
325 ; Use:          Lays out workspace and sets up workspace offsets.
326
327 sapph__setWSpace ROUT
328
329                 STMFD   R13!,{R0-R4,R14}        ;Save some registers
330 00              CMP     R0,R1                   ;Have we finished yet?
331                 LDMCSFD R13!,{R0-R4,PC}^        ;Yes -- then return
332                 LDMIA   R0!,{R2-R4,R14}         ;Load values from block
333                 ADD     R2,R2,#3                ;Make sure workspace is...
334                 BICS    R2,R2,#3                ;... word aligned
335                 STRNE   R7,[R3,#0]              ;If any wanted, save offset
336                 MOVNE   R14,#0                  ;Zero the first word
337                 STRNE   R14,[R7,R9]             ;Save that in there
338                 ADD     R7,R7,R2                ;And move pointer on
339                 B       %00sapph__setWSpace     ;And keep on going round
340
341                 LTORG
342
343 ; --- sapphire_doLibInit ---
344 ;
345 ; On entry:     R0 == address of library initialisation table
346 ;
347 ; On exit:      --
348 ;
349 ; Use:          Initialises all currently uninitialised library units.
350
351                 EXPORT  sapphire_doLibInit
352 sapphire_doLibInit ROUT
353
354                 STMFD   R13!,{R0-R4,R14}        ;Save some registers
355                 ADD     R4,R0,#4                ;Look after this pointer
356
357                 ADR     R0,sapph__ownTable      ;Point to our own init table
358                 LDMIA   R0,{R0,R1}              ;Load base and limit
359                 LDR     R2,sapph_workspace      ;Load workspace base address
360                 BL      sapph__init             ;Initialise from block
361
362 00              LDMIA   R4!,{R0,R1}             ;Load values from the block
363                 CMP     R0,#-1                  ;Have we reached the end yet?
364                 BLNE    sapph__init             ;No -- do more initialising
365                 BNE     %00sapphire_doLibInit   ;And go round again
366
367                 SUB     R4,R4,#4                ;We overshot a bit
368                 LDMIA   R4,{R3,R4}              ;Load extension table values
369 05              CMP     R3,R4                   ;Have we finished yet?
370                 BCS     %09sapphire_doLibInit   ;Yes -- skip out then
371                 MOV     R14,PC                  ;Set up return address
372                 LDR     PC,[R3],#4              ;Call finding routine
373                 LDR     R2,[R11,-R2]            ;Load workspace base address
374                 BL      sapph__init             ;Do more initialising
375                 B       %05sapphire_doLibInit   ;And go back round for more
376
377 09              LDMFD   R13!,{R0-R4,PC}^        ;And return to caller
378
379                 LTORG
380
381 ; --- sapph__init ---
382 ;
383 ; On entry:     R0 == pointer to base of initialise table
384 ;               R1 == pointer to limit of initialise table
385 ;               R2 == base of workspace chunk
386 ;
387 ; On exit:      --
388 ;
389 ; Use:          Initialises currently uninitialised library units.
390
391 sapph__init     ROUT
392
393                 STMFD   R13!,{R0-R7,R14}        ;Save some registers
394                 MOV     R3,R0                   ;Look after this pointer
395                 LDR     R0,sapph_appName        ;Find application's name
396 00              CMP     R3,R1                   ;Have we finished yet?
397                 LDMCSFD R13!,{R0-R7,PC}^        ;Yes -- then return
398                 LDMIA   R3!,{R4-R7}             ;Load values from block
399                 CMP     R7,#0                   ;Is there a init routine?
400                 MOVNE   R14,PC                  ;Yes -- set up return address
401                 MOVNE   PC,R7                   ;And call the routine
402                 B       %00sapph__init          ;And go round again
403
404                 LTORG
405
406 ; --- sapphire_doDisable ---
407 ;
408 ; On entry:     R0 == pointer to list of initialise routines to disable
409 ;               R1 == pointer to initialisation table
410 ;
411 ; On exit:      --
412 ;
413 ; Use:          Prevents the given initialisation routines from being
414 ;               called.  This is mainly useful in a dynamically linked
415 ;               environment.
416
417                 EXPORT  sapphire_doDisable
418 sapphire_doDisable ROUT
419
420                 STMFD   R13!,{R0-R7,R14}        ;Save some registers
421                 MOV     R7,R0                   ;Keep pointer safe
422                 ADD     R6,R1,#4                ;Point to initialise table
423
424 00              LDR     R5,[R7],#4              ;Load next entry to remove
425                 TEQ     R5,#0                   ;Is this the end yet?
426                 BEQ     %90sapphire_doDisable   ;Yes -- then return
427
428                 LDR     R14,[R5,#0]             ;Load the first instruction
429                 AND     R0,R14,#&FF000000       ;Get the opcode bits out
430                 CMP     R0,#&EA000000           ;Is this a branch instruction
431                 BICEQ   R14,R14,#&FF000000      ;Yes -- zap instruction bits
432                 ADDEQ   R14,R14,#2              ;Compensate for pipeline
433                 ADDEQ   R5,R5,R14,LSL #2        ;And work out destination
434
435                 ; --- Now find this routine somewhere ---
436
437                 ADR     R0,sapph__ownTable      ;Point to our own table
438                 LDMIA   R0,{R0,R1}              ;Load base and limit pointers
439                 LDR     R2,sapph_workspace      ;Load workspace base address
440                 BL      sapph__disable          ;See if it's in there
441                 BCS     %00sapphire_doDisable   ;If so, move to next routine
442
443                 ; --- Try the client table then ---
444
445                 MOV     R4,R6                   ;Point to init table
446 05              LDMIA   R4!,{R0,R1}             ;Load the values out
447                 CMP     R0,#0                   ;Have I finished here yet?
448                 BEQ     %09sapphire_doDisable   ;Yes -- skip out then
449                 BL      sapph__disable          ;See if it's in there
450                 BCS     %00sapphire_doDisable   ;If so, move to next routine
451                 B       %05sapphire_doDisable   ;Else try the next lot
452
453                 ; --- Now try the external table ---
454
455 09              SUB     R4,R4,#4                ;We overshot as usual
456                 LDMIA   R4,{R3,R4}              ;Load base and limit out
457 10              CMP     R3,R4                   ;Reached the end yet?
458                 BEQ     %00sapphire_doDisable   ;If so, move to next routine
459                 MOV     R14,PC                  ;Set up return address
460                 LDR     PC,[R3],#4              ;Find next init table
461                 LDR     R2,[R11,-R2]            ;Load the workspace base
462                 BL      sapph__disable          ;See if it's in there
463                 BCS     %00sapphire_doDisable   ;If so, move to next routine
464                 B       %10sapphire_doDisable   ;Else try the next lot
465
466                 ; --- Finished all of them ---
467
468 90              LDMFD   R13!,{R0-R7,PC}^        ;Return to caller
469
470                 LTORG
471
472 ; --- sapph__disable ---
473 ;
474 ; On entry:     R0 == base of initialise table
475 ;               R1 == limit of initialise table
476 ;               R2 == base of workspace for table
477 ;               R5 == address of init routine to match
478 ;
479 ; On exit:      CS if routine found, else CC
480 ;               R0 corrupted
481 ;
482 ; Use:          Finds and disables a given initialise routine.
483
484 sapph__disable  ROUT
485
486                 BIC     R14,R14,#C_flag         ;Clear carry flag initially
487                 STMFD   R13!,{R3,R4,R6,R14}     ;Save some registers
488 00              CMP     R0,R1                   ;Reached the end yet?
489                 LDMCSFD R13!,{R3,R4,R6,PC}^     ;Yes -- return sadly then
490                 LDMIA   R0!,{R3,R4,R6,R14}      ;Load values from table
491                 CMP     R3,#0                   ;Is there any workspace?
492                 BEQ     %00sapph__disable       ;No -- ignore this entry
493                 CMP     R14,R5                  ;Is this the routine?
494                 BNE     %00sapph__disable       ;No -- ignore this entry
495                 LDR     R4,[R4,#0]              ;Load workspace offset
496                 MOV     R14,#-1                 ;Set all of the bits
497                 STR     R14,[R2,R4]             ;Save it in workspace
498                 LDMFD   R13!,{R3,R4,R6,R14}     ;Unstack the registers
499                 ORRS    PC,R14,#C_flag          ;And return with C set
500
501                 LTORG
502
503 ; --- sapphire_heapAddr ---
504 ;
505 ; On entry:     --
506 ;
507 ; On exit:      R1 == pointer to the heap base (for passing to OS_Heap)
508 ;
509 ; Use:          Returns the address of the Sapphire heap.
510
511                 EXPORT  sapphire_heapAddr
512 sapphire_heapAddr ROUT
513
514                 LDR     R1,sapph_heapBase
515                 MOVS    PC,R14
516
517                 LTORG
518
519 ; --- sapphire_appName ---
520 ;
521 ; On entry:     --
522 ;
523 ; On exit:      R0 == pointer to application name (NULL terminated)
524 ;
525 ; Use:          Returns a pointer to the application's name.
526
527                 EXPORT  sapphire_appName
528 sapphire_appName ROUT
529
530                 LDR     R0,sapph_appName
531                 MOVS    PC,R14
532
533                 LTORG
534
535 ; --- sapphire_resetStack ---
536 ;
537 ; On entry:     --
538 ;
539 ; On exit:      R13 == stack pointer
540 ;
541 ; Use:          Resets R13 to point to the top of the stack.
542
543                 EXPORT  sapphire_resetStack
544 sapphire_resetStack
545                 ROUT
546
547                 LDR     R13,sapph_stackBase
548                 MOVS    PC,R14
549
550                 LTORG
551
552 ; --- sapphire_global ---
553 ;
554 ; On entry:     R0 == magic identifier for global variable
555 ;               R1 == size of area required
556 ;
557 ; On exit:      R0 == pointer to area
558 ;               CS if the area already exists, CC otherwise
559 ;
560 ; Use:          Locates (and creates if necessary) a `named' global area
561 ;               which can be used for inter-section communication without
562 ;               the necessity for dependencies.
563 ;
564 ;               There is a limit on the number of global areas allowed, but
565 ;               this can be raised fairly easily if necessary.
566 ;
567 ;               If an area can't be created, an error is generated.
568
569                 EXPORT  sapphire_global
570 sapphire_global ROUT
571
572                 ORR     R14,R14,#C_flag         ;Clear C flag normally
573                 STMFD   R13!,{R1-R4,R12,R14}    ;Save some registers
574                 LDR     R12,sapph_workspace     ;Find workspace base address
575                 SUB     R12,R12,#sapph__wSize   ;Subtract to get kernel space
576
577                 ; --- Try and find a matching global name ---
578
579                 ADR     R4,sapph__globals       ;Point to the globals block
580                 LDR     R2,sapph__globCnt       ;Load my current pointer
581                 MOVS    R3,R2                   ;Is it zero?
582                 BEQ     %10sapphire_global      ;If not present, skip ahead
583
584 00              LDR     R14,[R4],#8             ;Load the name of this one
585                 CMP     R0,R14                  ;Is this a match then?
586                 LDREQ   R0,[R4,#-4]             ;Yes -- point to the block
587                 LDMEQFD R13!,{R1-R4,R12,PC}^    ;Yes -- return the pointer
588                 SUBS    R3,R3,#1                ;Decrement the counter
589                 BGT     %00sapphire_global      ;If more left, check 'em
590
591                 ; --- No luck there -- allocate a new one ---
592
593 10              CMP     R3,#sapph__globMax      ;Are we at the limit?
594                 ADRGE   R0,sapph__noGlob        ;Yes -- point to the limit
595                 SWIGE   OS_GenerateError        ;And quit the proggy
596
597                 ADD     R2,R2,#1                ;Bump the global counter
598                 STR     R2,sapph__globCnt       ;Store the counter away
599                 STR     R0,[R4,#0]              ;Store the name of this one
600
601                 MOV     R3,R1                   ;Get the size in R3 nicely
602                 MOV     R0,#2                   ;Allocate a new heap block
603                 LDR     R1,sapph_heapBase       ;Load my heap pointer nicely
604                 SWI     OS_Heap                 ;Allocate the memory now
605                 STR     R2,[R4,#4]              ;Store the pointer for later
606                 MOV     R0,R2                   ;Return the pointer now
607
608                 LDMFD   R13!,{R1-R4,R12,R14}    ;Return to caller
609                 BICS    PC,R14,#C_flag          ;Explaining we had to create
610
611 sapph__noGlob   DCD     1
612                 DCB     "Too many global areas",0
613
614                 LTORG
615
616 ;----- Workspace ------------------------------------------------------------
617
618 ; --- Data relative to R11 ---
619
620                 ^       0,R11
621 sapph__R11      #       0                       ;Make a symbol for R11
622
623 sapph_scratchpad EQU    sapph__R11-0            ;Scratchpad data area
624 sapph_workspace EQU     sapph__R11-4            ;Workspace base address
625 sapph_stackBase EQU     sapph__R11-8            ;The top of the system stack
626 sapph_heapBase  EQU     sapph__R11-12           ;Base address of the heap
627 sapph_appName   EQU     sapph__R11-16           ;Pointer to application name
628 sapph_clientWS  EQU     sapph__R11-20           ;Address of client's space
629
630 sapph__minStack EQU     2048                    ;Minimum acceptable stack
631 sapph__globMax  EQU     5                       ;Maximum global areas allowed
632
633                 ^       0,R12
634 sapph__wStart   #       0
635
636 sapph__globCnt  #       4                       ;Number of global areas
637 sapph__globals  #       8*sapph__globMax        ;The actual global bits
638
639 sapph__wSize    EQU     {VAR}-sapph__wStart
640
641 ;----- That's all, folks ----------------------------------------------------
642
643                 END
644