这是Windows CE下面的IRQ处理函数代码:
;-------------------------------------------------------------------------------
NESTED_ENTRY IRQHandler
sub lr, lr, #4 ; fix return address
stmfd sp!, {r0-r3, r12, lr}
PROLOG_END
;
; Test interlocked API status.
;
sub r0, lr, #INTERLOCKED_START
cmp r0, #INTERLOCKED_END-INTERLOCKED_START
bllo CheckInterlockedRestart
;
; CAREFUL! The stack frame is being altered here. It's ok since
; the only routine relying on this was the Interlock Check. Note that
; we re-push LR onto the stack so that the incoming argument area to
; OEMInterruptHandler will be correct.
;
mrs r1, spsr ; (r1) = saved status reg
stmfd sp!, {r1} ; save SPSR onto the IRQ stack
mov r0,lr ; parameter to OEMInterruptHandler
msr cpsr_c, #SVC_MODE:OR:0x80 ; switch to supervisor mode w/IRQs disabled
stmfd sp!, {lr} ; save LR onto the SVC stack
stmfd sp!, {r0} ; save IRQ LR (in R0) onto the SVC stack (param)
;
; Now we call the OEM's interrupt handler code. It is up to them to
; enable interrupts if they so desire. We can't do it for them since
; there's only on interrupt and they haven't yet defined their nesting.
;
CALL OEMInterruptHandler
; (r0) = SYSINTR returned
; call the ISR hook (pfnOEMIntrOccurs is set to a faked function if not changed by OEM)
ldr r1, =pfnOEMIntrOccurs
ldr r1, [r1] ; (r1) = pfnOEMIntrOccurs
mov lr, pc ; (lr) = return address
IF Interworking :LOR: Thumbing
bx r1 ; call the pfnOEMIntrOccurs
ELSE
mov pc, r1 ; call the pfnOEMIntrOccurs
ENDIF
ldmfd sp!, {r1} ; dummy pop (parameter)
ldmfd sp!, {lr} ; restore SVC LR from the SVC stack
msr cpsr_c, #IRQ_MODE:OR:0x80 ; switch back to IRQ mode w/IRQs disabled
;
; Restore the saved program status register from the stack.
;
ldmfd sp!, {r1} ; restore IRQ SPSR from the IRQ stack
msr spsr, r1 ; (r1) = saved status reg
ldr lr, =KData ; (lr) = ptr to KDataStruct
cmp r0, #SYSINTR_RESCHED
beq %F10
sub r0, r0, #SYSINTR_DEVICES
cmp r0, #SYSINTR_MAX_DEVICES
;
; If not a device request (and not SYSINTR_RESCHED)
;
ldrhsb r0, [lr, #bResched] ; (r0) = reschedule flag
bhs %F20 ; not a device request
;
; mark reschedule needed
;
10 ldrb r0, [lr, #bResched] ; (r0) = reschedule flag
orr r0, r0, #1 ; set "reschedule needed bit"
strb r0, [lr, #bResched] ; update flag
20 mrs r1, spsr ; (r1) = saved status register value
and r1, r1, #0x1F ; (r1) = interrupted mode
cmp r1, #USER_MODE ; previously in user mode?
cmpne r1, #SYSTEM_MODE ; if not, was it system mode?
cmpeq r0, #1 ; user or system: is resched == 1
ldmnefd sp!, {r0-r3, r12, pc}^ ; can't reschedule right now so return
sub lr, lr, #4
ldmfd sp!, {r0-r3, r12}
stmdb lr, {r0-r3}
ldmfd sp!, {r0}
str r0, [lr] ; save resume address
mov r1, #ID_RESCHEDULE ; (r1) = exception ID