k_body 112 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
Ben Avison's avatar
Ben Avison committed
26
        GET     Hdr:OSMisc
Neil Turton's avatar
Neil Turton committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

        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|
51
        EXPORT  |_kernel_peek_last_oserror|
Neil Turton's avatar
Neil Turton committed
52 53 54 55 56 57 58
        EXPORT  |_kernel_system|
        EXPORT  |_kernel_getenv|
        EXPORT  |_kernel_setenv|

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

        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|
 ]
84
        EXPORT  |_kernel_irqs_disabled|
Neil Turton's avatar
Neil Turton committed
85 86 87 88 89 90 91 92 93 94
        EXPORT  |_kernel_processor_mode|
        EXPORT  |_kernel_RMAalloc|
        EXPORT  |_kernel_RMAfree|
        EXPORT  |_kernel_RMAextend|

        EXPORT  |_kernel_fpavailable|

        EXPORT  |_kernel_call_client|
        EXPORT  |_kernel_raise_error|

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

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

Neil Turton's avatar
Neil Turton committed
105
        EXPORT  |__counter|
Ben Avison's avatar
Ben Avison committed
106
        EXPORT  |AcquireMutex|
Neil Turton's avatar
Neil Turton committed
107 108 109 110

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

Neil Turton's avatar
Neil Turton committed
112
PSRIBit         *       &08000000
113
PSRFBit         *       &04000000
114 115
PSRMode         *       &00000003
PSRUSRMode      *       &00000000
Neil Turton's avatar
Neil Turton committed
116
PSRSVCMode      *       &00000003
117 118 119
PSRPrivileged   *       &00000003

PSR32IBit       *       &00000080
120
PSR32FBit       *       &00000040
121 122 123 124 125
PSR32Mode       *       &0000001F
PSR32USRMode    *       &00000010
PSR32SVCMode    *       &00000013
PSR32UNDMode    *       &0000001B
PSR32Privileged *       &0000000F
Neil Turton's avatar
Neil Turton committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162


; 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


163
        GET     Hdr:Wimp
Neil Turton's avatar
Neil Turton committed
164
 [ DDE
165
        GET     Hdr:DDEUtils
Neil Turton's avatar
Neil Turton committed
166
 ]
167 168
        GET     Hdr:Machine.<Machine>

Neil Turton's avatar
Neil Turton committed
169 170 171 172

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


|_kernel_call_client|
180
 [ :LNOT:(SharedLibrary :LAND: {CONFIG}=26)
Neil Turton's avatar
Neil Turton committed
181 182
        MOV     pc, a4
   |
183 184 185
  ; 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
186 187
        MOV     lr, pc
        MOV     pc, a4
188
        Return
Neil Turton's avatar
Neil Turton committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
 ]


 [ 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
205
        LDR     pc, [sp], #4
206
 ]
Neil Turton's avatar
Neil Turton committed
207 208

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

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

|_kernel_RMAextend|
230
        FunctionEntry
Neil Turton's avatar
Neil Turton committed
231 232
        CMP     a1, #0
        MOVEQ   a1, a2
233
        BEQ     |_kernel_RMAalloc_from_extend|
Neil Turton's avatar
Neil Turton committed
234
        CMP     a2, #0
235
        BEQ     |_kernel_RMAfree_from_extend|
Neil Turton's avatar
Neil Turton committed
236 237 238 239 240 241 242 243
        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
244
        Return
Neil Turton's avatar
Neil Turton committed
245 246

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

  |

|_kernel_RMAalloc|
|_kernel_RMAextend|
|_kernel_RMAfree|
        MOV     a1, #0
261
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
262 263 264

 ]

265 266
; Don't corrupt a1-a4 in these two routines, please.
; __counter relies on it, for one.
Neil Turton's avatar
Neil Turton committed
267
|_kernel_irqs_on|
268 269 270 271 272 273 274 275
 [ {CONFIG}=26
        BICS    pc, lr, #PSRIBit        ; 32-bit OK - in {CONFIG}=26
 |
        MRS     ip, CPSR
        BIC     ip, ip, #PSR32IBit
        MSR     CPSR_c, ip
        Return  ,LinkNotStacked
 ]
Neil Turton's avatar
Neil Turton committed
276 277

|_kernel_irqs_off|
278 279 280 281 282 283 284 285
      [ {CONFIG}=26
        ORRS    pc, lr, #PSRIBit
      |
        MRS     ip, CPSR
        ORR     ip, ip, #PSR32IBit
        MSR     CPSR_c, ip
        Return  ,LinkNotStacked
      ]
Neil Turton's avatar
Neil Turton committed
286 287

|_kernel_processor_mode|
288 289 290
      [ {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
291
                                ; the same.
292 293 294 295 296
      |
        MRS     a1, CPSR
        AND     a1, a1, #PSR32Mode
        MOV     pc, lr
      ]
Neil Turton's avatar
Neil Turton committed
297 298 299

|_kernel_client_is_module|
        LoadStaticBase a1, ip
300
      [ {CONFIG}=26
301
        TST     r14, #PSRPrivileged
302 303 304 305
      |
        MRS     ip, CPSR
        TST     ip, #PSR32Privileged
      ]
Neil Turton's avatar
Neil Turton committed
306 307
        MOVNE   a1, #0
        LDREQ   a1, [a1, #O_moduleDataWord]
308
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380

 [ 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
381
        WritePSRc 0, r5                  ; back to user mode
Neil Turton's avatar
Neil Turton committed
382
 [ DDE
383 384
        NOP
        SWI     XDDEUtils_GetCLSize
Neil Turton's avatar
Neil Turton committed
385 386 387 388 389 390 391 392 393 394 395 396
        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
397
        SWI     XDDEUtils_GetCl
Neil Turton's avatar
Neil Turton committed
398 399 400
        MOV     r6, r1
04
 |
401
        NOP
Neil Turton's avatar
Neil Turton committed
402 403 404 405 406 407 408 409 410 411 412 413 414
 ]
        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]
415
      [ {CONFIG}<>26
Ben Avison's avatar
Ben Avison committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
        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]
431 432 433 434 435
      |
        BL      CheckIfSwpAvailable
      ]
        MOV     r0, #1
        STR     r0, [v6, #O_extendChunkNotInUse]
Neil Turton's avatar
Neil Turton committed
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
        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]

465 466 467 468 469 470 471 472 473 474
        ; 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
475 476 477 478 479 480 481 482 483 484 485 486 487
        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
488 489 490 491 492 493
 [ 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
494 495 496 497
        MOV     r0, #0
        BL      InstallHandlers

        MOV     r0, #0
498
        SWI     XWimp_ReadSysInfo
Neil Turton's avatar
Neil Turton committed
499 500 501 502 503
        MOVVS   r0, #0                  ; error - presumably Wimp not present
        CMP     r0, #0
        MOVNE   r0, #1
        STRB    r0, [v6, #O_underDesktop]

504
        LDREQ   r1, [v6, #O_heapLimit]
Neil Turton's avatar
Neil Turton committed
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
        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

540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
 [ {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
575 576
;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
577
CopyHandler
578
        LDMIA   r5!, {r6, r7}                   ; first 2 instructions
Neil Turton's avatar
Neil Turton committed
579
        STMIA   r4!, {r6, r7}
580 581 582 583 584 585 586 587
        LDR     r6, =&E51FF004                  ; LDR PC,<nextword>
        STR     r6, [r4], #4
        STR     r5, [r4]                        ; address of main handler
        MOV     pc, r14

        LTORG

RSI6_List
588
        DCD     OSRSI6_UNDSTK, OSRSI6_SVCSTK, -1
Neil Turton's avatar
Neil Turton committed
589 590

|Sys$RCLimit|
Jeffrey Lee's avatar
Jeffrey Lee committed
591
        DCB     "Sys$$RCLimit", 0
Neil Turton's avatar
Neil Turton committed
592 593 594 595
        ALIGN

|_kernel_exit|
 [ ModeMayBeNonUser
596
        [ {CONFIG} = 26
Neil Turton's avatar
Neil Turton committed
597
        TST     r14, #3
598 599 600 601
        |
        MRS     ip, CPSR
        TST     ip, #PSR32Privileged
        ]
Neil Turton's avatar
Neil Turton committed
602 603 604
        BEQ     |_kernel_user_exit|
        MOV     ip, sp
        SUB     sp, sp, #4*12              ; set up an unwind block
Ben Avison's avatar
Ben Avison committed
605
        STR     sl, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
606 607 608 609 610 611 612 613 614 615 616
        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
617
        LDR     a1, [sp], #4
Neil Turton's avatar
Neil Turton committed
618
        CMP     a1, r14
Ben Avison's avatar
Ben Avison committed
619 620
        ADRCC   a1, E_Exit
        BLCC    |_kernel_copyerror|     ; BL<cond> 32-bit OK
621
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
622
        LDMIB   sp, {r4-r9, fp, sp, pc}^
623
        |
Ben Avison's avatar
Ben Avison committed
624
      [ {FALSE} ; this instruction is now deprecated
625
        LDMIB   sp, {r4-r9, fp, sp, pc}
Ben Avison's avatar
Ben Avison committed
626 627 628 629 630
      |
        LDMIB   sp, {r4-r9, fp, ip, lr}
        MOV     sp, ip
        MOV     pc, lr
      ]
631
        ]
Neil Turton's avatar
Neil Turton committed
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 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

        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
674
        STR     r0, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
675
        BL      Finalise
Ben Avison's avatar
Ben Avison committed
676
        LDR     r0, [sp],  #4
Neil Turton's avatar
Neil Turton committed
677 678 679 680 681 682 683 684 685
        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
686
        Return  ,LinkNotStacked, EQ
Neil Turton's avatar
Neil Turton committed
687
 [ ModeMayBeNonUser
688
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
689
        TST     r14, #3
690 691 692 693
        |
        MRS     ip, CPSR
        TST     ip, #PSR32Privileged
        ]
Neil Turton's avatar
Neil Turton committed
694 695 696 697 698 699 700 701
        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
702
        STR     a1, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
703
        BL      Finalise
Ben Avison's avatar
Ben Avison committed
704
        LDR     a1, [sp], #4
Neil Turton's avatar
Neil Turton committed
705 706 707
        SWI     GenerateError

Finalise
Ben Avison's avatar
Ben Avison committed
708
        STR     lr, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 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
        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
767
        LDR     lr, [sp], #4
Neil Turton's avatar
Neil Turton committed
768 769 770 771 772 773
        B       RestoreOSHandlers


|_kernel_setreturncode|
        LoadStaticBase ip, a2
        STR     a1, [ip, #O_returnCode]
774
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
775 776 777 778

|_kernel_fpavailable|
        LoadStaticBase ip, a1
        LDRB    a1, [ip, #O_fpPresent]
779
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
780 781 782 783 784 785 786

ABEXString
        =       "ABEX"

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

787 788
        LTORG

Neil Turton's avatar
Neil Turton committed
789 790 791 792 793 794 795 796 797 798 799 800
 ;*-------------------------------------------------------------------*
 ;* 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
801
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
802 803 804 805 806 807 808 809
        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
810 811 812 813
        STR     r14, [r12, #O_registerDump + 15 * 4]

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

816

Neil Turton's avatar
Neil Turton committed
817
PAHandlerInDataInitValue
818
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
819 820 821
        SUB     r12, pc, #O_PAHandlerInData+12
PAHandler Keep
        SUB     r14, r14, #4
822 823 824 825
        STR     r14, [r12, #O_registerDump + 15 * 4]

        LDR     r14, [r12, #O_oldAbortHandlers + 4]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
826 827 828
        B       Aborted

DAHandlerInDataInitValue
829
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
830 831 832
        SUB     r12, pc, #O_DAHandlerInData+12
DAHandler Keep
        SUB     r14, r14, #8
833 834 835 836
        STR     r14, [r12, #O_registerDump + 15 * 4]

        LDR     r14, [r12, #O_oldAbortHandlers + 8]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
837 838 839
        B       Aborted2

AEHandlerInDataInitValue
840
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
841 842 843
        SUB     r12, pc, #O_AEHandlerInData+12
AEHandler Keep
        SUB     r14, r14, #8
844 845 846 847
        STR     r14, [r12, #O_registerDump + 15 * 4]

        LDR     r14, [r12, #O_oldAbortHandlers + 12]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
848 849 850 851 852
;       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.
853
; Try the FPEmulator_Abort SWI
854 855

        LDR     r2, [sp, #24]
856 857
        ADD     r2, r2, #8              ; original r14
        LDR     r1, [sp, #20]           ; original r12
858
      [ {CONFIG}=26
859
        BIC     r2, r2, #PSRBits
860
      |
861 862
        TEQ     pc, pc
        BICNE   r2, r2, #PSRBits
863 864 865 866 867
        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
868 869
      ]
        MOV     r0, #-2                 ; current context
870 871 872 873 874 875 876
        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
877
       [ StrongARM_MSR_bug
878
        NOP                             ; avoid StrongARM bug
879
       ]
880 881 882
      ]
        BVS     NoFPEAbortSWI           ; in case someone really does error
        TEQ     r0, #0                  ; check for real "not FP abort" return
883
        LDMEQFD sp, {r0-r2}
884
        BEQ     Aborted                 ; not in FPEmulator
885 886
        CMP     r0, #&01000000          ; check for a bogus result
        BLO     NoFPEAbortSWI
887 888 889
        B       FPEFault

NoFPEAbortSWI
Neil Turton's avatar
Neil Turton committed
890
; If in user mode, can't be in FPE
891
      [ {CONFIG}=26
892
        LDR     r1, [sp, #24]
893 894
        TST     r1, #PSRPrivileged
      |
895 896 897 898
        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
899 900
        TST     r1, #PSR32Privileged
      ]
901
        LDMEQFD sp, {r0-r4}
Neil Turton's avatar
Neil Turton committed
902
        BEQ     Aborted
903

Neil Turton's avatar
Neil Turton committed
904
; Otherwise, find out where the FPE module is
905 906 907
      [ {CONFIG} <> 26
        TST     r2, #2_11100
      ]
908
        STMFD   sp!, {r0 - r6}
909
      [ {CONFIG} = 26
Neil Turton's avatar
Neil Turton committed
910
        BIC     r6, r14, #PSRBits
911 912 913 914
      |
        BICEQ   r6, r14, #PSRBits       ; 32-bit OK (26-bit cond)
        MOVNE   r6, r14
      ]
Neil Turton's avatar
Neil Turton committed
915 916 917
        MOV     r0, #18
        ADR     r1, FPEName
        SWI     Module
918
        LDMVSFD sp!, {r0 - r6}
Neil Turton's avatar
Neil Turton committed
919 920 921 922 923 924
        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
925
        LDMFD   sp!, {r0 - r6}
Neil Turton's avatar
Neil Turton committed
926 927 928
        BLT     Aborted

; It was a storage fault in the FP emulator.
929
; We assume FPEmulator 4.00 or later - r0
930 931 932 933 934
; 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
935
        ADD     r14, r12, #O_registerDump
936 937 938 939 940 941 942 943 944
        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}
945
      [ {CONFIG}<>26
946 947
        TEQ     pc, pc
        BEQ     FPEFault_32on32
948 949 950 951 952 953
      ]
        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
954
        B       FPEFault_Continue
955 956

FPEFault_32on26
957
        LDR     r2, [r0, #-72]          ; get the SPSR
958
        AND     r2, r2, #PSRBits
959 960 961 962 963
        BIC     r4, r4, #PSRBits
        ORR     r4, r4, r2
        STR     r4, [r14, #-4]          ; merge it with pc in register dump
      [ {CONFIG}<>26
        B       FPEFault_Continue
964 965

FPEFault_32on32
966
        LDR     r2, [r0, #-72]          ; get the SPSR
967
        STR     r2, [r14]               ; store it in the register dump
968
      ]
969

970 971
FPEFault_Continue
        LDMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
972 973 974 975 976 977 978 979 980 981

        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
982
  [ SASTMhatbroken
983 984 985 986
        STMIA   r14!, {r0-r12}
        STMIA   r14, {r13,r14}^
        NOP
        SUB     r14, r14, #13*4
Kevin Bracey's avatar
Kevin Bracey committed
987
  |
988 989
        STMIA   r14, {r0-r14}^
        NOP
Neil Turton's avatar
Neil Turton committed
990
  ]
Kevin Bracey's avatar
Kevin Bracey committed
991

992 993 994
        LDR     r0, [r13, #20]
        STR     r0, [r14, #r12*4]

995 996 997 998 999 1000 1001 1002
        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
1003 1004 1005 1006 1007
        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
1008
        ADD     r4, r14, #10 * 4        ; reg ptr into unbanked register
1009
        TEQ     pc, pc
1010 1011 1012 1013 1014 1015 1016 1017 1018
        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
1019 1020 1021 1022 1023 1024
        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
1025

Neil Turton's avatar
Neil Turton committed
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
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]

1049
        ADD     r11, v6, #O_registerDump+17*4
Neil Turton's avatar
Neil Turton committed
1050 1051 1052 1053 1054 1055
        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
1056 1057 1058 1059
        CMPHI   r2, r12
        ADDHI   r1, r12, #256
        CMPHI   r1, r10
        BLS     Trap_NoStackForHandler
Neil Turton's avatar
Neil Turton committed
1060 1061 1062 1063 1064 1065 1066
        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]

1067 1068 1069 1070
        ; 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
1071 1072 1073 1074 1075 1076
        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
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
        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
1089 1090 1091 1092
        TST     a1, #PSRIBit
        ORREQ   a1, a1, #PSRVBit
        BICNE   a1, a1, #PSRVBit
        TEQP    a1, #0
1093
02
Neil Turton's avatar
Neil Turton committed
1094
   |
1095
     [ No32bitCode
Neil Turton's avatar
Neil Turton committed
1096
        TEQP    pc, #PSRIBit:OR:PSRVBit                 ; user mode
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
     |
        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
1108 1109
 ]

1110
        NOP
Neil Turton's avatar
Neil Turton committed
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
        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]
1145 1146
        WritePSRc 0, lr
        NOP
Neil Turton's avatar
Neil Turton committed
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
        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
  ]
1166
        SavePSR v4
Neil Turton's avatar
Neil Turton committed
1167
        SWI     EnterSVC
1168 1169
        BLVC    open_messagefile        ; BL<cond> 32-bit OK
        RestPSR v4
Neil Turton's avatar
Neil Turton committed
1170
        MOV     r0, r0
1171 1172 1173
        ; 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
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
        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
1184
        ADD     a2, v6, #O_FatalErrorBuffer
Neil Turton's avatar
Neil Turton committed
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
        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]
1214
        ADD     r0, v6, #O_FatalErrorBuffer
Neil Turton's avatar
Neil Turton committed
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
 ]
        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]
 ]
1240
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1241 1242 1243 1244 1245 1246 1247 1248


|_kernel_exittraphandler|
        LoadStaticBase ip, a1
        MOV     a1, #0
        STRB    a1, [ip, #O_inTrapHandler]
        MOV     a1, #1
        STRB    a1, [ip, #O_callbackInactive]
1249
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260

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

1261
        ; set up an initial unwind block.  For our purposes, we don't care
Neil Turton's avatar
Neil Turton committed
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
        ; 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
1273
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
1274
        BIC     r1, r1, #PSRBits
Dan Ellis's avatar
Dan Ellis committed
1275 1276 1277 1278
        |
        MRS     v4, CPSR
        TST     v4, #2_11100
        BICEQ   r1, r1, #PSRBits
1279
        ]
Neil Turton's avatar
Neil Turton committed
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
        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]
1310 1311 1312 1313 1314
        BNE     FCH_CallClient
        MOV     lr, pc
        MOV     pc, r2
        B       FCH_ClientCalled
FCH_CallClient
Neil Turton's avatar
Neil Turton committed
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334