k_body 117 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
 [ StrongARM   ;CopyHandler does some dynamic code
505 506 507 508 509 510 511
        MOV     r0, #1
        ASSERT  O_IIHandlerInData < O_PAHandlerInData
        ASSERT  O_PAHandlerInData < O_DAHandlerInData
        ASSERT  O_DAHandlerInData < O_AEHandlerInData
        ADD     r1, v6, #O_IIHandlerInData
        ADD     r2, v6, #O_AEHandlerInData + 16
        SWI     XOS_SynchroniseCodeAreas
Neil Turton's avatar
Neil Turton committed
512 513
 ]

Neil Turton's avatar
Neil Turton committed
514 515 516 517
        MOV     r0, #0
        BL      InstallHandlers

        MOV     r0, #0
518
        SWI     XWimp_ReadSysInfo
Neil Turton's avatar
Neil Turton committed
519 520 521 522 523
        MOVVS   r0, #0                  ; error - presumably Wimp not present
        CMP     r0, #0
        MOVNE   r0, #1
        STRB    r0, [v6, #O_underDesktop]

524
        LDREQ   r1, [v6, #O_heapLimit]
Neil Turton's avatar
Neil Turton committed
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 556 557 558 559
        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

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 591 592 593 594
 [ {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
595 596
;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
597
CopyHandler
598
        LDMIA   r5!, {r6, r7}                   ; first 2 instructions
Neil Turton's avatar
Neil Turton committed
599
        STMIA   r4!, {r6, r7}
600 601 602 603 604 605 606 607
        LDR     r6, =&E51FF004                  ; LDR PC,<nextword>
        STR     r6, [r4], #4
        STR     r5, [r4]                        ; address of main handler
        MOV     pc, r14

        LTORG

RSI6_List
608
        DCD     OSRSI6_UNDSTK, OSRSI6_SVCSTK, -1
Neil Turton's avatar
Neil Turton committed
609 610

|Sys$RCLimit|
Jeffrey Lee's avatar
Jeffrey Lee committed
611
        DCB     "Sys$$RCLimit", 0
Neil Turton's avatar
Neil Turton committed
612 613 614 615
        ALIGN

|_kernel_exit|
 [ ModeMayBeNonUser
616
        [ {CONFIG} = 26
Neil Turton's avatar
Neil Turton committed
617
        TST     r14, #3
618 619 620 621
        |
        MRS     ip, CPSR
        TST     ip, #PSR32Privileged
        ]
Neil Turton's avatar
Neil Turton committed
622 623 624
        BEQ     |_kernel_user_exit|
        MOV     ip, sp
        SUB     sp, sp, #4*12              ; set up an unwind block
Ben Avison's avatar
Ben Avison committed
625
        STR     sl, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
626 627 628 629 630 631 632 633 634 635 636
        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
637
        LDR     a1, [sp], #4
Neil Turton's avatar
Neil Turton committed
638
        CMP     a1, r14
Ben Avison's avatar
Ben Avison committed
639 640
        ADRCC   a1, E_Exit
        BLCC    |_kernel_copyerror|     ; BL<cond> 32-bit OK
641
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
642
        LDMIB   sp, {r4-r9, fp, sp, pc}^
643
        |
Ben Avison's avatar
Ben Avison committed
644
      [ {FALSE} ; this instruction is now deprecated
645
        LDMIB   sp, {r4-r9, fp, sp, pc}
Ben Avison's avatar
Ben Avison committed
646 647 648 649 650
      |
        LDMIB   sp, {r4-r9, fp, ip, lr}
        MOV     sp, ip
        MOV     pc, lr
      ]
651
        ]
Neil Turton's avatar
Neil Turton committed
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 690 691 692 693

        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
694
        STR     r0, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
695
        BL      Finalise
Ben Avison's avatar
Ben Avison committed
696
        LDR     r0, [sp],  #4
Neil Turton's avatar
Neil Turton committed
697 698 699 700 701 702 703 704 705
        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
706
        Return  ,LinkNotStacked, EQ
Neil Turton's avatar
Neil Turton committed
707
 [ ModeMayBeNonUser
708
        [ {CONFIG}=26
Neil Turton's avatar
Neil Turton committed
709
        TST     r14, #3
710 711 712 713
        |
        MRS     ip, CPSR
        TST     ip, #PSR32Privileged
        ]
Neil Turton's avatar
Neil Turton committed
714 715 716 717 718 719 720 721
        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
722
        STR     a1, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
723
        BL      Finalise
Ben Avison's avatar
Ben Avison committed
724
        LDR     a1, [sp], #4
Neil Turton's avatar
Neil Turton committed
725 726 727
        SWI     GenerateError

Finalise
Ben Avison's avatar
Ben Avison committed
728
        STR     lr, [sp, #-4]!
Neil Turton's avatar
Neil Turton committed
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 783 784 785 786
        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
787
        LDR     lr, [sp], #4
Neil Turton's avatar
Neil Turton committed
788 789 790 791 792 793
        B       RestoreOSHandlers


|_kernel_setreturncode|
        LoadStaticBase ip, a2
        STR     a1, [ip, #O_returnCode]
794
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
795 796 797 798

|_kernel_fpavailable|
        LoadStaticBase ip, a1
        LDRB    a1, [ip, #O_fpPresent]
799
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
800 801 802 803 804 805 806

ABEXString
        =       "ABEX"

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

807 808
        LTORG

Neil Turton's avatar
Neil Turton committed
809 810 811 812 813 814 815 816 817 818 819 820
 ;*-------------------------------------------------------------------*
 ;* 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
821
        STMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
822 823 824 825 826 827 828 829
        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
830 831 832 833
        STR     r14, [r12, #O_registerDump + 15 * 4]

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

836

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

        LDR     r14, [r12, #O_oldAbortHandlers + 4]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
846 847 848
        B       Aborted

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

        LDR     r14, [r12, #O_oldAbortHandlers + 8]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
857 858 859
        B       Aborted2

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

        LDR     r14, [r12, #O_oldAbortHandlers + 12]
        STR     r14, [r13, #28]
Neil Turton's avatar
Neil Turton committed
868 869 870 871 872
;       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.
873
; Try the FPEmulator_Abort SWI
874 875

        LDR     r2, [sp, #24]
876 877
        ADD     r2, r2, #8              ; original r14
        LDR     r1, [sp, #20]           ; original r12
878
      [ {CONFIG}=26
879
        BIC     r2, r2, #PSRBits
880
      |
881 882
        TEQ     pc, pc
        BICNE   r2, r2, #PSRBits
883 884 885 886 887
        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
888 889
      ]
        MOV     r0, #-2                 ; current context
890 891 892 893 894 895 896
        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
897
       [ StrongARM_MSR_bug
898
        NOP                             ; avoid StrongARM bug
899
       ]
900 901 902
      ]
        BVS     NoFPEAbortSWI           ; in case someone really does error
        TEQ     r0, #0                  ; check for real "not FP abort" return
903
        LDMEQFD sp, {r0-r2}
904
        BEQ     Aborted                 ; not in FPEmulator
905 906
        CMP     r0, #&01000000          ; check for a bogus result
        BLO     NoFPEAbortSWI
907 908 909
        B       FPEFault

NoFPEAbortSWI
Neil Turton's avatar
Neil Turton committed
910
; If in user mode, can't be in FPE
911
      [ {CONFIG}=26
912
        LDR     r1, [sp, #24]
913 914
        TST     r1, #PSRPrivileged
      |
915 916 917 918
        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
919 920
        TST     r1, #PSR32Privileged
      ]
921
        LDMEQFD sp, {r0-r4}
Neil Turton's avatar
Neil Turton committed
922
        BEQ     Aborted
923

Neil Turton's avatar
Neil Turton committed
924
; Otherwise, find out where the FPE module is
925 926 927
      [ {CONFIG} <> 26
        TST     r2, #2_11100
      ]
928
        STMFD   sp!, {r0 - r6}
929
      [ {CONFIG} = 26
Neil Turton's avatar
Neil Turton committed
930
        BIC     r6, r14, #PSRBits
931 932 933 934
      |
        BICEQ   r6, r14, #PSRBits       ; 32-bit OK (26-bit cond)
        MOVNE   r6, r14
      ]
Neil Turton's avatar
Neil Turton committed
935 936 937
        MOV     r0, #18
        ADR     r1, FPEName
        SWI     Module
938
        LDMVSFD sp!, {r0 - r6}
Neil Turton's avatar
Neil Turton committed
939 940 941 942 943 944
        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
945
        LDMFD   sp!, {r0 - r6}
Neil Turton's avatar
Neil Turton committed
946 947 948
        BLT     Aborted

; It was a storage fault in the FP emulator.
949
; We assume FPEmulator 4.00 or later - r0
950 951 952 953 954
; 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
955
        ADD     r14, r12, #O_registerDump
956 957 958 959 960 961 962 963 964
        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}
965
      [ {CONFIG}<>26
966 967
        TEQ     pc, pc
        BEQ     FPEFault_32on32
968 969 970 971 972 973
      ]
        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
974
        B       FPEFault_Continue
975 976

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

FPEFault_32on32
986
        LDR     r2, [r0, #-72]          ; get the SPSR
987
        STR     r2, [r14]               ; store it in the register dump
988
      ]
989

990 991
FPEFault_Continue
        LDMFD   r13!, {r0-r4, r12, r14, pc}
Neil Turton's avatar
Neil Turton committed
992 993 994 995 996 997 998 999 1000 1001

        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
1002
  [ SASTMhatbroken
1003 1004 1005 1006
        STMIA   r14!, {r0-r12}
        STMIA   r14, {r13,r14}^
        NOP
        SUB     r14, r14, #13*4
Kevin Bracey's avatar
Kevin Bracey committed
1007
  |
1008 1009
        STMIA   r14, {r0-r14}^
        NOP
Neil Turton's avatar
Neil Turton committed
1010
  ]
Kevin Bracey's avatar
Kevin Bracey committed
1011

1012 1013 1014
        LDR     r0, [r13, #20]
        STR     r0, [r14, #r12*4]

1015 1016 1017 1018 1019 1020 1021 1022
        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
1023 1024 1025 1026 1027
        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
1028
        ADD     r4, r14, #10 * 4        ; reg ptr into unbanked register
1029
        TEQ     pc, pc
1030 1031 1032 1033 1034 1035 1036 1037 1038
        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
1039 1040 1041 1042 1043 1044
        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
1045

Neil Turton's avatar
Neil Turton committed
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
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]

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

        LDR     r12, [v6, #O_registerDump+sp*4]
Jeffrey Lee's avatar
Jeffrey Lee committed
1075 1076 1077 1078 1079
        ; Stack pointer and stack limit must both be word aligned
        ; Frame pointer might not be (bottom bit used as flag), so don't check for that (_kernel_unwind will check it before using it anyway)
        TST     r10, #3
        TSTEQ   r12, #3
        BNE     Trap_NoStackForHandler
Neil Turton's avatar
Neil Turton committed
1080
        CMP     r12, r1
1081 1082 1083 1084
        CMPHI   r2, r12
        ADDHI   r1, r12, #256
        CMPHI   r1, r10
        BLS     Trap_NoStackForHandler
Neil Turton's avatar
Neil Turton committed
1085 1086 1087 1088 1089 1090 1091
        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]

1092 1093 1094 1095
        ; 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
1096 1097 1098 1099 1100 1101
        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
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
        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
1114 1115 1116 1117
        TST     a1, #PSRIBit
        ORREQ   a1, a1, #PSRVBit
        BICNE   a1, a1, #PSRVBit
        TEQP    a1, #0
1118
02
Neil Turton's avatar
Neil Turton committed
1119
   |
1120
     [ No32bitCode
Neil Turton's avatar
Neil Turton committed
1121
        TEQP    pc, #PSRIBit:OR:PSRVBit                 ; user mode
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
     |
        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
1133 1134
 ]

1135
        NOP
Neil Turton's avatar
Neil Turton committed
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 1161 1162 1163 1164 1165 1166 1167 1168 1169
        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]
1170
        WritePSRc 0, lr
Neil Turton's avatar
Neil Turton committed
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
        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
  ]
1190
        SavePSR v4
Neil Turton's avatar
Neil Turton committed
1191
        SWI     EnterSVC
1192 1193
        BLVC    open_messagefile        ; BL<cond> 32-bit OK
        RestPSR v4
Neil Turton's avatar
Neil Turton committed
1194
        MOV     r0, r0
1195 1196 1197
        ; 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
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
        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
1208
        ADD     a2, v6, #O_FatalErrorBuffer
Neil Turton's avatar
Neil Turton committed
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
        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]
1238
        ADD     r0, v6, #O_FatalErrorBuffer
Neil Turton's avatar
Neil Turton committed
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263
 ]
        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]
 ]
1264
        Return  ,LinkNotStacked
Neil Turton's avatar
Neil Turton committed
1265 1266 1267 1268 1269 1270 1271