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

📄 entry.s

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 S
📖 第 1 页 / 共 3 页
字号:
	bne	_reschedule	nop	;; see if we need to run signal checks (important that r9 is intact here)	test.d	[$r0+LTASK_SIGPENDING]	bne	_signal_return	nop	_Rexit:	;; this epilogue MUST match the prologues in multiple_interrupt, irq.h and ptregs.h	pop	$r10		; frametype	bne	_RBFexit	; was not CRIS_FRAME_NORMAL, handle otherwise	addq	4, $sp		; skip orig_r10, in delayslot	movem	[$sp+], $r13	; registers r0-r13	pop	$mof		; multiply overflow register 	pop	$dccr		; condition codes	pop	$srp		; subroutine return pointer	;; now we have a 4-word SBFS frame which we do not want to restore	;; using RBF since it was not stacked with SBFS. instead we would like to	;; just get the PC value to restart it with, and skip the rest of	;; the frame.	;; Also notice that it's important to use instructions here that	;; keep the interrupts disabled (since we've already popped DCCR)	move	[$sp=$sp+16], $p8; pop the SBFS frame from the sp	jmpu	[$sp-16]	; return through the irp field in the sbfs frame_RBFexit:	movem	[$sp+], $r13	; registers r0-r13, in delay slot	pop	$mof		; multiply overflow register 	pop	$dccr		; condition codes	pop	$srp		; subroutine return pointer	rbf	[$sp+]		; return by popping the CPU status_tracesys:	;; this first invocation of syscall_trace _requires_ that	;; LR10 in the frame contains -ENOSYS (as is set in the beginning	;; of system_call).	jsr	syscall_trace	;; now we should more or less do the same things as in the system_call	;; but since our argument regs got clobbered during syscall_trace and	;; because syscall_trace might want to alter them, we need to reload them	;; from the stack-frame as we use them.	;; check for sanity in the requested syscall number	move.d	[$sp+LR9], $r9	movs.w	-ENOSYS, $r10	cmpu.w	NR_syscalls, $r9		bcc	1f	lslq	2, $r9		;  multiply by 4, in the delay slot	;; read the system call vector entry into r9		move.d	[$r9+sys_call_table], $r9	;; restore r10, r11, r12, r13, mof and srp into the needed registers	move.d	[$sp+LORIG_R10], $r10  ; LR10 is already filled with -ENOSYS.	move.d	[$sp+LR11],      $r11	move.d	[$sp+LR12],      $r12	move.d	[$sp+LR13],      $r13	move	[$sp+LMOF],      $mof	move	[$sp+LSRP],      $srp	;; as a bonus 7th parameter, we give the location on the stack	;; of the register structure itself. some syscalls need this.	push	$sp		;; the fifth and sixth parameters needs to be put on the stack for	;; the system call to find them	push	$srp	push	$mof	jsr	$r9		; actually call the system-call	addq	3*4, $sp	; pop the srp, mof and regs parameters1:	move.d	$r10, [$sp+LR10]; save the return value	;; second call of syscall_trace, to let it grab the results			jsr	syscall_trace	moveq	1, $r9		; "parameter" to ret_from_sys_call to show it was a sys call	ba	ret_from_sys_call	nop			;; resume performs the actual task-switching, by switching stack pointers	;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct	;; returns old current in r10	;;	;; TODO:  see the i386 version. The switch_to which calls resume in our version	;;        could really be an inline asm of this.resume:		push	$srp		         ; we keep the old/new PC on the stack 	add.d	$r12, $r10		 ; r10 = current tasks tss	move	$dccr, [$r10+LTHREAD_DCCR] ; save irq enable state	di	move	$usp, [$r10+LTHREAD_USP] ; save user-mode stackpointer		;; See copy_thread for the reason why register R9 is saved.	subq	10*4, $sp	movem	$r9, [$sp]		 ; save non-scratch registers and R9.		move.d	$sp, [$r10+LTHREAD_KSP]	 ; save the kernel stack pointer for the old task	move.d	$sp, $r10		 ; return last running task in r10	and.d   -8192, $r10	         ; get task ptr from stackpointer	add.d	$r12, $r11		 ; find the new tasks tss	move.d	[$r11+LTHREAD_KSP], $sp	 ; switch into the new stackframe by restoring kernel sp	movem	[$sp+], $r9		 ; restore non-scratch registers and R9.	move	[$r11+LTHREAD_USP], $usp ; restore user-mode stackpointer		move	[$r11+LTHREAD_DCCR], $dccr ; restore irq enable status	jump	[$sp+]		         ; restore PC	;; This is the MMU bus fault handler.	;; It needs to stack the CPU status and overall is different	;; from the other interrupt handlers.mmu_bus_fault:		sbfs	[$sp=$sp-16]	; push the internal CPU status	;; the first longword in the sbfs frame was the interrupted PC	;; which fits nicely with the "IRP" slot in pt_regs normally used to	;; contain the return address. used by Oops to print kernel errors..	push	$srp		; make a stackframe similar to pt_regs	push	$dccr	push	$mof	di	subq	14*4, $sp	movem	$r13, [$sp]	push	$r10		; dummy orig_r10	moveq	1, $r10	push	$r10		; frametype == 1, BUSFAULT frame type	move.d	$sp, $r10	; pt_regs argument to handle_mmu_bus_fault			jsr	handle_mmu_bus_fault  ; in arch/cris/mm/fault.c	;; now we need to return through the normal path, we cannot just	;; do the RBFexit since we might have killed off the running	;; process due to a SEGV, scheduled due to a page blocking or	;; whatever.	moveq	0, $r9		; busfault is equivalent to an irq			ba	ret_from_intr	nop			;; special handlers for breakpoint and NMI#if 0			hwbreakpoint:	push	$dccr	di	push	$r10	push	$r11	push	$r12	push	$r13	clearf	b	move	$brp,$r11	move.d	[hw_bp_msg],$r10	jsr	printk	setf	b	pop	$r13	pop	$r12	pop	$r11	pop	$r10	pop	$dccr	retb	nop#elsehwbreakpoint:	push	$dccr	di#if 1	push	$r10	push	$r11	move.d	[hw_bp_trig_ptr],$r10	move.d	[$r10],$r11	cmp.d	42,$r11	beq	1f	nop	move	$brp,$r11	move.d	$r11,[$r10+]	move.d	$r10,[hw_bp_trig_ptr]1:	pop	$r11	pop	$r10#endif	pop	$dccr	retb	nop#endif	IRQ1_interrupt:#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM);; If we receive a watchdog interrupt while it is not expected, then set;; up a canonical frame and dump register contents before dying.	;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!	move	$brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame	push	$srp	push	$dccr	push	$mof	di	subq	14*4, $sp	movem	$r13, [$sp]	push	$r10		; push orig_r10	clear.d [$sp=$sp-4]	; frametype == 0, normal frame;; We don't check that we actually were bit by the watchdog as opposed to;; an external NMI, since there is currently no handler for external NMI.;; Check if we're waiting for reset to happen, as signalled by;; hard_reset_now setting cause_of_death to a magic value.  If so, just;; get stuck until reset happens.	.comm	cause_of_death, 4	;; Don't declare this anywhere.	move.d	[cause_of_death], $r10	cmp.d	0xbedead, $r10_killed_by_death:	beq	_killed_by_death	nop;; We'll see this in ksymoops dumps.Watchdog_bite:#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY	;; We just restart the watchdog here to be sure we dont get	;; hit while printing the watchdogmsg below	;; This restart is compatible with the rest of the C-code, so	;; the C-code can keep restarting the watchdog after this point.	;; The non-NICE_DOGGY code below though, disables the possibility	;; to restart since it changes the watchdog key, to avoid any	;; buggy loops etc. keeping the watchdog alive after this.	jsr	reset_watchdog#else;; We need to extend the 3.3ms after the NMI at watchdog bite, so we have;; time for an oops-dump over a 115k2 serial wire.  Another 100ms should do.;; Change the watchdog key to an arbitrary 3-bit value and restart the;; watchdog.#define WD_INIT 2	moveq	  IO_FIELD (R_WATCHDOG, key, WD_INIT), $r10	move.d	R_WATCHDOG, $r11	move.d	$r10, [$r11]	moveq	  IO_FIELD (R_WATCHDOG, key,				\			    IO_EXTRACT (R_WATCHDOG, key,		\					IO_MASK (R_WATCHDOG, key))	\			    ^ WD_INIT)					\		| IO_STATE (R_WATCHDOG, enable, start), $r10	move.d	$r10, [$r11]#endif	;; Note that we don't do "setf m" here (or after two necessary NOPs),;; since *not* doing that saves us from re-entrancy checks.  We don't want;; to get here again due to possible subsequent NMIs; we want the watchdog;; to reset us.	move.d	_watchdogmsg,$r10	jsr	printk	move.d	$sp, $r10	jsr	watchdog_bite_hook;; This nop is here so we see the "Watchdog_bite" label in ksymoops dumps;; rather than "spurious_interrupt".	nop;; At this point we drop down into spurious_interrupt, which will do a;; hard reset.	.section .rodata,"a"_watchdogmsg:	.ascii	"Oops: bitten by watchdog\n\0"	.previous#endif /* CONFIG_ETRAX_WATCHDOG and not CONFIG_SVINTO_SIM */spurious_interrupt:		di	jump hard_reset_now	;; this handles the case when multiple interrupts arrive at the same time	;; we jump to the first set interrupt bit in a priority fashion	;; the hardware will call the unserved interrupts after the handler finishes	multiple_interrupt:	;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!	move	$irp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame	push	$srp	push	$dccr	push	$mof	di	subq	14*4, $sp	movem	$r13, [$sp]	push	$r10		; push orig_r10	clear.d [$sp=$sp-4]	; frametype == 0, normal frame		move.d	irq_shortcuts + 8, $r1	moveq	2, $r2		; first bit we care about is the timer0 irq	move.d	[R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq1:		btst	$r2, $r0	; check for the irq given by bit r2	bmi	_do_shortcut	; actually do the shortcut	nop	addq	1, $r2		; next vector bit	addq	4, $r1		; next vector	cmp.b	32, $r2	bne	1b	; process all irq's up to and including number 31	nop		;; strange, we didn't get any set vector bits.. oh well, just return		ba	_Rexit	nop_do_shortcut:	test.d	[$r1]	beq	_Rexit	nop	jump	[$r1]		; jump to the irq handlers shortcutdo_sigtrap:	;; 	;; SIGTRAP the process that executed the break instruction.	;; Make a frame that Rexit in entry.S expects.	;;	move	$brp, [$sp=$sp-16]	; Push BRP while faking a cpu status record.	push	$srp			; Push subroutine return pointer.	push	$dccr			; Push condition codes.	push	$mof			; Push multiply overflow reg.	di				; Need to disable irq's at this point.	subq	14*4, $sp		; Make room for r0-r13.	movem	$r13, [$sp]		; Push the r0-r13 registers.	push	$r10			; Push orig_r10.	clear.d	[$sp=$sp-4]		; Frametype - this is a normal stackframe.

⌨️ 快捷键说明

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