initmodule 16.4 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
; 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}

25 26 27
        GBLL    NoStubEntries
NoStubEntries   SETL    {TRUE}  ; stop h_modmacro defining Entry

Neil Turton's avatar
Neil Turton committed
28 29 30 31 32 33 34 35
        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

36 37
        GET     Hdr:Proc

Neil Turton's avatar
Neil Turton committed
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
        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
149 150 151 152
;              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
Neil Turton's avatar
Neil Turton committed
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
;              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.
175
        ;  0  old-style init.  Client uses APCS_A.  No longer supported.
Neil Turton's avatar
Neil Turton committed
176 177
        ;  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.
178 179
        ;  3  APCS-32 init.  Client uses APCS-3/32bit.
        ;  4  APCS-32 module init.  Stack is SWI stack, not in the heap.
Neil Turton's avatar
Neil Turton committed
180

181
        EntryS  "r0-r6"
Neil Turton's avatar
Neil Turton committed
182 183

        ; Check SWI in valid range
184 185 186 187 188 189 190 191 192
      [ {CONFIG}=26
        CMP     r11, #1
      |
        CMP     r11, #3
      ]
        ADRLO   r0, E_OldAPCS
        BLO     Failed

        CMP     r11, #4
Neil Turton's avatar
Neil Turton committed
193 194 195
        ADRHI   r0, E_UnknownSWI
        BHI     Failed

196 197
        CLRPSR  F_bit:OR:I_bit, lr      ; ensure IRQs enabled
        NOP
Neil Turton's avatar
Neil Turton committed
198 199 200 201 202 203 204

        ; 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?
205
        CMPNE   r11, #4
Neil Turton's avatar
Neil Turton committed
206 207 208 209 210 211
        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
212
        ; For things linked with old stubs r6 may be zero - if so,
Neil Turton's avatar
Neil Turton committed
213
        ; we use the old default root stack size
214
        MOVS    r6, r6, LSR #6
Neil Turton's avatar
Neil Turton committed
215 216 217 218 219 220 221
        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

222
      [ Proc_RegOffset = 0
Neil Turton's avatar
Neil Turton committed
223
        STMIA   r13, {r2, r12, lr}      ; return values of r0, r1 & r2 (Data end, stack base and stack top)
224 225 226 227 228 229 230
      |
        [ Proc_RegOffset = 4
        STMIB   r13, {r2, r12, lr}      ; return values of r0, r1 & r2 (Data end, stack base and stack top)
        |
        ! 1, "Proc_RegOffset = ?"
        ]
      ]
Neil Turton's avatar
Neil Turton committed
231
        CMP     r11, #2                 ; module?
232
        CMPNE   r11, #4
Neil Turton's avatar
Neil Turton committed
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
        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

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
        ; 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
Neil Turton's avatar
Neil Turton committed
332

333 334 335 336
        ADD     r3, r2, r4              ; r2, r3 now point to address constant table

        LDR     r4, [r14, #LI_EntryBase-LI_ItemSize]    ; Our entry table
FixAddresses
Neil Turton's avatar
Neil Turton committed
337 338
        CMP     r2, r3
        BEQ     ChunkEntriesDone
339 340 341 342 343 344 345 346
        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
Neil Turton's avatar
Neil Turton committed
347

348 349 350
        ; Create a table of BL &xxx

FixBranches
Neil Turton's avatar
Neil Turton committed
351 352 353 354
        LDR     r4, [r14, #LI_EntryBase-LI_ItemSize]    ; Our entry table
FixEntries
        CMP     r2, r3
        BEQ     ChunkEntriesDone
355
        LDR     r1, [r4]
Neil Turton's avatar
Neil Turton committed
356 357 358 359
        ADD     r1, r1, r4, LSR #2
        SUB     r1, r1, r2, LSR #2
        BIC     r1, r1, #&FF000000
        ORR     r1, r1, #&EA000000     ; le branch!
360
        ADD     r4, r4, #4
Neil Turton's avatar
Neil Turton committed
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
        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
376
 [ 1 = 1
Neil Turton's avatar
Neil Turton committed
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
        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
441
        LDR     r1, [r13, #Proc_RegOffset + 4]
Neil Turton's avatar
Neil Turton committed
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
        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?
464 465 466 467
        BNE     NextLibraryChunk
        CMP     r11, #3
        ORRGE   r3, r3, #ClientFlag_APCS_32
05      STRB    r3, [r2, #-32*4]        ; yuck! - set ClientFlags
Neil Turton's avatar
Neil Turton committed
468 469 470 471
        B       NextLibraryChunk

EndStubInit
        ; Set up SL_Lib_Offset
472
        LDR     r12, [r13, #Proc_RegOffset + 4]          ; r1 out
Neil Turton's avatar
Neil Turton committed
473 474
        STR     r5, [r12, #SC_SLOffset+SL_Lib_Offset]

Neil Turton's avatar
Neil Turton committed
475 476 477 478 479 480
  [ StrongARM
    ; patched branch code requires SynchroniseCodeAreas
    MOV    r0,#0                     ;fully synchronise (too lazy to narrow down address range)
    SWI    XOS_SynchroniseCodeAreas
  ]

Neil Turton's avatar
Neil Turton committed
481
        MOV     r6, #LibraryVersionNumber
482 483
Proc_RegList    SETS "r0-r5, r12"  ; don't restore r6 (hacky :))
        EXITS
Neil Turton's avatar
Neil Turton committed
484 485 486 487

Failed
        ; Here with r0=error block if failed for one reason or another
        BL      |_kernel_copyerror|
488 489
        STR     r0, [r13, #Proc_RegOffset]
        EXITVS
Neil Turton's avatar
Neil Turton committed
490 491 492 493 494 495 496 497 498

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
499
        ErrorBlock OldAPCS, "Calling standard no longer supported by C library", C71, withdefault
Neil Turton's avatar
Neil Turton committed
500 501 502 503 504
        ALIGN

        LTORG

        END