Initial revision
[ssr] / StraySrc / SDLS / DLLManager / s / app
1 ;
2 ; app.s
3 ;
4 ; Handling of application blocks
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Dynamic Linking System (SDLS)
12 ;
13 ; SDLS 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 ; SDLS 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 SDLS. 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 GET sh.wSpace
37 GET sh.appblock
38 GET sh.linkblock
39 GET sh.dllblock
40
41 GET sh.misc
42 GET sh.suballoc
43 GET sh.dll
44
45 GET sh.messages
46
47 ;----- External routines ----------------------------------------------------
48
49 AREA |DLLM$$Code|,CODE,READONLY
50
51 GBLL debug
52 debug SETL {FALSE}
53
54 ; --- app_init ---
55 ;
56 ; On entry: --
57 ; On exit: --
58
59 EXPORT app_init
60 app_init ROUT
61
62 STMFD R13!,{R1,R2,R14} ;Save some registers
63
64 ; --- Save workspace address ---
65 ;
66 ; This is so that app__epilogue can find our workspace.
67
68 STR R12,app__pw ;Store data relocation
69
70 ; --- Now locate the OS's pid word ---
71 ;
72 ; We do this using a table indexed by the OS version on the
73 ; grounds that it's easier to update if the address changes.
74 ; This is unlikely however, since DDEUtils uses this address
75 ; too, and it's right before the VDU driver workspace at
76 ; &1000, which seems to indicate it's there forever.
77
78 MOV R0,#&81 ;Read the OS version number
79 MOV R1,#0 ;Set up the odd arguments
80 MOV R2,#255 ;This is really very strange
81 SWI XOS_Byte ;Do the read operation
82
83 ADR R14,app__verTable ;Point to the table
84 00 LDMIA R14!,{R0,R2} ;Load version and address
85 CMP R0,R1 ;How do the versions compare?
86 BCC %b00 ;No match -- keep going
87
88 STR R2,app__pidAddr ;If matched, store address
89 LDMFD R13!,{R1,R2,PC}^ ;Restore caller's registers
90 BICS PC,R14,#V_flag ;And return to caller
91
92 app__verTable DCD -1,&FF8 ;All versions have PID here
93
94 LTORG
95
96 app__pw DCD 0 ;Where to store private word
97
98 ; --- app_checkQuit ---
99 ;
100 ; On entry: --
101 ; On exit: --
102
103 EXPORT app_checkQuit
104 app_checkQuit ROUT
105
106 LDR R0,app__list ;Get list head pointer
107 CMP R0,#0 ;Are there any applications?
108 MOVEQS PC,R14 ;No -- that's OK then
109 ADRL R0,msg_errInUse ;Point to error
110 ORRS PC,R14,#V_flag ;Return an error
111
112 LTORG
113
114 ; --- app_findDLL ---
115 ;
116 ; On entry: R0 == pointer to name of DLL to find
117 ; R1 == version number to load
118 ; On exit: R0 == DLL handle loaded
119
120 EXPORT app_findDLL
121 app_findDLL ROUT
122
123 STMFD R13!,{R11,R14} ;Stack registers nicely
124 BL app__sFindDLL ;Find the DLL etc.
125 BVC app__ok ;If it worked, make permanent
126 B app__dead ;Otherwise, tidy up
127
128 LTORG
129
130 ; --- app_loseDLL ---
131 ;
132 ; On entry: R0 == pointer to DLL to lose
133 ; On exit: --
134
135 EXPORT app_loseDLL
136 app_loseDLL ROUT
137
138 STMFD R13!,{R1-R3,R11,R14} ;Look after some registers
139 MOV R11,R0 ;Keep hold of pointer
140
141 ; --- Find the application's handle ---
142
143 BL app_getHandle ;Find application's time
144 BLVC app__find ;Find the application block
145 LDMVSFD R13!,{R1-R3,R11,PC} ;Return an error if any
146
147 ; --- Find the link block ---
148
149 MOV R3,R0 ;Keep hold of app pointer
150 MOV R1,R11 ;Point to application
151 BL app__findLink ;Find the link block
152 LDMVSFD R13!,{R1-R3,R11,PC} ;Return an error if any
153
154 ; --- Remove the link block ---
155
156 MOV R1,R0 ;Point to the link block
157 MOV R0,R3 ;Point to the application
158 BL app__freeLink ;Free the link block up
159
160 ; --- Decrement the DLL count ---
161 ;
162 ; This will release the DLL if it no longer has any clients
163
164 MOV R0,R11 ;Point to DLL
165 BL dll_dec ;Decrement its counter
166
167 ; --- Uncache the current link if we've removed it ---
168
169 LDR R0,[R3,#app_cachedll] ;Find which DLL we cached
170 CMP R0,R11 ;Have we just unlinked it?
171 MOVEQ R0,#0 ;Yes -- clear out the handle
172 STREQ R0,[R3,#app_cachedll] ;Won't match any more
173 STREQ R0,[R3,#app_cacheptr]
174
175 ; --- Return, deleting application if necessary ---
176
177 MOV R0,R3 ;Point to application
178 LDMFD R13!,{R1-R3,R11,R14} ;Unstack registers
179 B app__freeUnused ;Kill app block if no DLLs
180
181 LTORG
182
183 ; --- app_setname ---
184 ;
185 ; On entry: R0 == pointer to application's name
186 ; On exit: --
187
188 EXPORT app_setname
189 app_setname ROUT
190
191 STMFD R13!,{R1,R14} ;Store registers and things
192 MOV R1,R0 ;Keep pointer to the name
193 BL app__add ;Make sure the app exists
194
195 ADDVC R0,R0,#app_name ;Point to the name
196 BLVC misc_strcpy ;Copy the string across
197 LDMFD R13!,{R1,PC} ;Return to caller
198
199 LTORG
200
201 ; --- app_fromtable ---
202 ;
203 ; On entry: R0 == pointer to start of external DLL block
204 ; R1 == pointer to limit of same
205 ; On exit: --
206
207 EXPORT app_fromtable
208 app_fromtable ROUT
209
210 STMFD R13!,{R11,R14} ;Look after registers
211 BL app_sfromtbl ;Do primitive operation
212 BVC app__ok ;If it worked, to gadget
213 B app__dead ;If it failed,tidy up
214
215 LTORG
216
217 ; --- app_sfromtbl ---
218 ;
219 ; On entry: R0 == pointer to start of external DLL block
220 ; R1 == pointer to limit of same
221 ; On exit: --
222
223 EXPORT app_sfromtbl
224 app_sfromtbl ROUT
225
226 STMFD R13!,{R1-R5,R10,R11,R14} ;Stack some registers
227
228 MOV R10,R0 ;Keep pointer to base
229 MOV R11,R1 ;Keep pointer to limit
230
231 00app_sfromtbl CMP R10,R11 ;Is there anything to do?
232 LDMEQFD R13!,{R1-R5,R10,R11,PC}^ ;No -- return to caller
233
234 ; --- Load an entry from the table ---
235
236 LDMIA R10!,{R0-R3} ;Load values from table
237 BL app__sFindDLL ;Try to find the DLL
238 LDMVSFD R13!,{R1-R5,R10,R11,PC} ;Return the error if any
239
240 ; --- Fill in the veneer table ---
241
242 MOV R1,R2 ;Point to first name to load
243 MOV R2,R0 ;Keep pointer to DLL base
244 LDR R5,[R2,#dl_entries] ;Load the entry count
245 BIC R4,R5,#&FF000000 ;Clear entry type bits
246
247 01app_sfromtbl LDR R0,[R3,#0] ;Load value from table
248 CMP R0,R4 ;Is it a valid ordinal?
249 BHS %05app_sfromtbl ;No -- look up the name then
250
251 LDR R14,[R2,#dl_eveneer] ;Yes -- load entry point base
252 TST R5,#dl_shortEntries ;Are the entries short?
253 ADDEQ R0,R14,R0,LSL #4 ;No -- find base of veneer
254 LDRNE R0,[R14,R0,LSL #2] ;Yes -- load address
255 B %10app_sfromtbl ;And skip past name lookup
256
257 05app_sfromtbl LDRB R0,[R1] ;Load first byte from string
258 CMP R0,#0 ;Is it a zero (end of list)?
259 BEQ %00app_sfromtbl ;Yes -- do next table entry
260
261 ; --- Find entry point address ---
262
263 MOV R0,R2 ;Point to DLL base
264 BL dll_findEntry ;Find the entry point
265 LDMVSFD R13!,{R1-R5,R10,R11,PC} ;Return the error if any
266 MOV R4,#0 ;Remember to bump name
267
268 ; --- Convert it into a branch ---
269
270 10app_sfromtbl SUB R0,R0,R3 ;Convert to offset from R3
271 SUB R0,R0,#8 ;Subtract 8 (pipeline)
272 MOV R0,R0,LSR #2 ;Shift right to word align
273 BIC R0,R0,#&FF000000 ;Clear top (opcode and cond)
274 ORR R0,R0,#&EA000000 ;Put in BAL (Branch always)
275 STR R0,[R3],#4 ;Store in veneer table
276 CMP R4,#0 ;Did we look up a name?
277 BNE %01app_sfromtbl ;No -- examine next entry pt
278
279 ; --- Find next entry point address ---
280
281 02app_sfromtbl LDRB R0,[R1],#1 ;Load a byte from the name
282 CMP R0,#0 ;Is it the string end?
283 BNE %02app_sfromtbl ;No -- get another
284 B %01app_sfromtbl ;Fill in another entry point
285
286 LTORG
287
288 ; --- app_findNamed ---
289 ;
290 ; On entry: R0 == name of an application
291 ; On exit: R0 == pointer to application block base
292
293 EXPORT app_findNamed
294 app_findNamed ROUT
295
296 STMFD R13!,{R1-R3,R14} ;Preserve registers
297 MOV R1,R0 ;Keep pointer to string
298 LDR R3,app__list ;And load the pointer to list
299
300 00app_findNamed CMP R3,#0 ;Is this the end of the line?
301 BEQ %40app_findNamed ;Yes -- give an error
302 ADD R0,R3,#app_name ;Find the name string
303 MOV R2,#0 ;Caseless compare
304 BL misc_strcmp ;Compare the strings
305 LDRNE R3,[R3,#app_next] ;If no match, move on...
306 BNE %00app_findNamed ;... and try again
307 MOV R0,R3 ;Point to DLL (give handle)
308 LDMFD R13!,{R1-R3,PC}^ ;And return to caller
309
310 40app_findNamed ADRL R0,msg_errAppNotFound ;Couldn't find DLL name
311 BL misc_error ;... create an error message
312 LDMFD R13!,{R1-R3,R14} ;... restore registers
313 ORRS PC,R14,#V_flag ;... and return an error
314
315 LTORG
316
317 ; --- app_setBtable ---
318 ;
319 ; On entry: R0 == pointer to entry point table
320 ; R1 == pointer to name table
321 ; On exit: --
322
323 EXPORT app_setBtable
324 app_setBtable ROUT
325
326 STMFD R13!,{R1,R2,R14} ;Stick 'em on the stack
327 MOV R2,R0 ;Keep this safe
328 BL app__add ;Create an entry for the app
329 STRVC R2,[R0,#app_btable] ;Store the entry table ptr
330 STRVC R1,[R0,#app_nametable] ;Store the name table ptr
331 LDMFD R13!,{R1,R2,PC} ;Return to caller
332
333 LTORG
334
335 ; --- app_appEntry ---
336 ;
337 ; On entry: R0 == pointer to name to find
338 ; On exit: R0 == pointer to entry point
339
340 EXPORT app_appEntry
341 app_appEntry ROUT
342
343 STMFD R13!,{R1,R2,R14} ;Stack registers away
344
345 ; --- Find the application ---
346
347 MOV R2,R0 ;Point to name start
348 BL app_getHandle
349 BLVC app__find ;Try to find the app block
350 LDMVSFD R13!,{R1,R2,PC} ;If not there, error
351
352 ; --- Get the entry table info out ---
353
354 LDR R1,[R0,#app_nametable] ;Find name table address
355 LDR R0,[R0,#app_btable] ;Find entry table address
356 CMP R0,#0 ;Is there no entry table?
357 BEQ %50app_appEntry ;No -- complain about it
358
359 ; --- Find the entry point ---
360
361 BL dll_appEntry ;Do the actual find
362 LDMFD R13!,{R1,R2,PC} ;Return to caller
363
364 ; --- Application has no entry points ---
365
366 50app_appEntry ADRL R0,msg_errAppNoEntry ;Point to error message
367 LDMFD R13!,{R1,R2,R14} ;Unstack registers
368 ORRS PC,R14,#V_flag ;Return the error to caller
369
370 LTORG
371
372 ALIGN
373
374 ; --- app_fixExtension ---
375 ;
376 ; On entry: R0 == pointer to name table
377 ; R1 == pointer to branch table to fill in
378 ; On exit: --
379
380 EXPORT app_fixExtension
381 app_fixExtension
382
383 STMFD R13!,{R14} ;Save return address
384 BL app_fix ;Do the real job
385 LDMVSFD R13!,{PC} ;If it failed, return now
386 MOV R0,#0 ;Otherwise do global resync
387 SWI XOS_SynchroniseCodeAreas ;Do that then
388 LDMFD R13!,{R14} ;Restore return address
389 BICS PC,R14,#V_flag ;And return with V clear
390
391 LTORG
392
393 ; --- app_fix ---
394 ;
395 ; On entry: R0 == pointer to name table
396 ; R1 == pointer to branch table to fill in
397 ; On exit: --
398
399 EXPORT app_fix
400 app_fix ROUT
401
402 STMFD R13!,{R1-R6,R14} ;Stack registers away
403
404 ; --- Find the application ---
405
406 MOV R2,R0 ;Point to name start
407 MOV R3,R1 ;Keep entry table safe
408 BL app_getHandle
409 BLVC app__find ;Try to find the app block
410 LDMVSFD R13!,{R1-R6,PC} ;If not there, error
411
412 ; --- Get the entry table info out ---
413
414 LDR R4,[R0,#app_btable] ;Find entry table address
415 LDR R5,[R0,#app_nametable] ;Find name table address
416 MOV R6,#&1000 ;Guess number of entries
417 CMP R4,#0 ;Is there no entry table?
418 BEQ %50app_fix ;No -- complain about it
419
420 ; --- Set up for a nice loop ---
421
422 00app_fix LDR R0,[R3,#0] ;Load the word from btable
423 CMP R0,R6 ;Is it moderately sensible?
424 ADDLO R0,R4,R0,LSL #2 ;Yes -- find the entry
425 MOVLO R14,#1 ;Remember we done this
426 BLO %10app_fix ;And fill in the branch
427 LDRB R0,[R2] ;Get the first entry byte
428 CMP R0,#0 ;Is it the end of the table?
429 LDMEQFD R13!,{R1-R6,PC}^ ;Yes -- we did it OK
430
431 ; --- Find another entry point address ---
432
433 MOV R0,R4 ;Point to entry table
434 MOV R1,R5 ;Point to name table
435 BL dll_appEntry ;Find the actual entry name
436 LDMVSFD R13!,{R1-R6,PC} ;If not there, return error
437 MOV R6,#0 ;Move on to next string
438
439 ; --- Convert it to a branch instruction ---
440
441 10app_fix SUB R0,R0,R3 ;Convert to offset from R3
442 SUB R0,R0,#8 ;Subtract 8 (pipeline)
443 MOV R0,R0,LSR #2 ;Shift right to word align
444 BIC R0,R0,#&FF000000 ;Clear top (opcode and cond)
445 ORR R0,R0,#&EA000000 ;Put in BAL (Branch always)
446 STR R0,[R3],#4 ;Store in veneer table
447
448 ; --- Find next entry point address ---
449
450 CMP R6,#0 ;Do we need to move on?
451 BNE %00app_fix ;No -- just loop then
452 01app_fix LDRB R0,[R2],#1 ;Load a byte from the name
453 CMP R0,#0 ;Is it the string end?
454 BNE %01app_fix ;No -- get another
455 B %00app_fix ;Fill in another entry point
456
457 ; --- Application has no entry points to offer ---
458
459 50app_fix ADRL R0,msg_errAppNoEntry ;Point to error message
460 LDMFD R13!,{R1-R6,R14} ;Unstack registers
461 ORRS PC,R14,#V_flag ;Return the error to caller
462
463 LTORG
464
465 ; --- app_listDLLs ---
466 ;
467 ; On entry: R0 == pointer to name of an application
468 ; On exit: --
469
470 EXPORT app_listDLLs
471 app_listDLLs ROUT
472
473 STMFD R13!,{R1,R14} ;Stack registers nicely
474 BL app_findNamed ;Find the application block
475 LDMVSFD R13!,{R1,PC} ;Return if not found
476 LDR R1,[R0,#app_dlls] ;Load head of DLL list
477 CMP R1,#0 ;This shouldn't be 0
478 BEQ %01app_listDLLs ;If it is, print a message
479
480 BL dll_writeTitle ;Display the line along top
481
482 ; --- Main loop thing ---
483
484 00app_listDLLs LDR R0,[R1,#lk_dll] ;Point to the DLL
485 BL dll_writeInfo ;Display information about it
486 LDR R1,[R1,#lk_next] ;Move onto the next one
487 CMP R1,#0 ;Is that all?
488 BNE %00app_listDLLs ;No -- continue round
489
490 LDMFD R13!,{R1,PC}^ ;Return to caller
491
492 ; --- No DLLs to list. Hmm... ---
493
494 01app_listDLLs ADRL R0,msg_noDLLsForApp ;Point to the message
495 SWI OS_Write0 ;And display it
496 LDMFD R13!,{R1,PC}^ ;Return to caller
497
498 LTORG
499
500 ; --- app_listUsing ---
501 ;
502 ; On entry: R0 == pointer to a DLL name
503 ; On exit: --
504
505 EXPORT app_listUsing
506 app_listUsing ROUT
507
508 STMFD R13!,{R1,R2,R8-R11,R14} ;Stack registers
509
510 ; --- Check that the DLL exists ---
511
512 MOV R8,R0 ;Keep the name pointer safe
513 MOV R1,#0 ;Don't care which version
514 BL dll_find ;Try to find it
515 BVS %11app_listUsing ;If it's not there, error
516
517 ; --- Start a loop through the apps ---
518
519 LDR R11,app__list ;Find the list head pointer
520 MOV R10,#0 ;No matching DLLs found yet
521 CMP R11,#0 ;Are there any apps?
522 BEQ %10app_listUsing ;No -- print a message then
523
524 ; --- Start a loop through the DLLs with this app
525
526 00app_listUsing LDR R9,[R11,#app_dlls] ;Find the DLL list
527 CMP R9,#0 ;Are there any DLLs?
528 BEQ %03app_listUsing ;No -- move on to the next
529
530 ; --- Loop through DLLs on this app ---
531
532 01app_listUsing LDR R0,[R9,#lk_dll] ;Point to the DLL base
533 MOV R1,R8 ;Point to DLL name
534 MOV R2,#0 ;Don't care what version
535 BL dll_compare ;Compare with stuff given
536 CMP R0,#1 ;Is there a match?
537 BNE %02app_listUsing ;Move onto the next one
538
539 ; --- Print out info about this app ---
540
541 CMP R10,#1 ;Have we printed the title?
542 ADRNEL R0,msg_appHeader ;No -- point to header
543 SWINE XOS_Write0 ;And print it
544 MOV R10,#1 ;We've printed it now
545 ADD R0,R11,#app_name ;Point to application name
546 MOV R1,#12 ;Field width
547 BL dll_field ;Print it out
548 LDR R0,[R9,#lk_dll] ;Find DLL pointer again
549 LDR R0,[R0,#dl_version] ;Load version number
550 BL dll_convertVersion ;Convert it into a string
551 SWI XOS_Write0 ;Write it out as a string
552 SWI XOS_NewLine ;And move onto the next line
553
554 ; --- Finish off loop through app's DLLs ---
555
556 02app_listUsing LDR R9,[R9,#lk_next] ;Move on to next link block
557 CMP R9,#0 ;Anything to do here?
558 BNE %01app_listUsing ;Yes -- check that one too
559
560 ; --- Finish off loop through all apps ---
561
562 03app_listUsing LDR R11,[R11,#app_next] ;Move on to next application
563 CMP R11,#0 ;Is there any more to do?
564 BNE %00app_listUsing ;Yes -- do its DLLs
565
566 CMP R10,#0 ;Were any messages printed?
567 BEQ %10app_listUsing ;No -- print one
568 LDMFD R13!,{R1,R2,R8-R11,PC}^ ;Return to caller
569
570 ; --- No matching DLLs were found ---
571
572 10app_listUsing ADRL R0,msg_noAppsForDLL ;Point to message skeleton
573 MOV R1,R8 ;Point to the DLL name
574 BL misc_subst ;Do the substitution
575 SWI XOS_Write0 ;Display the string
576 LDMFD R13!,{R1,R2,R8-R11,PC}^
577
578 ; --- Print an error message about this ---
579
580 11app_listUsing MOV R1,R8 ;Point to DLL name
581 ADRL R0,msg_errDLLNotInMem ;Point to error block
582 BL misc_error ;Create error message fully
583 LDMFD R13!,{R1,R2,R8-R11,R14} ;Unstack all registers
584 ORRS PC,R14,#V_flag ;Return to caller with error
585
586 LTORG
587
588 ; --- app_list ---
589 ;
590 ; On entry: --
591 ; On exit: --
592
593 EXPORT app_list
594 app_list ROUT
595
596 STMFD R13!,{R1,R14} ;Stack registers
597
598 ; --- Prepare for a loop ---
599
600 LDR R1,app__list ;Point to first entry
601 CMP R1,#0 ;Are there any entries?
602 BEQ %10app_list ;No -- give a message
603
604 ; --- Display entries in order ---
605
606 00app_list ADD R0,R1,#app_name ;Point to name in structure
607 SWI XOS_Write0 ;Display the app's name
608 SWI XOS_NewLine ;Display a new line char
609 LDR R1,[R1,#app_next] ;Get next entry in the list
610 CMP R1,#0 ;Is it the end yet?
611 BNE %00app_list ;No -- do the next one
612 LDMFD R13!,{R1,PC}^ ;Return to caller
613
614 ; --- Display message about no apps ---
615
616 10app_list ADRL R0,msg_noApps ;Point to the message
617 SWI XOS_Write0 ;Display it on the screen
618 LDMFD R13!,{R1,PC}^ ;Return to caller
619
620 LTORG
621
622 ; --- app_dying ---
623 ;
624 ; On entry: --
625 ; On exit: --
626
627 EXPORT app_dying
628 app_dying ROUT
629
630 STMFD R13!,{R14} ;Stack return address
631 BL app_getHandle ;Find application's time
632 BLVC app__find ;Find the application block
633 LDMFD R13!,{R14} ;Retrieve the return address
634 BVC app_kill ;If there's no error, kill it
635 ORRS PC,R14,#V_flag ;Return to caller with error
636
637 LTORG
638
639 ; --- app_kill --
640 ;
641 ; On entry: R0 == pointer to application base
642 ; On exit: --
643
644 EXPORT app_kill
645 app_kill ROUT
646
647 STMFD R13!,{R1,R2,R14} ;Stack registers nicely
648 MOV R2,R0 ;Keep hold of this pointer
649
650 ; --- Free each DLL link ---
651
652 LDR R1,[R0,#app_dlls] ;Find head of link list
653 CMP R1,#0 ;Are there any DLLs?
654 BEQ %01app_kill ;No -- don't free them then
655
656 00app_kill LDR R0,[R1,#lk_dll] ;Find the DLL pointer
657 BL dll_dec ;Decrement its counter
658 MOV R0,R1 ;Point to old block
659 LDR R1,[R0,#lk_next] ;Point to next block
660 BL sub_free ;Free the old block
661 CMP R1,#0 ;Are there any more to do?
662 BNE %00app_kill ;Yes -- do the next one
663
664 ; --- Free the application block ---
665
666 01app_kill MOV R0,R2 ;Point to application block
667 LDMFD R13!,{R1,R2,R14} ;Restore registers
668 B app__free ;Free the application block
669
670 LTORG
671
672 ; --- app_killAll ---
673 ;
674 ; On entry: --
675 ; On exit: --
676
677 EXPORT app_killAll
678 app_killAll ROUT
679
680 STMFD R13!,{R1,R2,R14}
681
682 ; --- Start up the main loop ---
683
684 LDR R2,app__list ;Point to application list
685 CMP R2,#0 ;Is there anything to do?
686 BEQ %01app_killAll ;No -- skip the loop
687 MOV R0,#7 ;Free memory reason code
688
689 00app_killAll LDR R1,[R2,#app_next] ;Find next block in the list
690 SWI XOS_Module ;Free the block
691 MOVS R2,R1 ;Point to the next one
692 BNE %00app_killAll ;Loop round for the next one
693
694 01app_killAll STR R2,app__list ;Clear out list head pointer
695 STR R2,app__cachePtr ;Clear out cached pointer
696 STR R2,app__cacheHnd ;Clear out cached handle
697 LDMFD R13!,{R1,R2,PC}^ ;Return to caller
698
699 LTORG
700
701 ; --- app_instvars ---
702 ;
703 ; On entry: R0 == anything for first call, or pointer to data block
704 ; R4 == 0 for first call, or pointer to link block
705 ; On exit: R0 == size of block required
706 ; R4 == pointer to next link block, or 0 to end
707
708 EXPORT app_instvars
709 app_instvars ROUT
710
711 STMFD R13!,{R1,R14} ;Keep hold of link register
712 CMP R4,#0 ;Is this the first call?
713 BNE %00app_instvars ;No -- skip ahead quickly
714
715 ; --- Find start of application list ---
716
717 BL app_getHandle ;Get app's start time
718 BLVC app__find ;Locate the application
719 LDMVSFD R13!,{R1,PC}^ ;Return to caller on error
720 LDR R4,[R0,#app_dlls] ;Load list head pointer
721 B %01app_instvars ;Don't try registering vars
722
723 ; --- Register instance variables ---
724
725 00app_instvars CMP R0,#0 ;Check the allocator worked
726 BEQ %40app_instvars ;If not, give an error
727 MOV R1,R0 ;Point to the new block
728 LDR R0,[R4,#lk_dll] ;Point to the DLL block
729 BL dll_instvars ;Register the instance vars
730 LDR R0,[R4,#lk_dll] ;Point to the DLL block again
731 BL dll_convreloc ;Convert to a relocation
732 STR R0,[R4,#lk_work] ;Store relocation
733
734 ; --- Is this the end of the line? ---
735
736 02app_instvars LDR R4,[R4,#lk_next] ;Move to next block in list
737 01app_instvars CMP R4,#0 ;Is this the end?
738 LDMEQFD R13!,{R1,PC}^ ;Yes -- return to caller
739 LDR R0,[R4,#lk_work] ;Find workspace pointer
740 CMP R0,#0 ;Is there one yet?
741 BNE %02app_instvars ;Yes -- skip this one
742 LDR R0,[R4,#lk_dll] ;Point to DLL
743 BL dll_datasize ;Find how much space we need
744 CMP R0,#0 ;Is there any required?
745 BEQ %02app_instvars ;No -- skip to next block
746 LDMFD R13!,{R1,PC}^ ;Return -- that's done
747
748 40app_instvars ADRL R0,msg_errDLLNoMem ;Point to error message
749 LDMFD R13!,{R1,R14} ;Restore registers
750 ORRS PC,R14,#V_flag ;Return the error
751
752 LTORG
753
754 ; --- app_giveclib ---
755 ;
756 ; On entry: R0 == pointer to CLib data (__iob)
757 ; On exit: --
758
759 EXPORT app_giveclib
760 app_giveclib ROUT
761
762 STMFD R13!,{R1,R14} ;Stack registers
763 MOV R1,R0 ;Keep pointer to data
764 BL app__add ;Make sure there's an app
765 STRVC R1,[R0,#app_clibdata] ;Store the pointer nicely
766 LDMFD R13!,{R1,PC} ;Return to caller nicely
767
768 LTORG
769
770 ; --- app_appdata ---
771 ;
772 ; On entry: R0 == application's stack limit
773 ; On exit: --
774
775 EXPORT app_appdata
776 app_appdata ROUT
777
778 STMFD R13!,{R1,R14} ;Stack registers
779 LDR R1,[R0,#-536] ;Find application's reloc
780 BL app__add ;Ensure the app is present
781 STRVC R1,[R0,#app_owndata] ;Store the relocation nicely
782 LDMFD R13!,{R1,PC} ;Return to caller nicely
783
784 LTORG
785
786 ; --- app_findclib ---
787 ;
788 ; On entry: --
789 ; On exit: R0 == pointer to CLib data
790
791 EXPORT app_findclib
792 app_findclib ROUT
793
794 STMFD R13!,{R14} ;Keep return address safe
795 BL app_getHandle ;Find app's start time
796 BLVC app__find ;Look up application's block
797 LDRVC R0,[R0,#app_clibdata] ;Find C Library data pointer
798 LDMFD R13!,{PC} ;Return to caller
799
800 LTORG
801
802 ; --- app_readstackptr ---
803 ;
804 ; On entry: --
805 ; On exit: R0 == `magic cookie' for the stack pointer
806
807 EXPORT app_readstkptr
808 app_readstkptr ROUT
809
810 STMFD R13!,{R14} ;Keep return address safe
811 BL app_getHandle ;Find app's start time
812 BLVC app__find ;Locate the app's data block
813 LDRVC R0,[R0,#app_stackPtr] ;Find the stack pointer
814 LDMFD R13!,{PC}^ ;Return to caller
815
816 LTORG
817
818 ; --- app_setstkptr ---
819 ;
820 ; On entry: R0 == `magic cookie' from app_readstkptr
821 ; R1 == app's current stack limit
822
823 EXPORT app_setstkptr
824 app_setstkptr ROUT
825
826 STMFD R13!,{R11,R14} ;Keep return address safe
827
828 ; --- Find the application block ---
829
830 MOV R11,R0 ;Keep hold of new pointer
831 BL app_getHandle ;Find the app's start time
832 BLVC app__find ;Find the app's data block
833 LDMVSFD R13!,{R11,PC} ;If failed, return error
834
835 ; --- Find out what there is to do ---
836
837 LDR R14,[R0,#app_stackPtr] ;Load the old pointer
838 CMP R11,R14 ;How does it shape up?
839 LDMEQFD R13!,{R11,PC}^ ;Nothing doing here
840
841 ; --- Put back the new stack pointer and set relocation ---
842
843 STR R11,[R0,#app_stackPtr] ;Store new pointer
844 CMP R11,#0 ;Was the stack at top level?
845 ADDNE R0,R0,#app_stack ;Point to base of stack
846 SUBNE R11,R11,#8 ;Point to base of stack entry
847 LDRNE R0,[R0,R11] ;Find data relocation
848 LDREQ R0,[R0,#app_owndata] ;If toplevel, get client data
849 STR R0,[R1,#-536] ;Store in stack limit struct
850 LDMFD R13!,{R11,PC}^ ;Return to caller
851
852 LTORG
853
854 ; --- app_prologue ---
855 ;
856 ; On entry: R0 == return address for routine
857 ; R1 == pointer to stack limit structure
858 ; R2 == pointer to base of DLL code
859 ; On exit: R0 == new return address
860 ;
861 ; Note -- I'm directly accessing the DLL data here, which may be considered
862 ; naughty by some. I don't care.
863
864 EXPORT app_prologue
865 app_prologue ROUT
866
867 STMFD R13!,{R9-R11,R14} ;Stack some registers
868
869 ; --- Find application block ---
870
871 MOV R11,R0 ;Keep hold of this
872 BL app__add ;Make sure the app exists
873 LDMVSFD R13!,{R9-R11,PC} ;Return the error on fail
874
875 ; --- Stack current relocation and return address ---
876
877 LDR R14,[R0,#app_stackPtr] ;Find the stack pointer
878 CMP R14,#4096 ;Where is it currently?
879 BGE %00app_prologue ;Give error on overflow
880 ADD R10,R0,#app_stack ;Point to stack base
881 ADD R10,R10,R14 ;Add on stack pointer
882 LDR R9,[R1,#-536] ;Find the current reloc
883 STMIA R10,{R9,R11} ;Store registers on the stack
884 MOV R10,R1 ;Keep pointer to stack limit
885 ADD R14,R14,#8 ;Bump along stack pointer
886 STR R14,[R0,#app_stackPtr] ;Store stack pointer
887
888 ; --- Find workspace pointer ---
889
890 CMP R2,#0 ;What's the DLL pointer?
891 LDREQ R1,[R0,#app_owndata] ;0 -- find app workspace
892 BEQ %10app_prologue ;... and finish search
893 LDR R14,[R2,#dl_next-dl_extra] ;Find DLL's next ptr
894 CMP R14,#-1 ;Is it shared?
895 LDREQ R1,[R2,#dl_wspace-dl_extra] ;No -- find DLL workspace
896 BEQ %10app_prologue ;... and finish search
897
898 ; --- Get shared DLL workspace pointer ---
899
900 SUB R1,R2,#dl_extra ;Point to DLL handle
901 BL app__findLink ;Find the link block
902 LDMVSFD R13!,{R9-R11,PC} ;Return error if it failed
903 LDR R1,[R0,#lk_work] ;Find relocation offset
904
905 ; --- Round everything off ---
906
907 10app_prologue ADR R0,app__epilogue ;Point to tidy-up routine
908 STR R1,[R10,#-536] ;Store new data relocation
909 LDMFD R13!,{R9-R11,PC}^ ;Return to caller happy
910
911 ; --- Stack overflow error ---
912
913 00app_prologue ADRL R0,msg_errStackOvf ;Point to error
914 LDMFD R13!,{R9-R11,R14} ;Unstack registers
915 ORRS PC,R14,#V_flag ;Return the error
916
917 LTORG
918
919 ; --- app_restoreHandle ---
920 ;
921 ; On entry: R0 == an application handle to assume
922 ; On exit: --
923
924 EXPORT app_restoreHandle
925 app_restoreHandle ROUT
926
927 [ :LNOT::DEF:ddeutils_pid
928
929 STMFD R13!,{R0-R2,R14} ;Save some registers
930 SWI XOS_GetEnv ;Read current command string
931 MOV R1,R13 ;Point to new start time
932 SWI XOS_WriteEnv ;Set the start time back
933 LDMFD R13!,{R0-R2,PC}^ ;And return to caller
934
935 |
936
937 MOVS PC,R14 ;No need to do this
938
939 ]
940
941 LTORG
942
943 ; --- app_getHandle ---
944 ;
945 ; On entry: --
946 ; On exit: R0 == application's start time
947 ;
948 ; Since the application's start time is held in *five* bytes we use only the
949 ; least significant 4 (the four that change most).
950
951 EXPORT app_getHandle
952 app_getHandle ROUT
953
954 [ :LNOT::DEF:ddeutils_pid
955
956 STMFD R13!,{R1,R2,R14} ;Save some registers
957 SWI XOS_GetEnv ;Get the session info
958 LDR R0,[R2,#0] ;Load the start time nicely
959 LDMFD R13!,{R1,R2,PC}^ ;And return to caller
960
961 |
962
963 LDR R0,app__pidAddr ;Load the PID address
964 LDR R0,[R0] ;And load the current PID
965 MOVS PC,R14 ;Return to caller when done
966
967 ]
968
969 LTORG
970
971 ;----- Private routines -----------------------------------------------------
972
973 ; --- app__epilogue ---
974 ;
975 ; On entry: --
976 ; On exit: a1,a2 preserved. otherwise as APCS-R
977 ;
978 ; I've used APCS register names throughout here.
979
980 app__epilogue ROUT
981
982 STMFD sp!,{a1,a2} ;Keep two return values
983 LDR ip,app__pw ;Point to private word ptr
984 BL app_getHandle ;Find app's start time
985 BL app__find ;Find app block
986 LDR a2,[a1,#app_stackPtr] ;Find the stack pointer
987 ADD a3,a1,#app_stack ;Point to the stack base
988 ADD a3,a3,a2 ;Point to current stack pos
989 LDMDB a3!,{a4,lr} ;Find relocation and ret addr
990 SUB a2,a2,#8 ;Bump down the stack ptr
991 STR a2,[a1,#app_stackPtr] ;Store back in app block
992 STR a4,[sl,#-536] ;Store relocation offset
993 LDMFD sp!,{a1,a2} ;Restore return values
994 MOVS pc,lr ;Return to caller
995
996 LTORG
997
998 ; --- app__find ---
999 ;
1000 ; On entry: R0 == application handle (i.e. start time)
1001 ; On exit: R0 == pointer to application block, or error
1002
1003 app__find ROUT
1004
1005 STMFD R13!,{R1,R2,R14} ;Preserve nice registers
1006
1007 ; --- Try looking at the cached value ---
1008
1009 LDR R1,app__cacheHnd ;Load the cached handle
1010 CMP R1,R0 ;Is it a match?
1011 LDREQ R0,app__cachePtr ;Yes -- load the pointer
1012 LDMEQFD R13!,{R1,R2,PC}^ ;And return!
1013
1014 ; --- Otherwise, scan the list ---
1015
1016 LDR R2,app__list ;Get list head pointer
1017 CMP R2,#0 ;Is there an entry here?
1018 BEQ %10app__find ;No -- return an error
1019 00app__find LDR R1,[R2,#app_handle] ;Get the app's handle
1020 CMP R1,R0 ;Is it a match?
1021 BEQ %01app__find ;Yes -- deal with it
1022 LDR R2,[R2,#app_next] ;No -- get the next pointer
1023 CMP R2,#0 ;Is this the end?
1024 BNE %00app__find ;No -- continue round
1025
1026 ; --- Couldn't find the application ---
1027
1028 10app__find ADRL R0,msg_errUnknownApp ;Point to error message
1029 LDMFD R13!,{R1,R2,R14} ;Pull back registers
1030 ORRS PC,R14,#V_flag ;And return with an error
1031
1032 ; --- Found an application -- update the cache ---
1033
1034 01app__find STR R0,app__cacheHnd ;Store the new handle
1035 STR R2,app__cachePtr ;And the new pointer
1036 MOV R0,R2 ;Return the pointer to caller
1037 LDMFD R13!,{R1,R2,PC}^ ;And live happily ever after
1038
1039 LTORG
1040
1041 ; --- app__add ---
1042 ;
1043 ; On entry: --
1044 ; On exit: Application handle
1045
1046 app__add ROUT
1047
1048 STMFD R13!,{R1-R3,R14} ;Stack registers
1049
1050 ; --- Find out whether the app is registered yet ---
1051
1052 BL app_getHandle ;Find app's start time
1053 MOV R1,R0 ;Look after a copy
1054 BL app__find ;Call the find routine
1055 LDMVCFD R13!,{R1-R3,PC}^ ;If already there, return
1056
1057 ; --- Allocate a block from the RMA ---
1058
1059 MOV R0,#6 ;Code to allocate some store
1060 LDR R3,=app_strSize ;The size of an app block
1061 SWI XOS_Module ;Allocate the memory
1062 LDMVSFD R13!,{R1-R3,PC} ;If it failed, return error
1063
1064 ; --- Link the block into the list ---
1065
1066 LDR R0,app__list ;Find the list header
1067 STR R0,[R2,#app_next] ;Store in next pointer
1068 CMP R0,#0 ;Is there a next block?
1069 STRNE R2,[R0,#app_prev] ;Yes -- link in new block
1070 MOV R0,#0 ;Zero out the previous link
1071 STR R0,[R2,#app_prev] ;Store in previous entry
1072 STR R2,app__list ;Store this as new block
1073
1074 ; --- Set this block up in the cache ---
1075
1076 STR R1,app__cacheHnd ;Cache the app's start time
1077 STR R2,app__cachePtr ;Cache the app's pointer
1078
1079 ; --- Set up the block's data ---
1080
1081 MOV R0,#0 ;Zero some entries in block
1082 STR R0,[R2,#app_cachedll] ;No cached DLL yet
1083 STR R0,[R2,#app_cacheptr] ;No cached DLL yet
1084 STR R0,[R2,#app_dlls] ;No DLLs registered yet
1085 STR R0,[R2,#app_stackPtr] ;No entries on the stack
1086 STR R0,[R2,#app_btable] ;App has no entry table
1087 STR R1,[R2,#app_handle] ;Store the app's time info
1088 ADD R0,R2,#app_name ;Point to app's name field
1089 ADRL R1,msg_appName ;Point to default name
1090 BL misc_strcpy ;Copy the string across
1091
1092 ; --- Return the app's handle ---
1093
1094 MOV R0,R2 ;Return the app's pointer
1095 LDMFD R13!,{R1-R3,PC}^ ;Return to caller
1096
1097 LTORG
1098
1099 ; --- app__free ---
1100 ;
1101 ; On entry: R0 == pointer to app to free
1102 ; On exit: --
1103
1104 app__free ROUT
1105
1106 STMFD R13!,{R1,R2,R14} ;Keep registers safe
1107
1108 ; --- Remove the block from the list ---
1109
1110 LDR R1,[R0,#app_next] ;Get next block in the list
1111 LDR R2,[R0,#app_prev] ;Get previous block too
1112 CMP R1,#0 ;Is there a next block?
1113 STRNE R2,[R1,#app_prev] ;Yes -- fix up its prev
1114 CMP R2,#0 ;Is there a previous block?
1115 ADREQ R2,app__list ;No -- point to list head
1116 STR R1,[R2,#app_next] ;Fix up next pointer
1117
1118 ; --- Remove this app from the cache ---
1119
1120 LDR R2,app__cachePtr ;Find which app was cached
1121 CMP R2,R0 ;Is it this one?
1122 MOVEQ R2,#0 ;Yes -- overwrite handle
1123 STREQ R2,app__cacheHnd ;Won't match this app now
1124 STREQ R2,app__cachePtr
1125
1126 ; --- Free the block ---
1127
1128 MOV R2,R0 ;Point to the block to free
1129 MOV R0,#7 ;Magic reason code
1130 SWI XOS_Module ;Free the block
1131 LDMFD R13!,{R1,R2,PC} ;Return to caller if failed
1132
1133 LTORG
1134
1135 ; --- app__freeUnused ---
1136 ;
1137 ; On entry: R0 == pointer to application
1138 ; On exit: --
1139
1140 app__freeUnused ROUT
1141
1142 STMFD R13!,{R14} ;Keep link register
1143 LDR R14,[R0,#app_dlls] ;Find DLL link list
1144 CMP R14,#0 ;Are there any in the list?
1145 LDMFD R13!,{R14} ;Restore link register
1146 MOVNES PC,R14 ;Return is still attached
1147 B app__free ;Otherwise kill the app
1148
1149 LTORG
1150
1151 ; --- app__sFindDLL ---
1152 ;
1153 ; On entry: R0 == pointer to name of DLL to find
1154 ; R1 == version number to load
1155 ; On exit: R0 == DLL handle loaded
1156
1157 app__sFindDLL ROUT
1158
1159 STMFD R13!,{R1,R2,R9-R11,R14} ;Stack loads of registers
1160
1161 MOV R11,R0 ;Keep pointer safe
1162
1163 ; --- Ensure that the application structure is there ---
1164
1165 BL app__add ;Add the application if reqd.
1166 LDMVSFD R13!,{R1,R2,R9-R11,PC} ;If it failed, return now
1167 MOV R10,R0 ;Keep pointer to app block
1168
1169 ; --- Find out if there's anything to do ---
1170
1171 MOV R2,R1 ;Put version number nicely
1172 MOV R1,R11 ;Point to required name
1173 BL app__findNamedLink ;Is there anything to do?
1174 LDMVCFD R13!,{R1,R2,R9-R11,PC}^ ;If found, return to caller
1175 MOV R1,R2 ;Put version number back
1176
1177 ; --- Load the DLL if necessary ---
1178
1179 MOV R0,R11 ;Move DLL pointer back
1180 BL dll_ensure ;Load the DLL into memory
1181 MOVVS R9,R0 ;If it failed, keep the error
1182 BVS %50app__sFindDLL ;And tidy up properly
1183 MOV R11,R0 ;Keep pointer to DLL
1184 BL dll_tentative ;Mark the DLL as tentative
1185
1186 ; --- Add the link between the two ---
1187
1188 MOV R0,R10 ;Point to application
1189 MOV R1,R11 ;Point to DLL block
1190 BL app__addLink ;Link them together
1191 MOVVS R9,R0 ;Keep error if any
1192 BVS %51app__sFindDLL ;And tidy things up
1193
1194 ; --- Now we're done ---
1195
1196 MOV R0,R11 ;Point to DLL structure
1197 LDMFD R13!,{R1,R2,R9-R11,PC}^ ;Restore registers
1198
1199 ; --- Tidy up if link allocation failed ---
1200
1201 51app__sFindDLL
1202 50app__sFindDLL MOV R0,R10 ;Point to application block
1203 BL app__freeUnused ;If not being used, kill it
1204
1205 ; --- Return the error to the caller ---
1206
1207 MOV R0,R9 ;Point to the error message
1208 LDMFD R13!,{R1,R2,R9-R11,R14} ;Restore registers
1209 ORRS PC,R14,#V_flag ;Return to caller
1210
1211 LTORG
1212
1213 ; --- app__ok ---
1214 ;
1215 ; On entry: --
1216 ; On exit: All registers preserved
1217 ;
1218 ; Expects a stacked R11 and R14
1219
1220 app__ok ROUT
1221
1222 MOV R11,R0 ;Look after error pointer
1223 BL dll_confirm ;Cancel tentative DLL blocks
1224 BL app_getHandle ;Find app time info
1225 BLVC app__find ;Find the application block
1226 BLVC app__confLink ;Cancel tentative links
1227
1228 ; --- Resync code areas ---
1229 ;
1230 ; This seems as good a place as any to do this. I'm going
1231 ; to do a global resync, because I suspect that lots of
1232 ; local ones are going to be rather slower, actually.
1233 ; Besides, loading libraries isn't something which gets done
1234 ; /that/ often.
1235
1236 MOV R0,#0 ;Resync everything
1237 SWI XOS_SynchroniseCodeAreas ;Do that then, please
1238
1239 MOV R0,R11 ;Point to error again
1240 LDMFD R13!,{R11,R14} ;Restore registers
1241 BICS PC,R14,#V_flag ;Return to caller with V clr
1242
1243 LTORG
1244
1245 ; --- app__dead ---
1246 ;
1247 ; On entry: --
1248 ; On exit: All registers preserved
1249 ;
1250 ; Expects a stacked R11 and R14
1251
1252 app__dead ROUT
1253
1254 MOV R11,R0 ;Look after error pointer
1255 CMP R0,R0 ;Clear the V flag
1256 BL dll_retrace ;Destroy tentative DLL blocks
1257 BL app_getHandle ;Find app time info
1258 BLVC app__find ;Find the application block
1259 BLVC app__cancel ;Destroy tentative links
1260 MOV R0,R11 ;Point to error again
1261 LDMFD R13!,{R11,R14} ;Restore registers
1262 ORRS PC,R14,#V_flag ;Return to caller with V set
1263
1264 LTORG
1265
1266 ; --- app__findNamedLk ---
1267 ;
1268 ; On entry: R0 == pointer to application
1269 ; R1 == pointer to DLL's name
1270 ; R2 == DLL's version number
1271 ; On exit: R0 == V set if couldn't be found, clear otherwise
1272
1273 app__findNamedLink ROUT
1274
1275 STMFD R13!,{R3,R4,R14} ;Stack registers safely
1276 LDR R3,[R0,#app_dlls] ;Point to first DLL block
1277 CMP R3,#0 ;Is there anything to do?
1278 BEQ %20app__findNamedLink ;No -- that's an error
1279
1280 ; --- Now construct the proper DLL name ---
1281
1282 MOV R0,R1 ;Point to the DLL name
1283 00 LDRB R14,[R0],#1 ;Load the next byte
1284 CMP R14,#'[' ;Is this a new-style DAN?
1285 BEQ %f05 ;Yes -- sort this out then
1286 CMP R14,#'.' ;Or is it a dot?
1287 MOVEQ R1,R0 ;Yes -- remember this place
1288 CMP R14,#&20 ;End of the string yet?
1289 BCS %b00 ;No -- keep going
1290
1291 ADR R0,misc__sharedBuf ;Find the shared buffer
1292 00 LDRB R14,[R1],#1 ;Load a byte from the name
1293 CMP R14,#&20 ;Finished yet?
1294 MOVCC R14,#0 ;Yes -- zero-terminate
1295 STRB R14,[R0],#1 ;And store it out
1296 BCS %b00 ;No -- keep going
1297 B %10app__findNamedLink ;And skip to main matcher
1298
1299 ; --- Handle a new-style DAN ---
1300
1301 05 ADR R1,misc__sharedBuf ;Find the shared buffer
1302 00 LDRB R14,[R0],#1 ;Load a byte from the name
1303 CMP R14,#']' ;End of the name yet?
1304 MOVEQ R14,#0 ;Yes -- terminate here then
1305 CMP R14,#&20 ;Finished yet?
1306 MOVCC R14,#0 ;Yes -- zero-terminate
1307 STRB R14,[R1],#1 ;And store it out
1308 BCS %b00 ;No -- keep going
1309
1310 10app__findNamedLink
1311 ADR R1,misc__sharedBuf ;Point to the DLL name
1312
1313 00 LDR R0,[R3,#lk_dll] ;Find DLL pointer for block
1314 BL dll_compare ;Compare with passed values
1315 CMP R0,#1 ;Did it return TRUE?
1316 BEQ %30app__findNamedLink ;Yes -- be happy
1317 LDR R3,[R3,#lk_next] ;Find next pointer
1318 CMP R3,#0 ;Is there any more to do?
1319 BNE %b00 ;Yes -- loop round and do it
1320
1321 20app__findNamedLink
1322 LDMFD R13!,{R3,R4,R14} ;Restore registers
1323 ORRS PC,R14,#V_flag ;Return with V set
1324
1325 30app__findNamedLink
1326 LDR R0,[R3,#lk_dll] ;Load DLL pointer again
1327 LDMFD R13!,{R3,R4,R14} ;Restore registers
1328 BICS PC,R14,#V_flag ;Return with V clear
1329
1330 LTORG
1331
1332 ; --- app__findLink ---
1333 ;
1334 ; On entry: R0 == pointer to application
1335 ; R1 == pointer to DLL
1336 ; On exit: R0 == pointer to link structure
1337
1338 app__findLink ROUT
1339
1340 STMFD R13!,{R1,R2,R14} ;Preserve nice registers
1341
1342 ; --- Try looking at the cached value ---
1343
1344 LDR R2,[R0,#app_cachedll] ;Load the cached handle
1345 CMP R2,R1 ;Is it a match?
1346 LDREQ R0,[R0,#app_cacheptr] ;Yes -- load the pointer
1347 LDMEQFD R13!,{R1,R2,PC}^ ;And return!
1348
1349 ; --- Otherwise, scan the list ---
1350
1351 LDR R2,[R0,#app_dlls] ;Get list head pointer
1352 CMP R2,#0 ;Is there an entry here?
1353 BEQ %10app__findLink ;No -- return an error
1354 00app__findLink LDR R14,[R2,#lk_dll] ;Get the DLL's pointer
1355 CMP R1,R14 ;Is it a match?
1356 BEQ %01app__findLink ;Yes -- deal with it
1357 LDR R2,[R2,#lk_next] ;No -- get the next pointer
1358 CMP R2,#0 ;Is this the end?
1359 BNE %00app__findLink ;No -- continue round
1360
1361 ; --- Couldn't find the application ---
1362
1363 10app__findLink ADRL R0,msg_errLinkNotFound ;Point to error message
1364 LDMFD R13!,{R1,R2,R14} ;Pull back registers
1365 ORRS PC,R14,#V_flag ;And return with an error
1366
1367 ; --- Found an application -- update the cache ---
1368
1369 01app__findLink STR R1,[R0,#app_cachedll] ;Store the new handle
1370 STR R2,[R0,#app_cacheptr] ;And the new pointer
1371 MOV R0,R2 ;Return the pointer to caller
1372 LDMFD R13!,{R1,R2,PC}^ ;And live happily ever after
1373
1374 LTORG
1375
1376 ; --- app__addLink ---
1377 ;
1378 ; On entry: R0 == pointer to application
1379 ; R1 == pointer to DLL
1380 ; On exit: --
1381
1382 app__addLink ROUT
1383
1384 STMFD R13!,{R1,R11,R14} ;Stack registers
1385 MOV R11,R0 ;Keep pointer to application
1386
1387 ; --- Find out whether the link is registered yet ---
1388
1389 BL app__findLink ;Call the find routine
1390 LDMVCFD R13!,{R1,R11,PC}^ ;If already there, return
1391
1392 ; --- Allocate a block from the RMA ---
1393
1394 CMP R0,R0 ;Clear V flag
1395 BL sub_alloc ;Allocate a link block
1396 LDMVSFD R13!,{R1,R11,PC} ;If it failed, return error
1397
1398 ; --- Link the block into the list ---
1399
1400 LDR R14,[R11,#app_dlls] ;Find the list header
1401 STR R14,[R0,#lk_next] ;Store in next pointer
1402 CMP R14,#0 ;Is there a next block?
1403 STRNE R0,[R14,#lk_prev] ;Yes -- link in new block
1404 MOV R14,#0 ;Zero out the previous link
1405 STR R14,[R0,#lk_prev] ;Store in previous entry
1406 STR R0,[R11,#app_dlls] ;Store this as new block
1407
1408 ; --- Set this block up in the cache ---
1409
1410 STR R1,[R11,#app_cachedll] ;Cache the DLL's pointer
1411 STR R0,[R11,#app_cacheptr] ;Cache the app's pointer
1412
1413 ; --- Set up the block's data ---
1414
1415 STR R1,[R0,#lk_dll] ;Store pointer to DLL
1416 MOV R1,#0 ;No workspace yet
1417 STR R1,[R0,#lk_work] ;So store in the block
1418
1419 ; --- Mark as currently tentative ---
1420
1421 MOV R1,#lk_tentative ;Tentative flag
1422 STR R1,[R0,#lk_flags] ;Store in block's flags area
1423
1424 ; --- Return the app's handle ---
1425
1426 LDMFD R13!,{R1,R11,PC}^ ;Return to caller
1427
1428 LTORG
1429
1430 ; --- app__freeLink ---
1431 ;
1432 ; On entry: R0 == pointer to application
1433 ; R1 == pointer to link structure
1434 ; On exit: --
1435
1436 app__freeLink ROUT
1437
1438 STMFD R13!,{R1,R2,R14} ;Stack registers
1439
1440 ; --- Fix up list ---
1441
1442 LDR R2,[R1,#lk_next] ;Get next pointer
1443 LDR R14,[R1,#lk_prev] ;Get previous pointer
1444 CMP R2,#0 ;Is there a real next block?
1445 STRNE R14,[R2,#lk_prev] ;Yes -- fix backwards link
1446 CMP R14,#0 ;Is there a real prev block?
1447 ADDEQ R14,R0,#app_dlls ;No -- point to list head
1448 STR R2,[R14,#lk_next] ;Fix forwards link
1449
1450 ; --- Free the link ---
1451
1452 MOV R0,R1 ;Point to the link
1453 LDMFD R13!,{R1,R2,R14} ;Retreive registers
1454 B sub_free ;Free the link block
1455
1456 LTORG
1457
1458 ; --- app__confLk ---
1459 ;
1460 ; On entry: R0 == application to confirm
1461 ; On exit: --
1462
1463 app__confLink ROUT
1464
1465 STMFD R13!,{R1,R14} ;Stack registers
1466 LDR R0,[R0,#app_dlls] ;Find head of the link list
1467 CMP R0,#0 ;Is it empty?
1468 LDMEQFD R13!,{R1,PC}^ ;Yes -- return to caller
1469 00app__confLink LDR R1,[R0,#lk_next] ;Find the next entry
1470 LDR R14,[R0,#lk_flags] ;Load flags word
1471 BIC R14,R14,#lk_tentative ;Clear the magic flag
1472 STR R14,[R0,#lk_flags] ;Store the flags word back
1473 MOVS R0,R1 ;Move to next entry
1474 BNE %00app__confLink ;If more to do, do next one
1475 LDMFD R13!,{R1,PC}^ ;Return to caller, confirmed
1476
1477 LTORG
1478
1479 ; --- app__cancel ---
1480 ;
1481 ; On entry: R0 == app to cancel
1482 ; On exit: --
1483
1484 app__cancel ROUT
1485
1486 STMFD R13!,{R1,R2,R14} ;Stack registers
1487 MOV R2,R0 ;Keep pointer to app block
1488 LDR R0,[R0,#app_dlls] ;Find head of the link list
1489 CMP R0,#0 ;Is it empty?
1490 LDMEQFD R13!,{R1,R2,PC}^ ;Yes -- return to caller
1491 00app__cancel LDR R1,[R0,#lk_next] ;Find the next entry
1492 LDR R14,[R0,#lk_flags] ;Load flags word
1493 TST R14,#lk_tentative ;Is the flag set?
1494 BEQ %01app__cancel ;No -- move on to next one
1495
1496 LDR R14,[R0,#lk_prev] ;Find pointer to previous
1497 CMP R1,#0 ;Is there a next block?
1498 STRNE R14,[R1,#lk_prev] ;Fix up previous pointer
1499 CMP R14,#0 ;Is there a previous block?
1500 ADDEQ R14,R2,#app_dlls ;No -- point to list base
1501 STR R1,[R14,#lk_next] ;Fix up next pointer
1502 BL sub_free ;Free the block
1503
1504 01app__cancel MOVS R0,R1 ;Move to next entry
1505 BNE %00app__cancel ;If more to do, do next one
1506
1507 MOV R0,R2 ;Point to application block
1508 BL app__freeUnused ;If nothing left, kill app
1509 LDMFD R13!,{R1,R2,PC}^ ;Return to caller, cancelled
1510
1511 LTORG
1512
1513 ;----- That's all folks -----------------------------------------------------
1514
1515 END