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

📄 shexcept.src

📁 windows ce 3.00 嵌入式操作系统源代码
💻 SRC
📖 第 1 页 / 共 5 页
字号:

; Non-address error load exeception. Check for TLB Miss due to invalid entry and send
; to the tlb miss handler if necessary.
;
;	(r0) = EXPEVT | 0x20

	.align	4
geh30:	cmp/eq	#h'60, r0
	bf	geh35			; not a TLB Miss
	bra	TLBMissHandler
	nop
	.nopool

; General exception or TLB miss which cannot be resolved by the TLB miss handler.

TLBMissError:	; return here from TLB miss handler if invalid address
geh35:	mov	#_KData+bResched, r1
	mov.b	@(1,r1), r0		; (r0) = kernel reentrancy flag
	dt	r0			; decrement for each entry
	bf/s	geh33			; nested exception
	mov.b	r0, @(1,r1)		; save reentrancy level

; Handle a general exception that is NOT a system call.
;
;	(r5) = ptr to CtxPSR+4.
;	in register bank 1

	stc	SSR, @-r5		; save status register
	stc	SPC, @-r5		; save PC
	mov.l	r15, @-r5		; save stack pointer
	mov.l	r14, @-r5		; save register for ptr to current thread
	mov	r4, r14			; (r14) = ptr to current thread
	mov	#_KStack, r15		; switch to kernel's stack
geh36:	mov.l	@(EXPEVT,r7), r0	; (r0) = exception event code
	mov	#h'160, r2
	mov.l	@(MMUTEA,r7), r1	; (r1) = translation address
	cmp/eq	r0, r2
	bf	geh41			; not a TRAPA exception
	bra	geh41
	mov.l	@(TRPA,r7), r1		; (r1) = trapa value
	.nopool

; A nested exception has occured. Create a temporary thread
; structure on the stack and save the current state into that.
;
;	(r2) = old stack pointer
;	in register bank 1

geh33:	mov	r15, r5			; (r5) = ptr to context save area
  .aif SH_CPU eq h'40
	add	#h'80-CtxSizeof, r5
	add	#(CtxPsr+4)-h'80, r5 ; (r5) = ptr to PSR save
  .aelse
	add	#(CtxPsr+4)-CtxSizeof, r5 ; (r5) = ptr to PSR save
  .aendi
	stc	SSR, @-r5		; save status register
	stc	SPC, @-r5		; save PC
	mov.l	r15, @-r5		; save stack pointer
	mov.l	r14, @-r5		; save register for ptr to current thread
	mov	r5, r15
	add	#-CtxR14, r15
	add	#-THREAD_CONTEXT_OFFSET, r15
	mov	r15, r14		; (r14) = ptr to fake thread
	mov	#-1, r3
	mov.l 	r3, @(ThAKey, r14)	; Set access key to FFFFFFFF
	bra	geh36
	add	#-16, r15		; make room for argument spill area
	.nopool

; An interrupt has caused a reschedule. Setup the registers for a general
; exception and jump into the context save & exception dispatch.
;
;	(r4) = ptr to current thread
;	(r5) - ptr to context save area
;	(r7) - SH3CTL_BASE (used to access MMU & exception data)
;	cNest == 0 (not inside another exception)
;	in register bank 1

InterruptResched:
	stc	SSR, @-r5		; save status register
	stc	SPC, @-r5		; save PC
	mov.l	r15, @-r5		; save stack pointer
	mov.l	r14, @-r5		; save register for ptr to current thread ptr
	mov	#0, r0			; (r0) = fake EXPEVT value
	mov	#_KStack, r15		; switch to kernel's stack
	mov	r4, r14			; (r14) = ptr to current thread

geh41:	mov.l	r13, @-r5
	mov.l	r12, @-r5
	mov.l	r11, @-r5
	mov.l	r10, @-r5
	mov.l	r9, @-r5
	mov.l	r8, @-r5
	stc	r7_user, @-r5
	stc	r6_user, @-r5
	stc	r5_user, @-r5
	stc	r4_user, @-r5
	stc	r3_user, @-r5
	stc	r2_user, @-r5
	stc	r1_user, @-r5
	stc	r0_user, @-r5
	ldc	r1, r6_user		; (r6) = TEA or TRAPA value (arg2)
	stc	GBR, @-r5
	sts	MACL, @-r5
	mov	#CONTEXT_FULL, r1
	sts	MACH, @-r5
	sts	PR, @-r5
	mov.l	r1, @-r5		; set context flags
	mov	#PR_B0_IE, r1
	mov	r0, r8			; (r8) = exception cause
	ldc	r1, SR			; (SR) = privileged, bank 0, unblocked

; Check for interlocked API in progress. The interlocked apis setup the registers
; as follows: (r1) = starting address of sequence, (r2) = ending address of
; sequence, (r3) = (r1) ^ INTRLOCK_KEY.
;
;	(r6) = TEA or TRAPA code (arg2)
;	(r8) = exception cause (from EXPEVT, 0 if interrupt reschedule)
;	(r14) = ptr to current thread
;	in register bank 0.

	mov	#INTERLOCKED_END, r1	; (r1) = end of interlocked api block
	mov	r14, r9
	add	#THREAD_CONTEXT_OFFSET+CtxR2, r9
	mov.l	@(CtxFir-CtxR2,r9), r5	; (r5) = resume address
	cmp/hi	r5, r1			; 'T' = r1 > r5
	bt	geh70			; PC < INTERLOCKED_END

; Dispatch general exception.
;
;	(r6) = TEA or TRAPA code (arg2)
;	(r8) = exception cause
;	(r9) = ptr to CtxR2 in Current Thread's context
;	(r14) = ptr to current thread
;	All user registers saved into thread context
;	in register bank 0

geh45:	tst	r8, r8
	bt	geh55			; this is a reschedule request
 	mov	#_HandleException, r1
	mov	r8, r5			; (r5) = exception cause (arg1)
	jsr	@r1
	mov	r14, r4			; (r4) = ptr to current thread (arg0)

	tst	r0,r0
	bt	geh55			; must reschedule
	bra	geh60			; resume the current thread
	nop
	.nopool

; The current thread is yielding. Save the permanent registers into the
; thread's context structure and invoke NextThread.
;
;	(r14) = ptr to current thread
;	in register bank 0

	.align	4
SaveAndResched:
	mov	r14, r4
	add	#THREAD_CONTEXT_OFFSET, r4; (r4) = ptr to CtxFlags
	mov	#0, r0
	mov.l	r0, @(CtxContextFlags,r4)
	add	#CtxR8, r4		; (r4) = ptr to CtxR8
	mov.l	r8, @(CtxR8-CtxR8,r4)
	mov.l	r9, @(CtxR9-CtxR8,r4)
	mov.l	r10, @(CtxR10-CtxR8,r4)
	mov.l	r11, @(CtxR11-CtxR8,r4)
	mov.l	r12, @(CtxR12-CtxR8,r4)
	mov.l	r13, @(CtxR13-CtxR8,r4)

; The current thread has been blocked or a reschedule is pending.
; Call the scheduler to obtain the highest priority thread to run.
;
;	(r14) = ptr to current thread
;	register bank unknown

resched:
geh55:	mov	#PR_B0_IE, r1
	mov	#_KData+bResched, r9
	ldc	r1, SR			; (SR) = privileged, bank 0, unblocked
	mov.b	@(bPowerOff-bResched,r9), r0	; (r0) = "power off" flag
	mov	#_NextThread, r8
	tst	r0, r0
	bf	PowerOff			; go do power off processing
	mov.b	r0, @(bProfileOn-bResched,r9)	; clear profiling bit

renextthread:
	mov.b @r9, r0
	cmp/eq #1, r0
	bf nonextthread

	mov #0, r0
	jsr	@r8
	mov.w	r0, @r9			; clear reschedule, still in kernel

nonextthread:

	mov @(dwKCRes-bResched, r9), r0
	cmp/eq #1, r0
	bf nokcresched

	mov #_KCNextThread, r8
	mov #0, r0
	jsr @r8
	mov r0, @(dwKCRes-bResched, r9)

	mov @(dwKCRes-bResched,r9), r0
	cmp/eq #1, r0
	bt renextthread

nokcresched:

	mov #_RunList, r1
	mov @(4,r1), r0

	cmp/eq	#0, r0
	bt	Idle			; no thread to run
	cmp/eq	r0, r14
	bt	geh60			; resume current thread

; Switch to a different thread. Update current thread, current process, thread
; local storage data, and process virtual memory context.
;
;	(r0) = ptr to thread to dispatch
;	(r9) = ptr to bResched

	.align	4
geh56:	mov	#_KData+lpvTls, r6	; (r6) = &lpvTLS in KPage
	mov	r0, r14			; (r14) = ptr to thread
	mov.l	@(ThHandle,r14), r0	; (r0) = thread's handle
	mov	#SH3CTL_BASE, r7
	mov.l	r0, @(hCurThread-lpvTls,r6)	; save current thread handle in KPage
	mov.l	@(ThProc,r14), r1	; (r1) = ptr to current process
	mov.l	r14, @(pCurThd-bResched,r9)	; save current thread ptr in KPage
	mov.l	r1, @(pCurPrc-bResched,r9)	; save current process ptr
	mov.l	@(PrcHandle,r1), r0	; (r0) = process's handle
	add	#aSections-bResched, r9	; (r9) = ptr to SectionTable
	mov.l	r0, @(hCurProc-lpvTls,r6); save current process handle in KPage
	mov.l	@(PrcVMBase,r1), r0	; (r0) = memory section base address	    |
	mov	#2-VA_SECTION, r2	; (r2) = right shift count		    |
	mov.l	@(ThTlsPtr,r14), r3	; (r3) = thread local storage pointer	    |
	shld	r2, r0			; (r0) = section index * 4		    |
	mov.l	r3, @r6			; set TLS pointer			    |
	ldc	r14, r4_bank		; (r4_bank1) = ptr to current thread	    |
	ERRNZ PrcID			;					    |
	mov.b	@r1, r4			; (r4) = process ID			    |
	mov.l	@(r0,r9), r2		; (r2) = process's memory section	    |
	mov.l	r4, @(MMUPTEH,r7)	; set ASID				    |
	mov.l	r2, @r9			; swap in default process slot		    |

; Restore thread state.
;
;	(r14) = ptr to thread structure

geh60:	mov	r14, r7
	add	#THREAD_CONTEXT_OFFSET, r7
	mov	r7, r11
	mov.l	@r7+, r0		; (r0) = ContextFlags
	lds	@r7+, PR		; restore return address
	tst	r0, r0
	bt	geh65			; only partial restore needed
	lds	@r7+, MACH
	lds	@r7+, MACL
	ldc	@r7+, GBR
	add	#4, r7
	mov.l	@r7+, r1
	mov.l	@r7+, r2
	mov.l	@r7+, r3
	mov.l	@r7+, r4
	mov.l	@r7+, r5
	mov.l	@r7+, r6
	mov.l	@r7, r7

; Reload thread's permanent registers and return value.
;
;	(r11) = ptr to Current Thread's context structure
;	(r13) = ptr to float save area
;	(r14) = ptr to current thread

geh65:	mov.l	@(CtxR8,r11), r8
	mov.l	@(CtxR9,r11), r9
	mov	#PR_B1_BK, r10		; (r10) = new SR value
	mov.l	@(CtxR0,r11), r0	; (r0) = return value
	mov	#_KData+bResched, r12
	ldc	r10, SR			; (SR) = privileged, bank 1, blocked
	;++++ now in bank 1 ++++
	mov.w	@r12, r0		; (r0) = kernel reentrancy flag
	mov.l	@(CtxR10,r11), r10

	cmp/eq	#1, r0
	bt	resched			; reschedule required

	shlr8	r0
	add	#1, r0
	mov.b	r0, @(1,r12)		; save reentrancy level

; if high bit of wPriority is set, profiling should be on, else profiling off
;
;	(r12) = ptr to bResched
;	(r14) = ptr to current thread

	mov.w	@(ThwInfo,r14), r0	; (r0) = thread's wInfo field
	mov	r11, r5
	shlr16	r0			; (r0) = 0xFFFF iff high bit was set
	mov.b	r0, @(bProfileOn-bResched,r12)
	add	#CtxR11, r5		; (r5) = ptr to CtxR11

	mov.l	@r5+, r11
	mov.l	@r5+, r12
	mov.l	@r5+, r13
	mov.l	@r5+, r14
	mov.l	@r5+, r15		; restore stack pointer
	ldc	@r5+, SPC
	ldc @r5+, SSR

	rte
	nop
	.nopool

; PC is below the end of the INTERLOCKED APIs, check lower bound and adjust the PC
; to restart the routine.
;
;	(r5) = resume address
;	(r9) = ptr to CtxR2 in Current Thread's context
;	(r14) = ptr to current thread.

geh70:	mov	#INTERLOCKED_START, r1	; (r1) = start of interlocked api block
	mov	#1, r0
	tst	r0,r5
	bf	geh75			; PC is odd, don't change it
	cmp/hi	r5, r1			; 'T' = r1 > r5
	bt	geh75			; out of range, no backup
	mov	#-8, r1
	and	r1, r5			; (old PC) &= ~7

	.aif INTRLOCK_LEDS eq 1
	mov	#h'AA001010, r2		; (r2) = LED address
	mov.l	@r2, r0
	add	#1,r0
	mov.l	r0, @r2			; put it in lights
	.aendi

	mov.l	r5, @(CtxFir-CtxR2,r9)	; backup PC to start of intrlocked sequence
geh75:	bra	geh45
	nop
	.nopool

; There are no threads which are ready to run. Put the cpu to sleep until
; something is made ready. Since an interrupt may occur between when NextThread
; returns and we get here, the reschedule flag must be checked. To avoid a timing
; race between checking the flag and sleeping, interrupts are blocked but not
; masked before checking the flag. The CPU will acknowledge interrupts regardless
; of the block bit when it is in sleep state.
;
;	(r9) = ptr to bResched

Idle:	mov	#PR_B0_BK, r1
	mov	#_OEMIdle, r8
	ldc	r1, SR			; (SR) = privileged, bank 0, exceptions blocked
	mov.b	@r9, r0			; (r0) = reschedule flag
	tst	r0, r0
	bf	geh55			; reschedule needed, don't sleep
	jsr	@r8			; call OEMIdle to sleep
	nop

	mov	#_KData+bResched, r1
	mov #1, r0
	mov.b	r0, @r1		; (r0) = reschedule flag

	bra	geh55
	nop
	.nopool

; The power off flag has been set. Mask off interrupts, and call DoPowerOff() to
; notify the file system and invoke OEMPowerOff. Since the cpu state may be unknown
; upon return, the kernel's well known bank 1 registers must restored.
;
;	(r9) = ptr to bResched
;	(r14) = current thread

PowerOff:
	mov	#PR_B0_IM, r1
	mov	#_DoPowerOff, r2
	ldc	r1, SR			; (SR) = privileged, bank 0, ints masked
	mov	#0, r0
	jsr	@r2
	mov.w	r0, @r9			; clear reschedule, still in kernel
	mov	#SH3CTL_BASE, r0
	ldc	r0, r7_bank		; (r7_priv) = ptr to SH3 control registers
	mov	#0, r14			; (r14) = 0 (no current thread)
	mov	#0, r0
	bra	geh55
	mov.b	r0, @(bPowerOff-bResched,r9)
	.endf

	.PAGE
	.org	h'400
; TLB Miss handler
;
; Bank 1 registers are pre-loaded with the following values:
;
;	(r4) - ptr to current thread
;	(r5) - ptr to context save area
;	(r7) - SH3CTL_BASE (used to access MMU & exception data)

	LEAF_ENTRY TLBMissHandler
	mov.l	@(MMUTEA,r7), r1	; (r1) = faulting virtual address
	mov.l	@(MMUTTB,r7), r0	; (r0) = ptr to SectionTable array
tlb10:	cmp/pz	r1
	bf	tlb55			; address >2GB, out of SectionTable bounds
	shlr8	r1
	mov	r1, r2			; (r2) = TEA >> 8
	shlr16	r1			; (r1) = TEA >> 24
	shlr	r1			; (r1) = section table index (TEA>>25)
	shll2	r1
	mov.l	@(r1,r0), r0		; (r0) = ptr to section
	mov	r2, r1			; (r1) = TEA >> 8
	mov	#BLOCK_MASK, r3
	shlr8	r1			; (r1) = TEA >> 16
	and	r3, r1			; (r1) = block index
	shll2	r1
	mov.l	@(r1,r0), r1		; (r1) = ptr to MEMBLOCK structure
	mov.l	@(ThAKey,r4), r3	; (r3) = thread's access key
	cmp/pz	r1
	bt/s	tlb60			; unmapped block
	mov	r2, r0			; (r0) = TEA >> 8
	mov.l	@(mb_lock,r1), r2	; (r2) = block's access lock
	add	#mb_pages, r1		; (r1) = ptr to array of TLB entries
	tst	r2, r3			; (T) = 1 iff access is allowed
	bt	tlb60			; thread cannot access this block
  .aif VA_PAGE eq 12
	shlr2	r0			; (r0) = TEA >> 10
  .aendi
	and	#PAGE_MASK4, r0		; (r0) = page index * 4
	mov.l	@(r0,r1), r0		; (r0) = TLB entry
	tst	#1, r0
	bt	tlb60			; invalid entry
tlb40:
  .aif SH_CPU eq h'40
  	mov.l	r0, r1
	add #-1, r0			; // clear "write through" bit
  	mov #-9, r3
  	shld r3, r1
        mov #1, r3
        tst r3, r1
  	mov #-20, r3
  	shld r3, r1
        bt tlb40a
        add #16, r1
tlb40a:
	mov.l	r1, @(MMUPTEA,r7)	; set assistance part of TLB entry
  .aendi
	mov.l	r0, @(MMUPTEL,r7)	; set lower part of TLB entry
	ldtlb
	nop
	nop

  .aif CELOG eq h'01
        ;
        ; Update the TLBMiss counter for CELOG
        ;
        mov     #_dwCeLogTLBMiss, r2
        mov.l   @r2, r1

⌨️ 快捷键说明

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