k_body 115 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
; 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 -*-
;* Body of shared library kernel for Arthur/Brazil
;* Lastedit: 13 Dec 90 14:39:20 by Harry Meekings *
;
; Copyright (C) Acorn Computers Ltd., 1988.
;
; 23-Sep-94 AMcC  __rt_ symbols defined and exported (compatible with cc vsn 5 etc)
;

24 25
        GET     h_stack.s
        GET     h_workspc.s
26
        GET     h_common.s
Ben Avison's avatar
Ben Avison committed
27
        GET     Hdr:OSMisc
Neil Turton's avatar
Neil Turton committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

        EXPORT  |_kernel_exit|
        EXPORT  |_kernel_setreturncode|
        EXPORT  |_kernel_exittraphandler|
        EXPORT  |_kernel_unwind|
        EXPORT  |_kernel_procname|
        EXPORT  |_kernel_language|

        EXPORT  |_kernel_command_string|
        EXPORT  |_kernel_hostos|
        EXPORT  |_kernel_swi|
        EXPORT  |_kernel_swi_c|
        EXPORT  |_kernel_osbyte|
        EXPORT  |_kernel_osrdch|
        EXPORT  |_kernel_oswrch|
        EXPORT  |_kernel_osbget|
        EXPORT  |_kernel_osbput|
        EXPORT  |_kernel_osgbpb|
        EXPORT  |_kernel_osword|
        EXPORT  |_kernel_osfind|
        EXPORT  |_kernel_osfile|
        EXPORT  |_kernel_osargs|
        EXPORT  |_kernel_oscli|
        EXPORT  |_kernel_last_oserror|
52
        EXPORT  |_kernel_peek_last_oserror|
Neil Turton's avatar
Neil Turton committed
53 54 55 56 57 58 59
        EXPORT  |_kernel_system|
        EXPORT  |_kernel_getenv|
        EXPORT  |_kernel_setenv|

        EXPORT  |_kernel_register_allocs|
        EXPORT  |_kernel_register_slotextend|
        EXPORT  |_kernel_alloc|
60 61
        EXPORT  |__rt_allocauto|
        EXPORT  |__rt_freeauto|
Neil Turton's avatar
Neil Turton committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

        EXPORT  |_kernel_current_stack_chunk|
        EXPORT  |_kernel_stkovf_split_0frame|
        EXPORT  |_kernel_stkovf_split|
        EXPORT  |_kernel_stkovf_copyargs|
        EXPORT  |_kernel_stkovf_copy0args|

        EXPORT  |_kernel_udiv|
        EXPORT  |_kernel_urem|
        EXPORT  |_kernel_udiv10|
        EXPORT  |_kernel_sdiv|
        EXPORT  |_kernel_srem|
        EXPORT  |_kernel_sdiv10|

        EXPORT  |_kernel_escape_seen|
        EXPORT  |_kernel_init|
        EXPORT  |_kernel_client_is_module|
 [ ModeMayBeNonUser
        EXPORT  |_kernel_entermodule|
        EXPORT  |_kernel_moduleinit|
        EXPORT  |_kernel_irqs_on|
        EXPORT  |_kernel_irqs_off|
 ]
85
        EXPORT  |_kernel_irqs_disabled|
Neil Turton's avatar
Neil Turton committed
86 87 88 89 90 91 92 93 94 95
        EXPORT  |_kernel_processor_mode|
        EXPORT  |_kernel_RMAalloc|
        EXPORT  |_kernel_RMAfree|
        EXPORT  |_kernel_RMAextend|

        EXPORT  |_kernel_fpavailable|

        EXPORT  |_kernel_call_client|
        EXPORT  |_kernel_raise_error|

96 97
        EXPORT  |__rt_sdiv|
        EXPORT  |__rt_udiv|
Neil Turton's avatar
Neil Turton committed
98 99 100
        EXPORT  |__rt_udiv10|
        EXPORT  |__rt_sdiv10|

101 102 103 104 105
        EXPORT  |x$divide|
        EXPORT  |x$udivide|
        EXPORT  |x$remainder|
        EXPORT  |x$uremainder|

Neil Turton's avatar
Neil Turton committed
106
        EXPORT  |__counter|
Ben Avison's avatar
Ben Avison committed
107
 [ {CONFIG}<>26
Ben Avison's avatar
Ben Avison committed
108
        EXPORT  |AcquireMutex|
Ben Avison's avatar
Ben Avison committed
109
 ]
Neil Turton's avatar
Neil Turton committed
110 111 112 113

PSRBits         *       &FC000003
PSRZBit         *       &40000000
PSRVBit         *       &10000000
114

Neil Turton's avatar
Neil Turton committed
115
PSRIBit         *       &08000000
116
PSRFBit         *       &04000000
117 118
PSRMode         *       &00000003
PSRUSRMode      *       &00000000
Neil Turton's avatar
Neil Turton committed
119
PSRSVCMode      *       &00000003
120 121 122
PSRPrivileged   *       &00000003

PSR32IBit       *       &00000080
123
PSR32FBit       *       &00000040
124 125 126 127 128
PSR32Mode       *       &0000001F
PSR32USRMode    *       &00000010
PSR32SVCMode    *       &00000013
PSR32UNDMode    *       &0000001B
PSR32Privileged *       &0000000F
Neil Turton's avatar
Neil Turton committed
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


; A RTS$$Data area
                ^       0
lang_size       #       4
lang_codeBase   #       4
lang_codeLimit  #       4
lang_name       #       4
lang_Init       #       4
lang_Finalise   #       4
lang_Trap       #       4
lang_UncaughtTrap #     4
lang_Event      #       4
lang_UnhandledEvent #   4
lang_FastEvent  #       4
lang_Unwind     #       4
lang_ProcName   #       4

; a _kernel_unwindblock
                ^       0
uwb_r4          #       4
uwb_r5          #       4
uwb_r6          #       4
uwb_r7          #       4
uwb_r8          #       4
uwb_r9          #       4
uwb_fp          #       4
uwb_sp          #       4
uwb_pc          #       4
uwb_sl          #       4
uwb_f4          #       3*4
uwb_f5          #       3*4
uwb_f6          #       3*4
uwb_f7          #       3*4
uwb_size        #       0


166
        GET     Hdr:Wimp
Neil Turton's avatar
Neil Turton committed
167
 [ DDE
168
        GET     Hdr:DDEUtils
Neil Turton's avatar
Neil Turton committed
169
 ]
170 171
        GET     Hdr:Machine.<Machine>

Neil Turton's avatar
Neil Turton committed
172 173 174 175

        MACRO
        CallClient $r
        ; Always called with v6 = the kernel static base.
176
        ; If shared library, used to worry about calling standard change.
Neil Turton's avatar
Neil Turton committed
177 178 179 180 181 182
        MOV     lr, pc
        MOV     pc, $r
        MEND


|_kernel_call_client|
183
 [ :LNOT:(SharedLibrary :LAND: {CONFIG}=26)
Neil Turton's avatar
Neil Turton committed
184 185
        MOV     pc, a4
   |
186 187 188
  ; If we're 26-bit and a shared library, we need to cope with APCS-32
  ; clients not preserving flags
        FunctionEntry
Neil Turton's avatar
Neil Turton committed
189 190
        MOV     lr, pc
        MOV     pc, a4
191
        Return
Neil Turton's avatar
Neil Turton committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
 ]


 [ ModeMayBeNonUser
|_kernel_moduleinit|
; Preserve r9 (== v6) across this call
        ADD     sl, r1, #SC_SLOffset

        LoadStaticBase ip, r1
        LDMIB   r0, {r1-r2}
        MOV     r0, #0
        STMIA   ip, {r0-r2}
        ADR     r0, |_kernel_RMAalloc|
        STR     r0, [ip, #O_allocProc]  ; default alloc proc
        ADR     r0, |_kernel_RMAfree|
        STR     r0, [ip, #O_freeProc]   ; and no dealloc proc
Ben Avison's avatar
Ben Avison committed
208
        LDR     pc, [sp], #4
209
 ]
Neil Turton's avatar
Neil Turton committed
210 211

|_kernel_irqs_disabled|
212 213 214 215 216 217 218
 [ {CONFIG} = 26
        AND     a1, lr, #PSRIBit
 |
        MRS     a1, CPSR
        AND     a1, a1, #PSR32IBit
 ]
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
219

220
 [ ModeMayBeNonUser
Neil Turton's avatar
Neil Turton committed
221
|_kernel_RMAalloc|
222 223
        FunctionEntry
|_kernel_RMAalloc_from_extend|
Neil Turton's avatar
Neil Turton committed
224
        MOVS    r3, a1
225 226 227
        Return  ,,EQ
        MOV     r0, #Module_Claim
        SWI     Module
Neil Turton's avatar
Neil Turton committed
228 229
        MOVVS   a1, #0
        MOVVC   a1, r2
230
        Return
Neil Turton's avatar
Neil Turton committed
231 232

|_kernel_RMAextend|
233
        FunctionEntry
Neil Turton's avatar
Neil Turton committed
234 235
        CMP     a1, #0
        MOVEQ   a1, a2
236
        BEQ     |_kernel_RMAalloc_from_extend|
Neil Turton's avatar
Neil Turton committed
237
        CMP     a2, #0
238
        BEQ     |_kernel_RMAfree_from_extend|
Neil Turton's avatar
Neil Turton committed
239 240 241 242 243 244 245 246
        LDR     r3, [a1, #-4]
        SUB     r3, r3, #4              ; Correct to useable size
        SUB     r3, a2, r3
        MOV     r2, a1
        MOV     r0, #Module_Extend
        SWI     Module
        MOVVS   a1, #0
        MOVVC   a1, r2
247
        Return
Neil Turton's avatar
Neil Turton committed
248 249

|_kernel_RMAfree|
250 251
        FunctionEntry
|_kernel_RMAfree_from_extend|
Neil Turton's avatar
Neil Turton committed
252 253 254 255
        MOVS    r2, a1
        MOVNE   r0, #Module_Free
        SWINE   Module
        MOV     a1, #0
256
        Return
Neil Turton's avatar
Neil Turton committed
257 258 259 260 261 262 263

  |

|_kernel_RMAalloc|
|_kernel_RMAextend|
|_kernel_RMAfree|
        MOV     a1, #0
264
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
265 266 267

 ]

268 269
; Don't corrupt a1-a4 in these two routines, please.
; __counter relies on it, for one.
Neil Turton's avatar
Neil Turton committed
270
|_kernel_irqs_on|
271 272 273
 [ {CONFIG}=26
        BICS    pc, lr, #PSRIBit        ; 32-bit OK - in {CONFIG}=26
 |
274
   [ NoARMv6
275
|_kernel_irqs_on_NoARMv6|
276 277 278
        MRS     ip, CPSR
        BIC     ip, ip, #PSR32IBit
        MSR     CPSR_c, ip
279
        Return  ,LinkNotStacked
280
   ]
281 282 283
   [ SupportARMv6 :LAND: (:LNOT: NoARMv6 :LOR: SHARED_C_LIBRARY)
|_kernel_irqs_on_SupportARMv6|
        CPSIE   i
284
        Return  ,LinkNotStacked
285
   ]
286
 ]
Neil Turton's avatar
Neil Turton committed
287 288

|_kernel_irqs_off|
289
 [ {CONFIG}=26
290
        ORRS    pc, lr, #PSRIBit
291 292
 |
   [ NoARMv6
293
|_kernel_irqs_off_NoARMv6|
294 295 296
        MRS     ip, CPSR
        ORR     ip, ip, #PSR32IBit
        MSR     CPSR_c, ip
297
        Return  ,LinkNotStacked
298
   ]
299 300 301
   [ SupportARMv6 :LAND: (:LNOT: NoARMv6 :LOR: SHARED_C_LIBRARY)
|_kernel_irqs_off_SupportARMv6|
        CPSID   i
302
        Return  ,LinkNotStacked
303
   ]
304
 ]
Neil Turton's avatar
Neil Turton committed
305 306

|_kernel_processor_mode|
307 308 309
      [ {CONFIG}=26
        AND     a1, lr, #3      ; the question is anyway about the caller's
        MOVS    pc, lr          ; state, not ours - the answers are probably
Neil Turton's avatar
Neil Turton committed
310
                                ; the same.
311 312 313 314 315
      |
        MRS     a1, CPSR
        AND     a1, a1, #PSR32Mode
        MOV     pc, lr
      ]
Neil Turton's avatar
Neil Turton committed
316 317 318

|_kernel_client_is_module|
        LoadStaticBase a1, ip
319
      [ {CONFIG}=26
320
        TST     r14, #PSRPrivileged
321 322 323 324
      |
        MRS     ip, CPSR
        TST     ip, #PSR32Privileged
      ]
Neil Turton's avatar
Neil Turton committed
325 326
        MOVNE   a1, #0
        LDREQ   a1, [a1, #O_moduleDataWord]
327
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
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

 [ ModeMayBeNonUser
|_kernel_entermodule|
        ; user entry to a module.  Need to allocate a stack in application
        ; workspace.
        ; r0 points to a kernel init block
        ; (for old stubs) r12 is the module's private word pointer.
        ; (for new stubs) r12 is -1
        ;                r8 is the module's private word pointer
        ;                r6 is the requested root stack size
        MOV     r9, r0
        SWI     GetEnv
        MOV     r4, r1
        MOV     r1, #Application_Base
        CMPS    r12, #0
        MOVLT   r12, r8
        MOVGE   r6, #OldRootStackSize
        STR     r6, [r1, #SC_size]
        LDR     r12, [r12]
        LDMIB   r12, {r2, r3}           ; relocation offsets
        ADD     r5, r1, #SC_SLOffset+SL_Lib_Offset
        STMIA   r5, {r2, r3}            ; transfer to user stack chunk
        ADD     r2, r1, r6
        MOV     r3, #1                  ; 'is a module' flag
        MOV     r0, r9
 ]

|_kernel_init|
        ; r0 points to a kernel init block.
        ; r1 = base of root stack chunk
        ; r2 = top of root stack chunk (= initial sp)
        ; r3 = 0 if ordinary application, 1 if module
        ; r4 = end of workspace (= heap limit).
        ; Always in user mode.
        MOV     sp, r2
        ADD     sl, r1, #SC_SLOffset
        MOV     fp, #0                  ; mark base of stack
        STR     fp, [r1, #SC_next]
        STR     fp, [r1, #SC_prev]
        STR     fp, [r1, #SC_deallocate]
        LDR     r5, =IsAStackChunk
        STR     r5, [r1, #SC_mark]

        LoadStaticBase v6, ip
        STR     r1, [v6, #O_heapBase]
        STR     r1, [v6, #O_rootStackChunk]
        LDMIA   r0, {r0-r2}
        CMP     r3, #0                  ; if module, imagebase (in RMA) isn't
        MOVNE   r0, #Application_Base   ; interesting
        STMIA   v6, {r0-r2}

        ; Copy the argument string (in SWI mode), so we can access it
        ; (assumed in page 0), while all user access to page 0 is disabled
        MOV     r6, sp                  ; (sp may be different in SWI mode)
        SWI     EnterSVC
        SWI     GetEnv
        MOV     r1, r0
01      LDRB    r5, [r1], #+1
 [ DDE
        CMP     r5, #' '                ; I seem to be getting LF terminated
        BCS     %B01                    ; commands. I don't know why.
 |
        CMP     r5, #0
        BNE     %B01
 ]
        SUB     r1, r1, r0
        ADD     r1, r1, #3
        BIC     r1, r1, #3
02      SUBS    r1, r1, #4
        LDR     r5, [r0, r1]
        STR     r5, [r6, #-4]!
        BNE     %B02
400
        WritePSRc 0, r5                  ; back to user mode
Neil Turton's avatar
Neil Turton committed
401
 [ DDE
402
        SWI     XDDEUtils_GetCLSize
Neil Turton's avatar
Neil Turton committed
403 404 405 406 407 408 409 410 411 412 413 414
        MOVVS   r0, #0
        CMP     r0, #0
        BEQ     %F04
        ADD     r0, r0, #3
        BIC     r0, r0, #3
        SUB     r1, r6, r0
        MOV     r0, r1
03      LDRB    r2, [r6], #+1
        CMP     r2, #' '
        MOVCC   r2, #' '
        STRB    r2, [r0], #+1
        BCS     %B03
415
        SWI     XDDEUtils_GetCl
Neil Turton's avatar
Neil Turton committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
        MOV     r6, r1
04
 ]
        STR     r6, [v6, #O_ArgString]

        ADRL    r0, |_kernel_malloc|
        STR     r0, [v6, #O_allocProc]  ; default alloc proc
        ADRL    r0, |_kernel_free|
        STR     r0, [v6, #O_freeProc]   ; and no dealloc proc

        ; set up a small stack chunk for use in performing stack extension.
        ; We needn't bother with most of the fields in the description of
        ; this chunk - they won't ever be used.  We must set mark (to be
        ; not IsAStackChunk) and SL_xxx_Offset. Also prev.
        STR     sp, [v6, #O_extendChunk]
431
      [ {CONFIG}<>26
Ben Avison's avatar
Ben Avison committed
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
        MOV     r0, #OSPlatformFeatures_ReadCodeFeatures
        SWI     XOS_PlatformFeatures
        MOVVS   r0, #0
        ; _swp_available is used as a bitfield:
        ; bit 0 => SWP available
        ; bit 1 => LDREX/STREX available
        ; bit 2 => LDREX[B|D|H]/STREX[B|D|H] available
        ; This is a simple manipulation of the PlatformFeatures return flags
        ASSERT  CPUFlag_NoSWP                 = 1:SHL:11
        ASSERT  CPUFlag_LoadStoreEx           = 1:SHL:12
        ASSERT  CPUFlag_LoadStoreClearExSizes = 1:SHL:13
        EOR     r0, r0, #CPUFlag_NoSWP
        MOV     r1, #7
        AND     r1, r1, r0, LSR #11
        STR     r1, [v6, #O__swp_available]
447 448 449 450 451
      |
        BL      CheckIfSwpAvailable
      ]
        MOV     r0, #1
        STR     r0, [v6, #O_extendChunkNotInUse]
Neil Turton's avatar
Neil Turton committed
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
        ADD     r0, sl, #SL_Lib_Offset
        LDMIA   r0, {r1, r2}
        ADD     r0, sp, #SC_SLOffset+SL_Lib_Offset
        STMIA   r0, {r1, r2}
        STR     sp, [sp, #SC_mark]
        STR     fp, [sp, #SC_prev]      ; 0 to mark end of chain
        MOV     r0, #ExtendStackSize
        STR     r0, [sp, #SC_size]
        ADD     sp, sp, #ExtendStackSize
        STR     sp, [v6, #O_heapTop]    ; save updated value for heap base
        STR     r4, [v6, #O_heapLimit]
        MOV     sp, r6

        MOV     r0, #1
        STRB    r0, [v6, #O_callbackInactive]
        STR     fp, [v6, #O_hadEscape]
        STR     r3, [v6, #O_moduleDataWord]
        STRB    fp, [v6, #O_escapeSeen]

        ; Determine whether FP is available (to decide whether fp regs need
        ; saving over _kernel_system)
        ; The SWI will fail if it isn't
        SWI     FPE_Version
        MOVVC   r0, #&70000     ; IVO, DVZ, OFL cause a trap
        WFSVC   r0
        MOVVC   r0, #1
        MOVVS   r0, #0
        STRB    r0, [v6, #O_fpPresent]

481 482 483 484 485 486 487 488 489 490
        ; Check where the stacks are
        ASSERT  O_svcStack = O_undStack + 4
        MOV     r0, #6
        ADR     r1, RSI6_List
        ADD     r2, v6, #O_undStack
        SWI     XOS_ReadSysInfo
        LDRVS   r0, =&01E02000
        LDRVS   r1, =&01C02000
        STMVSIA r2, {r0, r1}

Neil Turton's avatar
Neil Turton committed
491 492 493 494 495 496 497 498 499 500 501 502 503
        ADD     r4, v6, #O_IIHandlerInData
        ADR     r5, IIHandlerInDataInitValue
        BL      CopyHandler
        ADD     r4, v6, #O_PAHandlerInData
        ADR     r5, PAHandlerInDataInitValue
        BL      CopyHandler
        ADD     r4, v6, #O_DAHandlerInData
        ADR     r5, DAHandlerInDataInitValue
        BL      CopyHandler
        ADD     r4, v6, #O_AEHandlerInData
        ADR     r5, AEHandlerInDataInitValue
        BL      CopyHandler

Neil Turton's avatar
Neil Turton committed
504 505 506 507 508 509
 [ StrongARM   ;CopyHandler does some dynamic code
   ;r0,lr are free to use here
   MOV   r0, #0
   SWI   XOS_SynchroniseCodeAreas
 ]

Neil Turton's avatar
Neil Turton committed
510 511 512 513
        MOV     r0, #0
        BL      InstallHandlers

        MOV     r0, #0
514
        SWI     XWimp_ReadSysInfo
Neil Turton's avatar
Neil Turton committed
515 516 517 518 519
        MOVVS   r0, #0                  ; error - presumably Wimp not present
        CMP     r0, #0
        MOVNE   r0, #1
        STRB    r0, [v6, #O_underDesktop]

520
        LDREQ   r1, [v6, #O_heapLimit]
Neil Turton's avatar
Neil Turton committed
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
        MOVNE   r0, #Env_ApplicationSpace
        MOVNE   r1, #0
        SWINE   ChangeEnv
        STR     r1, [v6, #O_knownSlotSize]
        STR     r1, [v6, #O_initSlotSize]

        MOV     v1, #0
        LDMIB   v6, {v2, v3}
CallInitProcs Keep
        CMP     v2, v3
        BGE     EndInitProcs
        LDR     v4, [v2, #lang_size]
        CMP     v4, #lang_Init
        BLE     NoInitProc
        LDR     a1, [v2, #lang_Init]
        CMP     a1, #0
        BEQ     NoInitProc
        CallClient a1
        CMP     a1, #0
        MOVNE   v1, a1
NoInitProc
        ADD     v2, v2, v4
        B       CallInitProcs
EndInitProcs
        CMP     v1, #0
        BEQ     NoMainProgram
        CallClient v1

NoMainProgram
        BL      Finalise
        ADR     r0, E_NoMainProgram
        BL      |_kernel_copyerror|
FatalError Keep
        SWI     GenerateError

556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
 [ {CONFIG}=26
; v6 = static base
; sp -> extendChunk, which we will use as workspace
; assumed entered in USR mode with SVC stack empty
CheckIfSwpAvailable
        STMIA   sp!, {r0-r12,r14}      ; error handler might corrupt anything
        MOV     r0, #0                 ; start off assuming error will happen
        STR     r0, [v6, #O__swp_available]

        MOV     r0, #6
        MOV     r1, #0
        MOV     r2, #0
        MOV     r3, #0
        SWI     XOS_ChangeEnvironment           ; read existing error handler
        STMIA   sp!, {r1-r3}
        MOV     r0, #6
        ADR     r1, %FT01
        MOV     r2, sp
        MOV     r3, sp
        SWI     XOS_ChangeEnvironment           ; set temp error handler

        SWP     r0, r0, [sp]                    ; try a SWP

        MOV     r0, #1
        STR     r0, [v6, #O__swp_available]     ; note we were successful
        B       %FT02
01
        MOV     sp, r0                          ; put back sp after error
02
        MOV     r0, #6
        LDMDB   sp!, {r1-r3}
        SWI     XOS_ChangeEnvironment           ; restore error handler
        LDMDB   sp!, {r0-r12,pc}
 ]

Neil Turton's avatar
Neil Turton committed
591 592
;StrongARM - there is dynamic code here, but this is sorted in _kernel_init, after
;all calls to CopyHandler
Neil Turton's avatar
Neil Turton committed
593
CopyHandler
594
        LDMIA   r5!, {r6, r7}                   ; first 2 instructions
Neil Turton's avatar
Neil Turton committed
595
        STMIA   r4!, {r6, r7}
596 597 598 599 600 601 602 603
        LDR     r6, =&E51FF004                  ; LDR PC,<nextword>
        STR     r6, [r4], #4
        STR     r5, [r4]                        ; address of main handler
        MOV     pc, r14

        LTORG

RSI6_List
604
        DCD     OSRSI6_UNDSTK, OSRSI6_SVCSTK, -1
Neil Turton's avatar
Neil Turton committed
605 606

|Sys$RCLimit|
Jeffrey Lee's avatar
Jeffrey Lee committed
607
        DCB     "Sys$$RCLimit", 0
Neil Turton's avatar
Neil Turton committed
608 609 610 611
        ALIGN

|_kernel_exit|
 [ ModeMayBeNonUser
612
        [ {CONFIG} = 26
Neil Turton's avatar
Neil Turton committed
613
        TST     r14, #3
614 615 616 617
        |
        MRS     ip, CPSR
        TST     ip, #PSR32Privileged
        ]
Neil Turton's avatar
Neil Turton committed
618 619 620
        BEQ     |_kernel_user_exit|
        MOV     ip, sp
        SUB     sp, sp, #4*12              ; set up an unwind block
Ben Avison's avatar
Ben Avison committed
621
        STR     sl, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
622 623 624 625 626 627 628 629 630 631 632
        STMFD   sp!, {a1, r3-r9, fp, ip, r14}  ; r3 to reserve an extra word
        BL      |_kernel_exittraphandler|
01      ADD     a1, sp, #8
        ADD     a2, sp, #4
        BL      |_kernel_unwind|
        CMP     a1, #0
        BNE     %B01
        MOV     r0, #1                  ; get base address of RMA
        SWI     XOS_ReadDynamicArea
        MOVVC   r14, r0
        MOVVS   r14, #&01800000         ; default to fixed base if SWI fails
Ben Avison's avatar
Ben Avison committed
633
        LDR     a1, [sp], #4
Neil Turton's avatar
Neil Turton committed
634
        CMP     a1, r14
Ben Avison's avatar
Ben Avison committed
635 636
        ADRCC   a1, E_Exit
        BLCC    |_kernel_copyerror|     ; BL<cond> 32-bit OK
637
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
638
        LDMIB   sp, {r4-r9, fp, sp, pc}^
639
        |
Ben Avison's avatar
Ben Avison committed
640
      [ {FALSE} ; this instruction is now deprecated
641
        LDMIB   sp, {r4-r9, fp, sp, pc}
Ben Avison's avatar
Ben Avison committed
642 643 644 645 646
      |
        LDMIB   sp, {r4-r9, fp, ip, lr}
        MOV     sp, ip
        MOV     pc, lr
      ]
647
        ]
Neil Turton's avatar
Neil Turton committed
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689

        ALIGN

        ErrorBlock Exit, "Exit called", C49

|_kernel_user_exit|
 ]
        LoadStaticBase v6, ip
; the work of finalisation gets done in the Exit handler.
; Due to a bug in the RISC OS kernel where the PC value in the error block
; is incorrectly written if OS_Exit is called with a return value outside
; the range 0 .. Sys$RCLimit we perform the check ourselves and call
; GenerateError directly
        LDR     r2, [v6, #O_returnCode]
        CMP     r2, #0
        SWIEQ   Exit
        ADR     r0, |Sys$RCLimit|
        ADD     r1, v6, #O_returnCodeLimit
        MOV     r2, #4
        MOV     r3, #0
        MOV     r4, #0
        SWI     XOS_ReadVarVal
        MOVVS   r3, #&100
        BVS     KernelExit1
        MOV     r3, #0
KernelExit2
        LDRB    r0, [r1], #1
        SUB     r0, r0, #'0'
        CMP     r0, #10
        BCS     KernelExit1
        ADD     r3, r3, r3, LSL #2
        ADD     r3, r0, r3, LSL #1
        B       KernelExit2
KernelExit1
        ADR     r0, E_BadReturnCode
        BL      |_kernel_copyerror|
        LDR     r2, [v6, #O_returnCode]
        CMP     r2, #0
        ADDLTS  r2, r2, r3
        CMPNE   r2, r3
        LDR     r1, ABEXString
        SWICC   Exit
Ben Avison's avatar
Ben Avison committed
690
        STR     r0, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
691
        BL      Finalise
Ben Avison's avatar
Ben Avison committed
692
        LDR     r0, [sp],  #4
Neil Turton's avatar
Neil Turton committed
693 694 695 696 697 698 699 700 701
        SWI     GenerateError

; Generate an external error. Re-init the stack to the root stack chunk.
; The stack contents are not needed since this is an external error.
; In some cases we must re-init the stack (eg. stack overflow).
; The only case where it might may a difference is under a debugger in which
; case tough luck, you don't get a backtrace.
|_kernel_raise_error|
        TEQ     r0, #0
702
        Return  ,LinkNotStacked, EQ
Neil Turton's avatar
Neil Turton committed
703
 [ ModeMayBeNonUser
704
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
705
        TST     r14, #3
706 707 708 709
        |
        MRS     ip, CPSR
        TST     ip, #PSR32Privileged
        ]
Neil Turton's avatar
Neil Turton committed
710 711 712 713 714 715 716 717
        BNE     |_kernel_exit|
 ]
        LoadStaticBase v6, ip
        LDR     sl, [v6, #O_rootStackChunk]
        LDR     sp, [sl, #SC_size]
        ADD     sp, sl, sp
        ADD     sl, sl, #SC_SLOffset
        MOV     fp, #0
Ben Avison's avatar
Ben Avison committed
718
        STR     a1, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
719
        BL      Finalise
Ben Avison's avatar
Ben Avison committed
720
        LDR     a1, [sp], #4
Neil Turton's avatar
Neil Turton committed
721 722 723
        SWI     GenerateError

Finalise
Ben Avison's avatar
Ben Avison committed
724
        STR     lr, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
        LDMIB   v6, {v2, v3}
CallFinaliseProcs
        CMP     v2, v3
        BGE     EndFinaliseProcs
        LDR     v4, [v2, #lang_size]
        CMP     v4, #lang_Finalise
        BLE     NoFinaliseProc
        LDR     v1, [v2, #lang_Finalise]
        CMP     v1, #0
        BEQ     NoFinaliseProc
        CallClient v1
NoFinaliseProc
        ADD     v2, v2, v4
        B       CallFinaliseProcs
EndFinaliseProcs
 [ SharedLibrary
        ; Then do finalisation for the shared library (if we are one)
        ; Not CallClient here, because change of calling standards is
        ; inappropriate.
        LDR     v2, =|RTSK$$Data$$Base|
        LDR     v3, =|RTSK$$Data$$Limit|
CallFinaliseProcs_SL
        CMP     v2, v3
        BGE     EndFinaliseProcs_SL
        LDR     v4, [v2, #lang_size]
        CMP     v4, #lang_Finalise
        BLE     NoFinaliseProc_SL
        ; Before doing a shared library module finalisation we must check it
        ; was initialised by the client. Do this by comparing the language
        ; names.
        STMDB   sp!, {v1, v2, v3}
        LDR     v1, [v2, #lang_name]
        LDMIB   v6, {v2, v3}
CheckClientInit
        CMP     v2, v3
        LDMGEIA sp!, {v1, v2, v3}
        BGE     NoFinaliseProc_SL ; No client init found so can't finalise
        MOV     a1, v1
        LDR     a2, [v2, #lang_name]
CompareClientAndLibraryNames
        LDRB    a3, [a1], #1
        LDRB    a4, [a2], #1
        CMP     a3, a4
        LDRNE   a1, [v2, #lang_size]
        ADDNE   v2, v2, a1
        BNE     CheckClientInit
        CMP     a3, #0
        BNE     CompareClientAndLibraryNames
        LDMIA   sp!, {v1, v2, v3}
        LDR     v1, [v2, #lang_Finalise]
        CMP     v1, #0
        MOVNE   lr, pc
        MOVNE   pc, v1
NoFinaliseProc_SL
        ADD     v2, v2, v4
        B       CallFinaliseProcs_SL
EndFinaliseProcs_SL
 ]
Ben Avison's avatar
Ben Avison committed
783
        LDR     lr, [sp], #4
Neil Turton's avatar
Neil Turton committed
784 785 786 787 788 789
        B       RestoreOSHandlers


|_kernel_setreturncode|
        LoadStaticBase ip, a2
        STR     a1, [ip, #O_returnCode]
790
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
791 792 793 794

|_kernel_fpavailable|
        LoadStaticBase ip, a1
        LDRB    a1, [ip, #O_fpPresent]
795
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
796 797 798 799 800 801 802

ABEXString
        =       "ABEX"

        ErrorBlock BadReturnCode, "Return code too large", C50
        ErrorBlock NoMainProgram, "No main program", C51

803 804
        LTORG

Neil Turton's avatar
Neil Turton committed
805 806 807 808 809 810 811 812 813 814 815 816
 ;*-------------------------------------------------------------------*
 ;* Abort Handlers                                                    *
 ;*-------------------------------------------------------------------*

; The handlers called by the OS are in my static data, written there on
; startup, because that's the only way they can find out where the static data
; is.  They don't do much, other than save some registers and load r12 with
; the static base.  They are all the same length, and all immediately precede
; the real handler; when they are installed, a branch to the real handler is
; tacked on the end.

IIHandlerInDataInitValue
817
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
818 819 820 821 822 823 824 825
        SUB     r12, pc, #O_IIHandlerInData+12

; Now the bits of the abort handlers which get executed from the code.
; r12 is the address of my static data; the user's values of r0 and r12 are
; on the SVC stack.  (SVC mode, interrupts disabled).

IIHandler Keep
        SUB     r14, r14, #4
826 827 828 829
        STR     r14, [r12, #O_registerDump + 15 * 4]

        LDR     r14, [r12, #O_oldAbortHandlers + 0]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
830 831
        B       Aborted

832

Neil Turton's avatar
Neil Turton committed
833
PAHandlerInDataInitValue
834
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
835 836 837
        SUB     r12, pc, #O_PAHandlerInData+12
PAHandler Keep
        SUB     r14, r14, #4
838 839 840 841
        STR     r14, [r12, #O_registerDump + 15 * 4]

        LDR     r14, [r12, #O_oldAbortHandlers + 4]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
842 843 844
        B       Aborted

DAHandlerInDataInitValue
845
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
846 847 848
        SUB     r12, pc, #O_DAHandlerInData+12
DAHandler Keep
        SUB     r14, r14, #8
849 850 851 852
        STR     r14, [r12, #O_registerDump + 15 * 4]

        LDR     r14, [r12, #O_oldAbortHandlers + 8]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
853 854 855
        B       Aborted2

AEHandlerInDataInitValue
856
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
857 858 859
        SUB     r12, pc, #O_AEHandlerInData+12
AEHandler Keep
        SUB     r14, r14, #8
860 861 862 863
        STR     r14, [r12, #O_registerDump + 15 * 4]

        LDR     r14, [r12, #O_oldAbortHandlers + 12]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
864 865 866 867 868
;       B       Aborted2

Aborted2 Keep
; Abort which may be in the FP emulator, and if so should be reported
; as occurring at the instruction being emulated.
869
; Try the FPEmulator_Abort SWI
870 871

        LDR     r2, [sp, #24]
872 873
        ADD     r2, r2, #8              ; original r14
        LDR     r1, [sp, #20]           ; original r12
874
      [ {CONFIG}=26
875
        BIC     r2, r2, #PSRBits
876
      |
877 878
        TEQ     pc, pc
        BICNE   r2, r2, #PSRBits
879 880 881 882 883
        MRSEQ   r3, CPSR
        BICEQ   r0, r3, #PSR32Mode
        ORREQ   r0, r0, #PSR32SVCMode
        MSREQ   CPSR_c, r0              ; if in 32-bit mode, probably ABT
        STREQ   lr, [sp, #-4]!          ; so switch to SVC to preserve R14_svc
884 885
      ]
        MOV     r0, #-2                 ; current context
886 887 888 889 890 891 892
        SWI     XFPEmulator_Abort       ; WILL NOT ERROR ON SOME OLD FPEs - acts as
                                        ; if FPEmulator_Version, hence returning a
                                        ; small number
      [ {CONFIG}<>26
        TEQ     pc, pc
        LDREQ   lr, [sp], #4            ; get back R14_svc
        MSREQ   CPSR_c, r3              ; back to original mode
893
       [ StrongARM_MSR_bug
894
        NOP                             ; avoid StrongARM bug
895
       ]
896 897 898
      ]
        BVS     NoFPEAbortSWI           ; in case someone really does error
        TEQ     r0, #0                  ; check for real "not FP abort" return
899
        LDMEQFD sp, {r0-r2}
900
        BEQ     Aborted                 ; not in FPEmulator
901 902
        CMP     r0, #&01000000          ; check for a bogus result
        BLO     NoFPEAbortSWI
903 904 905
        B       FPEFault

NoFPEAbortSWI
Neil Turton's avatar
Neil Turton committed
906
; If in user mode, can't be in FPE
907
      [ {CONFIG}=26
908
        LDR     r1, [sp, #24]
909 910
        TST     r1, #PSRPrivileged
      |
911 912 913 914
        TEQ     pc, pc
        LDRNE   r1, [sp, #24]
        ANDNE   r1, r1, #PSRMode        ; obtain aborter's mode from R14
        MRSEQ   r1, SPSR                ; obtain aborter's mode from SPSR
915 916
        TST     r1, #PSR32Privileged
      ]
917
        LDMEQFD sp, {r0-r4}
Neil Turton's avatar
Neil Turton committed
918
        BEQ     Aborted
919

Neil Turton's avatar
Neil Turton committed
920
; Otherwise, find out where the FPE module is
921 922 923
      [ {CONFIG} <> 26
        TST     r2, #2_11100
      ]
924
        STMFD   sp!, {r0 - r6}
925
      [ {CONFIG} = 26
Neil Turton's avatar
Neil Turton committed
926
        BIC     r6, r14, #PSRBits
927 928 929 930
      |
        BICEQ   r6, r14, #PSRBits       ; 32-bit OK (26-bit cond)
        MOVNE   r6, r14
      ]
Neil Turton's avatar
Neil Turton committed
931 932 933
        MOV     r0, #18
        ADR     r1, FPEName
        SWI     Module
934
        LDMVSFD sp!, {r0 - r6}
Neil Turton's avatar
Neil Turton committed
935 936 937 938 939 940
        BVS     Aborted
; (r3 = code base of FPE; word before is length of FPE code)
        CMP     r6, r3
        LDRGE   r4, [r3, #-4]
        ADDGE   r3, r3, r4
        CMPGE   r3, r6
941
        LDMFD   sp!, {r0 - r6}
Neil Turton's avatar
Neil Turton committed
942 943 944
        BLT     Aborted

; It was a storage fault in the FP emulator.
945
; We assume FPEmulator 4.00 or later - r0
946 947 948 949 950
; will point to a full register save. The format differs slightly
; depending on whether the FPEmulator is 32-bit or not. If we're
; in a 32-bit mode, we know the FPEmulator will be. If not, check
; to see if the saved r12 is in the UND stack.
FPEFault
Neil Turton's avatar
Neil Turton committed
951
        ADD     r14, r12, #O_registerDump
952 953 954 955 956 957 958 959 960
        LDMIA   r0!, {r1-r4}            ; copy R0-R15
        STMIA   r14!, {r1-r4}
        LDMIA   r0!, {r1-r4}
        STMIA   r14!, {r1-r4}
        LDMIA   r0!, {r1-r4}
        STMIA   r14!, {r1-r4}
        LDMIA   r0!, {r1-r4}
        SUB     r4, r4, #4              ; adjust PC back 4
        STMIA   r14!, {r1-r4}
961
      [ {CONFIG}<>26
962 963
        TEQ     pc, pc
        BEQ     FPEFault_32on32
964 965 966 967 968 969
      ]
        LDR     r3, [r12, #O_undStack]
        MOV     r2, r1, LSR #20         ; we're on a 26-bit system
        TEQ     r2, r3, LSR #20         ; is the stack frame in the UND stack?
        BEQ     FPEFault_32on26
FPEFault_26on26
970
        B       FPEFault_Continue
971 972

FPEFault_32on26
973
        LDR     r2, [r0, #-72]          ; get the SPSR
974
        AND     r2, r2, #PSRBits
975 976 977 978 979
        BIC     r4, r4, #PSRBits
        ORR     r4, r4, r2
        STR     r4, [r14, #-4]          ; merge it with pc in register dump
      [ {CONFIG}<>26
        B       FPEFault_Continue
980 981

FPEFault_32on32
982
        LDR     r2, [r0, #-72]          ; get the SPSR
983
        STR     r2, [r14]               ; store it in the register dump
984
      ]
985

986 987
FPEFault_Continue
        LDMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
988 989 990 991 992 993 994 995 996 997

        ErrorBlock  PrefetchAbort,      "Prefetch Abort", C60
        ErrorBlock  DataAbort,          "Data Abort", C61
        ErrorBlock  AddressException,   "Address Exception", C53
        ErrorBlock  IllegalInstruction, "Illegal Instruction", C54
FPEName =       "FPEmulator",0
        ALIGN

Aborted Keep
        ADD     r14, r12, #O_registerDump
Kevin Bracey's avatar
Kevin Bracey committed
998
  [ SASTMhatbroken
999 1000 1001 1002
        STMIA   r14!, {r0-r12}
        STMIA   r14, {r13,r14}^
        NOP
        SUB     r14, r14, #13*4
Kevin Bracey's avatar
Kevin Bracey committed
1003
  |
1004 1005
        STMIA   r14, {r0-r14}^
        NOP
Neil Turton's avatar
Neil Turton committed
1006
  ]
Kevin Bracey's avatar
Kevin Bracey committed
1007

1008 1009 1010
        LDR     r0, [r13, #20]
        STR     r0, [r14, #r12*4]

1011 1012 1013 1014 1015 1016 1017 1018
        TEQ     pc, pc
        MOVNE   r3, pc
        ANDNE   r3, r3, #PSRBits
        MRSEQ   r3, CPSR
        LDRNE   r0, [sp, #24]
        ANDNE   r0, r0, #PSRMode        ; obtain aborter's mode from R14
        MRSEQ   r0, SPSR                ; obtain aborter's mode from SPSR
        STREQ   r0, [r14, #16*4]        ; store aborter's SPSR if in 32-bit mode
1019 1020 1021 1022 1023
        TST     r0, #PSR32Privileged
        BEQ     NotPrivileged
        LDR     r0, [r14, #r14*4]       ; if abort in a privileged mode, save
        STR     r0, [r14, #pc*4]        ; PC as user R14
        LDR     r0, [r12, #O_svcStack]  ; switch to SVC mode and look at R13_svc
1024
        ADD     r4, r14, #10 * 4        ; reg ptr into unbanked register
1025
        TEQ     pc, pc
1026 1027 1028 1029 1030 1031 1032 1033 1034
        MSREQ   CPSR_c, #PSR32SVCMode+PSR32IBit+PSR32FBit
        TEQNEP  pc, #PSRSVCMode+PSRIBit+PSRFBit
        MOV     r1, r0, LSR #20         ; r0 = stack top
        MOV     r1, r1, LSL #20         ; r1 = stack base
        SUB     r2, r0, #12             ; r2 = stack top - 12
        CMP     r13, r1                 ; r1 <= r13 <= r2?
        CMPHS   r2, r13
        LDMHSDB r0, {r0-r2}             ; Pull R10-R12 off of top of SVC stack
        STMHSIA r4, {r0-r2}             ; if there were at least 3 words on it
1035 1036 1037 1038 1039 1040
        TEQ     pc, pc
        MSREQ   CPSR_cxs, r3
        TEQNEP  pc, r3
        NOP
NotPrivileged
        LDMFD   r13!, {r0-r4, r12, r14, pc}
Dan Ellis's avatar
Dan Ellis committed
1041

Neil Turton's avatar
Neil Turton committed
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
AbortFindHandler Keep
; We can only call an abort handler if we had a stack at the
; time of the abort.  If not, we have to say 'uncaught trap'.
; There is a problem as soon as interrupts are enabled, that an event may
; arrive and trash the register dump.  If there's a stack, this is solved
; by copying the dump onto it.  Otherwise, we protect ourselves while
; constructing the error by pretending there's a callback going on.
; Entry may be in SWI mode (faults) or user mode (stack overflow,
; divide by zero).
; r0 is the address of an error block describing the fault.
; r12 is the address of our static data.

        MOV     v6, r12
        BL      CopyErrorV6OK
        LDRB    r2, [v6, #O_inTrapHandler]
        CMP     r2, #0
        BNE     RecursiveTrap
        LDRB    r2, [v6, #O_unwinding]
        CMP     r2, #0
        BNE     duh_abort
        MOV     r2, #1
        STRB    r2, [v6, #O_inTrapHandler]

1065
        ADD     r11, v6, #O_registerDump+17*4
Neil Turton's avatar
Neil Turton committed
1066 1067 1068 1069 1070 1071
        LDR     r10, [v6, #O_registerDump+sl*4]
        LDR     r1, [v6, #O_heapBase]
        LDR     r2, [v6, #O_heapLimit]

        LDR     r12, [v6, #O_registerDump+sp*4]
        CMP     r12, r1
1072 1073 1074 1075
        CMPHI   r2, r12
        ADDHI   r1, r12, #256
        CMPHI   r1, r10
        BLS     Trap_NoStackForHandler
Neil Turton's avatar
Neil Turton committed
1076 1077 1078 1079 1080 1081 1082
        LDR     r3, =IsAStackChunk
        LDR     r4, [r10, #SC_mark-SC_SLOffset]
        EOR     r4, r4, r3
        BICS    r4, r4, #&80000000 ; a chunk marked 'handling extension' will do
        BNE     Trap_NoStackForHandler
        LDR     v1,  [v6, #O_registerDump+fp*4]

1083 1084 1085 1086
        ; At this point, r12 is the user mode stack pointer and r11 points just past
        ; the 17th entry of the register dump.
        LDMDB   r11!, {a1-a4, v2-v5, lr}
        STMDB   r12!, {a1-a4, v2-v5, lr}
Neil Turton's avatar
Neil Turton committed
1087 1088 1089 1090 1091 1092
        LDMDB   r11!, {a1-a4, v2-v5}
        STMDB   r12!, {a1-a4, v2-v5}
        ; Some agony here about preventing an event handler running
        ; (on the user stack) while the registers describing the stack
        ; (sp & sl) haven't both been updated.
 [ ModeMayBeNonUser
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
        MOV     a1, #0
        MRS     a1, CPSR
        TST     a1, #2_11100
        BEQ     %FT01                                   ; 26-bit mode
     [ {CONFIG}=26
        MSR     CPSR_c, #PSR32IBit + PSRUSRMode         ; USR26, I set
     |
        MSR     CPSR_c, #PSR32IBit + PSR32USRMode       ; USR32, I set
     ]
        MSR     CPSR_f, #PSRVBit                        ; set V for calling IntOn.
        B       %FT02
01      LDR     a1, [v6, #O_registerDump+pc*4]
Neil Turton's avatar
Neil Turton committed
1105 1106 1107 1108
        TST     a1, #PSRIBit
        ORREQ   a1, a1, #PSRVBit
        BICNE   a1, a1, #PSRVBit
        TEQP    a1, #0
1109
02
Neil Turton's avatar
Neil Turton committed
1110
   |
1111
     [ No32bitCode
Neil Turton's avatar
Neil Turton committed
1112
        TEQP    pc, #PSRIBit:OR:PSRVBit                 ; user mode
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
     |
        MRS     a1, CPSR
        ORR     a1, a1, #PSR32IBit                      ; may not need this
        ORR     a1, a1, #PSRVBit
      [ {CONFIG}=26
        BIC     a1, a1, #PSR32Privileged                ; into USR26 mode
      |
        BIC     a1, a1, #PSR32Mode                      ; into USR32 mode
      ]
        MSR     CPSR_cf, a1                             ; switch to user mode
     ]
Neil Turton's avatar
Neil Turton committed
1124 1125
 ]

1126
        NOP
Neil Turton's avatar
Neil Turton committed
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
        MOV     sp, r12
        MOV     sl, r10
        MOV     fp, v1
        SWIVS   IntOn

        LDR     v1, [v6, #O_errorNumber]
        MOV     r0, sp
        MOV     v2, #lang_Trap
        BL      FindAndCallHandlers

        MOV     r0, sp
        MOV     v2, #lang_UncaughtTrap
        BL      FindAndCallHandlers

        BL      RestoreOSHandlers
        MOV     v5, sp
        ADD     fp, v6, #O_errorNumber
        ADR     ip, E_UncaughtTrap
        B       FatalErrorX

Trap_NoStackForHandler
        ADR     ip, E_NoStackForTrapHandler
        B       FatalErrorY

        ErrorBlock NoStackForTrapHandler, "No stack for trap handler", C55

RecursiveTrap Keep
        ADR     ip, E_RecursiveTrap
FatalErrorY
        ; Pointer to error block in ip. (beware, RestoreOSHandlers
        ; corrupts r0-r8).
        MOV     fp, r0
        MOV     r0, #0
        STRB    r0, [v6, #O_callbackInactive]
1161
        WritePSRc 0, lr
Neil Turton's avatar
Neil Turton committed
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
        BL      RestoreOSHandlers
        ADD     v5, v6, #O_registerDump
FatalErrorX
 [ SharedLibrary
        LDR     a1, [v5, #pc*4]
        ADD     a2, v6, #O_pc_hex_buff
        BL      HexOut
        MOV     a1, v5
        ADD     a2, v6, #O_reg_hex_buff
        BL      HexOut
        MOV     r0, ip
  [ :DEF:DEFAULT_TEXT
        ADD     r0, r0, #4
10      LDRB    r2, [r0], #1
        CMP     r2, #0
        BNE     %B10
        ADD     r0, r0, #3
        BIC     r0, r0, #3
  ]
1181
        SavePSR v4
Neil Turton's avatar
Neil Turton committed
1182
        SWI     EnterSVC
1183 1184
        BLVC    open_messagefile        ; BL<cond> 32-bit OK
        RestPSR v4
Neil Turton's avatar
Neil Turton committed
1185
        MOV     r0, r0
1186 1187 1188
        ; We just trample all over the start of our workspace.
        ; Fine, as we've removed handlers and are about to go pop.
        ADD     r2, v6, #O_FatalErrorBuffer
Neil Turton's avatar
Neil Turton committed
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
        MOV     r3, #256
        ADD     r4, fp, #4
        ADD     r5, v6, #O_pc_hex_buff
        ADD     r6, v6, #O_reg_hex_buff
        MOV     r7, #0
        SWI     XMessageTrans_ErrorLookup
 |
        MOV     r0, ip
        BL      |_kernel_copyerror|
        MOV     a4, r0
1199
        ADD     a2, v6, #O_FatalErrorBuffer
Neil Turton's avatar
Neil Turton committed
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228
        BL      CopyError2
        SUB     a2, a2, #1
        ADR     a4, str1
        BL      CopyErrorString
        SUB     a2, a2, #1
        ADD     a4, fp, #4
        BL      CopyErrorString
        SUB     a2, a2, #1
        ADR     a4, str2
        BL      CopyErrorString
        SUB     a2, a2, #1
        LDR     a1, [v5, #pc*4]
        BL      HexOut
        MOV     a4, a2
        [ :DEF:DEFAULT_TEXT
        ADR     a1, str3
        ADR     a2, str3tok
        |
        ADR     a1, str3tok
        ]
        BL      |_kernel_getmessage|
        MOV     a2, a4
        MOV     a4, r0
        BL      CopyErrorString
        SUB     a2, a2, #1
        MOV     a1, v5
        BL      HexOut
        MOV     a1, #0
        STRB    a1, [a2]
1229
        ADD     r0, v6, #O_FatalErrorBuffer
Neil Turton's avatar
Neil Turton committed
1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
 ]
        B       FatalError

str1    = ": ", 0
str2    = ", pc = ", 0
 [ :DEF:DEFAULT_TEXT
str3    = ": registers at ", 0
 ]
str3tok = "C56", 0
        ALIGN

; a1 = Hex value to convert
; a2 = Buffer
HexOut  MOV     a4, #8
01      MOV     a1, a1, ROR #28
        AND     a3, a1, #15
        CMP     a3, #10
        ADDLT   a3, a3, #"0"
        ADDGE   a3, a3, #"A"-10
        STRB    a3, [a2], #+1
        SUBS    a4, a4, #1
        BNE     %B01
 [ SharedLibrary
        STRB    a4, [a2]
 ]
1255
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1256 1257 1258 1259 1260 1261 1262 1263


|_kernel_exittraphandler|
        LoadStaticBase ip, a1
        MOV     a1, #0
        STRB    a1, [ip, #O_inTrapHandler]
        MOV     a1, #1
        STRB    a1, [ip, #O_callbackInactive]
1264
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275

FindAndCallHandlers Keep
        ; Finds a handler of type offset v2 in a language description,
        ; responsible for the current pc value.  If one (non-zero) is found,
        ; calls it, and resumes the program if it so requests.
        ; Otherwise, unwinds the stack and repeats the operation.
        ; r0 addresses the register dump
        ; v1 is the first argument for the handler (fault / event code)
        ; v2 is the handler offset
        ; v6 is my static data base

1276
        ; set up an initial unwind block.  For our purposes, we don't care
Neil Turton's avatar
Neil Turton committed
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
        ; about the values of callee-save registers (ARM or FP).
        STMFD   sp!, {r0, r14}
        MOV     v3, fp
        MOV     v4, sp
        LDR     v5, [r0, #pc*4]
        MOV     ip, sl
        MOV     r1, v5
        SUB     sp, sp, #uwb_size+4
        ADD     v4, sp, #uwb_fp+4
        STMIA   v4, {v3, v4, v5, ip}
FCH_NextFrame
1288
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
1289
        BIC     r1, r1, #PSRBits
Dan Ellis's avatar
Dan Ellis committed
1290 1291 1292 1293
        |
        MRS     v4, CPSR
        TST     v4, #2_11100
        BICEQ   r1, r1, #PSRBits
1294
        ]
Neil Turton's avatar
Neil Turton committed
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
        LDMIB   v6, {v4, v5}
FCH_NextLanguage Keep
        ; find to which language the current pc corresponds (between which
        ; language's code bounds it lies).
        CMP     v4, v5
        BGE     FCH_NoHandlerFound

        LDMIA   v4, {r0, r2, r3}
        CMP     r1, r2
        CMPGE   r3, r1
        ADDLT   v4, v4, r0
        BLT     FCH_NextLanguage

        ; If the language has a handler procedure of the right type, call it
        ; (it may not have one either by not having a large enough area, or
        ;  a zero entry).
        CMP     r0, v2
        BLE     FCH_Unwind
        LDR     r2, [v4, v2]
        CMP     r2, #0
        BEQ     FCH_Unwind

        ; arguments for the handler are
        ;   fault or event code
        ;   pointer to dumped registers
        ; return value is non-zero to resume; otherwise, search continues
        LDR     a1, =|RTSK$$Data$$Limit|
        CMP     v5, a1
        MOV     a1, v1
        LDR     a2, [sp, #uwb_size+4]
1325 1326 1327 1328 1329
        BNE     FCH_CallClient
        MOV     lr, pc
        MOV     pc, r2
        B       FCH_ClientCalled
FCH_CallClient
Neil Turton's avatar
Neil Turton committed
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
        CallClient r2
FCH_ClientCalled
        CMP     v2, #lang_Event  ; event handlers are only allowed to pass escape
        BNE     FCH_NotEvent
        CMP     v1, #-1
        BNE     FCH_Exit
FCH_NotEvent
        CMP     a1, #0
        BEQ     FCH_Unwind
        ; if resuming after a trap, clear the 'in trap handler' status
FCH_Exit
        SUBS    r0, v2, #lang_Trap
        SUBNES  r0, v2, #lang_UncaughtTrap
        STREQB  r0, [v6, #O_inTrapHandler]
        LDR     r0, [sp, #uwb_size+4]
        B       ReloadUserState

FCH_NoHandlerFound Keep
        ; pc is not within a known code area in the image.  Perhaps it is
        ; within a library area (if the image uses a shared library).
 [ SharedLibrary
        LDR     r0, =|RTSK$$Data$$Limit|
        CMP     v5, r0
        MOVNE   v5, r0
        LDRNE   v4, =|RTSK$$Data$$Base|
        BNE     FCH_NextLanguage
 ]
FCH_Unwind  Keep
        ADD     a1, sp, #4
        MOV     a2, sp
        BL      |_kernel_unwind|
        CMP     a1, #0
        LDRGT   r1, [sp, #uwb_pc+4]
        BGT     FCH_NextFrame

        ADD     sp, sp, #uwb_size+4+4
1366
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
1367
        LDMFD   sp!, {pc}^
1368
        |
Ben Avison's avatar
Ben Avison committed
1369
        LDR     pc, [sp], #4
1370
        ]
Neil Turton's avatar
Neil Turton committed
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385

        ErrorBlock UncaughtTrap, "Uncaught trap", C57
        ErrorBlock RecursiveTrap, "Trap while in trap handler", C58

RestoreOSHandlers Keep
        ; (there may not be a valid sp)
        STR     lr, [v6, #O_lk_RestoreOSHandlers]
        BL      InstallCallersHandlers
        LDRB    r1, [v6, #O_underDesktop]
        CMP     r1, #0
        LDRNE   r1, [v6, #O_knownSlotSize]
        LDRNE   r0, [v6, #O_initSlotSize]
        CMPNE   r1, r0
        LDR     lr, [v6, #O_lk_RestoreOSHandlers]
        BNE     SetWimpSlot
1386
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401

SetWimpSlot_Save_r4r5
        STMFD   sp!, {r4, r5}
SetWimpSlot  Keep
        ; Set the wimp slot to r0 - ApplicationBase.
        ; Destroys r4, r5
        ; May need to set MemoryLimit temporarily to the slot size,
        ; in order that Wimp_SlotSize not refuse.
        ; (Note that preservation of r4 is required anyway because of
        ;  fault in Wimp_SlotSize which corrupts it).
        ; Returns the slot size set.
        MOV     r4, r0
        MOV     r0, #Env_MemoryLimit
        MOV     r1, #0
        SWI     ChangeEnv
1402
        MOV     r5, r1                          ; r5 = current memory limit
Neil Turton's avatar
Neil Turton committed
1403 1404 1405
        MOV     r0, #Env_ApplicationSpace
        MOV     r1, #0
        SWI     ChangeEnv
1406 1407
        CMP     r1, r5                          ; is memory limit=application space?
        BNE     SetWimpSlot_DoFudge             ; if not, make it so.
Neil Turton's avatar
Neil Turton committed
1408 1409
        SUB     r0, r4, #Application_Base
        MOV     r1, #-1
1410
        SWI     XWimp_SlotSize                  ; change slot size
1411
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1412

1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424
SetWimpSlot_DoFudge
        MOV     r0, #Env_MemoryLimit
        SWI     ChangeEnv
        SUB     r0, r4, #Application_Base
        MOV     r1, #-1
        SWI     XWimp_SlotSize                  ; change slot size
        MOV     r4, r0
        MOV     r0, #Env_MemoryLimit
        MOV     r1, r5
        SWI     ChangeEnv
        MOV     r0, r4
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448

; Our own exit handler, which restores our parent's environment then exits.
; Just in case a C program manages to (call something which) does a SWI Exit.
; Necessary otherwise because of Obey.
; The register state prevailing when exit was called is completely undefined;
; all we can rely on is that r12 addresses our static data.  The stack
; description may be junk so we reset the stack to its base.
ExitHandler Keep
        MOV     v6, r12
        LDR     sl, [v6, #O_rootStackChunk]
        LDR     sp, [sl, #SC_size]
        ADD     sp, sl, sp
        ADD     sl, sl, #SC_SLOffset
        MOV     fp, #0
  ; so the user can get to hear about faults in his atexit procs, unset
  ;  inTrapHandler.  This is safe (will terminate) because all finalisation
  ; is one-shot.
        STRB    fp, [v6, #O_inTrapHandler]
        STMFD   sp!, {r0-r2}
        BL      Finalise
        LDMIA   sp!, {r0-r2}
        SWI     Exit

UpCallHandler
1449
        TEQ     r0, #256
Neil Turton's avatar
Neil Turton committed
1450 1451 1452 1453 1454 1455 1456
        MOVNE   pc, r14
; Entered in SWI mode.  A new application is starting (not started by system,
; for which there's a different UpCall handler).  It has the same MemoryLimit
; as this application, so is free to overwrite it.  We'd better close ourselves
; down.
; The register state is undefined, except that r13 must be the SWI stack
; pointer.
Ben Avison's avatar
Ben Avison committed
1457
        STMFD   sp!, {r0-r3, v1-v6, sl, fp, lr}
Neil Turton's avatar
Neil Turton committed
1458
        MOV     v6, r12
1459
        WritePSRc PSRUSRMode, r0
Neil Turton's avatar
Neil Turton committed
1460 1461 1462 1463 1464 1465 1466
        LDR     sl, [v6, #O_rootStackChunk]
        LDR     sp, [sl, #SC_size]
        ADD     sp, sl, sp
        ADD     sl, sl, #SC_SLOffset
        MOV     fp, #0
        BL      Finalise
        SWI     EnterSVC
Ben Avison's avatar
Ben Avison committed
1467
        LDMFD   sp!, {r0-r3, v1-v6, sl, fp, pc}
Neil Turton's avatar
Neil Turton committed
1468 1469 1470 1471 1472

InstallHandlers Keep
        ; r0 is zero for the initial call (previous values for the handlers
        ; to be saved).
        ; If non-zero, it is the value memoryLimit should be set to.
Ben Avison's avatar
Ben Avison committed
1473
        STR     r0, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
        MOV     r8, r0
        MOV     r0, #0
        MOV     r1, #0
        MOV     r2, #0
        MOV     r3, #0
        ADD     r4, v6, #O_IIHandlerInData
        ADD     r5, v6, #O_PAHandlerInData
        ADD     r6, v6, #O_DAHandlerInData
        ADD     r7, v6, #O_AEHandlerInData
        SWI     SetEnv
        CMP     r8, #0
        ADDEQ   r8, v6, #O_oldAbortHandlers
        STMEQIA r8!, {r4-r7}

        MOV     r0, #Env_ExitHandler
        ADR     r1, ExitHandler
        MOV     r2, v6
        SWI     ChangeEnv
        STMEQIA r8!, {r1, r2}

        MOV     r0, #Env_MemoryLimit
Ben Avison's avatar
Ben Avison committed
1495
        LDR     r1, [sp], #4
Neil Turton's avatar
Neil Turton committed
1496
        SWI     ChangeEnv
Ben Avison's avatar
Ben Avison committed
1497
        STREQ   r1, [r8], #4
Neil Turton's avatar
Neil Turton committed
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535

        MOV     r0, #Env_ErrorHandler
        ADR     r1, ErrorHandler
        MOV     r2, v6
        ADD     r3, v6, #O_errorBuffer
        SWI     ChangeEnv
        STMEQIA r8!, {r1, r2, r3}

        ; callback, escape and event handlers must be updated atomically
        SWI     IntOff

        MOV     r0, #Env_CallBackHandler
        ADR     r1, CallBackHandler
        MOV     r2, v6
        ADD     r3, v6, #O_registerDump
        SWI     ChangeEnv
        STMEQIA r8!, {r1, r2, r3}

        MOV     r0, #Env_EscapeHandler
        ADR     r1, EscapeHandler
        MOV     r2, v6
        SWI     ChangeEnv
        STMEQIA r8!, {r1, r2}

        MOV     r0, #Env_EventHandler
        ADR     r1, EventHandler
        MOV     r2, v6
        SWI     ChangeEnv
        STMEQIA r8!, {r1, r2}

        SWI     IntOn

        MOV     r0, #Env_UpCallHandler
        ADR     r1, UpCallHandler
        MOV     r2, v6
        SWI     ChangeEnv
        STMEQIA r8!, {r1, r2}

1536
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552


InstallCallersHandlers Keep
        ADD     r8, v6, #O_oldAbortHandlers
        MOV     r0, #0
        MOV     r1, #0
        MOV     r2, #0
        MOV     r3, #0
        LDMIA   r8!, {r4-r7}
        SWI     SetEnv

        MOV     r0, #Env_ExitHandler
        LDMIA   r8!, {r1, r2}
        SWI     ChangeEnv

        MOV     r0, #Env_MemoryLimit
Ben Avison's avatar
Ben Avison committed
1553
        LDR     r1, [r8], #4
Neil Turton's avatar
Neil Turton committed
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581
        SWI     ChangeEnv
        MOV     r4, r1

        MOV     r0, #Env_ErrorHandler
        LDMIA   r8!, {r1, r2, r3}
        SWI     ChangeEnv

        ; callback, escape and event handlers must be updated atomically
        SWI     IntOff

        MOV     r0, #Env_CallBackHandler
        LDMIA   r8!, {r1, r2, r3}
        SWI     ChangeEnv

        MOV     r0, #Env_EscapeHandler
        LDMIA   r8!, {r1, r2}
        SWI     ChangeEnv

        MOV     r0, #Env_EventHandler
        LDMIA   r8!, {r1, r2}
        SWI     ChangeEnv

        SWI     IntOn

        MOV     r0, #Env_UpCallHandler
        LDMIA   r8!, {r1, r2}
        SWI     ChangeEnv

1582
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598



 ;*-------------------------------------------------------------------*
 ;* Error handler                                                     *
 ;*-------------------------------------------------------------------*

ErrorHandler Keep
; Now Brazil compatibility is discarded and all SWI calls in the library
; are X-bit set (other than _kernel_swi if non-X bit set has been explicitly
; asked for), any error is treated as fatal here.
;
; Entry with static data base in r0.  User mode, interrupts on
; Since it would be nice to preserve as much as possible for the FP fault case
; we switch back to SWI mode to save the registers.
        SWI     EnterSVC
Kevin Bracey's avatar
Kevin Bracey committed
1599

1600 1601 1602 1603 1604
        LDR     r14, [r0, #O_errorNumber]
        TEQ     r14, #Error_IllegalInstruction
        TEQNE   r14, #Error_PrefetchAbort
        TEQNE   r14, #Error_DataAbort
        TEQNE   r14, #Error_AddressException
Kevin Bracey's avatar
Kevin Bracey committed
1605
  [ SASTMhatbroken
1606 1607 1608 1609 1610
        ADDNE   r14, r0, #O_registerDump
        STMNEIA r14!, {r0-r12}
        STMNEIA r14, {r13,r14}^
        NOP
        SUBNE   r14, r14, #13*4
Kevin Bracey's avatar
Kevin Bracey committed
1611
  |
1612
        STMNEIA r14, {r0-r14}^
Kevin Bracey's avatar
Kevin Bracey committed
1613 1614
  ]

Neil Turton's avatar
Neil Turton committed
1615 1616
        MOV     r12, r0
        ADD     r0, r0, #O_errorNumber
1617 1618
        BEQ     AbortFindHandler

Neil Turton's avatar
Neil Turton committed
1619
        LDMDA   r0, {r1, r2}            ; r1 is error pc, r2 error number
1620 1621 1622 1623 1624
        MOV     r14, #0
        STR     r14, [r12, #O_registerDump+16*4]        ; zero PSR
        MRS     r14, CPSR
        TST     r14, #2_11100
        BICEQ   r1, r1, #&fc000003      ; Sanitize PC value
Neil Turton's avatar
Neil Turton committed
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
        CMP     r2, #Error_BranchThroughZero
        MOVEQ   r1, #0
        STR     r1, [r12, #O_registerDump+pc*4]
        B       AbortFindHandler

 ;*-------------------------------------------------------------------*
 ;* Escape and event handling                                         *
 ;*-------------------------------------------------------------------*

|_kernel_escape_seen|
1635
      [ No32bitCode
Neil Turton's avatar
Neil Turton committed
1636 1637 1638 1639
        MOV     a4, r14
        LoadStaticBase a3, ip
        MOV     a2, #0
        TST     r14, #PSRSVCMode
1640
        SWIEQ   EnterSVC
Neil Turton's avatar
Neil Turton committed
1641 1642 1643 1644
        TEQP    pc, #PSRIBit+PSRSVCMode  ; interrupts off, for atomic read and update
        LDRB    a1, [a3, #O_escapeSeen]
        STRB    a2, [a3, #O_escapeSeen]
        MOVS    pc, a4
1645 1646
      |
        LoadStaticBase a3
Ben Avison's avatar
Ben Avison committed
1647 1648 1649 1650
      [ SupportARMK :LAND: NoARMK
        LDR     a4, [a3, #O__swp_available]
        TST     a4, #4 ; CPU supports LDREXB?
      ]
1651 1652 1653
        MOV     a2, #0
        ADD     a3, a3, #O_escapeSeen :AND: :NOT: &FF
        ADD     a3, a3, #O_escapeSeen :AND: &FF         ; Yuckeroo
Ben Avison's avatar
Ben Avison committed
1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664
      [ SupportARMK
       [ NoARMK
        SWPEQB  a1, a2, [a3]
        BEQ     %FT02
       ]
01      LDREXB  a1, [a3]
        STREXB  a4, a2, [a3]
        TEQ     a4, #1
        BEQ     %BT01
02
      |
1665
        SWPB    a1, a2, [a3]
Ben Avison's avatar
Ben Avison committed
1666
      ]
1667 1668
        Return  "", LinkNotStacked
      ]
Neil Turton's avatar
Neil Turton committed
1669 1670 1671

EventHandler Keep
        TEQ     r0, #4
1672
        MOVEQ   pc, lr
Neil Turton's avatar
Neil Turton committed
1673 1674 1675
        STMFD   r13!, {r11, r14}
        STR     r0, [r12, #O_eventCode]
        ADD     r11, r12, #O_eventRegisters
Ben Avison's avatar
Ben Avison committed
1676
      [ {FALSE} ; this instruction is now deprecated
Neil Turton's avatar
Neil Turton committed
1677
        STMIA   r11, {r0-r10, r13}
Ben Avison's avatar
Ben Avison committed
1678 1679 1680 1681
      |
        STMIA   r11, {r0-r10}
        STR     r13, [r11, #11*4]
      ]
Kevin Bracey's avatar
Kevin Bracey committed
1682

Neil Turton's avatar
Neil Turton committed
1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
        STMDB   r11, {r13}^
        MOV     v6, r12
        MOV     v2, r11
        LDMIB   r12, {v4, v5}
02      CMP     v4, v5
        BGE     EndFastEventHandlers
        LDR     v1, [v4]
        CMP     v1, #lang_FastEvent
        LDRGT   r1, [v4, #lang_FastEvent]
        CMPGT   r1, #0
        BLE     %F01
        MOV     a1, v2
        MOV     v1, r12
        MOV     fp, #0                          ; nb fp is NOT r13
        ; SL not set up - handlers must not have stack checking on,
        ; and may not require relocation of data references.
        MOV     r14, pc
        MOV     pc, r1
        MOV     r12, v1
01      ADD     v4, v4, v1
        B       %B02
EndFastEventHandlers
        ; If callback is possible (not already in a callback), set r12 to 1 to
        ; request it.
        LDRB    r12, [v6, #O_callbackInactive]

        ADD     v6, v6, #O_eventRegisters
        LDMIA   v6, {r0-r10}
        LDMFD   r13!, {r11, pc}


EscapeHandler Keep
        TSTS    r11, #&40
1716
        BNE     haveEscape
Ben Avison's avatar
Ben Avison committed
1717
        STR     r0, [r13, #-4]!
1718 1719
        MOV     r0, #0
        STRB    r0, [r12, #O_hadEscape]
Ben Avison's avatar
Ben Avison committed
1720
        LDR     r0, [r13], #4
1721
        MOV     pc, r14         ; ignore flag going away
Neil Turton's avatar
Neil Turton committed
1722

1723
haveEscape
Neil Turton's avatar
Neil Turton committed
1724 1725
        ; In Arthur, it is NEVER safe to call a handler now: we always have to
        ; wait for CallBack.
Ben Avison's avatar
Ben Avison committed
1726
        STR     r0, [r13, #-4]!
Neil Turton's avatar
Neil Turton committed
1727 1728
        MOV     r0, #-1
        STRB    r0, [r12, #O_hadEscape]
1729
        LDRB    r0, [r12, #O_eventCode]
Neil Turton's avatar
Neil Turton committed
1730 1731 1732 1733 1734
        STRB    r0, [r12, #O_escapeSeen]
        STR     r0, [r12, #O_eventCode]
        LDRB    r11, [r12, #O_callbackInactive]
        CMP     r11, #0
        MOVNE   r12, #1
Ben Avison's avatar
Ben Avison committed
1735
        LDR     r0, [r13], #4
Neil Turton's avatar
Neil Turton committed
1736 1737 1738 1739 1740 1741 1742 1743 1744 1745
        MOV     pc, r14

; Callback handler - entered in either SWI or IRQ mode, interrupts disabled,
; just before OS return to user mode with interrupts on.
CallBackHandler Keep
        ; Set 'in callback' to prevent callback being reentered before it finishes
        ; when we enable interrupts later on.
        MOV     r0, #0
        STRB    r0, [r12, #O_callbackInactive]

1746 1747 1748
        MRS     r0, CPSR
        TST     r0, #2_11100

Neil Turton's avatar
Neil Turton committed
1749 1750 1751 1752 1753 1754 1755 1756 1757 1758
        MOV     v6, r12                 ; get SB into our standard place
        ; Copy the register set from our static callback buffer, onto the stack
        ; (If we appear to have a valid stack pointer).  Otherwise, we just
        ; ignore the event.
        ADD     r11, v6, #O_registerDump+16*4
        LDR     r10, [v6, #O_registerDump+sl*4]
        LDR     r1, [v6, #O_heapBase]
        LDR     r2, [v6, #O_heapLimit]
        LDR     r3, =IsAStackChunk

1759 1760 1761
        ; if in a 26-bit mode - mark PSR in register dump as invalid.
        MOVEQ   r12, #-1
        STREQ   r12, [r11]
Neil Turton's avatar
Neil Turton committed
1762 1763 1764 1765

        LDR     r12, [v6, #O_registerDump+sp*4]
        LDR     v5, [v6, #O_registerDump+fp*4]
        CMP     r12, r1
1766 1767 1768 1769 1770
        CMPHI   r2, r12         ; sp within heap and ...
        CMPHI   r10, r1
        CMPHI   r2, r10         ; sl within heap and ...
        CMPHI   r12, r10        ; sp > sl and ...
        BLS     Event_BadStack
1771 1772 1773 1774
        TST     r10, #3         ; sl word aligned
        TSTEQ   r12, #3         ; sp word aligned
        LDREQ   r4, [r10, #SC_mark-SC_SLOffset]
        CMPEQ   r4, r3          ; sl points at stack chunk
Neil Turton's avatar
Neil Turton committed
1775 1776 1777 1778 1779 1780 1781
        BEQ     Event_StackOK
Event_BadStack
        MOV     r12, #-1
        B       Event_NoStackForHandler

Event_StackOK

1782 1783 1784
        LDMDA   r11!, {r0-r7, r14}
        STMDB   r12!, {r0-r7, r14}
        LDMDA   r11!, {r0-r7}
Neil Turton's avatar
Neil Turton committed
1785 1786 1787
        STMDB   r12!, {r0-r7}

Event_NoStackForHandler
1788
        WritePSRc PSRIBit+PSRSVCMode, r1; we want the testing for an escape and
Neil Turton's avatar
Neil Turton committed
1789 1790 1791 1792 1793 1794
        MOV     r1, #1                  ; allowing callbacks to be indivisible
        LDRB    r0, [v6, #O_hadEscape]  ; (otherwise an escape may be lost).
        STRB    r1, [v6, #O_callbackInactive]
        MOV     r1, #0
        STRB    r1, [v6, #O_hadEscape]
        LDR     v1, [v6, #O_eventCode]
1795 1796 1797
        TEQ     r0, #0                  ; if hadEscape = 0
        CMPEQ   v1, #-1                 ; and it's an escape event
        BEQ     %FT02                   ; then the escape's gone.
Neil Turton's avatar
Neil Turton committed
1798
        CMP     r0, #0
1799
        BEQ     %FT01
1800
        MOV     r0, #126                ; acknowledge escape
1801 1802 1803 1804 1805 1806 1807 1808 1809
        SWI     Byte
        MOV     v1, #-1                 ; escape overrides everything else
01
        [ {CONFIG}=26
        TEQP    pc, #PSRIBit            ; to user mode, with interrupts off
        NOP
        |
        WritePSRc PSRIBit+PSRUSRMode, r0
        ]
Neil Turton's avatar
Neil Turton committed
1810 1811 1812

        CMP     r12, #0
        BGE     CallEventHandlers
1813
02
Neil Turton's avatar
Neil Turton committed
1814 1815 1816 1817 1818
        ADD     r0, v6, #O_registerDump
        B       ReloadUserState

CallEventHandlers
        MOV     sp, r12
1819
        ASSERT  sl = r10
Neil Turton's avatar
Neil Turton committed
1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835
        MOV     fp, v5
        SWI     IntOn
        MOV     r0, sp
        MOV     v2, #lang_Event
        BL      FindAndCallHandlers

        MOV     r0, sp
        MOV     v2, #lang_UnhandledEvent
        BL      FindAndCallHandlers

        MOV     r0, sp
ReloadUserState
        ; Here we must unset the 'callback active' flag and restore our state
        ; from the callback buffer atomically. 3u ARMs unsupported now
        ; User r13, r14 must be reloaded from user mode.
        SWI     EnterSVC
1836
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
1837
        TEQP    pc, #PSRIBit+PSRSVCMode
1838 1839 1840 1841 1842 1843 1844 1845
        NOP
        |
        LDR     r1, [r0, #16*4]
        CMP     r1, #-1
        MSRNE   CPSR_c, #PSR32IBit+PSR32SVCMode
        MSREQ   CPSR_c, #PSR32IBit+PSRSVCMode
        MSRNE   SPSR_cxsf, r1
        ]
Neil Turton's avatar
Neil Turton committed
1846 1847
        ADD     r14, r0, #pc*4
        LDMDB   r14, {r0-r14}^
1848
        NOP
Neil Turton's avatar
Neil Turton committed
1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861
        LDMIA   r14, {pc}^

        LTORG

 ;*-------------------------------------------------------------------*
 ;* Debugging support                                                 *
 ;*-------------------------------------------------------------------*

FindHandler Keep
        ; find to which language the r1 corresponds (between which
        ; language's code bounds it lies).
        LDMIB   v6, {v4, v5}
01      CMP     v4, v5
1862
        BHS     FH_NoHandlerFound
Neil Turton's avatar
Neil Turton committed
1863 1864
        LDMIA   v4, {r0, r2, r3}
        CMP     r1, r2
1865 1866 1867
        CMPHS   r3, r1
        ADDLO   v4, v4, r0
        BLO     %B01
Neil Turton's avatar
Neil Turton committed
1868 1869 1870 1871 1872 1873

        ; If the language has a handler procedure of the right type, return
        ; it in r2 (otherwise 0)
        CMP     r0, v2
        LDRGT   r2, [v4, v2]
        MOVLE   r2, #0
1874
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1875 1876 1877 1878 1879 1880 1881 1882 1883 1884

FH_NoHandlerFound
 [ SharedLibrary
        LDR     r0, =|RTSK$$Data$$Limit|
        CMP     v5, r0
        MOVNE   v5, r0
        LDRNE   v4, =|RTSK$$Data$$Base|
        BNE     %B01
 ]
        MOV     r2, #0
1885
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1886 1887 1888

; char *_kernel_language(int pc);
|_kernel_language|
1889
        FunctionEntry "v2, v4-v6"
Neil Turton's avatar
Neil Turton committed
1890 1891
        LoadStaticBase v6, ip
        MOV     v2, #lang_name
1892
        RemovePSRFromReg a1, lr, r1
Neil Turton's avatar
Neil Turton committed
1893
        BL      FindHandler
1894
        MOV     a1, r2
1895
        Return  "v2, v4-v6"
Neil Turton's avatar
Neil Turton committed
1896 1897 1898

; char *_kernel_procname(int pc);
|_kernel_procname|
1899
        FunctionEntry "v2, v4-v6"
Neil Turton's avatar
Neil Turton committed
1900 1901
        LoadStaticBase v6, ip
        MOV     v2, #lang_ProcName
1902
        RemovePSRFromReg a1, lr, r1
Neil Turton's avatar
Neil Turton committed
1903 1904 1905
        BL      FindHandler
        CMP     r2, #0
        MOVEQ   a1, #0
1906
        Return  "v2, v4-v6",,EQ
Neil Turton's avatar
Neil Turton committed
1907 1908

        MOV     a1, r1
1909 1910 1911
 [ {CONFIG}=26
        MOV     lr, pc
        MOV     pc, r2          ; can't tail-call as may be APCS-32
1912
        Return  "v2, v4-v6"
1913 1914 1915 1916
 |
        LDMFD   sp!, {v2, v4-v6, r14}
        MOV     pc, r2
 ]
Neil Turton's avatar
Neil Turton committed
1917 1918 1919

; int _kernel_unwind(_kernel_unwindblock *inout, char **language);
|_kernel_unwind|
1920
        FunctionEntry "a1, a2, v2, v4-v6"
Neil Turton's avatar
Neil Turton committed
1921 1922
        LoadStaticBase v6, ip
        LDR     r1, [a1, #uwb_pc]
1923
        RemovePSRFromReg r1, lr
Neil Turton's avatar
Neil Turton committed
1924 1925 1926 1927 1928
        MOV     v2, #lang_Unwind
        BL      FindHandler
        CMP     r2, #0
        BEQ     call_default_unwind_handler

1929
 [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
1930
        LDMFD   sp!, {a1, a2}
1931 1932
        MOV     lr, pc
        MOV     pc, r2          ; can't tail-call as may be APCS-32
1933
        Return  "v2, v4-v6"
1934 1935 1936 1937
 |
        LDMFD   sp!, {a1, a2, v2, v4-v6, r14}
        MOV     pc, r2
 ]
Neil Turton's avatar
Neil Turton committed
1938 1939 1940 1941 1942 1943 1944 1945 1946

call_default_unwind_handler
        LDMFD   sp!, {a1, a2, v2, v4-v6, r14}
default_unwind_handler Keep
        STMFD   sp!, {v1-v6, r14}
        LoadStaticBase v6
        MOV     v2, #1
        STRB    v2, [v6, #O_unwinding]
        LDR     a4, [a1, #uwb_fp]
1947
        BICS    a4, a4, #ChunkChange
Neil Turton's avatar
Neil Turton committed
1948 1949 1950 1951
        MOVEQ   v5, #0
        BEQ     duh_exit

        ; a minimal sensibleness check on the FP's value
1952
        ; (bottom bit used to mark stack extension, masked out above).
Neil Turton's avatar
Neil Turton committed
1953

1954
        TST     a4, #&00000002
Neil Turton's avatar
Neil Turton committed
1955 1956 1957
        BNE     duh_corrupt

        LDR     a3, [a4, #frame_entrypc]
1958
        RemovePSRFromReg a3, v1
1959

1960 1961 1962
        TST     a3, #3                  ; If low bits of PC set...
        BNE     duh_corrupt             ; ...then either stack corrupt or was in Thumb mode (and if Thumb, the STM check below will fail anyway)

Neil Turton's avatar
Neil Turton committed
1963 1964 1965 1966
        STMFD   sp!, {a1-a2}
        MOV     a1, #0
        SWI     XOS_PlatformFeatures
        MOVVS   a1, #0
1967
        TST     a1, #8                  ; Is it PC+8 or PC+12?
1968
        ADDNE   a3, a3, #4
Neil Turton's avatar
Neil Turton committed
1969
        LDMFD   sp!, {a1-a2}
1970

1971
        LDR     v1, [a3, #-12]
Neil Turton's avatar
Neil Turton committed
1972 1973 1974 1975 1976

        ; check that the save mask instruction is indeed the right sort of STM
        ; If not, return indicating stack corruption.
        MOV     ip, v1, LSR #16
        EOR     ip, ip, #&e900
1977
        EORS    ip, ip, #&002d          ; STMFD sp!, ... (sp = r13)
Neil Turton's avatar
Neil Turton committed
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992
        BNE     duh_corrupt

        ; update register values in the unwindblock which the save mask says
        ; were saved in this frame.
        MOV     ip, #1
        ADD     v2, a4, #frame_prevfp
        MOV     v3, #v6
        ADD     v4, a1, #uwb_r4-r4*4
01      TST     v1, ip, ASL v3
        LDRNE   r14, [v2, #-4]!
        STRNE   r14, [v4, v3, ASL #2]
        SUB     v3, v3, #1
        CMP     v3, #v1
        BGE     %B01

1993 1994 1995 1996 1997 1998
        ; skip over saved arguments
16      TST     v1, ip, ASL v3
        SUBNE   v2, v2, #4
        SUBS    v3, v3, #1
        BGE     %B16

Neil Turton's avatar
Neil Turton committed
1999 2000 2001
        ; now look for floating point stores immediately after the savemask
        ; instruction, updating values in the saveblock if they are there.
        SUB     a3, a3, #8
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037
        LDR     v1, [a3]                ; check for SUB fp, ip, #n
        LDR     v4, =&e24cb             ; (assumes fp=r11, ip=r12)
        CMP     v4, v1, LSR #12
        ADDEQ   a3, a3, #4              ; skip over it

        ; first look for SFM F4,<count>,[sp,#-count*12]!
        LDR     v4, =&ed2d4200          ; assume sp = r13 if SFM
        LDR     v1, [a3]
        LDR     r14, =&004080ff         ; ignore count + offset
        BIC     r14, v1, r14
        CMP     r14, v4
        BNE     UnwindNotSFM            ; it's not SFM

        LDRB    v3, [v6, #O_fpPresent]
        TEQ     v3, #0
        BEQ     UnwindEndFP             ; can only unwind this if FP present
        AND     v3, v1, #&FF            ; v3 = offset
        AND     v4, v1, #&8000          ; v4 = bottom bit of count
        TST     v1, #&400000
        ORRNE   v4, v4, #&10000         ; add in top bit
        MOVS    v4, v4, LSR #15
        MOVEQ   v4, #4                  ; v4 = count
        ADD     v4, v4, v4, LSL #1      ; v4 = count * 3
        TEQ     v4, v3
        BNE     UnwindEndFP             ; count didn't match offset

        ADD     v3, a1, #uwb_f4         ; v3 -> uwb_f4
        SUB     v2, v2, v4, LSL #2      ; pull v2 down to base of stored FP regs
15      LFM     f0, 1, [v2], #12
        SUBS    v4, v4, #3
        STFE    f0, [v3], #12
        BNE     %B15
        B       UnwindEndFP

        ; or alternatively multiple STFE Fn,[sp,#-12]!
UnwindNotSFM
Neil Turton's avatar
Neil Turton committed
2038 2039
        LDR     v4, =&ed6c0103
02      LDR     v1, [a3], #+4
2040
        BIC     r14, v1, #&17000        ; sp = r12 or r13
Neil Turton's avatar
Neil Turton committed
2041 2042 2043 2044 2045 2046 2047
        CMP     r14, v4
        BNE     UnwindEndFP
        MOV     v1, v1, LSR #10
        AND     v1, v1, #&1c
        ADD     v1, v1, v1, ASL #1
        ADD     v1, a1, v1
        LDR     r14, [v2, #-4]!
2048
        STR     r14, [v1, #uwb_f4-r4*4*3+8]
Neil Turton's avatar
Neil Turton committed
2049
        LDR     r14, [v2, #-4]!
2050
        STR     r14, [v1, #uwb_f4-r4*4*3+4]
Neil Turton's avatar
Neil Turton committed
2051
        LDR     r14, [v2, #-4]!
2052
        STR     r14, [v1, #uwb_f4-r4*4*3]
Neil Turton's avatar
Neil Turton committed
2053 2054 2055 2056 2057 2058 2059
        B       %B02

UnwindEndFP
        LDMDB   a4, {a3, a4, v1}        ; saved fp, sp, link
        ; if the new fp is in a different stack chunk, must amend sl
        ; in the unwind block.
        TST     a3, #ChunkChange
2060
        BIC     a3, a3, #ChunkChange
Neil Turton's avatar
Neil Turton committed
2061 2062 2063 2064 2065 2066
        LDR     v3, [a1, #uwb_sl]
        LDRNE   v3, [v3, #SC_prev-SC_SLOffset]
        ADDNE   v3, v3, #SC_SLOffset
        ADD     ip, a1, #uwb_fp
        STMIA   ip, {a3, a4, v1, v3}
        MOV     v3, a2
2067
        RemovePSRFromReg v1, v2, r1
Neil Turton's avatar
Neil Turton committed
2068 2069 2070 2071 2072 2073 2074 2075
        MOV     v2, #lang_name
        BL      FindHandler
        STR     r2, [v3]
        MOV     v5, #1
duh_exit
        MOV     a1, #0
        STRB    a1, [v6, #O_unwinding]
        MOV     a1, v5
2076
        Return  "v1-v6"
Neil Turton's avatar
Neil Turton committed
2077 2078 2079

duh_abort
        LDR     r12, [v6, #O_registerDump+r12*4]  ; abort handling trampled this.
2080 2081 2082 2083 2084 2085 2086
        MOV     r14, #0
        MRS     r14, CPSR
        TST     r14, #2_11100
        LDRNE   r14, [v6, #O_registerDump+16*4]
        MSRNE   CPSR_c, r14
        LDREQ   r14, [v6, #O_registerDump+pc*4]
        TEQEQP  r14, #0                 ; Back to the mode and interrupt
Neil Turton's avatar
Neil Turton committed
2087
                                        ; status before we got the abort
2088
        NOP
Neil Turton's avatar
Neil Turton committed
2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
duh_corrupt
        MOV     v5, #-1
        B       duh_exit


 ;*-------------------------------------------------------------------*
 ;* SWI interfaces                                                    *
 ;*-------------------------------------------------------------------*


|_kernel_hostos|
        EnterLeafProcContainingSWI
        MOV     r0, #0
        MOV     r1, #1
        SWI     Byte
        MOV     a1, r1
        ExitLeafProcContainingSWI

2107
; Abort handlers assume that lr is preserved
Neil Turton's avatar
Neil Turton committed
2108
|_kernel_swi_c|
2109
        FunctionEntry "a3, a4, v1-v6", makeframe
Neil Turton's avatar
Neil Turton committed
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121
        BIC     r12, a1, #&80000000
        TST     a1, #&80000000          ; non-X bit requested?
        ORREQ   r12, r12, #X
        LDMIA   r1, {r0-r9}
        SWI     XOS_CallASWIR12
        LDMFD   sp!, {ip, lr}
        STMIA   ip, {r0 - r9}
        MOV     ip, #0
        MOVCS   ip, #1
        MOVVS   ip, #0
        STR     ip, [lr]
        MOVVC   a1, #0
2122 2123
        BLVS    CopyError               ; BL<cond> 32-bit OK
        Return  "v1-v6", fpbased
Neil Turton's avatar
Neil Turton committed
2124

2125
; Abort handlers assume that lr is preserved
Neil Turton's avatar
Neil Turton committed
2126
|_kernel_swi|
2127
        FunctionEntry "a3, v1-v6"
Neil Turton's avatar
Neil Turton committed
2128 2129 2130 2131 2132 2133 2134 2135
        BIC     r12, a1, #&80000000
        TST     a1, #&80000000
        ORREQ   r12, r12, #X
        LDMIA   r1, {r0-r9}
        SWI     XOS_CallASWIR12
        LDR     ip, [sp]
        STMIA   ip, {r0-r9}
        MOVVC   a1, #0
2136 2137
        BLVS    CopyError               ; BL<cond> 32-bit OK
        Return  "a3, v1-v6"
Neil Turton's avatar
Neil Turton committed
2138

Neil Turton's avatar
Neil Turton committed
2139 2140 2141 2142

|_kernel_command_string|
        LoadStaticBase a1
        LDR     a1, [a1, #O_ArgString]
2143
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
2144 2145

|_kernel_osbyte|
2146
        FunctionEntry "v6"
Neil Turton's avatar
Neil Turton committed
2147 2148 2149 2150 2151 2152 2153
        SWI     Byte
        BVS     ErrorExitV6Stacked
        AND     a1, a2, #&ff
        ORR     a1, a1, a3, ASL #8
        MOV     a1, a1, ASL #16
        ADC     a1, a1, #0
        MOV     a1, a1, ROR #16
2154
        Return  "v6"
Neil Turton's avatar
Neil Turton committed
2155 2156

|_kernel_osrdch|
2157
        FunctionEntry "v6"
Neil Turton's avatar
Neil Turton committed
2158 2159
        SWI     ReadC
        BVS     ErrorExitV6Stacked
2160
        Return  "v6",,CC
Neil Turton's avatar
Neil Turton committed
2161 2162 2163
        CMPS    a1, #27         ; escape
        MOVEQ   a1, #-27
        MOVNE   a1, #-1         ; other error, EOF etc
2164
        Return  "v6"
Neil Turton's avatar
Neil Turton committed
2165 2166

|_kernel_oswrch|
2167 2168 2169
        FunctionEntry "v6"
        SWI     XOS_WriteC
        Return  "v6",,VC
Neil Turton's avatar
Neil Turton committed
2170
ErrorExitV6Stacked
2171 2172 2173
        BL      CopyError
        MOV     a1, #-2
        Return  "v6"
Neil Turton's avatar
Neil Turton committed
2174 2175

|_kernel_osbget|
2176
        FunctionEntry "v6"
Neil Turton's avatar
Neil Turton committed
2177 2178 2179 2180
        MOV     r1, a1
        SWI     BGet
        BVS     ErrorExitV6Stacked
        MOVCS   a1, #-1
2181
        Return  "v6"
Neil Turton's avatar
Neil Turton committed
2182 2183

|_kernel_osbput|
2184
        FunctionEntry "v6"
Neil Turton's avatar
Neil Turton committed
2185
        SWI     BPut
2186
        Return  "v6",,VC
Neil Turton's avatar
Neil Turton committed
2187 2188 2189 2190 2191 2192 2193 2194 2195 2196
        BVS     ErrorExitV6Stacked

|_kernel_osgbpb|
; typedef struct {
;         void * dataptr;
;         int nbytes, fileptr;
;         int buf_len;
;         char * wild_fld;
; } _kernel_osgbpb_block;
; int _kernel_osgbpb(int op, unsigned handle, _kernel_osgbpb_block *inout);
2197
        FunctionEntry "r4, r5, r6, r7, v6"
Neil Turton's avatar
Neil Turton committed
2198 2199 2200 2201
        MOV     r7, a3
        LDMIA   a3, {r2 - r6}
        SWI     Multiple
        STMIA   r7, {r2 - r6}
2202 2203
        BLVS    CopyError               ; BL<cond> 32-bit OK
        MOVCS   a1, #-1                 ; CopyError preserves C and V
Neil Turton's avatar
Neil Turton committed
2204
        MOVVS   a1, #-2
2205
        Return  "r4, r5, r6, r7, v6"
Neil Turton's avatar
Neil Turton committed
2206 2207

|_kernel_osword|
2208
        FunctionEntry "v6"
Neil Turton's avatar
Neil Turton committed
2209 2210 2211
        SWI     Word
        BVS     ErrorExitV6Stacked
        MOV     a1, r1
2212
        Return  "v6"
Neil Turton's avatar
Neil Turton committed
2213 2214

|_kernel_osfind|
2215 2216 2217
        FunctionEntry "v6"
        SWI     XOS_Find
        Return  "v6",,VC
Neil Turton's avatar
Neil Turton committed
2218 2219 2220 2221 2222 2223 2224 2225
        BVS     ErrorExitV6Stacked

|_kernel_osfile|
; typedef struct {
;         int load, exec;
;         int start, end;
; } _kernel_osfile_block;
; int _kernel_osfile(int op, const char *name, _kernel_osfile_block *inout);
2226
        FunctionEntry "r4-r6,v6"
Neil Turton's avatar
Neil Turton committed
2227 2228
        MOV     r6, a3
        LDMIA   a3, {r2 - r5}
2229
        SWI     XOS_File
Neil Turton's avatar
Neil Turton committed
2230
        STMIA   r6, {r2 - r5}
2231
        BLVS    CopyError               ; BL<cond> 32-bit OK
Neil Turton's avatar
Neil Turton committed
2232
        MOVVS   a1, #-2
2233
        Return  "r4-r6,v6"
Neil Turton's avatar
Neil Turton committed
2234 2235

|_kernel_osargs|
2236
        FunctionEntry "v6"
Neil Turton's avatar
Neil Turton committed
2237 2238 2239 2240 2241 2242
        MOV     ip, a1
        ORR     ip, ip, a2
        SWI     Args
        BVS     ErrorExitV6Stacked
        CMP     ip, #0
        MOVNE   a1, r2
2243
        Return  "v6"
Neil Turton's avatar
Neil Turton committed
2244 2245

|_kernel_oscli|
2246
        FunctionEntry "v6"
Neil Turton's avatar
Neil Turton committed
2247 2248 2249
        SWI     CLI
        BVS     ErrorExitV6Stacked
        MOV     a1, #1      ; return 1 if OK
2250
        Return  "v6"
Neil Turton's avatar
Neil Turton committed
2251 2252 2253 2254 2255 2256 2257 2258

|_kernel_last_oserror|
        LoadStaticBase ip, a1
        LDR     a1, [ip, #O_errorBuffer]
        CMP     a1, #0
        ADDNE   a1, ip, #O_errorNumber
        MOVNE   a2, #0
        STRNE   a2, [ip, #O_errorBuffer]
2259
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
2260

2261 2262 2263 2264 2265 2266 2267
|_kernel_peek_last_oserror|
        LoadStaticBase ip, a1
        LDR     a1, [ip, #O_errorBuffer]
        TEQ     a1, #0
        ADDNE   a1, ip, #O_errorNumber
        Return  ,LinkNotStacked

Neil Turton's avatar
Neil Turton committed
2268 2269 2270 2271 2272 2273 2274 2275
|_kernel_system|
; Execute the string a1 as a command;  if a2 is zero, as a subprogram,
; otherwise a replacement.
;
        STMFD   sp!, {v1-v6, r14}
        LoadStaticBase  v6, ip
        LDRB    v5, [v6, #O_fpPresent]
        CMPS    v5, #0
2276
        SFMNEFD f4, 4, [sp]!
Neil Turton's avatar
Neil Turton committed
2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300
        RFSNE   v5
        STMFD   sp!, {a1, v5}

        LDR     v5, [v6, #O_heapLimit]
        LDR     v4, [v6, #O_heapTop]
        LDR     v3, [v6, #O_imageBase]
        ; if the heap has been extended, copying the image is futile at best
        ; (and maybe harmful if it has a hole)
        LDR     v2, [v6, #O_initSlotSize]
        CMP     v5, v2
        MOVGT   v4, v5                  ; so pretend top = limit.

; Calculate len of image and size of gap.  We will not bother copying at all if gap
; is too small (but can't fault, because the command may not be an application)
        SUB     r0, v4, v3              ; Len = heapTop - imageBase
        ADD     r0, r0, #15
        BIC     v2, r0, #15             ; rounded Len, multiple of 16
        SUB     r14, v5, v3             ; heapLimit - imageBase
        SUB     r14, r14, v2            ; Gap = (heapLimit -imageBase) - Len
        ; if gap is too small, don't bother with copy.  1024 is an arbitrary
        ; small number, but what this is mainly aiming to avoid is the
        ; (otherwise possible) case of v6 < 0.
        CMP     r14, #1024
        MOVLT   r14, #0
Ben Avison's avatar
Ben Avison committed
2301
      [ {FALSE} ; this instruction is now deprecated
Neil Turton's avatar
Neil Turton committed
2302
        STMFD   sp!, {a2, v2-v5, r14, r15}   ; save them away
Ben Avison's avatar
Ben Avison committed
2303 2304 2305 2306
      |
        SUB     sp, sp, #4
        STMFD   sp!, {a2, v2-v5, r14}        ; save them away
      ]
Neil Turton's avatar
Neil Turton committed
2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320
                                        ;subr/chain, len, base, top, limit, gap
                                        ; hole for memoryLimit

        BL      InstallCallersHandlers  ; sets r4 to current memoryLimit
        STR     r4, [sp, #24]
        ADD     r14, sp, #16
        LDMIA   r14, {v5, r14}          ; recover limit, gap

        LDRB    r0, [v6, #O_underDesktop]  ; if under desktop, find what the
        CMP     r0, #0                     ; Wimp slot size currently is, so we
        MOVNE   r0, #Env_ApplicationSpace  ; can reset it later on
        MOV     r1, #0
        SWINE   ChangeEnv

Ben Avison's avatar
Ben Avison committed
2321
        STR     r1, [sp, #-4]!          ; remember slot size
Neil Turton's avatar
Neil Turton committed
2322 2323 2324 2325
        ; All registers must be preserved whose values are wanted afterwards.
        ; v1 to v6 are already on the stack.
        ADD     ip, sp, r14
        ADD     r5, v6, #O_languageEnvSave
Ben Avison's avatar
Ben Avison committed
2326
        STMIA   r5, {sl, fp, ip}        ; save ptr to moved stack
Neil Turton's avatar
Neil Turton committed
2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337
        ADD     v6, v6, r14             ; now points to the to be copied data

; The following loop copies the image up memory. It avoids overwriting
; itself by jumping to its copied copy as soon as it has copied itself,
; unless, of course, it's running in the shared C library...
; The image is copied in DECREASING address order.
CopyUp  CMP     r14, #0
        BEQ     CopyUpDone
        LDR     v2, [sp, #8]            ; image base
        LDR     v3, [sp, #12]           ; Len
        ADD     r1, v3, v2              ; imageBase + Len = initial src
2338
        RemovePSRFromReg pc, v4, v4     ; where to copy down to before jumping
Neil Turton's avatar
Neil Turton committed
2339
        CMP     v4, v5                  ; copy code > limit?
2340 2341 2342
        ADDHI   v4, v3, #16             ; yes => in shared lib so fake v4
        MOVHI   v2, #0                  ; and don't jump to non-copied code
        MOVLS   v2, r14                 ; else jump to copied code
Neil Turton's avatar
Neil Turton committed
2343 2344 2345
01      LDMDB   r1!, {r0,r2-r4}
        STMDB   v5!, {r0,r2-r4}
        CMP     r1, v4                  ; r1 < %B01 ?
2346
        BHI     %B01                    ; no, so keep going...
Neil Turton's avatar
Neil Turton committed
2347 2348 2349 2350 2351 2352
  [ StrongARM
    ;in case we are jumping to code we have just copied here (ie not shared Clib)...
    CMP   v2, #0
    MOVNE r0, #0
    SWINE XOS_SynchroniseCodeAreas
  ]
Neil Turton's avatar
Neil Turton committed
2353 2354 2355 2356 2357
        ADD     r0, pc, v2              ; ... go to moved image
        MOV     pc, r0                  ; and continue copying up...
01      LDMDB   r1!, {r0,r2-r4}
        STMDB   v5!, {r0,r2-r4}
        CMP     r1, v3                  ; src > imageBase ?
2358
        BHI     %B01                    ; yes, so continue
Neil Turton's avatar
Neil Turton committed
2359

Neil Turton's avatar
Neil Turton committed
2360 2361 2362
  ;StrongARM - no need to synchronise for rest of copied code here, since we will not
  ;be executing it (we have to synchronise later, after copying down)

Neil Turton's avatar
Neil Turton committed
2363 2364 2365 2366
CopyUpDone
        ; ip is the relocated sp.
        LDR     r0, [ip, #4]           ; chain/subr
        CMP     r0, #0
2367
        BNE     %FT01
Neil Turton's avatar
Neil Turton committed
2368

2369 2370 2371 2372
        MOV     r0, #Env_MemoryLimit
        LDR     r1, [v6, #O_imageBase]
        ADD     r1, r1, r14
        SWI     ChangeEnv
Neil Turton's avatar
Neil Turton committed
2373

2374 2375 2376
        MOV     r0, #Env_ErrorHandler
        ADR     r1, s_ErrHandler
        MOV     r2, v6
Jeffrey Lee's avatar
Jeffrey Lee committed
2377
        ADD     r3, v6, #O_errorBuffer
2378
        SWI     ChangeEnv
Neil Turton's avatar
Neil Turton committed
2379

2380 2381 2382 2383
        MOV     r0, #Env_ExitHandler
        ADR     r1, s_ExitHandler
        MOV     r2, v6
        SWI     ChangeEnv
Neil Turton's avatar
Neil Turton committed
2384

2385 2386 2387 2388
        MOV     r0, #Env_UpCallHandler  ; We don't really want one of these, ...
        ADR     r1, s_UpCallHandler     ; but RISCOS rules say we must have it
        MOV     r2, v6
        SWI     ChangeEnv
Neil Turton's avatar
Neil Turton committed
2389

2390
01      LDR     r0, [ip, #32]           ; the CLI string to execute
Neil Turton's avatar
Neil Turton committed
2391 2392
        ADD     r0, r0, r14             ; ... suitably relocated...

2393
        SWI     OS_CLI                  ; force non-X variant
Neil Turton's avatar
Neil Turton committed
2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409
        B       s_Exit

s_UpCallHandler
        MOV     pc, r14

s_ErrHandler
        MOV     v6, r0
        MOV     r0, #-2
        B       s_Exit2

s_ExitHandler
        MOV     v6, r12
s_Exit
        MOV     r0, #0
s_Exit2
        ADD     r5, v6, #O_languageEnvSave
Ben Avison's avatar
Ben Avison committed
2410 2411 2412 2413 2414 2415
      [ {FALSE} ; this instruction is now deprecated
        LDMIA   r5, {sl, fp, sp}
      |
        LDMIA   r5, {sl, fp}
        LDR     sp, [r5, #2*4]
      ]
Neil Turton's avatar
Neil Turton committed
2416 2417 2418 2419 2420 2421
        LDMFD   sp!, {a2, a3, v1-v5}    ; slotsize,
                                        ;subr/chain, Len, Base, Top, Limit, Gap
        STR     r0, [sp, #4]            ; ... over prev saved r0...
        CMP     a3, #0
        SWINE   Exit
        MOVS    a1, a2
2422 2423 2424
        BEQ     %FT01
        BL      SetWimpSlot_Save_r4r5   ; set slot size back to value before CLI
        LDMFD   sp!, {r4, r5}
Neil Turton's avatar
Neil Turton committed
2425

2426
01      SUB     sp, sp, v5              ; and relocate sp...
Neil Turton's avatar
Neil Turton committed
2427 2428 2429 2430 2431 2432 2433 2434 2435 2436
        SUB     v6, v6, v5              ; ...and the static data ptr

; The following loop copies the image down memory. It avoids overwriting
; itself by jumping to its copied copy as soon as it has copied itself,
; unless of course, this code is running in the shared C library...
; The image is copied in ASCENDING address order.
        CMP     v5, #0
        BEQ     CopyDnDone
CopyDn
        SUB     r0, v4, v1              ; limit - L = init src
2437
        RemovePSRFromReg pc, v3, v3     ; == BIC v3, pc, #&FC000003 in 26bit
Neil Turton's avatar
Neil Turton committed
2438 2439
        ADD     v3, v3, #%F02-.-4       ; where to copy to before jumping
        CMP     v3, v4                  ; copy code > limit?
2440 2441 2442
        SUBHI   v3, v4, #16             ; yes => in shared lib so fake v3
        MOVHI   v1, #0                  ; and don't jump to not copied code...
        MOVLS   v1, v5                  ; else jump...
Neil Turton's avatar
Neil Turton committed
2443 2444 2445
01      LDMIA   r0!, {r1-r3,ip}
        STMIA   v2!, {r1-r3,ip}
        CMP     r0, v3                  ; copied the copy code?
2446
        BLO     %B01                    ; no, so continue...
Neil Turton's avatar
Neil Turton committed
2447 2448 2449 2450 2451 2452 2453 2454
  [ StrongARM
    ;in case we are jumping to code we have just copied here (ie not shared Clib)...
    MOV   r1, r0
    CMP   v1, #0
    MOVNE r0, #0
    SWINE XOS_SynchroniseCodeAreas
    MOV   r0, r1
  ]
Neil Turton's avatar
Neil Turton committed
2455 2456 2457 2458 2459
        SUB     ip, pc, v1              ; yes => copied this far ...
        MOV     pc, ip                  ; ... so branch to copied copy loop
01      LDMIA   r0!, {r1-r3,ip}
        STMIA   v2!, {r1-r3,ip}
        CMP     r0, v4                  ; finished copying?
2460
        BLO     %B01                    ; no, so continue...
Neil Turton's avatar
Neil Turton committed
2461 2462
02
CopyDnDone
Neil Turton's avatar
Neil Turton committed
2463 2464 2465 2466 2467
  [ StrongARM
    ;you've guessed it
    MOV    r0, #0
    SWI    XOS_SynchroniseCodeAreas
  ]
Ben Avison's avatar
Ben Avison committed
2468
        LDR     r0, [sp], #4            ; old memoryLimit
Neil Turton's avatar
Neil Turton committed
2469 2470 2471 2472 2473 2474
        BL      InstallHandlers

        LDMFD   sp!, {a1, v5}
        LDRB    v4, [v6, #O_fpPresent]
        CMPS    v4, #0
        WFSNE   v5
2475 2476
        LFMNEFD f4, 4, [sp]!
        Return  "v1-v6"
Neil Turton's avatar
Neil Turton committed
2477 2478 2479 2480

CopyError  Keep ; a1 is the address of an error block (may be ours)
                ; we want to copy its contents into our error block,
                ; so _kernel_last_oserror works.
2481 2482
        ; This routine MUST preserve the C and V flags across the call.
        ; The BICS only affects N and Z (C not changed as barrel shifter not used)
Neil Turton's avatar
Neil Turton committed
2483 2484 2485 2486 2487 2488
        LoadStaticBase v6, a2
CopyErrorV6OK
        MOV     a4, a1
        ADD     a2, v6, #O_errorNumber
CopyError2
        STR     pc, [a2, #-4]           ; mark as valid
Ben Avison's avatar
Ben Avison committed
2489 2490
        LDR     a3, [a4], #4
        STR     a3, [a2], #4
Neil Turton's avatar
Neil Turton committed
2491 2492 2493
CopyErrorString
01      LDRB    a3, [a4], #+1
        STRB    a3, [a2], #+1
2494 2495 2496
        BICS    a3, a3, #&1F            ; replaces CMP a3, #' '
        BNE     %B01                    ; replaces BCS %B01
        MOV     pc, lr
Neil Turton's avatar
Neil Turton committed
2497 2498 2499

|_kernel_getenv|
; _kernel_oserror *_kernel_getenv(const char *name, char *buffer, unsigned size);
2500
        FunctionEntry "v1,v2,v6", frame
Neil Turton's avatar
Neil Turton committed
2501
        LoadStaticBase v6, ip
2502
        SUB     r2, r2, #1
Neil Turton's avatar
Neil Turton committed
2503 2504
        MOV     r3, #0
        MOV     r4, #3
2505
        SWI     XOS_ReadVarVal
Neil Turton's avatar
Neil Turton committed
2506 2507
        MOVVC   a1, #0
        STRVCB  a1, [r1, r2]
2508 2509
        BLVS    CopyError               ; BL<cond> 32-bit OK
        Return  "v1,v2,v6", "fpbased"
Neil Turton's avatar
Neil Turton committed
2510 2511 2512

|_kernel_setenv|
; _kernel_oserror *_kernel_setenv(const char *name, const char *value);
2513
        FunctionEntry "v1,v6"
Neil Turton's avatar
Neil Turton committed
2514 2515 2516
        LoadStaticBase v6, ip
        ; Apparently, we need to say how long the value string is as well
        ; as terminating it.
Stewart Brodie's avatar
Stewart Brodie committed
2517 2518 2519 2520 2521
        TEQ     a2, #0
        MOV     a3, #-1
01      ADDNE   a3, a3, #1
        LDRNEB  ip, [a2, a3]
        CMPNE   ip, #0
Neil Turton's avatar
Neil Turton committed
2522 2523 2524
        BNE     %B01
        MOV     r3, #0
        MOV     r4, #0
2525
        SWI     XOS_SetVarVal
Neil Turton's avatar
Neil Turton committed
2526
        MOVVC   a1, #0
2527 2528
        BLVS    CopyError               ; BL<cond> 32-bit OK
        Return  "v1,v6"
Neil Turton's avatar
Neil Turton committed
2529 2530 2531 2532 2533 2534 2535 2536 2537 2538

 ;*-------------------------------------------------------------------*
 ;* Storage management                                                *
 ;*-------------------------------------------------------------------*

|_kernel_register_allocs|
; void _kernel_register_allocs(allocproc *malloc, freeproc *free);
        LoadStaticBase ip, a3
        ADD     ip, ip, #O_allocProc
        STMIA   ip, {a1, a2}
2539
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
2540 2541 2542 2543 2544 2545 2546


|_kernel_register_slotextend|
        LoadStaticBase ip, a3
        MOVS    a2, a1
        LDR     a1, [ip, #O_heapExtender]
        STRNE   a2, [ip, #O_heapExtender]
2547
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615

|_kernel_alloc|
; unsigned _kernel_alloc(unsigned minwords, void **block);
;  Tries to allocate a block of sensible size >= minwords.  Failing that,
;  it allocates the largest possible block of sensible size.  If it can't do
;  that, it returns zero.
;  *block is returned a pointer to the start of the allocated block
;  (NULL if none has been allocated).
        LoadStaticBase ip, a3

        CMP     r0, #2048
        MOVLT   r0, #2048

        ADD     ip, ip, #O_heapTop
        LDMIA   ip, {r2, r3}

        SUB     r3, r3, r0, ASL #2      ; room for a block of this size?
        CMP     r3, r2                  ; if so, ...
        BGE     alloc_return_block

        ; There's not going to be room for the amount required.  See if
        ; we can extend our workspace.
        LDRB    r3, [ip, #O_underDesktop-O_heapTop]
        CMP     r3, #0
 [ SharedLibrary
; See if we are allowed to extend the wimp-slot - depends on the stub vintage
; if running under the shared library. If not shared, we can do it provided
; we're running under the desktop.
        LDRNEB  r3, [ip, #O_kallocExtendsWS-O_heapTop]
        CMPNE   r3, #0
 ]
        BEQ     alloc_cant_extend       ; not under desktop or old stubs

        STMFD   sp!, {r0, r1, lr}

        LDR     r3, [ip, #O_heapExtender-O_heapTop]
        CMP     r3, #0
        BEQ     alloc_no_extender
        LDR     r0, [sp], #-4           ; ask for the amount we were asked for
        MOV     r0, r0, ASL #2          ; (since what we are given may well
                                        ;  not be contiguous with what we had
                                        ;  before).
        ; Set to a silly value, guaranteed not to be equal to initSlotSize, to ensure
        ; reset on exit.
        STR     r3, [ip, #O_knownSlotSize-O_heapTop]
        MOV     r1, sp
        MOV     lr, pc
        MOV     pc, r3
        LoadStaticBase ip, a3           ; restore our static base
        ADD     ip, ip, #O_heapTop
        LDR     r1, [sp], #+4           ; base of area acquired
        CMP     r0, #0                  ; size (should be 0 or big enough)
        BEQ     alloc_cant_extend_0

        LDMIA   ip, {r2, lr}
        CMP     lr, r1
        SUBNE   r3, lr, r2              ; if not contiguous with old area, amount free
        ADD     lr, r1, r0              ; adjust heapLimit
        MOVNE   r0, r2                  ; if not contiguous, remember old heapTop
        MOVNE   r2, r1                  ; and adjust
        STMIA   ip, {r2, lr}
        CMPNE   r3, #0                  ; if contiguous, or old area had no free space,
        BEQ     alloc_cant_extend_0     ; return from new area

        ADD     sp, sp, #4              ; otherwise, return block from top of old area
        LDMFD   sp!, {r1, lr}           ; first (malloc will try again and get from
        STR     r0, [r1]                ; new area).
        MOV     r0, r3, ASR #2
2616
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664

alloc_no_extender
        ; if current slotsize = heap limit, try to extend the heap by the
        ; amount required (or perhaps by just enough to allow allocation
        ; of the amount required)
        ADD     lr, r2, r0, ASL #2      ; heaptop if request could be granted
        MOV     r0, #Env_ApplicationSpace ; find current slotsize
        MOV     r1, #0
        SWI     ChangeEnv
        LDR     r0, [ip, #O_knownSlotSize-O_heapTop]
        CMP     r1, r0
        BNE     alloc_cant_extend_0

        ; If the extension will be contiguous with the current heap top,
        ; then we need just enough to allow the requested allocation.
        LDMIA   ip, {r2, r3}
        CMP     r3, r0
        BEQ     alloc_extend_slot
        ; Otherwise, we must extend by the amount requested.  If there's still
        ; some space left in the previous area, give that back first.
        CMP     r2, r3
        BNE     alloc_cant_extend_0
        STR     r0, [ip, #O_heapTop-O_heapTop]
        LDR     r2, [sp]
        ADD     lr, r0, r2, ASL #2
alloc_extend_slot
        ; lr holds the slot size we want.  r1 is the current memory limit.
        ; Now if memory limit is not slot size, we must reset memory limit
        ; temporarily over the call to Wimp_SlotSize (or it will refuse).
        MOV     r0, lr
        BL      SetWimpSlot_Save_r4r5
        LDMFD   sp!, {r4, r5}
        ADD     r0, r0, #Application_Base
        STR     r0, [ip, #O_knownSlotSize-O_heapTop]
        STR     r0, [ip, #O_heapLimit-O_heapTop]

alloc_cant_extend_0
        LDMFD   sp!, {r0, r1, lr}
alloc_cant_extend
        LDMIA   ip, {r2, r3}

        SUB     r3, r3, r0, ASL #2      ; room for a block of this size?
        CMP     r3, r2                  ; if so, ...

alloc_return_block
        STRGE   r2, [r1]                ; return it above the previous heapTop
        ADDGE   r2, r2, r0, ASL #2      ; and update heapTop
        STRGE   r2, [ip]
2665
        Return  ,LinkNotStacked, GE
Neil Turton's avatar
Neil Turton committed
2666 2667 2668 2669 2670 2671 2672

        ADD     r0, r0, r3, ASR #2      ; otherwise, return whatever is free
        SUB     r0, r0, r2, ASR #2
        CMP     r0, #0
        BGT     alloc_return_block

        STR     r0, [r1]                ; (if none, returned block is NULL,
2673
        Return  ,LinkNotStacked         ; and don't update heapTop)
Neil Turton's avatar
Neil Turton committed
2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692


|_kernel_malloc|
; void * _kernel_malloc(int numbytes);
;  Allocates numbytes bytes (rounded up to number of words), and returns
;  the block allocated.  If it can't, returns NULL.
;  Normally, this will be replaced by the real malloc very early in the
;  startup procedure.
        LoadStaticBase ip, a2

        ADD     ip, ip, #O_heapTop
        LDMIA   ip, {r2, r3}

        SUB     r3, r3, r0              ; room for a block of this size?
        CMP     r3, r2                  ; if so, ...
        ADDGE   r3, r2, r0
        MOVGE   r0, r2                  ; return it above heapTop
        STRGE   r3, [ip]
        MOVLT   r0, #0
2693
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
2694 2695 2696 2697 2698 2699 2700 2701

|_kernel_free|
; void free(void *);
;  Frees the argument block.
;  Normally, this will be replaced by the real free very early in the
;  startup procedure.
;  I don't think there's much point in providing a real procedure for this;
;  if I do, it complicates malloc and alloc above.
2702
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
2703

2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716
; In future these could be sophisticated allocators that associate
; allocated blocks with stack chunks, allowing longjmp() et al to
; clear them up. But for now, this suffices for C99's VLAs.
|__rt_allocauto|
        FunctionEntry
        LoadStaticBase ip, a2
        MOV     lr, pc
        LDR     pc, [ip, #O_allocProc]
        TEQ     a1, #0
        Return  ,,NE
        LoadStaticBase ip, a1
        LDR     lr, [sp], #4
        ADD     ip, ip, #O_registerDump
Ben Avison's avatar
Ben Avison committed
2717
      [ {FALSE} ; this instruction is now deprecated
2718
        STMIA   ip, {a1 - r14}
Ben Avison's avatar
Ben Avison committed
2719 2720 2721 2722 2723
      |
        STMIA   ip, {a1 - r12}
        STR     r13, [ip, #13*4]
        STR     r14, [ip, #14*4]
      ]
2724 2725 2726 2727 2728 2729 2730 2731 2732
        ADR     r0, E_StackOverflow
        BL      |_kernel_copyerror|
        SWI     GenerateError

|__rt_freeauto|
        LoadStaticBase ip, a2
        LDR     pc, [ip, #O_freeProc]


Neil Turton's avatar
Neil Turton committed
2733 2734 2735 2736 2737 2738
 ;*-------------------------------------------------------------------*
 ;* Stack chunk handling                                              *
 ;*-------------------------------------------------------------------*

|_kernel_current_stack_chunk|
        SUB     a1, sl, #SC_SLOffset
2739
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750

 ;*-------------------------------------------------------------------*
 ;* Stack overflow handling                                           *
 ;*-------------------------------------------------------------------*

|_kernel_stkovf_split_0frame|
; Run out of stack.
; Before doing anything else, we need to acquire some work registers
; as only ip is free.
; We can save things on the stack a distance below fp which allows the
; largest possible list of saved work registers (r0-r3, r4-r9 inclusive,
2751 2752
; plus fp, sp, lr = 13 regs in total) plus a minimal stack
; frame for return from StkOvfExit (a further 4 words, giving 17 in total)
Neil Turton's avatar
Neil Turton committed
2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777
; plus 4 extended floating point registers (a further 3*4 words)
        MOV     ip, sp
|_kernel_stkovf_split|
        SUB     ip, sp, ip              ; size required
        SUB     sp, fp, #29*4
        STMFD   sp!, {a1, a2, v1-v6, lr}; to save a1-a2, v1-v6
 [ 0 = 1
        LoadStaticAddress disable_stack_extension, a1, lr
        LDR     a1, [a1]
        CMP     a1, #0
        BNE     StackOverflowFault
 ]
        ADD     v4, ip, #SC_SLOffset    ; required size + safety margin
        SUBS    v1, fp, #30*4           ; save area ptr, clear V flag
        BL      GetStackChunk
        BVS     StackOverflowFault
; Get here with v2 pointing to a big enough chunk of size v3
; (Not yet marked as a stack chunk)
        ADD     sl, v2, #SC_SLOffset    ; make the new sl
        ADD     sp, v2, v3              ; and initial sp
        LDR     a1, =IsAStackChunk
        STR     a1, [sl, #SC_mark-SC_SLOffset]
; v1 is save area in old frame... will be temp sp in old frame
        ADD     a1, v1, #4*4            ; temp fp in old frame
        LDMDA   fp, {v3-v6}             ; old fp, sp,lr, pc
2778

Neil Turton's avatar
Neil Turton committed
2779 2780 2781 2782
        STMFD   sp!,{a1-a2}
        MOV     a1,#0
        SWI     XOS_PlatformFeatures
        MOVVS   a1,#0
2783
        TST     a1,#8                   ; Stores PC+8 or PC+12?
Neil Turton's avatar
Neil Turton committed
2784 2785 2786
        ADREQ   v6, StkOvfPseudoEntry+12
        ADRNE   v6, StkOvfPseudoEntry+8
        LDMFD   sp!,{a1-a2}
2787

Neil Turton's avatar
Neil Turton committed
2788 2789 2790 2791 2792
        STMDA   a1, {v3-v6}             ; new return frame in old chunk...
        ADR     lr, StackOverflowExit
        MOV     a2, sp                  ; saved sp in old frame = NEW sp
                                        ; (otherwise exit call is fatal)
        STMDB   fp, {a1, a2, lr}        ; pervert old frame to return here...
2793
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
2794
        LDMDA   v1, {a1, a2, v1-v6, pc}^
2795 2796 2797
        |
        LDMDA   v1, {a1, a2, v1-v6, pc}
        ]
Neil Turton's avatar
Neil Turton committed
2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853

|_kernel_stkovf_copy0args|
; Run out of stack.
; Before doing anything else, we need to acquire some work registers
; (IP is free in the StkOvf case, but not in the StkOvfN case).
; We can save things on the stack a distance below FP which allows the
; largest possible list of saved work registers (R0-R3, R4-9 inclusive,
; plus FP, SP, LR, entry PC, = 14 regs in total) plus 4 extended floating
; point registers, a further 3*4 words
        MOV     ip, #0                  ; STKOVF not STKOVFN
|_kernel_stkovf_copyargs|
; the (probable) write below sp here is inevitable - there are no registers
; free.  The only way to make this safe against events is to pervert sl
; temporarily.
        ADD     sl, sl, #4
        STR     lr, [fp, #-26*4]        ; save LR
        SUB     lr, fp, #26*4           ; & use as temp SP
        STMFD   lr!, {a1, a2, v1-v6}    ; to save A1-A2, V1-V6
       [ 0 = 1
        LoadStaticAddress disable_stack_extension, a1, lr
        LDR     a1, [a1]
        CMP     a1, #0
        BNE     StackOverflowFault
       ]
        SUB     v4, fp, sp              ; needed frame size
        ADD     v4, v4, #SC_SLOffset    ; + safety margin
        MOV     sp, lr                  ; got an SP now...
        SUB     sl, sl, #4
        ; We do not drop SL here : the code that gets called to acquire a new
        ; stack chunk had better not check for stack overflow (and also had
        ; better not use more than the minimum that may be available).
        SUBS    v1, fp, #26*4           ; save area ptr, clear V flag
        BL      GetStackChunk
        BVS     StackOverflowFault      ; out of stack

; Get here with V2 pointing to a big enough chunk of size V3
        ADD     sl, v2, #SC_SLOffset    ; make the new SL
        ADD     sp, v2, v3              ; and initial SP
        LDR     a1, =IsAStackChunk
        STR     a1, [sl, #SC_mark-SC_SLOffset]
; Copy over 5th and higher arguments, which are expected on the stack...
        CMP     ip, #0
        BLE     DoneArgumentCopy
01      LDR     v5, [fp, ip, ASL #2]    ; copy args in high->low
        STR     v5, [sp, #-4]!          ; address order
        SUBS    ip, ip, #1
        BNE     %B01
DoneArgumentCopy
; Now create a call frame in the new stack chunk by copying
; over stuff saved in the frame in the old stack chunk to the
; new, perverting LR so that, on return, control comes back to
; this code and perverting SP and FP to give us a save area
; containing none of the V registers.
        MOV     v1, fp                  ; old chunk's frame pointer
        SUB     ip, v4, #SC_SLOffset    ; needed frame size, no margin
        LDMDA   v1!, {a1, a2, v2-v6}    ; 1st 7 of possible 14 saved regs
2854
        ADR     v5, StackOverflowExit
Neil Turton's avatar
Neil Turton committed
2855 2856 2857 2858 2859 2860
        MOV     v4, sp                  ; SP in NEW chunk
        ORR     v3, fp, #ChunkChange    ; new FP in old chunk
        SUB     fp, sp, #4              ; FP in new chunk
        STMFD   sp!, {a1, a2, v2-v6}    ; 1st 7 copied frame regs
        LDMDA   v1!, {a1, a2, v2-v6}    ; and the 2nd 7 regs
        STMFD   sp!, {a1, a2, v2-v6}    ; copied to the new frame
2861

Neil Turton's avatar
Neil Turton committed
2862
; Now adjust the PC value saved in the old chunk to say "no registers"
Neil Turton's avatar
Neil Turton committed
2863 2864 2865
        MOV     a1,#0
        SWI     XOS_PlatformFeatures
        MOVVS   a1,#0
2866
        TST     a1,#8                   ; PC+8 or PC+12?
Neil Turton's avatar
Neil Turton committed
2867 2868
        ADREQ   v2, StkOvfPseudoEntry+12
        ADRNE   v2, StkOvfPseudoEntry+8
2869

Neil Turton's avatar
Neil Turton committed
2870 2871 2872 2873
        STR     v2, [v1, #26*4]
; Set the SP to be FP - requiredFrameSize and return by reloading regs
; from where they were saved in the old chunk on entry to STKOVF/N
        SUB     sp, fp, ip
2874
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
2875
        LDMDA   v1, {a1, a2, v1-v6, pc}^
2876 2877 2878
        |
        LDMDA   v1, {a1, a2, v1-v6, pc}
        ]
Neil Turton's avatar
Neil Turton committed
2879 2880 2881 2882 2883 2884 2885 2886

StkOvfPseudoEntry
        STMFD   sp!, {fp, ip, lr, pc}   ; A register save mask

StackOverflowExit Keep
; We return here when returning from the procedure which caused the
; stack to be extended. FP is in the old chunk SP and SL are still
; in the new one.
2887

Neil Turton's avatar
Neil Turton committed
2888 2889 2890 2891 2892
        ; We need to move sp and sl back into the old chunk.  Since this happens
        ; in two operations, we need precautions against events while we're
        ; doing it.
        ADD     sl, sl, #4              ; (an invalid stack-chunk handle)
        SUB     sp, fp, #3*4            ; get a sensible sp in the old chunk
2893
        STMFD   sp!, {a1-a2, v1-v4}     ; Save some work regs
Neil Turton's avatar
Neil Turton committed
2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909
        MOV     v4, r14                 ; Remember if register permute needed
; Now see if the new chunk has a next chunk and deallocate it if it has.
        SUB     v1, sl, #4
        LDR     v2, [v1, #SC_next-SC_SLOffset]
        LDR     sl, [v1, #SC_prev-SC_SLOffset]
        LDR     a1, [sl, #SC_mark]      ; make not a stack chunk (before making
        EOR     a1, a1, #&40000000      ; sl a proper stackchunk handle).
        STR     a1, [sl, #SC_mark]
        ADD     sl, sl, #SC_SLOffset
        SUB     sp, sp, #4
DeallocateChunkLoop
        CMP     v2, #0                  ; is there a next next chunk?
        BEQ     DoneDeallocateChunks    ; No! - do nothing
        LDR     v3, [v2, #SC_next]      ; next chunk
        MOV     a1, v2
        LDR     ip, [v2,#SC_deallocate] ; deallocate proc for this chunk
2910
        CMPS    ip, #0                  ; is there a proc?
Neil Turton's avatar
Neil Turton committed
2911
        MOVEQ   v1, v2                  ; no deallocate proc: try next chunk
2912 2913 2914 2915 2916 2917
        BEQ     DeallocateChunkLoopSkip ; go around next chunk
        MOV     lr, pc
        MOV     pc, ip                  ; there was, so call it...
        MOV     a2, #0
        STR     a2, [v1, #SC_next-SC_SLOffset] ; and unhook next chunk
DeallocateChunkLoopSkip
Neil Turton's avatar
Neil Turton committed
2918 2919 2920 2921 2922 2923 2924 2925
        MOV     v2, v3
        B       DeallocateChunkLoop
DoneDeallocateChunks
; Clear the chunk change bit, and return to caller by reloading the saved work
; regs and the frame regs that were adjusted at the time the stack was extended
        LDR     a1, =IsAStackChunk
        STR     a1, [sl, #SC_mark-SC_SLOffset]
        BIC     fp, fp, #ChunkChange
2926 2927
; Return
        Return  "a1-a2, v1-v4", fpbased
Neil Turton's avatar
Neil Turton committed
2928 2929 2930 2931 2932 2933 2934

GetStackChunk Keep
; Naughty procedure with non-standard argument conventions.
; On entry, V1 = save area ptr in case of error return; V4 = needed size;
; On exit, V1, and V4 are preserved, V2 points to the newly inserted chunk
; and V3 is the chunk's size. In case of error, V is set.
StkOvfGetChunk
2935
      [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
2936 2937 2938
        TST     r14, #PSRSVCMode        ; in SWI mode, stack overflow is fatal
        ORRNES  pc, r14, #PSRVBit       ; (could have been detected earlier,
                                        ; but deferral to now is simpler).
2939 2940
      |
        MRS     v2, CPSR
Ben Avison's avatar
Ben Avison committed
2941 2942
        MOVS    v2, v2, LSL #28
        TEQHI   v2, #&F0000000          ; allow stack extension in SYS mode
2943 2944 2945
        MSRNE   CPSR_f, #V_bit          ; maintain NE
        MOVNE   pc, lr
      ]
Neil Turton's avatar
Neil Turton committed
2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972
; Check that the current chunk really is a stack chunk...
        STMFD   sp!, {a3, a4, ip, lr}   ; save args not saved before
        LDR     v2, =IsAStackChunk      ; magic constant...
        LDR     v3, [sl, #SC_mark-SC_SLOffset]
        CMP     v2, v3                  ; matches magic in chunk?
        BNE     StkOvfError             ; No! - die horribly
        EOR     v3, v3, #&80000000      ; make not a stack chunk, so recursive
        STR     v3, [sl, #SC_mark-SC_SLOffset] ; extension faults
; We have a chunk, see if there's a usable next chunk...
        SUB     v2, sl, #SC_SLOffset
02      LDR     v2, [v2, #SC_next]
        CMP     v2, #0
        BEQ     StkOvfGetNewChunk       ; No! - so make one
        LDR     v3, [v2, #SC_size]
        CMP     v4, v3                  ; is it big enough?
        BGT     %B02                    ; No! so try next chunk
; unlink the usable chunk from the chain...
        LDR     a1, [v2, #SC_prev]      ; previous chunk
        LDR     a2, [v2, #SC_next]      ; next chunk
        STR     a2, [a1, #SC_next]      ; prev->next = next
        CMPS    a2, #0                  ; next == NULL ?
        STRNE   a1, [a2, #SC_prev]      ; next->prev = prev
        B       StkOvfInsertChunk
StkOvfGetNewChunk Keep
        ; Now we swap to the special extension chunk (to give a reasonable
        ; stack size to malloc).
        LoadStaticBase v2, ip
2973 2974 2975 2976 2977 2978 2979 2980
03      MOV     a1, #0
        ADD     a2, v2, #O_extendChunkNotInUse
      [ {CONFIG}=26
        LDR     lr, [v2, #O__swp_available]
        TEQ     lr, #0
        SWPNE   a1, a1, [a2]
        BLEQ    Arm2Swp
      |
Ben Avison's avatar
Ben Avison committed
2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994
       [ SupportARMv6
        [ NoARMv6
        LDR     lr, [v2, #O__swp_available]
        TST     lr, #2 ; CPU supports LDREX?
        SWPEQ   a1, a1, [a2]
        BEQ     %FT02
        ]
        MOV     lr, #0
01      LDREXB  a1, [a2]
        STREXB  a3, lr, [a2]
        TEQ     a3, #1
        BEQ     %BT01
02
       |
2995
        SWP     a1, a1, [a2]
Ben Avison's avatar
Ben Avison committed
2996
       ]
2997 2998 2999 3000
      ]
        TEQ     a1, #0
        BLEQ    Sleep                     ; preserves Z
        BEQ     %BT03
Neil Turton's avatar
Neil Turton committed
3001 3002 3003
        LDR     a2, [v2, #O_extendChunk]
        LDR     a3, [a2, #SC_size]
        ADD     a3, a2, a3                ; new sp
Ben Avison's avatar
Ben Avison committed
3004
      [ {FALSE} ; this instruction is now deprecated
Neil Turton's avatar
Neil Turton committed
3005
        STMFD   a3!, {sl, fp, sp}         ; save old stack description
Ben Avison's avatar
Ben Avison committed
3006 3007 3008 3009
      |
        STR     sp, [a3, #-4]!
        STMFD   a3!, {sl, fp}             ; save old stack description
      ]
Neil Turton's avatar
Neil Turton committed
3010 3011 3012 3013 3014 3015 3016 3017 3018 3019
        MOV     sp, a3
        ADD     sl, a2, #SC_SLOffset
        MOV     fp, #0

        MOV     a1, #RootStackSize; new chunk is at least this big
        CMP     a1, v4            ; but may be bigger if he wants a huge frame
        MOVLT   a1, v4
        LDR     ip, [v2, #O_allocProc]
        CMPS    ip, #0
        BEQ     %F01                    ; (restore stack chunk, then error)
3020 3021
        LDR     lr, [v2, #O_freeProc]
        STMFD   sp!, {a1, lr}           ; chunk size in bytes, dealloc proc
Neil Turton's avatar
Neil Turton committed
3022 3023
        MOV     lr, pc
        MOV     pc, ip
3024
        MOV     lr, v2
Neil Turton's avatar
Neil Turton committed
3025 3026 3027
        MOVS    v2, a1
        LDMFD   sp!, {v3, ip}           ; size in bytes, dealloc
01
Ben Avison's avatar
Ben Avison committed
3028
      [ {FALSE} ; this instruction is now deprecated
Neil Turton's avatar
Neil Turton committed
3029
        LDMFD   sp, {sl, fp, sp}        ; back to old chunk
Ben Avison's avatar
Ben Avison committed
3030 3031 3032 3033
      |
        LDMFD   sp!, {sl, fp}           ; back to old chunk
        LDR     sp, [sp]
      ]
3034 3035
        MOV     a1, #1
        STR     a1, [lr, #O_extendChunkNotInUse]
Neil Turton's avatar
Neil Turton committed
3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055
        BEQ     StkOvfError
        STR     v3, [v2, #SC_size]
        STR     ip, [v2, #SC_deallocate]
        LDR     a1, [sl, #SL_Lib_Offset]
        STR     a1, [v2, #SL_Lib_Offset+SC_SLOffset]
        LDR     a1, [sl, #SL_Client_Offset]
        STR     a1, [v2, #SL_Client_Offset+SC_SLOffset]
; and re-link it in its proper place...
StkOvfInsertChunk
        SUB     a1, sl, #SC_SLOffset    ; chunk needing extension...
        LDR     a2, =IsAStackChunk
        STR     a2, [a1, #SC_mark]      ; remark as stack chunk
        LDR     a2, [a1, #SC_next]      ; its next chunk
        STR     a2, [v2, #SC_next]      ; this->next = next
        STR     v2, [a1, #SC_next]      ; prev->next = this
        STR     a1, [v2, #SC_prev]      ; this->prev = prev
        CMPS    a2, #0
        STRNE   v2, [a2, #SC_prev]      ; next->prev = this
        STR     pc, [v2, #SC_mark]      ; Not a stack chunk (for safe non-atomic
                                        ; update of sp and sl).
3056
        Return  "a3, a4, ip"            ; restore extra saved regs
Neil Turton's avatar
Neil Turton committed
3057
StkOvfError
3058
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
3059 3060
        LDMFD   sp!, {a3, a4, ip, lr}
        ORRS    pc, lr, #PSRVBit        ; return with V set
3061 3062 3063 3064
        |
        MSR     CPSR_f, #V_bit
        LDMFD   sp!, {a3, a4, ip, pc}
        ]
Neil Turton's avatar
Neil Turton committed
3065 3066 3067 3068 3069 3070

StackOverflowFault Keep
        LoadStaticBase ip, a1
        MOV     sp, v1
        LDMDA   v1, {a1, a2, v1-v6, lr}
        ADD     ip, ip, #O_registerDump
Ben Avison's avatar
Ben Avison committed
3071
      [ {FALSE} ; this instruction is now deprecated
Neil Turton's avatar
Neil Turton committed
3072
        STMIA   ip, {a1 - r14}
Ben Avison's avatar
Ben Avison committed
3073 3074 3075 3076 3077
      |
        STMIA   ip, {a1 - r12}
        STR     r13, [ip, #13*4]
        STR     r14, [ip, #14*4]
      ]
Neil Turton's avatar
Neil Turton committed
3078 3079 3080 3081
        ADR     r0, E_StackOverflow
        BL      |_kernel_copyerror|
        SWI     GenerateError

Ben Avison's avatar
Ben Avison committed
3082
        LTORG
Neil Turton's avatar
Neil Turton committed
3083 3084
        ErrorBlock StackOverflow, "Stack overflow", C45

3085 3086 3087 3088 3089 3090 3091 3092
 [ {CONFIG}=26
Arm2Swp ; like SWP a1,a1,[a2] but corrupts a3, lr and flags
        SWI     IntOff
        LDR     a3, [a2]
        STR     a1, [a2]
        SWI     IntOn
        MOV     a1, a3
        MOV     pc, lr
Ben Avison's avatar
Ben Avison committed
3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127
 |
AcquireMutex
        FunctionEntry
        MOV     a2, a1
  [ SupportARMv6
   [ NoARMv6
        LoadStaticBase a4, ip
        LDR     a1, [a4, #O__swp_available]
        TST     a1, #2 ; does CPU support LDREX?
        BEQ     %FT03
   ]
        MOV     a3, #0
  ]
        B       %FT02
  [ SupportARMv6
01      MOV     a1, #6
        SWI     XOS_UpCall
02      LDREX   a1, [a2]
        STREX   a4, a3, [a2]
        TEQ     a4, #1
        BEQ     %BT02
        TEQ     a1, #0
        BEQ     %BT01
        Return
  ]
  [ NoARMv6
01      MOV     a1, #6
        SWI     XOS_UpCall
02
03      MOV     a1, #0
        SWP     a1, a1, [a2]
        TEQ     a1, #0
        BEQ     %BT01
        Return
  ]
3128 3129 3130 3131 3132 3133
 ]

Sleep
; a2 -> pollword
; must exit with Z set
        MOV     a1, #6
3134
        SWI     XOS_UpCall
3135 3136 3137
        CMP     a1, a1
        MOV     pc, lr

Neil Turton's avatar
Neil Turton committed
3138 3139 3140 3141
 ;*-------------------------------------------------------------------*
 ;* Arithmetic                                                        *
 ;*-------------------------------------------------------------------*

3142
|__rt_udiv|
Neil Turton's avatar
Neil Turton committed
3143
|_kernel_udiv|
3144
|x$udivide|
Neil Turton's avatar
Neil Turton committed
3145
; Unsigned divide of a2 by a1: returns quotient in a1, remainder in a2
3146
; Destroys a3 and ip
3147
      [ NoARMVE
3148
|_kernel_udiv_NoARMVE|
3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195
        MOV     a3, #0
        RSBS    ip, a1, a2, LSR #3
        BCC     u_sh2
        RSBS    ip, a1, a2, LSR #8
        BCC     u_sh7
        MOV     a1, a1, LSL #8
        ORR     a3, a3, #&FF000000
        RSBS    ip, a1, a2, LSR #4
        BCC     u_sh3
        RSBS    ip, a1, a2, LSR #8
        BCC     u_sh7
        MOV     a1, a1, LSL #8
        ORR     a3, a3, #&00FF0000
        RSBS    ip, a1, a2, LSR #8
        MOVCS   a1, a1, LSL #8
        ORRCS   a3, a3, #&0000FF00
        RSBS    ip, a1, a2, LSR #4
        BCC     u_sh3
        RSBS    ip, a1, #0
        BCS     dividebyzero
u_loop  MOVCS   a1, a1, LSR #8
u_sh7   RSBS    ip, a1, a2, LSR #7
        SUBCS   a2, a2, a1, LSL #7
        ADC     a3, a3, a3
u_sh6   RSBS    ip, a1, a2, LSR #6
        SUBCS   a2, a2, a1, LSL #6
        ADC     a3, a3, a3
u_sh5   RSBS    ip, a1, a2, LSR #5
        SUBCS   a2, a2, a1, LSL #5
        ADC     a3, a3, a3
u_sh4   RSBS    ip, a1, a2, LSR #4
        SUBCS   a2, a2, a1, LSL #4
        ADC     a3, a3, a3
u_sh3   RSBS    ip, a1, a2, LSR #3
        SUBCS   a2, a2, a1, LSL #3
        ADC     a3, a3, a3
u_sh2   RSBS    ip, a1, a2, LSR #2
        SUBCS   a2, a2, a1, LSL #2
        ADC     a3, a3, a3
u_sh1   RSBS    ip, a1, a2, LSR #1
        SUBCS   a2, a2, a1, LSL #1
        ADC     a3, a3, a3
u_sh0   RSBS    ip, a1, a2
        SUBCS   a2, a2, a1
        ADCS    a3, a3, a3
        BCS     u_loop
        MOV     a1, a3
3196 3197 3198 3199
        Return  ,LinkNotStacked
      ]
      [ SupportARMVE :LAND: (:LNOT: NoARMVE :LOR: SHARED_C_LIBRARY)
|_kernel_udiv_SupportARMVE|
3200 3201 3202 3203 3204 3205
; Long delay on UDIV result makes it faster to divide and then check for error
        UDIV    a3, a2, a1
        TEQ     a1, #0
        BEQ     dividebyzero
        MLS     a2, a3, a1, a2
        MOV     a1, a3
3206
        Return  ,LinkNotStacked
3207
      ]
Neil Turton's avatar
Neil Turton committed
3208 3209 3210 3211 3212 3213 3214

; Unsigned remainder of a2 by a1: returns remainder in a1
; Could be faster (at expense in size) by duplicating code for udiv,
; but removing the code to generate a quotient.  As it is, a sensible
; codegenerator will call udiv directly and use the result in a2

|_kernel_urem|
3215
|x$uremainder|
3216
        FunctionEntry
Neil Turton's avatar
Neil Turton committed
3217 3218
        BL      |_kernel_udiv|
        MOV     a1, a2
3219
        Return
Neil Turton's avatar
Neil Turton committed
3220 3221 3222 3223 3224 3225

; Fast unsigned divide by 10: dividend in a1
; Returns quotient in a1, remainder in a2

|__rt_udiv10|
|_kernel_udiv10|
3226
      [ NoARMM
3227
|_kernel_udiv10_NoARMM|
3228 3229
        SUB     a2, a1, #10
        SUB     a1, a1, a1, LSR #2
Neil Turton's avatar
Neil Turton committed
3230 3231 3232 3233
        ADD     a1, a1, a1, LSR #4
        ADD     a1, a1, a1, LSR #8
        ADD     a1, a1, a1, LSR #16
        MOV     a1, a1, LSR #3
3234 3235 3236 3237
        ADD     a3, a1, a1, LSL #2
        SUBS    a2, a2, a3, LSL #1
        ADDPL   a1, a1, #1
        ADDMI   a2, a2, #10
3238 3239 3240 3241
        Return  ,LinkNotStacked
      ]
      [ SupportARMM :LAND: (:LNOT: NoARMM :LOR: SHARED_C_LIBRARY)
|_kernel_udiv10_SupportARMM|
3242 3243 3244 3245 3246 3247 3248 3249
; For small numbers, UDIV would be faster than this, but not enough to make it
; worth dynamically switching between algorithms.
        LDR     a2, =&CCCCCCCD ; (8^32) / 10
        UMULL   ip, a3, a2, a1
        MOV     a3, a3, LSR #3 ; Accurate division by 10
        SUB     a2, a1, a3, LSL #1
        MOV     a1, a3
        SUB     a2, a2, a3, LSL #3
3250
        Return  ,LinkNotStacked
3251
      ]
Neil Turton's avatar
Neil Turton committed
3252 3253


3254
|__rt_sdiv|
Neil Turton's avatar
Neil Turton committed
3255
|_kernel_sdiv|
3256
|x$divide|
Neil Turton's avatar
Neil Turton committed
3257 3258 3259 3260
; Signed divide of a2 by a1: returns quotient in a1, remainder in a2
; Quotient is truncated (rounded towards zero).
; Sign of remainder = sign of dividend.
; Destroys a3, a4 and ip
3261
      [ NoARMVE
3262
|_kernel_sdiv_NoARMVE|
Neil Turton's avatar
Neil Turton committed
3263 3264
; Negates dividend and divisor, then does an unsigned divide; signs
; get sorted out again at the end.
3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317

        ANDS    a3, a1, #&80000000
        RSBMI   a1, a1, #0
        EORS    a4, a3, a2, ASR #32
        RSBCS   a2, a2, #0
        RSBS    ip, a1, a2, LSR #3
        BCC     s_sh2
        RSBS    ip, a1, a2, LSR #8
        BCC     s_sh7
        MOV     a1, a1, LSL #8
        ORR     a3, a3, #&FF000000
        RSBS    ip, a1, a2, LSR #4
        BCC     s_sh3
        RSBS    ip, a1, a2, LSR #8
        BCC     s_sh7
        MOV     a1, a1, LSL #8
        ORR     a3, a3, #&00FF0000
        RSBS    ip, a1, a2, LSR #8
        MOVCS   a1, a1, LSL #8
        ORRCS   a3, a3, #&0000FF00
        RSBS    ip, a1, a2, LSR #4
        BCC     s_sh3
        RSBS    ip, a1, #0
        BCS     dividebyzero
s_loop  MOVCS   a1, a1, LSR #8
s_sh7   RSBS    ip, a1, a2, LSR #7
        SUBCS   a2, a2, a1, LSL #7
        ADC     a3, a3, a3
s_sh6   RSBS    ip, a1, a2, LSR #6
        SUBCS   a2, a2, a1, LSL #6
        ADC     a3, a3, a3
s_sh5   RSBS    ip, a1, a2, LSR #5
        SUBCS   a2, a2, a1, LSL #5
        ADC     a3, a3, a3
s_sh4   RSBS    ip, a1, a2, LSR #4
        SUBCS   a2, a2, a1, LSL #4
        ADC     a3, a3, a3
s_sh3   RSBS    ip, a1, a2, LSR #3
        SUBCS   a2, a2, a1, LSL #3
        ADC     a3, a3, a3
s_sh2   RSBS    ip, a1, a2, LSR #2
        SUBCS   a2, a2, a1, LSL #2
        ADC     a3, a3, a3
s_sh1   RSBS    ip, a1, a2, LSR #1
        SUBCS   a2, a2, a1, LSL #1
        ADC     a3, a3, a3
s_sh0   RSBS    ip, a1, a2
        SUBCS   a2, a2, a1
        ADCS    a3, a3, a3
        BCS     s_loop
        EORS    a1, a3, a4, ASR #31
        ADD     a1, a1, a4, LSR #31
        RSBCS   a2, a2, #0
3318 3319 3320 3321
        Return  ,LinkNotStacked
      ]
      [ SupportARMVE :LAND: (:LNOT: NoARMVE :LOR: SHARED_C_LIBRARY)
|_kernel_sdiv_SupportARMVE|
3322 3323 3324 3325 3326
        SDIV    a3, a2, a1
        TEQ     a1, #0
        BEQ     dividebyzero
        MLS     a2, a3, a1, a2
        MOV     a1, a3
3327
        Return  ,LinkNotStacked
3328
      ]
Neil Turton's avatar
Neil Turton committed
3329 3330 3331 3332

; Signed remainder of a2 by a1: returns remainder in a1

|_kernel_srem|
3333
|x$remainder|
3334
        FunctionEntry
Neil Turton's avatar
Neil Turton committed
3335 3336
        BL      |_kernel_sdiv|
        MOV     a1, a2
3337
        Return
Neil Turton's avatar
Neil Turton committed
3338 3339 3340 3341 3342 3343 3344

; Fast signed divide by 10: dividend in a1
; Returns quotient in a1, remainder in a2
; Quotient is truncated (rounded towards zero).

|__rt_sdiv10|
|_kernel_sdiv10|
3345
      [ NoARMM
3346
|_kernel_sdiv10_NoARMM|
Neil Turton's avatar
Neil Turton committed
3347 3348
        MOVS    a4, a1
        RSBMI   a1, a1, #0
3349 3350
        SUB     a2, a1, #10
        SUB     a1, a1, a1, LSR #2
Neil Turton's avatar
Neil Turton committed
3351 3352 3353 3354
        ADD     a1, a1, a1, LSR #4
        ADD     a1, a1, a1, LSR #8
        ADD     a1, a1, a1, LSR #16
        MOV     a1, a1, LSR #3
3355 3356 3357 3358 3359
        ADD     a3, a1, a1, LSL #2
        SUBS    a2, a2, a3, LSL #1
        ADDPL   a1, a1, #1
        ADDMI   a2, a2, #10
        MOVS    a4, a4
Neil Turton's avatar
Neil Turton committed
3360 3361
        RSBMI   a1, a1, #0
        RSBMI   a2, a2, #0
3362 3363 3364 3365
        Return  ,LinkNotStacked
      ]
      [ SupportARMM :LAND: (:LNOT: NoARMM :LOR: SHARED_C_LIBRARY)
|_kernel_sdiv10_SupportARMM|
3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376
; Using SMULL here would be tricky due to the need to round towards zero
        MOVS    a4, a1
        LDR     a2, =&CCCCCCCD ; (8^32) / 10
        RSBMI   a1, a1, #0
        UMULL   ip, a3, a2, a1
        MOV     a3, a3, LSR #3 ; Accurate division by 10
        SUB     a2, a1, a3, LSL #1
        MOV     a1, a3
        SUB     a2, a2, a3, LSL #3
        RSBMI   a1, a1, #0
        RSBMI   a2, a2, #0
3377
        Return  ,LinkNotStacked
3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392
      ]

        RoutineVariant _kernel_udiv, ARMVE, UDIV_SDIV, MLS
        RoutineVariant _kernel_udiv10, ARMM, UMULL_UMLAL
        RoutineVariant _kernel_sdiv, ARMVE, UDIV_SDIV, MLS
        RoutineVariant _kernel_sdiv10, ARMM, UMULL_UMLAL
      [ {CONFIG}=26
        EXPORT  |_kernel_irqs_on$variant|
        EXPORT  |_kernel_irqs_off$variant|
|_kernel_irqs_on$variant| * |_kernel_irqs_on|
|_kernel_irqs_off$variant| * |_kernel_irqs_off|
      |
        RoutineVariant _kernel_irqs_on, ARMv6, SRS_RFE_CPS
        RoutineVariant _kernel_irqs_off, ARMv6, SRS_RFE_CPS
      ]
Neil Turton's avatar
Neil Turton committed
3393

3394 3395
        EXPORT  __rt_div0
__rt_div0
Neil Turton's avatar
Neil Turton committed
3396 3397 3398 3399 3400 3401 3402
dividebyzero
        ; Dump all registers, then enter the abort code.
        ; We need to discover whether we were doing a divide (in which case,
        ; r14 is a valid link), or a remainder (in which case, we must retrieve
        ; the link from the stack).
        LoadStaticBase ip, a3
        ADD     ip, ip, #O_registerDump
Ben Avison's avatar
Ben Avison committed
3403
      [ {FALSE} ; this instruction is now deprecated
Neil Turton's avatar
Neil Turton committed
3404
        STMIA   ip, {r0-r13}
Ben Avison's avatar
Ben Avison committed
3405 3406 3407 3408
      |
        STMIA   ip, {r0-r12}
        STR     r13, [ip, #13*4]
      ]
3409
        RemovePSRFromReg r14, r1, r0            ; == BIC r0, r14, #PSRBits  IFF 26bit
Neil Turton's avatar
Neil Turton committed
3410 3411 3412
        SUBS    r1, pc, r0
        ADRGE   r1, |_kernel_udiv|
        CMPGE   r0, r1
Ben Avison's avatar
Ben Avison committed
3413
        LDRGE   r14, [sp], #4
Neil Turton's avatar
Neil Turton committed
3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424
        STR     r14, [ip, #r14*4]
        ADR     r0, E_DivideByZero
10
        SUB     r14, r14, #4
        STR     r14, [ip, #pc*4]

        BL      |_kernel_copyerror|

        SWI     EnterSVC
        LDR     r14, [ip, #pc * 4]
        LDMIB   ip, {r1-r14}^
3425
        NOP
Neil Turton's avatar
Neil Turton committed
3426
        STMDB   sp!, {r10, r11, r12}
Ben Avison's avatar
Ben Avison committed
3427
        STR     r14, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
3428 3429 3430 3431 3432 3433 3434 3435 3436 3437
        SWI     GenerateError

        EXPORT  |_kernel_fault|
|_kernel_fault|
        ; r0 points to an error block;
        ; original r0 is on the stack.
        ; r14 is the place to pretend the fault happened
        STMFD   sp!, {r1, ip}
        LoadStaticBase ip, r1
        ADD     ip, ip, #O_registerDump
Ben Avison's avatar
Ben Avison committed
3438
      [ {FALSE} ; this instruction is now deprecated
Neil Turton's avatar
Neil Turton committed
3439
        STMIA   ip, {r0-r14}
Ben Avison's avatar
Ben Avison committed
3440 3441 3442 3443 3444
      |
        STMIA   ip, {r0-r12}
        STR     r13, [ip, #13*4]
        STR     r14, [ip, #14*4]
      ]
Neil Turton's avatar
Neil Turton committed
3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456
        LDMFD   sp!, {r1, r2, r3}
        STR     r3, [ip]
        STR     r2, [ip, #ip*4]
        STR     r1, [ip, #r1*4]
        B       %B10

        ErrorBlock DivideByZero, "Divide by zero", C06

; --- International message lookup routines ----------------------------

        EXPORT  |_kernel_copyerror|
        EXPORT  |_kernel_getmessage|
3457
        EXPORT  |_kernel_getmessage_def|
3458
        EXPORT  |_kernel_getmessage2|
Neil Turton's avatar
Neil Turton committed
3459 3460 3461

        [ SharedLibrary   ; Only works with module for the moment

3462
        GET     Hdr:MsgTrans
Neil Turton's avatar
Neil Turton committed
3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485

n_module_claim      EQU  6
n_module_lookupname EQU 18

; Lookup an error message
;
; On entry:
;   R0 = Pointer to "international" error block.
;        +--------------------+
;        | Default error no.  | - Default error no and str are used if message file
;        +--------------------+   cannot be opened or an error occurs trying to read
;        | Default error str. |   the message file.
;        +--------------------+
;        | Pad. to word align |
;        +--------------------+
;        | Error no.          | - Real error numbers (may be same as default)
;        +--------------------+
;        | Error message tag  |   Message tag in message file
;        +--------------------+
; Return:
;   R0 = Pointer to selected error block (default or from message file)
;
|_kernel_copyerror|
3486
        FunctionEntry "r1-r7,r12"
Neil Turton's avatar
Neil Turton committed
3487 3488 3489 3490 3491 3492 3493
        BL      open_messagefile
        MOV     r2, #0
        ADR     r4, module_name
        MOV     r5, #0
        MOV     r6, #0
        MOV     r7, #0
        SWI     XMessageTrans_ErrorLookup
3494
        Return  "r1-r7,r12"
Neil Turton's avatar
Neil Turton committed
3495 3496 3497 3498 3499 3500 3501 3502 3503 3504

; Try to get a message from the message file
;
; On entry:
;   R0 = Message to use if failed to get message from message file
;   R1 = Message tag
;
; Return:
;   R0 = Message
;
3505
      [ :DEF:DEFAULT_TEXT
Neil Turton's avatar
Neil Turton committed
3506
|_kernel_getmessage|
3507 3508
      ]
|_kernel_getmessage_def|
3509
        FunctionEntry "r0-r7,r12"
Neil Turton's avatar
Neil Turton committed
3510 3511 3512 3513 3514 3515 3516 3517 3518 3519
        BL      open_messagefile
        MOV     r0, r1
        LDR     r1, [sp, #4]
        MOV     r2, #0
        MOV     r4, #0
        MOV     r5, #0
        MOV     r6, #0
        MOV     r7, #0
        SWI     XMessageTrans_Lookup
        STRVC   r2, [sp]
3520
        Return  "r0-r7,r12"
Neil Turton's avatar
Neil Turton committed
3521

3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535
      [ :LNOT::DEF:DEFAULT_TEXT
; On entry:
;   R0 = Message tag
;
; Return:
;   R0 = Message
;
|_kernel_getmessage|
        FunctionEntry "r1"
        MOV     r1, r0
        BL      |_kernel_getmessage_def|
        Return  "r1"
      ]

3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570
; On entry:
; [ DEFAULT_TEXT
;   R0 = Message to use if failed to get message from message file
;   R1 = Message tag
;   R2 = Destination buffer
;   R3 = Size of buffer
; |
;   R0 = Message tag
;   R1 = Destination buffer
;   R2 = Size of buffer
; ]
;
; Return:
;   R0 = Message
;
|_kernel_getmessage2|
        FunctionEntry "r0-r7"
        BL      open_messagefile
        MOV     r0, r1
      [ :DEF:DEFAULT_TEXT
        LDR     r1, [sp, #4]
      |
        MOV     r3, r2
        LDR     r2, [sp, #4]
        LDR     r1, [sp]
      ]
        MOV     r4, #0
        MOV     r5, #0
        MOV     r6, #0
        MOV     r7, #0
        SWI     XMessageTrans_Lookup
        STRVC   r2, [sp]
        Return  "r0-r7"


Neil Turton's avatar
Neil Turton committed
3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581
message_filename
        DCB     "SharedCLibrary:Messages", 0
        ALIGN

module_name
        DCB     "SharedCLibrary", 0
        ALIGN

; Try to open the message file.
;
open_messagefile
3582
        FunctionEntry "r0,r2-r5"
3583 3584 3585 3586 3587 3588 3589 3590
        MOV     r0, #6
        MOV     r1, #0
        MOV     r2, #OSRSI6_CLibWord
        SWI     XOS_ReadSysInfo
        MOVVS   r2, #0
        MOVS    r5, r2
        LDREQ   r5, =Legacy_CLibWord
        LDR     r1, [r5]
Neil Turton's avatar
Neil Turton committed
3591
        CMP     r1, #0
3592
        Return  "r0,r2-r5",,NE
Neil Turton's avatar
Neil Turton committed
3593 3594
        MOV     r0, #Module_Claim
        MOV     r3, #Module_WorkSpace
3595 3596
        SWI     XOS_Module
        Return  "r0,r2-r5",,VS                  ; NB R1 = 0
3597 3598
        SavePSR r1
        SWI     XOS_EnterOS
3599
        STR     r2, [r5]
3600
        RestPSR r1
Neil Turton's avatar
Neil Turton committed
3601 3602 3603 3604 3605
        MOV     r0, r2
        ADR     r1, message_filename
        MOV     r2, #0
        SWI     XMessageTrans_OpenFile
        MOVVC   r1, r0
3606
        Return  "r0,r2-r5",,VC
Neil Turton's avatar
Neil Turton committed
3607
        MOV     r0, #Module_Free
3608
        LDR     r2, [r5]
3609
        SWI     XOS_Module
Neil Turton's avatar
Neil Turton committed
3610
        MOV     r1, #0
3611
        Return  "r0,r2-r5"
Neil Turton's avatar
Neil Turton committed
3612 3613 3614 3615

        |

|_kernel_copyerror|
3616
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
3617 3618

|_kernel_getmessage|
3619
|_kernel_getmessage_def|
3620
|_kernel_getmessage2|
3621
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
3622 3623 3624 3625

        ]

|__counter|
3626
        MOV     ip, lr
3627
 [ {CONFIG}=26
3628
        MOV     a4, pc
3629
 |
3630
        MRS     a4, CPSR
3631
 ]
3632 3633 3634 3635 3636 3637 3638
        MOV     a1, #6
        MOV     a2, #0
        MOV     a3, #OSRSI6_CLibCounter
        SWI     XOS_ReadSysInfo
        MOVVS   a3, #0
        CMP     a3, #0
        LDREQ   a3, =Legacy_CLibCounter
3639
        SWI     EnterSVC
3640
        MOV     a2, ip
Neil Turton's avatar
Neil Turton committed
3641
        BL      |_kernel_irqs_off|      ; Disable IRQs round update.
3642
        LDRB    a1, [a3]
3643
        ADD     ip, a1, #1
3644
        STRB    ip, [a3]
3645
 [ {CONFIG}=26
3646
        TEQP    pc, a4                  ; Restore mode and IRQs
3647
 |
3648
        MSR     CPSR_c, a4              ; Restore mode and IRQs
3649
 ]
3650
        Return  ,LinkNotStacked,,a2
Neil Turton's avatar
Neil Turton committed
3651 3652 3653


        END