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

📄 vectors.s

📁 开放源码实时操作系统源码.
💻 S
📖 第 1 页 / 共 2 页
字号:
	
	pusha			# save registers
	hal_fpu_push_int	# save FPU state

#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || \
    defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) || \
    defined(CYGPKG_PROFILE_GPROF)
	# Save the context just to be able to set a breakpoint
	# when we have a CTRL-C
	.extern hal_saved_interrupt_state
	movl %esp,hal_saved_interrupt_state
#endif

#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \
    !defined(CYGPKG_HAL_SMP_SUPPORT)
	# Increment scheduler lock
	.extern cyg_scheduler_sched_lock
	incl	cyg_scheduler_sched_lock
#endif

	movl	%esp,%ebp			# EBP = copy of ESP
	
        # adjust ESP by 16 for the state stored before the pusha
        add     $16,i386reg_esp(%esp)
		
	hal_to_intstack
		
	hal_fpu_push_int_annex			# save extra FPU state
	
#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING

	# If we are allowing nested interrupts, restore the flags pushed
	# by the hardware when this interrupt was taken.
	
	movl	i386reg_eflags(%ebp), %eax
	btrl	$8,%eax			# Clear TF bit
	pushl	%eax
	popfl
#endif

#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)

	# Call cyg_instrument to record that this interrupt is being raised.

	movl	i386reg_vector(%ebp), %ecx # vector number from saved state
	movl	%ecx,%edi		# EDI = copy of vector
	subl	$0x20,%edi		# EDI = interrupt table offset
			
	pushl	%edi			# arg3 = interrupt number
	pushl	%ecx			# arg2 = vector number
	pushl	$0x0301			# arg1 = type = INTR.RAISE

	call	cyg_instrument		# call instrument function
	add	$12,%esp		# skip arguments
#endif
	
	# Call hal_interrupt_handlers[vector](vector, cyg_hal_interrupt_data[vector])
	
	movl	i386reg_vector(%ebp), %ecx # vector number from saved state
	movl	%ecx,%edi		# EDI = copy of vector
	subl	$0x20,%edi		# EDI = interrupt table offset
	movl	$hal_interrupt_handlers, %ebx
	movl	(%ebx, %edi, 4), %edx	# EDX = interrupt routine
	movl	$hal_interrupt_data, %ebx
	movl	(%ebx, %edi, 4), %eax	# EAX = interrupt data
	pushl	%eax			# arg2 = data
	pushl	%ecx			# arg1 = vector
	call	*%edx			# EAX = return value, needed for interrupt_end()
	addl	$8,%esp			# pop args

	# At this point:
	# EAX = ISR return code (returned by call)
	# EDI = ISR table offset (saved across call)
	# EBP = State pointer (saved across call)

	hal_fpu_pop_int_annex		# Pop any saved interrupt state
		
	# 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.
	
	hal_from_intstack	
			
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT

	# Call interrupt_end(r, cyg_hal_interrupt_objects[vector], regs)
	# - r is the return value from the ISR
	# - regs points to saved CPU context

	movl	$hal_interrupt_objects, %ebx
	movl	(%ebx, %edi, 4), %edx	# EDX = interrupt object ptr
	pushl	%ebp			# arg3 = ptr to saved registers
	pushl	%edx			# arg2 = object
	pushl	%eax			# arg1 = ISR return code
	call	interrupt_end		# Call it
	addl	$12, %esp		# pop args
	
#endif

	# Now pull saved state from stack and return to 
	# what thread was originally doing.
	
	hal_fpu_pop_int			# restore FPU state
	popa				# restore all our registers.
	addl	$4, %esp		# skip the vector number.
	iret				# and return to the thread.

#==============================================================================
## Execute pending DSRs on the interrupt stack with interrupts enabled.
## Note: this can only be called from code running on a thread stack so we 
## can always just jump to the interrupt stack without looking.

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK

	.extern cyg_interrupt_call_pending_DSRs
	.global hal_interrupt_stack_call_pending_DSRs
	
hal_interrupt_stack_call_pending_DSRs:	

	pushl	%ebp			# save EBP
	pushfl				# save flags
	movl	%esp,%ebp		# EBP = saved SP

	hal_load_istack	%edx		# load new SP into EDX
	movl	%edx,%esp		# move it to ESP
	
	sti				# Enable interrupts

	# Call back to kernel to run DSRs
	call	cyg_interrupt_call_pending_DSRs

	# On return EBP will still contain the old ESP since
	# it is a callee saved register.
	
	movl	%ebp,%esp		# restore saved SP

	# Now merge the original IF bit into the current
	# EFLAGS. 
	
	popl	%eax			# EAX = saved flags
	pushfl				# 0(%esp) = current flags
	btrl	$9,0(%esp)		# clear IF bit in current flags
	andl	$0x00000200,%eax	# isolate saved IF bit
	orl	%eax,0(%esp)		# OR it in to the saved flags
	popfl				# restore flags
	
	popl	%ebp			# restore EBP
	ret				# and return
	
#endif				

#==============================================================================
# FPU lazy state switch VSR
# This is invoked via hardware exception 7 (FPU unavailable) as a result of
# setting the TS bit in CR0 whenever we context switch. If we discover here
# that a different context from the current owner of the FPU has attempted
# a floating point operation, we save the old context and load the new before 
# allowing it to proceed.
	
#ifdef CYGHWR_HAL_I386_FPU_SWITCH_LAZY		

#ifndef CYGPKG_HAL_SMP_CPU_MAX
#define CYGPKG_HAL_SMP_CPU_MAX 1
#endif
				
	.data
	.global cyg_hal_fpustate_owner
cyg_hal_fpustate_owner:
	.rept	CYGPKG_HAL_SMP_CPU_MAX
	.long	0				# pointer to FPU owning context
	.endr
	.global cyg_hal_fpustate_current	
cyg_hal_fpustate_current:	
	.rept	CYGPKG_HAL_SMP_CPU_MAX
	.long	0				# pointer to current threads FPU context
	.endr
			
	.text	
__fpu_switch_vsr:

	## We enter here with the CPU state still in the registers and:
	##  0(%esp)	vector number pushed by trampoline
	##  4(%esp)	PC pushed by hardware
	##  8(%esp)	CS pushed by hardware
	## 12(%esp)	EFLAGS pushed by hardware
	
	clts					# clear CR0:TS bit
	pusha					# save all regs

	hal_smp_cpu %ecx			# ECX = CPU id
	movl	$cyg_hal_fpustate_owner,%eax	# EAX = FPU context owner table
	leal	0(%eax,%ecx,4),%esi		# ESI = address of owner pointer
	movl	$cyg_hal_fpustate_current,%ebx	# EBX = current threads context table
	leal	0(%ebx,%ecx,4),%edi		# EDI = address of context pointer
	movl	0(%esi),%eax			# EAX = Current FPU context owner
	movl	0(%edi),%ebx			# EBX = Current threads FPU context
	cmpl	%ebx,%eax			# current == owner ?
	je	9f				# yes, nothing else to do
	cmpl	$0,%eax				# is FPU even in use?
	je	1f				# if not, skip save
	fnsave	i386reg_fpucontext_state(%eax)	# save FPU state
#ifdef CYGHWR_HAL_I386_PENTIUM_SSE
	# Save SIMD state.

	# FIXME. This is awfully inefficient. Need to use FXSAVE to
	# save FPU and SIMD at same time. FXSAVE requires a 16 byte
	# alignment and does not have an implicit finit as does FSAVE.

	stmxcsr	i386reg_simd_mxcsr(%eax)
	movups	%xmm0,i386reg_simd_xmm0(%eax)
	movups	%xmm1,i386reg_simd_xmm1(%eax)
	movups	%xmm2,i386reg_simd_xmm2(%eax)
	movups	%xmm3,i386reg_simd_xmm3(%eax)
	movups	%xmm4,i386reg_simd_xmm4(%eax)
	movups	%xmm5,i386reg_simd_xmm5(%eax)
	movups	%xmm6,i386reg_simd_xmm6(%eax)
	movups	%xmm7,i386reg_simd_xmm7(%eax)
#endif
	movl	$1,i386reg_fpucontext_valid(%eax) # mark valid
1:
	movl	%ebx,0(%esi)            	# Set new owner
	btl	$0,i386reg_fpucontext_valid(%ebx) # Valid state?
	jc	2f				# If yes, go to restore it
	finit					# Otherwise init FPU
#ifdef CYGHWR_HAL_I386_PENTIUM_SSE
	# FIXME. Anything needed here?
#endif
	jmp	9f				# skip restore
2:
	frstor	i386reg_fpucontext_state(%ebx)	# restore FPU state
#ifdef CYGHWR_HAL_I386_PENTIUM_SSE
	# Restore SIMD state.

	# FIXME. This is awfully inefficient. Need to use FXRSTOR to
	# restore FPU and SIMD at same time. FXRSTOR requires a 16 byte
	# alignment.

	movups	i386reg_simd_xmm0(%ebx),%xmm0
	movups	i386reg_simd_xmm1(%ebx),%xmm1
	movups	i386reg_simd_xmm2(%ebx),%xmm2
	movups	i386reg_simd_xmm3(%ebx),%xmm3
	movups	i386reg_simd_xmm4(%ebx),%xmm4
	movups	i386reg_simd_xmm5(%ebx),%xmm5
	movups	i386reg_simd_xmm6(%ebx),%xmm6
	movups	i386reg_simd_xmm7(%ebx),%xmm7
	ldmxcsr	i386reg_simd_mxcsr(%ebx)
#endif
9:
	popa					# restore all our registers.
	addl	$4, %esp			# skip the vector number.
	iret					# and return to the thread.
		
#endif

#if 0			
#==============================================================================
# Assembler swap routines
	
		
# x = CPU_swap_u16(x)
	.align	4
	.global CPU_swap_u16
CPU_swap_u16:
	xorl	%eax, %eax
	movb	4(%esp), %ah
	movb	5(%esp), %al
	ret

# x = CPU_swap_u32(x)
	.align	4
	.global CPU_swap_u32
CPU_swap_u32:
	xorl	%eax, %eax
	movb	4(%esp), %ah
	movb	5(%esp), %al
	sall	$16, %eax
	movb	6(%esp), %ah
	movb	7(%esp), %al
	ret
#endif
		
#==============================================================================
# Exception trampolines
# IDT exception gates point to short code sequences that push the vector
# number on to the stack and then indirect via the VSR table to a handler.
# 

	# Just for yuks we keep a count of the number of times each
	# vector is called.
	.bss
	.globl hal_vsr_stats
hal_vsr_stats:	
	.rept 64	// Default VSR table is 64 entries long
	.long 0
	.endr

	# When an exception which supplies an error code is generated,
	# we move the code here. 
hal_trap_error_code:
	.long 0

	.text
	
	# macro to create exception handler (no error code)
	.macro  hal_pc_exception_noerr idx
hal_pc_exception_\idx:
	movl	$0,hal_trap_error_code
	pushl	$\idx
	incl	(hal_vsr_stats+\idx*4)
	jmp	*(hal_vsr_table+\idx*4)
	.endm

	# macro to create exception handler (with error code)
	.macro  hal_pc_exception_err idx
hal_pc_exception_\idx:
	popl	hal_trap_error_code
	pushl	$\idx
	incl	(hal_vsr_stats+\idx*4)
	jmp	*(hal_vsr_table+\idx*4)
	.endm

	# Now generate all the default exception VSR trampolines.
	
	hal_pc_exception_noerr  0
	hal_pc_exception_noerr  1
	hal_pc_exception_noerr  2
	hal_pc_exception_noerr  3	
	hal_pc_exception_noerr  4
	hal_pc_exception_noerr  5	
	hal_pc_exception_noerr  6
	hal_pc_exception_noerr  7	
	hal_pc_exception_err    8
	hal_pc_exception_noerr  9	
	hal_pc_exception_err   10
	hal_pc_exception_err   11	
	hal_pc_exception_err   12
	hal_pc_exception_err   13	
	hal_pc_exception_err   14
	hal_pc_exception_noerr 15	
	hal_pc_exception_noerr 16
	hal_pc_exception_err   17	
	hal_pc_exception_noerr 18
	hal_pc_exception_noerr 19	
	hal_pc_exception_noerr 20
	hal_pc_exception_noerr 21	
	hal_pc_exception_noerr 22
	hal_pc_exception_noerr 23	
	hal_pc_exception_noerr 24
	hal_pc_exception_noerr 25	
	hal_pc_exception_noerr 26
	hal_pc_exception_noerr 27	
	hal_pc_exception_noerr 28
	hal_pc_exception_noerr 29	
	hal_pc_exception_noerr 30
	hal_pc_exception_noerr 31	

#==============================================================================
# IRQ handler trampolines


	# macro to create exception handler (no error code)
	.macro  hal_pc_irq_handler idx
hal_pc_irq_\idx:
	pushl	$\idx
	incl	(hal_vsr_stats+\idx*4)
	jmp	*(hal_vsr_table+\idx*4)
	.endm

	hal_pc_irq_handler 32
	hal_pc_irq_handler 33
	hal_pc_irq_handler 34
	hal_pc_irq_handler 35
	hal_pc_irq_handler 36
	hal_pc_irq_handler 37
	hal_pc_irq_handler 38
	hal_pc_irq_handler 39
	hal_pc_irq_handler 40
	hal_pc_irq_handler 41
	hal_pc_irq_handler 42
	hal_pc_irq_handler 43
	hal_pc_irq_handler 44
	hal_pc_irq_handler 45
	hal_pc_irq_handler 46
	hal_pc_irq_handler 47
#ifdef CYGPKG_HAL_SMP_SUPPORT

	# Extra interrupt vectors for IOAPIc routed PCI and
	# other interrupt sources
	hal_pc_irq_handler 48
	hal_pc_irq_handler 49
	hal_pc_irq_handler 50
	hal_pc_irq_handler 51
	hal_pc_irq_handler 52
	hal_pc_irq_handler 53
	hal_pc_irq_handler 54
	hal_pc_irq_handler 55
	hal_pc_irq_handler 56
	hal_pc_irq_handler 57
	hal_pc_irq_handler 58
	hal_pc_irq_handler 59
	hal_pc_irq_handler 60
	hal_pc_irq_handler 61
	hal_pc_irq_handler 62
	hal_pc_irq_handler 63

	# Inter-CPU interrupts start at 64
	hal_pc_irq_handler 64
	hal_pc_irq_handler 65
	hal_pc_irq_handler 66
	hal_pc_irq_handler 67
#endif		


	# default vsr entries: pop the vector code from the stack and return.
default_vsr_iret:
	add $4,%esp
	iret

	# GNUPro apps use "int $0x80" for syscalls.
        # There is no vsr table entry for this.
	.global __syscall_tramp
__syscall_tramp:
	pushl $0x80
	jmp __default_exception_vsr

#==============================================================================
# Initial and interrupt stack

#ifndef CYG_HAL_I386_INTERRUPT_STACK_DEFINED

	.bss

#ifndef CYGPKG_HAL_SMP_SUPPORT	

	.balign 16
	.global cyg_interrupt_stack_base
cyg_interrupt_stack_base:
__interrupt_stack_base:
	.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
	.byte 0
	.endr
	.balign 16
	.global cyg_interrupt_stack
cyg_interrupt_stack:
__interrupt_stack:
        
        .long   0,0,0,0,0,0,0,0

#else // CYGPKG_HAL_SMP_SUPPORT		

__interrupt_stack_vector:
	.rept CYGPKG_HAL_SMP_CPU_MAX
	.long 0
	.endr
		
	.balign 16
	.global cyg_interrupt_stack_base
cyg_interrupt_stack_base:
__interrupt_stack_base:
__interrupt_stack_first:
	.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
	.byte 0
	.endr
	.global cyg_interrupt_stack
cyg_interrupt_stack:
__interrupt_stack:
	.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE*(CYGPKG_HAL_SMP_CPU_MAX-1)
	.byte 0
	.endr
	
#endif // CYGPKG_HAL_SMP_SUPPORT	

#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
	.global __stub_stack_base
__stub_stack_base:
	.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
	.byte 0
	.endr
	.balign 16
	.global __stub_stack
__stub_stack:
        
        .long   0,0,0,0,0,0,0,0
#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS

	
#endif // CYG_HAL_I386_INTERRUPT_STACK_DEFINED
		
#------------------------------------------------------------------------------
# end of vectors.S

⌨️ 快捷键说明

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