⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 armtrap.s

📁 WinCE5.0部分核心源码
💻 S
📖 第 1 页 / 共 5 页
字号:
        subeq   lr, lr, #4                      ;   accordingly
        str     lr, [sp, #-4]                   ; update lr on stack
 ELSE
        sub     lr, lr, #4                      ; (lr) = address of undefined instruction
        stmdb   sp, {r0-r3, lr}
 ENDIF
        PROLOG_END
  IF {FALSE}
        ldr     r0, =LED_ALPHA
10      ldr     r1, =0x0DEF
        str     r1, [r0]
        mov     r1, #SPIN_DELAY
15      subs    r1, r1, #1
        bgt     %B15
        str     lr, [r0]
        mov     r1, #SPIN_DELAY
17      subs    r1, r1, #1
        bgt     %B17
  ENDIF

        mov     r1, #ID_UNDEF_INSTR
        b       CommonHandler
        ENTRY_END UndefException

        LEAF_ENTRY SWIHandler
  IF {FALSE}
        ldr     r0, =LED_ALPHA
10      ldr     r1, =0x99999999
        str     r1, [r0]
        mov     r1, #SPIN_DELAY
15      subs    r1, r1, #1
        bgt     %B15
        str     lr, [r0]
        mov     r1, #SPIN_DELAY
17      subs    r1, r1, #1
        bgt     %B17
        b       %B10
  ENDIF
        movs    pc, lr
        ENTRY_END SWIHandler



;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
        NESTED_ENTRY FIQHandler
        sub     lr, lr, #4                      ; fix return address
        stmfd   sp!, {r0-r3, r12, lr}
        PROLOG_END

        CALL    OEMInterruptHandlerFIQ

        ldmfd   sp!, {r0-r3, r12, pc}^          ; restore regs & return for NOP
        ENTRY_END FIQHandler


        LTORG

;-------------------------------------------------------------------------------
;++
; The following code is never executed. Its purpose is to support unwinding
; through the calls to API dispatch and return routines.
;--
;-------------------------------------------------------------------------------

; field description for OBJCALLSTRUCT/SVRRTNSTRUCT
apiMethod      equ   0                    ; API method
objcallstr     equ   apiMethod            ; argument to ObjectCall
apiPrevSP      equ   (apiMethod + 4)      ; previous SP if stack changed
svrrtnstr      equ   apiPrevSP            ; argument to ServerCallReturn
apiMode        equ   (apiMethod + 8)      ; which mode we call from
apiExtra       equ   (apiMethod + 12)     ; extra info 
apiRa          equ   (apiMethod + 16)     ; return address
size_api_args  equ   (apiMethod + 20)     ; length of stack frame

        NESTED_ENTRY    PrefetchAbortEH
        stmfd   sp!, {r0-r3}
        sub     sp, sp, #8
        PROLOG_END

        ALTERNATE_ENTRY PrefetchAbort

        sub     lr, lr, #0xF0000004
        cmp     lr, #0x00010400
        bhs     ProcessPrefAbort
        mrs     r12, spsr
        and     r12, r12, #0x0ff
        orr     r12, r12, lr, LSL #8            ; (r12) = old mode + 24 lower bits of LR. 
        msr     cpsr_c, #SYSTEM_MODE            ; switch to System Mode

; Find the address of the API function to dispatch to by:
;  ObjectCall(OBJCALLSTRUCT*)
;
;       (r0-r3) = function parameters or return values
;       (r12) = abort address - 0xF0000000 (bits 31-8) (encodes API set & method index)
;               combined with the previous mode (bits 7-0)


        ; we need some scratch registers but we don't have any to use here. So, we'll have to 
        ; use caller's stack to save off the registers. Need to be careful not to forget about
        ; it when we switch stack
        stmfd   sp!, {r0-r3}                    ; save function parameters onto the stack
        mov     r0, #FIRST_METHOD - 0xF0000000
        rsb     r0, r0, r12, LSR #8
        mov     r0, r0, ASR #2                  ; (r0) = iMethod
        cmp     r0, #-1
        beq     CBRtn                           ; process callback return if it is

        ;
        ; PSL call
        ;
        mov     r1, #0                          ; (r1) = prevSP, init to 0
        and     r2, r12, #0x1f                  ; (r2) = previous mode (User/Kernel)
        cmp     r2, #SYSTEM_MODE
        beq     KPSLCall

        ;
        ; PSL Call from USER MODE
        ;

        ; special case for RaiseException
        mov     r3, #RAISEEXCEPTION
        cmp     r0, r3                          ; RaiseException?
        beq     PSLCallCommon                   ; do not switch stack if it is
        
        ; check trust level
        ldr     r3, =KData                      ; (r3) = ptr to KData page
        ldr     r2, [r3,#pCurPrc]               ; (r2) = pCurProc
        ldrb    r2, [r2, #PrcTrust]             ; (r2) = pCurProc->bTrustLevel
        cmp     r2, #KERN_TRUST_FULL            ; Is it fully trusted?
        mov     r2, #USER_MODE                  ; (r2) = USER_MODE
        beq     PSLCallCommon                   ; go to common code if fully trusted

        ;
        ; not trusted, switch stack (r3) = KData
        ;

        ; update TLS first
        ldr     r2, [r3, #pCurThd]              ; (r2) = pCurThread
        ldr     r1, [r2, #ThTlsSecure]          ; (r1) = pCurThread->tlsSecure
        str     r1, [r2, #ThTlsPtr]             ; pCurThread->tlsPtr = pCurThread->tlsSecure
        str     r1, [r3, #lpvTls]               ; lpvTls = pCurThread->tlsSecure
        
        sub     r1, r1, #SECURESTK_RESERVE      ; (r1) = new stack, init to (tlsptr - SECURESTK_RESERVE)
        
        ; find the 'real' callstack (SEH might put in a faked one)
        ldr     r2, [r2, #ThPcstkTop]           ; (r2) = pCurThread->pcstkTop
NextCStk
        tst     r2, r2                          ; pcstk == NULL?
        beq     CopyStack

        ldr     r3, [r2, #CstkAkyLast]          ; (r3) = pcstk->akyLast
        tst     r3, r3
        bne     FoundCStk                       ; pcstk->akyLast != 0 ==> Found

        ldr     r2, [r2, #CstkNext]             ; pcstk = pcstk->pcstkNext
        b       NextCStk

FoundCStk
        ldr     r1, [r2, #CstkPrevSP]           ; (r1) = pcstk->dwPrevSP (new stack)

CopyStack
        ; (r1) = new STACK
        ; (sp) = old stack (original r0 - r3 are on stack too)
        ;       I'd like to use stm/ldm, but we're out of registers...

        ; need to update SP before touch the new stack or we might have a inconsistant
        ; stack bound
        mov     r2, r1                          ;\   ; don't remove this or '\' at the end of line will bite
        mov     r1, sp                          ; * exchange old and new stack
        sub     sp, r2, #MAX_PSL_ARGS           ;/   ; also make room for PSL args

        ldr     r2, [r1]
        str     r2, [sp]
        ldr     r2, [r1, #4]
        str     r2, [sp, #4]
        ldr     r2, [r1, #8]
        str     r2, [sp, #8]
        ldr     r2, [r1, #12]
        str     r2, [sp, #12]
        ldr     r2, [r1, #16]
        str     r2, [sp, #16]
        ldr     r2, [r1, #20]
        str     r2, [sp, #20]
        ldr     r2, [r1, #24]
        str     r2, [sp, #24]
        ldr     r2, [r1, #28]
        str     r2, [sp, #28]
        ldr     r2, [r1, #32]
        str     r2, [sp, #32]
        ldr     r2, [r1, #36]
        str     r2, [sp, #36]
        ldr     r2, [r1, #40]
        str     r2, [sp, #40]
        ldr     r2, [r1, #44]
        str     r2, [sp, #44]
        ldr     r2, [r1, #48]
        str     r2, [sp, #48]
        ldr     r2, [r1, #52]
        str     r2, [sp, #52]

        add     r1, r1, #16                     ; we've pushed 4 args onto the old stack, take it out

        ; (r0) = iMethod
        ; (r1) = old SP 
        mov     r2, #USER_MODE                  ; (r2) = USER_MODE
        b       PSLCallCommon

KPSLCall
        cmp     r0, #PERFORMCALLBACK            ; is it callback?
        beq     DoPerformCallBack

        ; fall thru to common code
        
PSLCallCommon

        ; (r0) = iMethod
        ; (r1) = old sp
        ; (r2) = previous mode
        ; (r3) = linkage (don't care in ARM)
        ; (lr) = return address
        ; original r0 - r3 are on stack
        ;
        ; The following stmfd instruction is assuming that it's going to put
        ; the registers in the stack from high to low. i.e. we're assuming
        ; it's equivalent to 
        ;       push lr         (Ra in OBJCALLSTRUCT)
        ;       push r3         (linkage)
        ;       push r2         (mode)
        ;       push r1         (prevSP)
        ;       push r0         (iMethod)
        ;
        stmfd   sp!, {r0-r3, lr}
        mov     r0, sp                          ; (r0) = ptr to OBJCALLSTRUCT
        CALL    ObjectCall

        ; always run PSL in KMODE
        add     sp, sp, #size_api_args          ; pop of the 5 args we pushed for ObjectCall
        mov     r12, r0                         ; (r12) = function to call

        ldmfd   sp!, {r0-r3}                    ; reload function paramters
        add     lr, pc, #DirectRet-(.+8)        ; update return address
  IF Interworking :LOR: Thumbing
        bx      r12                             ; invoke function in "kernel mode"
  ELSE
        mov     pc, r12                         ; invoke function in "kernel mode"
  ENDIF

DirectRet
        ;
        ;       (r0) = return value
        ;nop
        ;nop
        sub     sp, sp, #size_api_args          ;  make room for ServerCallReturn arugments

        str     r0, [sp, #apiRa]                ; save return value
        add     r0, sp, #svrrtnstr              ; (r0) = ptr to SVRRTNSTRUCT

        CALL    ServerCallReturn

        ; (r0) = address to continue
        mov     r12, r0                         ; (r12) = address to Continue
        ldr     r0, [sp, #apiRa]                ; restore return value
        ldr     r2, [sp, #apiMode]              ; (r1) = return mode
        ldr     r3, [sp, #apiPrevSP]            ; (r3) = target sp
        
        add     sp, sp, #size_api_args          ; pop the temp stuffs
        cmp     r2, #USER_MODE                  ; return to user mode?

  IF Interworking :LOR: Thumbing
        bxne    r12                             ; return in "kernel mode"
  ELSE
        movne   pc, r12                         ; return in "kernel mode"
  ENDIF
  
        ; returning to user mode. check if stack need to be changed
        tst     r3, r3
        beq     RtnToUMode

        ; need to switch STACK 
        mov     sp, r3                          ; update SP
        ; update TLS
        ldr     r3, =KData                      ; (r3) = ptr to KData page
        ldr     r2, [r3, #pCurThd]              ; (r2) = pCurThread
        ldr     r1, [r2, #ThTlsNonSecure]       ; (r1) = pCurThread->tlsNonSecure
        str     r1, [r2, #ThTlsPtr]             ; pCurThread->tlsPtr = pCurThread->tlsNonSecure
        str     r1, [r3, #lpvTls]               ; lpvTls = pCurThread->tlsNonSecure
        
RtnToUMode
        ; return to user mode
        ;  (r12) = address to continue
        msr     cpsr_c, #SVC_MODE:OR:0x80       ; switch to SVC Mode w/IRQs disabled

        tst     r12, #0x01                      ; returning to Thumb mode ??
        msrne   spsr_c, #USER_MODE | THUMB_STATE
        msreq   spsr_c, #USER_MODE              ; set the Psr according to returning state

        movs    pc, r12                         ; switch to User Mode and return


DoPerformCallBack
        ; orignal r0 - r3 are on stack already
        add     r1, sp, #16                     ; (r1) = original SP (+16 for r0-r3 we pushed)
        sub     sp, sp, #size_api_args          ; make room for PerformCallBackExt arguments

        ; setup PerformCallBackExt arguments
        str     lr, [sp, #apiRa]                ; return address
        str     r1, [sp, #apiPrevSP]            ; original SP

        add     r0, sp, #objcallstr             ; (r0) = ptr to OBJCALLSTRUCT
        CALL    PerformCallBackExt              ; call PerformCallBackExt

        ; (r0) = function to call
        mov     r12, r0                         ; (r12) = function to call
        ldr     r3, [sp, #apiMode]              ; (r3) = mode to call into
        ldr     r1, [sp, #apiPrevSP]            ; (r1) = target SP if non-zero
        add     sp, sp, #size_api_args          ; pop the temp stuffs

        tst     r1, r1                          ; need stack switch?
        beq     CBCommon                        ; go to common code if not

        ; need to switch stack
        ;
        ; must update TLS and SP before the copy, or stack bound might become inconsistent
        ; (r1) = new SP
        ; (r3) = mode to call into
        ; (r12) = function to call

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -