chiark / gitweb /
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