1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; -*- Mode: Assembler -*-
;* module initialisation for shared libraries
;* Lastedit: 03 Apr 90 10:51:05 by Harry Meekings *
; Copyright (C) Acorn Computers Ltd., 1988
;
; IDJ: 19-Jul-91: removed message C03
GBLL SharedLibrary
SharedLibrary SETL {TRUE}
GBLL NoStubEntries
NoStubEntries SETL {TRUE} ; stop h_modmacro defining Entry
AREA |AA$$code|, CODE, READONLY
GET s.h_Regs
GET s.h_Brazil
GET s.h_stack
GET s.h_modmacro
GET s.h_workspc
GET Hdr:Proc
IMPORT |Lib$$Init$$Base|
IMPORT |Lib$$Init$$Limit|
IMPORT |Image$$ZI$$Base|
[ Code_Destination = "RAM"
IMPORT |__RelocCode|
]
IMPORT |_kernel_copyerror|
IMPORT |_kernel_getmessage|
EXPORT |_Lib$Reloc$Off|
EXPORT |_Mod$Reloc$Off|
EXPORT |_Shared_Lib_Module_SWI_Code|
EXPORT |_Shared_Lib_Module_Init_Code|
EXPORT |_Shared_Lib_Module_Die_Code|
|_Lib$Reloc$Off| * -SL_Lib_Offset
|_Mod$Reloc$Off| * -SL_Client_Offset
OverflowBit * &10000000
n_module_claim EQU 6
sharedclibrary_path
DCB "SharedCLibrary$Path"
DCB 0
risc_oslibrary_path
DCB "RISC_OSLibrary$Path"
DCB 0
sharedclibrary_resources
DCB "Resources:$.Resources.CLib."
DCB 0
risc_oslibrary_resources
DCB "Resources:$.Resources.RISC_OSLib."
DCB 0
ALIGN
|_Shared_Lib_Module_Init_Code|
STMFD r13!, {r7-r11, lr}
[ Code_Destination = "RAM"
BL |__RelocCode|
]
MOV r14, #0
STR r14, [r14, #CLibWorkSpace]
STR r14, [r14, #RISCOSLibWorkSpace]
ADR r0, sharedclibrary_path
ADR r1, sharedclibrary_resources
MOV r5, #?sharedclibrary_resources
BL setresourcevar
ADR r0, risc_oslibrary_path
ADR r1, risc_oslibrary_resources
MOV r5, #?risc_oslibrary_resources
BL setresourcevar
LDMFD r13!, {r7-r11, pc}^
setresourcevar
MOV r11, lr
MOV r10, r0
MOV r2, #-1
MOV r3, #0
MOV r4, #0
SWI ReadVarVal
MOV r0, r10
CMP r2, #0
MOVEQ r2, r5
MOVEQ r3, #0
MOVEQ r4, #0
SWIEQ SetVarVal
MOVS pc, r11
XMessageTrans_CloseFile EQU &61504 ; Put in hdr file someday
|_Shared_Lib_Module_Die_Code|
STMDB r13!, {lr}
MOV r3, #0
LDR r2, [r3, #CLibWorkSpace]
CMP r2, #0
BEQ %F00
MOV r0, r2
SWI XMessageTrans_CloseFile
MOV r0, #Module_Free
SWI Module
STR r3, [r3, #CLibWorkSpace]
00
LDMIA r13!, {pc}^
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This is the SWI Lib_Init code
;
; Entered with r0 pointer to description of stubs present in image
; each having format
; library chunk id
; entry vector base
; entry vector limit
; static data base
; static data limit
; terminated by an entry with stub id -1
; For each of these, there must be an entry in the shared
; library description (in the Lib$$Init area) with the same
; id and the the same static data size.
; r1 pointer to low end of workspace
; r2 pointer to high end of workspace
; r3 base of client's zero-initialise area (at end of statics)
; r4 pointer to start of client's statics
; r5 pointer to end of clients's statics
; (old stubs) r6 = 0
; r6 [0] = 0 if client is running in a 26-bit mode (may still be APCS-32)
; = 1 if client is running in a 32-bit mode (=> must be APCS-32,
; and address constant table must follow vectors)
; r6 [1:15] = 0
; r6 [16:31] = requested root stack size (Kb)
; Returns with stub vector patched
; if input r5>r4, user statics copied and [sl, #SL_Client_Offset]
; initialised
; library statics copied and [sl, #SL_Lib_Offset] initialised
; r1 stack base
; r2 stack top (sp value)
; r6 = library version number
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
^ 0
; Format of Lib$$Init area entry
LI_Id # 4
LI_EntryBase # 4
LI_EntryEnd # 4
LI_DataStart # 4
LI_DataEnd # 4
LI_ItemSize # 0
|_Shared_Lib_Module_SWI_Code|
; Relative SWI number in r11.
; 0 old-style init. Client uses APCS_A. No longer supported.
; 1 new-style init. Client uses APCS_U; so must this module.
; 2 (new-style) module init. Stack is SWI stack, not in the heap.
; 3 APCS-32 init. Client uses APCS-3/32bit.
; 4 APCS-32 module init. Stack is SWI stack, not in the heap.
EntryS "r0-r6"
; Check SWI in valid range
[ {CONFIG}=26
CMP r11, #1
|
CMP r11, #3
]
ADRLO r0, E_OldAPCS
BLO Failed
CMP r11, #4
ADRHI r0, E_UnknownSWI
BHI Failed
CLRPSR F_bit:OR:I_bit, lr ; ensure IRQs enabled
NOP
; Check memory constraints work:
; lr = end of required workspace (data + stack), ie stack top for non-modules
; r12 = stack base
SUBS lr, r5, r4 ; size of client's statics
MOVMI lr, #0 ; no client statics really.
CMP r11, #2 ; module?
CMPNE r11, #4
MOVEQ r12, sp, LSR #20
MOVEQ r12, r12, ASL #20
ADDEQ lr, lr, r1
BEQ CheckEnoughStore
ADD r12, r1, lr ; heap base plus size of copied statics
; For things linked with old stubs r6 may be zero - if so,
; we use the old default root stack size
MOVS r6, r6, LSR #6
MOVEQ r6, #OldRootStackSize
ADD lr, r12, r6 ; plus size of root stack
CheckEnoughStore
CMP lr, r2 ; must fit within available workspace
ADRGT r0, E_BadMemory
BGT Failed
[ Proc_RegOffset = 0
STMIA r13, {r2, r12, lr} ; return values of r0, r1 & r2 (Data end, stack base and stack top)
|
[ Proc_RegOffset = 4
STMIB r13, {r2, r12, lr} ; return values of r0, r1 & r2 (Data end, stack base and stack top)
|
! 1, "Proc_RegOffset = ?"
]
]
CMP r11, #2 ; module?
CMPNE r11, #4
STRNE r6, [r12, #SC_size] ; Start filling stack chunk header for non-modules
; Copy the non-zeroed client statics
SUBS lr, r5, r4 ; see again whether client statics to copy
MOVMI r4, r1
SUBS r6, r3, r4
BLE ZeroInitClientStatics
CopyClientStatics
LDR lr, [r4], #+4
STR lr, [r1], #+4
SUBS r6, r6, #4
BNE CopyClientStatics
; Zero the client statics which need zeroing
ZeroInitClientStatics
SUB lr, r1, r4 ; the value for SL_Client_Offset
SUBS r5, r5, r3
BLE DoneClientStatics
MOV r6, #0
01 STMIA r1!, {r6}
SUBS r5, r5, #4
BGT %B01
; Client statics copied/zeroed, fill in SC_Client_Offset for -zm1 clients
DoneClientStatics
STR lr, [r12, #SC_SLOffset+SL_Client_Offset]
; r5 is used to hold SL_Lib_Offset - if a library chunk has an different value
; its time to barf! r5=0 is the initial value to indicate 'r5 isn't set yet'
MOV r5, #0
NextLibraryChunk
; Pick up:
; r14 = Start of our table of libraries
; r12 = End of our table of libraries
; r1 = next client library chunk number
; r2 = next client library chunk branch table start
; r3 = next client library chunk branch table end
LDR r14, =|Lib$$Init$$Base|
LDR r12, =|Lib$$Init$$Limit|
LDMIA r0!, {r1, r2, r3}
; If end of client's library table we've finished
CMP r1, #0
BLT EndStubInit
FindLibraryChunk
; If finished with our table of libraries then the client's chunk isn't recognised
CMP r14, r12
ADRGE r0, E_UnknownLib
BGE Failed
; Check if this chunk matches the client's, if yes, then drop through
LDR r4, [r14], #LI_ItemSize
BIC r4, r4, #library_segment_is_ROM_only
CMP r4, r1
BNE FindLibraryChunk
FoundLibraryChunk
; We've now matched a client library chunk to a library chunk we know about
; so, we should now patch the branches and copy and initialise the data
; Check not attempting to bind ROM chunk to RAM application
LDR r4, [r14, #LI_Id - LI_ItemSize]
TST r4, #library_segment_is_ROM_only
TEQNE r2, r3
ADRNE r0, E_UnknownLib
BNE Failed
; I suppose it would be friendly to check here that there are
; no fewer entries in the library than in the stub.
LDR r12, StubInitValue
; Branch patchup for SWI Lib_Init1 to 4
; r2 = entry vector base
; r3 = entry vector limit
; r6 bit 0 set => 32-bit mode (so BL not valid), and address constant table
; of same size follows immediately after
LDR r6, [r13, #Proc_RegOffset + 6*4]
TST r6, #1 ; if in 26-bit mode, just use the BL form
BEQ FixBranches ; as it works, and is faster
; Create a table of LDR PC,&xxx followed by the address constants
LDR r1, =&E59FF000 ; LDR PC,[PC,#+0]
SUB r4, r3, r2 ; r4 = size of table (remember for later)
SUBS r6, r4, #8 ; r6 = offset to use in LDR
BICMI r1, r1, #1:SHL:23 ; handle the negative case (just possible
RSBMI r6, r6, #0 ; for a single entry stub table)
CMP r6, #&1000 ; Offset must be <= &FFF
ADRHS r0, E_UnknownLib ; Can't be bothered to make a new error
BHS Failed
ORR r6, r1, r6
FixLDRs
CMP r2, r3
STRNE r6, [r2], #4
BNE FixLDRs ; Write the LDR PC,[PC,#<xxx>] into each entry
ADD r3, r2, r4 ; r2, r3 now point to address constant table
LDR r4, [r14, #LI_EntryBase-LI_ItemSize] ; Our entry table
FixAddresses
CMP r2, r3
BEQ ChunkEntriesDone
LDR r1, [r4], #+4
MOV r1, r1, ASL #8 ; sign-extend branch offset
ADD r1, r4, r1, ASR #6 ; and convert to bytes
ADD r1, r1, #8-4 ; +8 for pc, -4 for ,#+4 above
LDR r6, [r2], #4 ; patch the stub entry only if it's
CMP r6, r1 ; not already right.
STRNE r1, [r2, #-4]
B FixAddresses
; Create a table of BL &xxx
FixBranches
LDR r4, [r14, #LI_EntryBase-LI_ItemSize] ; Our entry table
FixEntries
CMP r2, r3
BEQ ChunkEntriesDone
LDR r1, [r4]
ADD r1, r1, r4, LSR #2
SUB r1, r1, r2, LSR #2
BIC r1, r1, #&FF000000
ORR r1, r1, #&EA000000 ; le branch!
ADD r4, r4, #4
LDR r6, [r2], #4 ; patch the stub entry only if it's
CMP r6, r1 ; not already right.
STRNE r1, [r2, #-4]
B FixEntries
ChunkEntriesDone
; Having patched up the branch table, lets copy the library's static data
; The space reserved in the image for static data for this chunk
; must match the actual size in the shared library.
LDMIA r0!, {r2, r3}
LDMDB r14, {r4, r6}
SUB r1, r2, r3
ADD r1, r1, r6
SUBS r1, r1, r4
[ 1 = 1
ADRNE r0, E_StaticSizeWrong
BNE Failed
|
BEQ staticsizeok
STMDB sp!, {r0, r1, r2}
[ :DEF:DEFAULT_TEXT
ADR r0, stubdatasize_text
ADR r1, stubdatasize_tag
|
ADR r0, stubdatasize_tag
]
BL |_kernel_getmessage|
BL writectrl
SUB r0, r3, r2
SUB r1, sp, #12
MOV r2, #9
SWI &d4
SWI 2
SWI 3
[ :DEF:DEFAULT_TEXT
ADR r0, libdatasize_text
ADR r1, libdatasize_tag
|
ADR r0, libdatasize_tag
]
BL |_kernel_getmessage|
BL writectrl
SUB r0, r6, r4
MOV r1, sp
MOV r2, #9
SWI &d4
SWI 2
SWI 3
ADD sp, sp, #8
LDMIA sp!, {r0, r1, r2}
ADR r0, E_StaticSizeWrong
B Failed
writectrl
STMDB sp!, {r1,lr}
MOV r1, r0
01 LDRB r0, [r1], #1
CMP r0, #" "
LDMCCIA sp!, {r1,pc}
SWI 0
B %BT01
stubdatasize_tag
DCB "C67",0
libdatasize_tag
DCB "C68",0
[ :DEF:DEFAULT_TEXT
stubdatasize_text
DCB "Stub data size = ",0
libdatasize_text
DCB "Library data size = ",0
ALIGN
]
staticsizeok
]
SUB r3, r3, r2 ; size of library chunk statics
; and the offset must agree with that for all earlier chunks
LDR r1, [r13, #Proc_RegOffset + 4]
LDR r1, [r1, #SC_SLOffset+SL_Client_Offset]
ADD r2, r2, r1 ; relocate address to copy to!!
SUB r1, r2, r4
CMP r5, #0
CMPNE r5, r1
ADRNE r0, E_StaticOffsetInconsistent
BNE Failed
MOV r5, r1
CMP r3, #0
BLE NextLibraryChunk ; no statics for this chunk
; Copy the data from our fixed static data area to the clients dynamic
; static data area. No zero initialised data at all.
CopyLibStatics
LDR r1, [r4], #+4
STR r1, [r2], #+4
SUBS r3, r3, #4
BNE CopyLibStatics
LDR r1, [r14, #LI_Id-LI_ItemSize]
CMP r1, #1 ; was this the library kernel?
BNE NextLibraryChunk
CMP r11, #3
ORRGE r3, r3, #ClientFlag_APCS_32
05 STRB r3, [r2, #-32*4] ; yuck! - set ClientFlags
B NextLibraryChunk
EndStubInit
; Set up SL_Lib_Offset
LDR r12, [r13, #Proc_RegOffset + 4] ; r1 out
STR r5, [r12, #SC_SLOffset+SL_Lib_Offset]
[ StrongARM
; patched branch code requires SynchroniseCodeAreas
MOV r0,#0 ;fully synchronise (too lazy to narrow down address range)
SWI XOS_SynchroniseCodeAreas
]
MOV r6, #LibraryVersionNumber
Proc_RegList SETS "r0-r5, r12" ; don't restore r6 (hacky :))
EXITS
Failed
; Here with r0=error block if failed for one reason or another
BL |_kernel_copyerror|
STR r0, [r13, #Proc_RegOffset]
EXITVS
StubInitValue
MOV pc, #0
ErrorBlock UnknownSWI, "SWI value out of range for module %0", BadSWI
ErrorBlock BadMemory, "Not enough memory for C library", C01
ErrorBlock UnknownLib, "Unknown library chunk", C02
ErrorBlock StaticSizeWrong, "Static data size in library and stub disagree", C04
ErrorBlock StaticOffsetInconsistent, "Static data offset not the same for all library chunks", C05
ErrorBlock OldAPCS, "Calling standard no longer supported by C library", C71
ALIGN
LTORG
END