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

📄 shexcept.src

📁 windows ce 3.00 嵌入式操作系统源代码
💻 SRC
📖 第 1 页 / 共 5 页
字号:
	.HEADING "SH3 Interrupt and Exception Processing"
;++
;
; Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.
;
; Module Name:
;
;    shexcept.src
;
; Abstract:
;
;    This module implements the code necessary to field and process SH3
;    interrupt and exception conditions.
;
;    WARNING: This module executes in KSEG0 and, in general, cannot
;	tolerate a TLB Miss. Registers k0 and k1 are used during initial
;	interrupt and exception processing, and therefore, extreme care must
;	be exercised when modifying this module.
;
; Revision History:
;
;--

	.list OFF
	.include "ksshx.h"
	.list ON

VALIDATE_CACHE: .equ 0			; set to force cache validation.
INTRLOCK_LEDS: .equ 0

API_MAX: .equ	FIRST_METHOD - (h'3fff * 2)

	.import	_DoPowerOff
	.import _DumpFrame
	.import _HandleException
	.import _KernelInit
	.import	_NextThread
	.import _KCNextThread
	.import	_RunList
	.import _SleepList
	.import	_ObjectCall
	.import	_ServerCallReturn
	.import _SH3Init
	.import _ExceptionDispatch
	.import	OEMNMI
	.import	_OEMIdle
	.import	_SetBadHandleError
  .aif SH_CPU eq h'40
	.import _dwStoreQueueBase
	.import _SH4CacheLines
  .aelse
   	.import _SH3CacheLines
  .aendi
  .aif CELOG eq h'01
        .import _CeLogInterruptSHx
        .import _CELOG_ThreadMigrateSHx
        .import _dwCeLogTLBMiss
  .aendi

	.PAGE
	.section .data,data
	.align	4
	.export _InterruptTable
	.export	ExceptionTable
ExceptionTable:
	.data.l	_UnusedHandler		; 0x000 power-on reset (intr resched)
	.data.l	_UnusedHandler		; 0x020 manual restart
	.data.l	_UnusedHandler		; 0x040 TLB miss load
	.data.l	_UnusedHandler		; 0x060 TLB miss store
	.data.l	_UnusedHandler		; 0x080 initial page write
	.data.l	_UnusedHandler		; 0x0A0 TLB protection violation (load)
	.data.l	_UnusedHandler		; 0x0c0 TLB protection violation (store)
	.data.l	_UnusedHandler		; 0x0e0 address error (load)
	.data.l	_UnusedHandler		; 0x100 address error (store)
	.data.l	_UnusedHandler		; 0x120 reserved
	.data.l	_UnusedHandler		; 0x140 reserved
	.data.l	_UnusedHandler		; 0x160 TRAPA instruction
	.data.l	_UnusedHandler		; 0x180 reserved instruction
	.data.l	_UnusedHandler		; 0x1A0 invalid delay slot instruction
	.data.l	OEMNMI				; 0x1C0 NMI (general interrupt request)
	.data.l	_UnusedHandler		; 0x1E0 user breakpoint (HW breakpoints)
_InterruptTable:
	.arepeat 112				; 0x200-0xfe0 HW interrupts
	.data.l	_UnusedHandler
	.aendr
  .aif SH_CPU eq h'40
_bEnableRAMMode:
	.res.l 1
  .aendi
 .export _IntrPrio
_IntrPrio:
	.data.b 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 ; 0x200-0x3e0
	.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0x400-0x5e0
	.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0x600-0x7e0
	.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0x800-0x9e0
	.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0xa00-0xbe0
	.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0xc00-0xde0
	.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0xe00-0xfe0

	.section .KDATA,stack
	.export _KDBase
	.export _KStack
_KDBase: .res.b h'1000	; reserve an extra page for the debugger
	 .res.b	h'7e0
_KStack: .res.l	8
	.export	_KData
_KData:	.res.b	cMsec
	.export _CurMSec
_CurMSec: .res.b 4
	.export _DiffMSec
_DiffMSec: .res.b h'400 - cDMsec

	.section .text,code,align=16

KPAGE_PTEL: .equ _KData + h'14a	; user read-only, 1k, cachable, !dirty, shared, valid

   .aif SH_CPU eq h'40

PR_B1_BK: .equ h'70008000	; privileged mode, bank 1, exceptions blocked
PR_B0_IE: .equ h'40008000	; privileged mode, bank 0, un-blocked, intr unmasked
PR_B0_IM: .equ h'400080f0	; privileged mode, bank 0, un-blocked, intr masked
PR_B0_BK: .equ h'50008000	; privileged mode, bank 0, exceptions blocked

	.aelse

PR_B1_BK: .equ h'70000000	; privileged mode, bank 1, exceptions blocked
PR_B0_IE: .equ h'40000000	; privileged mode, bank 0, un-blocked, intr unmasked
PR_B0_IM: .equ h'400000f0	; privileged mode, bank 0, un-blocked, intr masked
PR_B0_BK: .equ h'50000000	; privileged mode, bank 0, exceptions blocked

	.aendi

	START_REGION	ExceptionBase	; base to load into VBR

	LEAF_ENTRY _DebugBreak
	trapa	#1
	rts
	nop
	.endf

	LEAF_ENTRY _INTERRUPTS_ON
	mov	#h'ffffff0f, r1
	stc	SR, r0
	and	r1, r0
	ldc	r0, SR
	rts
	nop
	.endf

	LEAF_ENTRY _INTERRUPTS_OFF
	stc	SR, r0
	or	#h'f0, r0
	ldc	r0, SR
	rts
	nop
	.endf	

	.align	4
	.export	_PtrCurMSec
_PtrCurMSec: .data.l _CurMSec


; SetCPUASID - set address space id
;
;   SetCPUASID updates the MMU control registers and kernel page info
; when a thread's current process or access key is changed.
;
;	Entry	(r4) = ptr to thread
;	Return	nothing
;	Uses	r0, r1, r2, r3, r7

	LEAF_ENTRY _SetCPUASID

  .aif CELOG eq h'01
        ;
        ; NOTE : To make things relatively consistent, I'm going to make
        ; the registers R0-R3, R6 available for use. On entry to
        ; CeLogThreadMigrateSHx R0 will contain the handle of the process.
        ;
        ; I'm assuming that at this point the only registers that I need to
        ; preserve are R4 (ptr to thread) and PR (return address)
        ;

        mov.l	@(ThProc,r4), r0	; (r0) = ptr to current process
        mov	@(PrcHandle,r0), r0	; (r0) = handle of current process
        mov	#_KData+hCurProc, r1	; (r1) = &hCurProc
	mov	@r1, r1			; (r1) = old process handle
        cmp/eq  r0, r1                  ; if new process == old process
        bt/s    celog10                 ; then skip CeLog call
        nop

        sts     pr, @-r15               ; Save current return address
        mov.l   r4, @-r15               ; Save register

        mov.l	@(ThProc,r4), r5	; (r5) = ptr to current process
        mov	@(PrcHandle,r5), r4	; (r4) = handle of current process

        mov     #_CELOG_ThreadMigrateSHx, r2
        jsr     @r2                     ; CELOG_ThreadMigrateSHx(hProc)
        nop

        mov.l   @r15+, r4               ; Restore register
        lds     @r15+, pr               ; Restore return address

celog10:

  .aendi

        mov.l	@(ThProc,r4), r1	; (r1) = ptr to current process
        mov	#_KData+hCurProc, r0	; (r0) = &hCurProc
        mov	@(PrcHandle,r1), r7	; (r7) = handle of current process
	mov	#2-VA_SECTION, r2	; (r2) = right shift count
	mov	r7, @r0			; set current process handle
	add	#bResched-hCurProc, r0	; (r0) = &bResched
	mov.l	r1, @(pCurPrc-bResched,r0)	; set current process pointer	   |
	add	#aSections-bResched, r0	; (r0) = ptr to SectionTable		   |
	mov.l	@(PrcVMBase,r1), r3	; (r3) = memory section base address	   |
	mov	#SH3CTL_BASE, r7	;					   |
	ERRNZ PrcID			;					   |
	mov.b	@r1, r1			; (r1) = process ID			   |
	shld	r2, r3			; (r3) = section index * 4		   |
	mov.l	@(r0,r3), r2		; (r2) = process's memory section	   |
	mov.l	r1, @(MMUPTEH,r7)	; set ASID				   |
	rts
	mov.l	r2, @r0			; swap in default process slot
        .endf

	LEAF_ENTRY _SetCPUGlobals
	mov #_KData+pCurThd, r0
	mov @r0, r0
	ldc	r0, r4_bank
	rts
	nop
	.endf

	.PAGE
	LEAF_ENTRY KernelStart
;* Inititalize Status register:
;	Kernel mode,
;	exceptions blocked,
;	register bank 1
	mov	#PR_B1_BK, r0
	ldc	r0, SR			; (SR) = kmode, blocked, bank1
	mov	#SH3CTL_BASE, r7	; (r7_priv) = ptr to SH3 control registers
	mov	#h'A0000000, r2		; (r2) = un-cached, un-mapped region base
	mov	#_SH3Init, r1
	mov	#_KStack, r15
	or	r2, r15			; (r15) = un-cached stack
	or	r2, r1			; (r1) = un-cached destination

	mov	#SH_CPU, r4		; (r4) = processor type
	mov	#ExceptionBase, r3	; (r3) = kernel exception handlers
	jsr	@r1			; perform general SH3 initialization
	ldc	r3, VBR			; switch to kernel's exception handlers

; Switch stack to cached, un-mapped region.
	mov	#_KStack, r15		; switch to normal kernel stack

; Load new status register with:
;	kernel mode,
;	excpetions enabled,
;	register bank 0,
;	interrupts un-masked.

	mov	#SH3CTL_BASE, r7	; (r7_priv) = ptr to SH3 control registers
	mov	#PR_B0_IE, r1
	mov	#_KernelInit, r8
	ldc	r1, SR			; (SR) = privileged, bank 0, unblocked
	jsr	@r8
	nop
	bra	resched
	mov	#0, r14			; no current thread
	.endf

	.PAGE
;++
; The following code is never executed. Its purpose is to support unwinding
; through the call to the exception dispatcher.
;--
	NESTED_ENTRY APICall
	sts.l	pr, @-r15
	add	#-24, r15
	PROLOG_END

	.PAGE
; 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)

	.org	h'100
	mov	@(EXPEVT,r7), r0	; (r0) = exception code
	mov	#h'e0, r1		; (r1) = address error load/excecute code
	cmp/eq	r1, r0
	bf/s	geh30			; not an address error,
	or	#h'20, r0		; turn TLB load into 0x60 instead of 0x40

; Address error on load or execute: check if system call. System calls are generated as
; a jump to an odd address at the high end of the address space.

	mov	#FIRST_METHOD, r1
	stc	SPC, r0
	mov	#API_MAX, r3		; (r3) = lower bound of API addresses
	tst	#1, r0
	bt	geh35			; SPC even: not a system call
	cmp/hs	r3, r0			; 'T' set iff SPC >= API_MAX
	bf	geh35			; address is outside of API range
	sub	r1, r0
	shar	r0			; (r0) = method index
	stc	SSR, r2			; (r2) = previous status
	mov	#PR_B0_IE, r1
	ldc	r0, r3_user		; pass method index
	ldc	r2, r2_user		; pass previous mode
	ldc	r1, SR			; (SR) = privileged, bank 0, unblocked

; Interrupts and preemption enabled but executing in kernel mode. Process system call or
; return.
;
;	(r2) = previous status
;	(r3) = iMethod
;	(r0) = possible return value
;	(r4-r7) = first four function arguments

	mov	#SYSCALL_RETURN, r1
	mov.l	r1, @-r15		; space for "extra info"

	shlr16	r2
	shlr8	r2			; (r2) = old status >> 24
	mov	#h'40, r1
	and	r1, r2			; (r2) = thread mode
	mov	r2, @-r15		; save current thread mode

	mov	#-1, r1
	cmp/eq	r1, r3
	bt	geh20			; PSL call returning

;	Process system call. Save argument registers onto the stack.

	mov.l	r4, @(8,r15)
	mov.l	r5, @(12,r15)
	mov.l	r6, @(16,r15)
	mov.l	r7, @(20,r15)
	sts	PR, r5			; (r5) = return address (arg1)
	mov	r15, r6
	add	#8, r6			; (r6) = ptr to argument list (arg2)
	mov	#_ObjectCall, r0
	mov	r15, r4			; (r4) = pMode (arg0)
	add	#-20, r15		; make space for args
	jsr	@r0
	mov	r3, r7			; (r7) = method index (arg3)

	mov.l	@(20,r15), r2		; (r2) = thread's execution mode
	mov.l	@(28,r15), r4		;\				;
	mov.l	@(32,r15), r5		; \				;
	mov.l	@(36,r15), r6		;  > reload function arguments	;
	mov.l	@(40,r15), r7		; /				;

; Dispatch system call.
;
;	(r0) = API function address
;	(r2) = mode to dispatch API call in
;	(r4-r7) = first 4 API arguments

	mov	#SYSCALL_RETURN, r3
	tst	r2, r2
	bf/s	geh19			; invoke API function in kernel mode
	add	#28, r15		; clear ObjectCall parameters from the stack
	lds	r3, PR			; (pr) = PSL call return

; Continue thread in user mode. This may be either an API call or
; an API return.
;
;	(r0) = address to continue at
;	(r3) = API return value (if returning)

geh15:	mov	#PR_B0_BK, r1
	ldc	r1, SR			; bank 0, exceptions blocked
	ldc	r0, SPC

	; handle fpu
	.aif SH_CPU eq h'40
	mov #_KData+g_CurFPUOwner, r1
	mov @r1, r1
	mov #_KData+pCurThd, r0
	mov @r0, r0
	cmp/eq r0,r1
	bt geh16
	mov #h'8000, r1
	or r1, r2
    .aelse
    ;  SH3. Check for DSP owner in case of SH3DSP (else CurDSPOwner == 0)
    mov     #_KData+g_CurDSPOwner, r1
    mov     @r1, r1
    mov     #_KData+pCurThd, r0
    mov     @r0, r0
    cmp/eq  r0, r1
    bf      geh16
    mov     #h'1000, r1             ; set DSP enable (bit 12)
    or      r1, r2
	.aendi
geh16:

	ldc	r2, SSR
	rte
	mov	r3, r0			; (r0) = possible API return value
	.nopool

; Invoke API function in kernel mode.
;
;	(r0) = function address
;	(r4-r7) = first 4 api arguments

geh19:
	jsr	@r0
	nop
  ALTERNATE_ENTRY _APICallReturn
	mov	#h'40, r2		; (r2) = KERNEL_MODE
	mov.l	r2, @-r15		; "extra info"
	mov.l	r2, @-r15		; (TOS) = previous mode

; The exception PC is SYSCALL_RETURN. Restore the thread's access key,
; ASID and return to the original caller.
;
;	(r2) = previous status
;	(r0) = return value
;	(TOS) = previous mode
;	(TOS+4) = space for "extra info"

	.align	4
geh20:
	mov	#_ServerCallReturn, r1
	mov	r15, r4			; (r4) = pMode (arg0)
	mov.l	r0, @-r15		; save return value
	jsr	@r1
	add	#-16, r15		; make room for argument spill area

	mov.l	@(20,r15), r2		; (r2) = mode to return to
	mov.l	@(16,r15), r3		; (r3) = API return value
	tst	r2, r2
	bt/s	geh15			; return to user mode
	add	#28, r15		; clear parameters from the stack
	jmp	@r0
	mov	r3, r0			; (r0) = API return value
  	.endf

;++
; The following code is never executed. Its purpose is to support unwinding
; through the call to the exception dispatcher.
;--
	NESTED_ENTRY GeneralException
	;;add	#CtxR8-CtxSizeof, r14		; (r14) = ptr to CtxR8
	mov.l	r14, @(CtxR14-CtxR8,r14)	; save R14
	mov.l	r15, @(CtxR15-CtxR8,r14)	; save stack pointer
	stc	SSR, r1
	mov.l	r1, @(CtxPsr-CtxR8,r14)		; save processor status
	stc	SPC, r1
	mov.l	r1, @(CtxFir-CtxR8,r14)		; save original PC
	add	#-CtxR8, r14			; (r14) = ptr to
	sts	PR, r1
	mov.l	r1, @(CtxPR,r14)
	add	#-THREAD_CONTEXT_OFFSET, r14
	PROLOG_END

⌨️ 快捷键说明

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