vectors.s

来自「eCos操作系统源码」· S 代码 · 共 1,024 行 · 第 1/2 页

S
1,024
字号
	sgpr	31,sp	# == RA	.set	at		mfhi	a0	mflo	a1	shi	a0,sp	slo	a1,sp	# K1 contains original SP	ssp	k1,sp			# store in reg dump				mfc0	t1,status	mfc0	t2,cachectrl	mvafc0	t3,epc		sw	t1,mipsreg_sr(sp)	sw	t2,mipsreg_cachectrl(sp)	sva	t3,mipsreg_pc(sp)	hal_fpu_save sp			# The machine state is now all saved on the stack.	# Load Global Pointer register.	la	gp,_gp	#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT				.extern	cyg_scheduler_sched_lock	la	v0,cyg_scheduler_sched_lock	lw	a0,0(v0)	addi	a0,a0,1	sw	a0,0(v0)#endif	move	s0,sp				# save pointer to saved state#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK		la	a0,__interrupt_stack		# a0 = stack top	la	a1,__interrupt_stack_base	# a1 = stack base	sub	a3,sp,a1			# a3 = sp - base	bltz	a3,1f				# not on istack if < 0 	nop					# delay slot	sub	t0,a0,sp			# t0 = top - sp	bgtz	t0,8f				# already on istack if > 0 	nop					# delay slot1:		move	sp,a0				# switch to istack8:	addi	sp,sp,-8			# space for old SP 						# (8 to keep dword alignment!)	sw	s0,0(sp)			# save old SP on stack	#endif						subu	sp,sp,mips_stack_frame_size	# make a null frame		# Need to set up back pointers etc. ???	# Decode external interrupt via interrupt controller	hal_intc_decode	s2	# Here, s2 contains the number of the interrupt being serviced,	# we need to derive from that the vector number to call in the ISR	# table.		hal_intc_translate s2,s1		# Here s1 is the number of the vector to be called and s2 is	# the number of the interrupt being serviced. 	hal_diag_intr_start		#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)	# Call cyg_instrument to record that this interrupt is being raised.			li	a0,0x0301			# a0 = type = INTR,RAISE	move	a1,s1				# a1 = vector number	jal	cyg_instrument			# call instrument function	 move	a2,s2				# a2 = interrupt number#endif#if defined(CYGDBG_HAL_MIPS_DEBUG_GDB_CTRLC_SUPPORT)	# If we are supporting Ctrl-C interrupts from GDB, we must squirrel	# away a pointer to the save interrupt state here so that we can	# plant a breakpoint at some later time.		.extern	hal_saved_interrupt_state	la	v0,hal_saved_interrupt_state	sw	s0,0(v0)	#endif		sll	s1,s1,2				# s1 = byte offset of vector	hal_cpu_except_enable			# reenable exceptions				la	t2,hal_interrupt_handlers	# handler table	add	t2,t2,s1			# address of ISR ptr	lw	t2,0(t2)			# ISR pointer	la	a1,hal_interrupt_data		# data table	add	a1,a1,s1			# address of data ptr	lw	a1,0(a1)			# Data pointer	move	a0,s2				# pass interrupt number	move	a2,s0				# pass saved interrupt state	jalr	t2				# call ISR via t2	nop					# (delay slot)#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK	# If we are returning from the last nested interrupt, move back	# to the thread stack. interrupt_end() must be called on the	# thread stack since it potentially causes a context switch.	# Since we have arranged for the top of stack location to	# contain the sp we need to go back to here, just pop it off	# and put it in SP.		lw	sp,mips_stack_frame_size(sp)	# sp = *sp	subu	sp,sp,mips_stack_frame_size	# make a null frame		#endif	#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT	# We only need to call _interrupt_end() when there is a kernel	# present to do any tidying up.		# On return v0 bit 1 will indicate whether a DSR is	# to be posted. Pass this together with a pointer to	# the interrupt object we have just used to the	# interrupt tidy up routine.	# Note that s0, s1 and s2 are defined to be preserved across	# calls by the calling convention, so they still contain	# the register dump, the vector offset and the interrupt number	# respectively.	move	s2,v0			la	a1,hal_interrupt_objects	# interrupt object table	add	a1,a1,s1			# address of object ptr	lw	a1,0(a1)			# a1 = object ptr	move	a2,s0				# arg3 = saved register dump		.extern	interrupt_end	jal	interrupt_end			# call into C to finish off 	 move	a0,v0				# put ISR result in arg0		move	v0,s2				# return value from isr#endif				restore_state:#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)	move	k0,v0#endif	# All done, restore CPU state and continue	addi	sp,sp,mips_stack_frame_size	# retrieve CPU state ptr	# Disable interrupts again while we restore state. 	hal_cpu_int_disable	hal_diag_restore	hal_fpu_load sp	lw	t0,mipsreg_cachectrl(sp)	lhi	t1,sp	llo	t2,sp	mtc0	t0,cachectrl	mthi	t1	mtlo	t2	# load GPRs	.set	noat#	lgpr	0,sp	lgpr	1,sp	lgpr	2,sp	lgpr	3,sp	lgpr	4,sp	lgpr	5,sp	lgpr	6,sp	lgpr	7,sp	lgpr	8,sp	lgpr	9,sp	lgpr	10,sp	lgpr	11,sp	lgpr	12,sp	lgpr	13,sp	lgpr	14,sp	lgpr	15,sp	lgpr	16,sp	lgpr	17,sp	lgpr	18,sp	lgpr	19,sp	lgpr	20,sp	lgpr	21,sp	lgpr	22,sp	lgpr	23,sp	lgpr	24,sp	lgpr	25,sp#	lgpr	26,sp	# == K0#	lgpr	27,sp	# == K1	lgpr	28,sp	# == GP#	lgpr	29,sp	# == SP	lgpr	30,sp	# == FP	lgpr	31,sp	# == RA	.set	at#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)        # If we have a Cygmon that wants to listen to network interrupts, then        # the return code from the earlier call to hal_default_isr() will        # have been negative to indicate this. So we jump into Cygmon here        # because Cygmon requires the processor state to be the same as when        # the interrupt was taken, but with k0 as the exception number.        	bgez	k0,1f	nop	# Check for new cygmon	sw	k0,(mipsreg_regs+26*4)(sp)	# save k0	la	k1,0x80000100 + 41*4		# New cygmon "magic" id	lw	k1,0(k1)	lui	k0,0x55aa	ori	k0,0x4321	bne	k0,k1,1f				# Need to let cygmon handle this	la	k1,0x80000100 + 39*4		# stub entry vector	lw	k0,(mipsreg_regs+26*4)(sp)	# restore k0	lw	k1,0(k1)	lw	sp,(mipsreg_regs+29*4)(sp)	# restore SP	sll	k0,1				# clear bit 31.	jr	k1        srl	k0,1    1:#endif	lw	k1,mipsreg_sr(sp)		# K1 = saved SR#if 0 < CYGINT_HAL_MIPS_INTERRUPT_RETURN_KEEP_SR_IM	# Keep the current settings of the IM[7:0] bits within the status	# register.  These may be used as interrupt masks, so if an ISR or	# DSR masks interrupts they must be preserved.	# If they are not used, then this does no harm.	ori	k0,zero,0xff00	nor	k0,k0,k0			# 0xffff00ff	and	k1,k1,k0			# all interrupts disabled	mfc0	k0,status			# V0 = current SR	nop	nop	andi	k0,k0,0xff00			# preserve interrupt set	or	k1,k1,k0			# insert into "saved SR"#endif // 0 < CYGINT_HAL_MIPS_INTERRUPT_RETURN_KEEP_SR_IM	lva	k0,mipsreg_pc(sp)		# K0 = return PC	lsp	sp,sp				# load SP	# Invoke CPU specific mechanism for returning from this	# exception		hal_cpu_eret k0,k1		FUNC_END(__default_interrupt_vsr)	hal_intc_decode_data##-----------------------------------------------------------------------------## Execute pending DSRs on the interrupt stack with interrupts enabled.## Note: this can only be called from code running on a thread stack	#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK	.extern cyg_interrupt_call_pending_DSRsFUNC_START(hal_interrupt_stack_call_pending_DSRs)	mfc0	t0,status			# get status register value	la	v0,__interrupt_stack		# v0 = interrupt stack	move	v1,sp				# v1 = original stack ptr	move	sp,v0				# sp = interrupt stack	addi	sp,sp,-32			# make a null frame	sw	v1,16(sp)			# save old sp	sw	ra,20(sp)			# save old ra	sw	t0,24(sp)			# save old sr	hal_cpu_int_enable	jal	cyg_interrupt_call_pending_DSRs	# call back to kernel	nop	lw	a0,24(sp)			# get status reg	hal_cpu_int_merge a0			# merge with current SR		lw	ra,20(sp)			# restore ra	lw	sp,16(sp)			# restore sp	jr	ra				# go back	nop					# delay slot	FUNC_END(hal_interrupt_stack_call_pending_DSRs)	#endif		##-----------------------------------------------------------------------------## Short circuit in case any code tries to use "__gccmain()"FUNC_START(__gccmain)	jr	ra	nopFUNC_END(__gccmain)##-----------------------------------------------------------------------------## Switch to a new stack.## This is used in RedBoot to allow code to execute in a different## stack context.FUNC_START(hal_program_new_stack)	# Arguments are:	# a0 = function to call	# a1 = stack pointer to use	move	v1,sp				# v1 = original stack ptr	move	sp,a1				# sp = new stack	addi	sp,sp,-32			# make a null frame	sva	v1,8(sp)			# save old sp	sva	ra,16(sp)			# save old ra	jalr	a0				# call function	 nop	lva	ra,16(sp)			# restore ra	lva	sp,8(sp)			# restore sp	jr	ra				# go back	 nop					# delay slot	FUNC_END(hal_program_new_stack)		##-----------------------------------------------------------------------------## hal_zero_bss## Zero bss. Done in assembler to be optimal rather than using memset,## which would risk zeroing bss while using it.        FUNC_START(hal_zero_bss)#ifdef CYGHWR_HAL_MIPS_64BIT#define STORE_OP        sd#define BLOCK_SHIFT     6#else#define STORE_OP        sw#define BLOCK_SHIFT     5#endif        la      a0,__bss_start          # start of bss        la      a1,__bss_end            # end of bss        andi    a2,a0,mips_regsize-1    # is bss aligned?        bne     a2,zero,1f              # skip word copy        nop                # loop with 8 stores per loop        subu            a3,a1,a0                # get length        srl             a3,a3,BLOCK_SHIFT       # get number of blocks        sll             a3,a3,BLOCK_SHIFT       # get length of blocks        addu            a3,a0,a3                # get end addr of blocks2:      STORE_OP        zero,(mips_regsize*0)(a0)        STORE_OP        zero,(mips_regsize*1)(a0)        STORE_OP        zero,(mips_regsize*2)(a0)        STORE_OP        zero,(mips_regsize*3)(a0)        STORE_OP        zero,(mips_regsize*4)(a0)        STORE_OP        zero,(mips_regsize*5)(a0)        STORE_OP        zero,(mips_regsize*6)(a0)        STORE_OP        zero,(mips_regsize*7)(a0)        addu            a0,a0,mips_regsize*8    # next addr        bne             a3,a0,2b                # to next store        nop        # If length is a multiple of block size then we        # are done and need to skip the byte loop        beq		a1,a0,3f        nop	        # finish 1 byte at a time1:      sb      zero,0(a0)              # zero memory        addiu   a0,a0,1                 # next addr        bne     a0,a1,1b                # to next store        nop3:      jr      ra        nopFUNC_END(hal_zero_bss)        ##-----------------------------------------------------------------------------## VSR springboard for break instruction exceptions## Both GCC and GDB use break instructions. GCC for division-by-zero## notification and GDB for program-flow breakpoints. This springboard## looks for the d-b-z kind and directs them to another vector so libc## can handle these without affecting the debugger.	FUNC_START(__break_vsr_springboard)	mvafc0	k0,epc	mfc0	k1,cause	bltzl   k1,1f	addi    k0,k0,4                 # delay slot (only executed if BD set)1:	lw      k1,0(k0)                # get break instruction	la      k0,0x0007000d           # break 0x7 used by GCC for d-b-z	bne     k0,k1,2f	nop	ori     k0,$0,14*4              # CYGNUM_HAL_VECTOR_DIV_BY_ZERO	la	k1,hal_vsr_table	# address of VSR table	add	k1,k1,k0		# offset of VSR entry	lw	k1,0(k1)		# k1 = pointer to VSR	jr	k1			# go there	nop				# (delay slot)2:	ori     k0,$0,9*4               # CYGNUM_HAL_VECTOR_BREAKPOINT	j       __default_exception_vsr	nop				# (delay slot)FUNC_END(__break_vsr_springboard)##-----------------------------------------------------------------------------## Interrupt Stack.## Used during intialization and for executing ISRs.		.bss	.balign 16	.global cyg_interrupt_stack_basecyg_interrupt_stack_base:__interrupt_stack_base:	.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE	.byte 0	.endr	.balign 16	.global cyg_interrupt_stackcyg_interrupt_stack:__interrupt_stack:	.long	0,0,0,0,0,0,0,0	##-----------------------------------------------------------------------------## VSR table.## The main interrupt code indirects through here to find the VSR## to execute for each architecture defined interrupt.## This is only used for simulated targets, on real targets a fixed location VSR## table is now allocated at 0x80000100.#ifndef CYG_HAL_MIPS_VSR_TABLE_DEFINED	##	.section ".vsr_table","a"		.data				.globl	hal_vsr_tablehal_vsr_table:		.long	__default_interrupt_vsr		.rept	63	.long	__default_exception_vsr		.endr#endif		#------------------------------------------------------------------------------# Interrupt vector tables.# These tables contain the isr, data and object pointers used to deliver# interrupts to user code.# hal_interrupt_level contains the interrupt level set by # HAL_INTERRUPT_CONFIGURE().# This is a default set that provide support only for the 6 external# interrupts in the status/cause registers. Platforms or boards are expected# to define their own versions of these if they have their own interrupt mappings.#ifndef CYG_HAL_MIPS_ISR_TABLES_DEFINED		.extern hal_default_isr		.data	.globl	hal_interrupt_handlershal_interrupt_handlers:	.long	hal_default_isr	.long	hal_default_isr	.long	hal_default_isr	.long	hal_default_isr	.long	hal_default_isr	.long	hal_default_isr	.globl	hal_interrupt_datahal_interrupt_data:	.rept	6	.long	0	.endr	.globl	hal_interrupt_objectshal_interrupt_objects:	.rept	6	.long	0	.endr#endif	##-----------------------------------------------------------------------------## end of vectors.S

⌨️ 快捷键说明

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