📄 armtrap.s
字号:
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 + -