locore.s

来自「操作系统SunOS 4.1.3版本的源码」· S 代码 · 共 1,251 行 · 第 1/2 页

S
1,251
字号
	ld	[%l3 + R_PSR], %l0	set	PSR_EF, %l5		! FPU enable bit	btst	%l5, %l0		! was the FPU enabled?	bz	1f	nop	!	! Save floating point registers and status.	! All floating point operations must be complete.	! Storing the fsr will accomplish this.	!	set	fpuregs, %g7	st	%fsr, [%g7+(32*4)]	std	%f0, [%g7+(0*4)]	std	%f2, [%g7+(2*4)]	std	%f4, [%g7+(4*4)]	std	%f6, [%g7+(6*4)]	std	%f8, [%g7+(8*4)]	std	%f10, [%g7+(10*4)]	std	%f12, [%g7+(12*4)]	std	%f14, [%g7+(14*4)]	std	%f16, [%g7+(16*4)]	std	%f18, [%g7+(18*4)]	std	%f20, [%g7+(20*4)]	std	%f22, [%g7+(22*4)]	std	%f24, [%g7+(24*4)]	std	%f26, [%g7+(26*4)]	std	%f28, [%g7+(28*4)]	std	%f30, [%g7+(30*4)]1:	set	_scb, %g1		! setup kadb tbr	mov	%g1, %tbr	nop				! tbr delay	call	_cmd	nop				! tbr delay	mov	%psr, %g1		! disable traps, goto window 0	bclr	PSR_CWP, %g1	mov	%g1, %psr	nop; nop; nop;			! psr delay	wr	%g1, PSR_ET, %psr	nop; nop; nop;			! psr delay	mov	%g0, %wim		! zero wim so that we can move around	!	! Restore fpu	!	! If there is not an fpu, we are emulating and the	! registers are already in the right place, the u area.	! If we have not modified the u area there is no problem	! If we have it is not the debuggers problem	!	sethi	%hi(_fpu_exists), %g1	ld	[%g1 + %lo(_fpu_exists)], %g1	tst	%g1			! don't bother if no fpu	bz	2f			! its already in the u area	nop	set	_regsave, %l3		! was it on?	ld	[%l3 + R_PSR], %l0	set	PSR_EF, %l5		! FPU enable bit	btst	%l5, %l0		! was the FPU enabled?	bz	2f	nop	set	fpuregs, %g7	ldd	[%g7+(0*4)], %f0	! restore registers	ldd	[%g7+(2*4)], %f2	ldd	[%g7+(4*4)], %f4	ldd	[%g7+(6*4)], %f6	ldd	[%g7+(8*4)], %f8	ldd	[%g7+(10*4)], %f10	ldd	[%g7+(12*4)], %f12	ldd	[%g7+(14*4)], %f14	ldd	[%g7+(16*4)], %f16	ldd	[%g7+(18*4)], %f18	ldd	[%g7+(20*4)], %f20	ldd	[%g7+(22*4)], %f22	ldd	[%g7+(24*4)], %f24	ldd	[%g7+(26*4)], %f26	ldd	[%g7+(28*4)], %f28	ldd	[%g7+(30*4)], %f30	ld	[%g7+(32*4)], %fsr	! restore fsr2:	set	_regsave, %g7	add	%g7, R_WINDOW, %g7	set	_nwindows,%g6	ld	[%g6], %g61:	ld	[%g7 + 0*4], %l0	! restore locals	ld	[%g7 + 1*4], %l1	ld	[%g7 + 2*4], %l2	ld	[%g7 + 3*4], %l3	ld	[%g7 + 4*4], %l4	ld	[%g7 + 5*4], %l5	ld	[%g7 + 6*4], %l6	ld	[%g7 + 7*4], %l7	ld	[%g7 + 8*4], %i0	! restore ins	ld	[%g7 + 9*4], %i1	ld	[%g7 + 10*4], %i2	ld	[%g7 + 11*4], %i3	ld	[%g7 + 12*4], %i4	ld	[%g7 + 13*4], %i5	ld	[%g7 + 14*4], %i6	ld	[%g7 + 15*4], %i7	add	%g7, WINDOWSIZE, %g7	subcc	%g6, 1, %g6		! all windows done?	bnz	1b	restore				! delay slot, increment CWP	!	! Should be back in window 0.	!	set	_regsave, %g7	ld	[%g7 + R_PC], %l1	! restore pc	ld	[%g7 + R_NPC], %l2	! restore npc	ld	[%g7 + R_WIM], %g1	mov	%g1, %wim	ld	[%g7 + R_TBR], %g1	srl	%g1, 4, %g1		! realign ...	and	%g1, 0xff, %g1		!... and mask to get trap number	set	(TRAPBRKNO | 0x80), %g2	cmp	%g1, %g2		! compare to see this is a breakpoint	bne	debugtrap		! a debugger trap return PC+1	nop! return from breakpoint trap	ld	[%g7 + R_PSR], %g1	! restore psr	mov	%g1, %psr	nop; nop; nop;			! psr delay	ld	[%g7 + R_TBR], %g1	mov	%g1, %tbr	ld	[%g7 + R_Y], %g1	mov	%g1, %y	mov	%g7, %l3		! put state ptr in local	ld	[%l3 + R_G1], %g1	! restore globals	ld	[%l3 + R_G2], %g2	ld	[%l3 + R_G3], %g3	ld	[%l3 + R_G4], %g4	ld	[%l3 + R_G5], %g5	ld	[%l3 + R_G6], %g6	ld	[%l3 + R_G7], %g7	nop	jmp	%l1			! return from trap	rett	%l2! return from debugger trapdebugtrap:	ld	[%g7 + R_PSR], %g1	! restore psr	mov	%g1, %psr	nop; nop; nop;			! psr delay	ld	[%g7 + R_TBR], %g1	mov	%g1, %tbr	ld	[%g7 + R_Y], %g1	mov	%g1, %y	mov	%g7, %l3		! put state ptr in local	ld	[%l3 + R_G1], %g1	! restore globals	ld	[%l3 + R_G2], %g2	ld	[%l3 + R_G3], %g3	ld	[%l3 + R_G4], %g4	ld	[%l3 + R_G5], %g5	ld	[%l3 + R_G6], %g6	ld	[%l3 + R_G7], %g7	jmp	%l2			! return from trap	rett	%l2 + 4LPSR = 0*4LPC = 1*4LNPC = 2*4LSP = 3*4LG1 = 4*4LG2 = 5*4LG3 = 6*4LG4 = 7*4LG5 = 8*4LG6 = 9*4LG7 = 10*4REGSIZE = 11*4/* * General debugger trap handler. * This is only used by traps that happen while the debugger is running. * It is not used for any debuggee traps. * Does overflow checking then vectors to trap handler. */sys_trap:	!	! Prepare to go to C (batten down the hatches).	! Save volatile regs.	!	sub	%fp, MINFRAME+REGSIZE, %l7 ! make room for reg save area	st	%g1, [%l7 + MINFRAME + LG1]	st	%g2, [%l7 + MINFRAME + LG2]	st	%g3, [%l7 + MINFRAME + LG3]	st	%g4, [%l7 + MINFRAME + LG4]	st	%g5, [%l7 + MINFRAME + LG5]	st	%g6, [%l7 + MINFRAME + LG6]	st	%g7, [%l7 + MINFRAME + LG7]	st	%fp, [%l7 + MINFRAME + LSP]	st	%l0, [%l7 + MINFRAME + LPSR]	st	%l1, [%l7 + MINFRAME + LPC]	st	%l2, [%l7 + MINFRAME + LNPC]	!	! Check for window overflow.	!	mov	0x01, %g1		! CWM = 0x01 << CWP	sll	%g1, %l0, %g1	mov	%wim, %l5		! get WIM	btst	%g1, %l5		! compare WIM and CWM	bz	st_have_window	nop	!	! The next window is not empty. Save it.	!	srl	%l5, 1, %g1		! WIM = %g1 = ror(WIM, 1, NW)	sll	%l5, %l6, %l5	or	%l5, %g1, %g1	save				! get into window to be saved	mov	%g1, %wim		! install new WIM	SAVE_WINDOW(%sp)	restore				! get back to original window	!	! The next window is available.	!st_have_window:	mov	%l7, %sp		! install new sp	mov	%tbr, %o0		! get trap number	bclr	PSR_PIL, %l0		! PIL = 15	bset	(15 << 8), %l0	wr	%l0, PSR_ET, %psr	! enable traps	srl	%o0, 4, %o0		! psr delay	and	%o0, 0xff, %o0	ld	[%l7 + MINFRAME + LPC], %o1	ld	[%l7 + MINFRAME + LNPC], %o2	set	_fault, %l3	cmp	%l4, 0x9	be	1f	nop	set	_level15, %l3	cmp	%l4, 0x1f		! the next 3 inst. are worthless	be	1f	nop1:		call	%l3			! call trap handler(trap number)	nop	!	! Return from trap.	!	ld	[%l7 + MINFRAME + LPSR], %l0 ! get saved psr	bclr	PSR_PIL, %l0		! PIL = 14	bset	(14 << 8), %l0	mov	%psr, %g1		! use current CWP	mov	%g1,%g3	and	%g1, PSR_CWP, %g1	andn	%l0, PSR_CWP, %l0	or	%l0, %g1, %l0	mov	%l0, %g1	mov	%l0, %psr		! install old psr, disable traps	nop;nop;nop	!	! Make sure that there is a window to return to.	!	mov	0x2, %g1		! compute mask for CWP + 1	sll	%g1, %l0, %g1	set	_nwindows, %g3		! get NW	ld	[%g3], %g3	srl	%g1, %g3, %g2	or	%g1, %g2, %g1	mov	%wim, %g2		! cmp with wim to check for underflow	btst	%g1, %g2	bz	sr_out	nop	!	! No window to return to. Restore it.	!	sll	%g2, 1,%g1		! compute new WIM = rol(WIM, 1, NW)	set	_nwindows, %g3		! gnerate NW-1	ld	[%g3], %g3	dec	%g3	srl	%g2, %g3, %g2	or	%g1, %g2, %g1	mov	%g1, %wim		! install it	nop; nop; nop;			! wim delay	restore				! get into window to be restored	RESTORE_WINDOW(%sp)	save				! get back to original window	!	! There is a window to return to.	! Restore the volatile regs and return.	!sr_out:	mov	%l0, %psr		! install old PSR_CC	ld	[%l7 + MINFRAME + LG1], %g1	ld	[%l7 + MINFRAME + LG2], %g2	ld	[%l7 + MINFRAME + LG3], %g3	ld	[%l7 + MINFRAME + LG4], %g4	ld	[%l7 + MINFRAME + LG5], %g5	ld	[%l7 + MINFRAME + LG6], %g6	ld	[%l7 + MINFRAME + LG7], %g7	ld	[%l7 + MINFRAME + LSP], %fp	ld	[%l7 + MINFRAME + LPC], %l1	ld	[%l7 + MINFRAME + LNPC], %l2	jmp	%l1	rett	%l2	.empty/* * Trap handlers. *//* * Window overflow trap handler. */	.global _window_overflow_window_overflow:	!	! Compute new WIM.	!	mov	%wim, %l3		! get wim	mov	%g1, %l7		! save %g1	srl	%l3, 1, %g1		! next WIM = %g1 = ror(WIM, 1, NW)	sll	%l3, %l6, %l4		! %l6 = NW-1	or	%l4, %g1, %g1	save				! get into window to be saved	mov	%g1, %wim		! install new wim	nop; nop; nop;			! wim delay	!	! Put it on the stack.	!	SAVE_WINDOW(%sp)	restore				! go back to trap window	mov	%l7, %g1		! restore g1	jmp	%l1			! reexecute save	rett	%l2/* * Window underflow trap handler. */	.global _window_underflow_window_underflow:	mov	%wim, %l3		! get wim	sll	%l3, 1, %l4		! next WIM = rol(WIM, 1, NW)	srl	%l3, %l6, %l5		! %l6 = NW-1	or	%l5, %l4, %l5	mov	%l5, %wim		! install it	nop; nop; nop;			! wim delay	restore				! (wim delay 3) get into last window	restore				! get into window to be restored	RESTORE_WINDOW(%sp)	save				! get back to original window	save	jmp	%l1			! reexecute restore	rett	%l2/* * Misc subroutines. *//* * Get trap base register. * * char * * gettbr() */	ENTRY(gettbr)	mov	%tbr, %o0	srl	%o0, 12, %o0	retl	sll	%o0, 12, %o0/* * Return current sp value to caller * * char * * getsp() */	ENTRY(getsp)	retl	mov	%sp, %o0/* * Get system enable register * * char * getenablereg() */	ENTRY(getenablereg)	set	ENABLEREG, %o0	lduba	[%o0]ASI_CTL, %o0	retl	nop/* * Set priority level hi. * * splhi() */	ENTRY(splhi)	mov	%psr, %o0	or	%o0, PSR_PIL, %g1	mov	%g1, %psr	nop				! psr delay	retl	nop/* * Set priority level 13. * * spl13() */        ENTRY(spl13)        mov     %psr, %o0        bclr    PSR_PIL, %o0            ! PIL = 13        mov     %g0, %g1        bset    (13 << 8), %g1        or      %g1, %o0, %g1        mov     %g1, %psr        nop                             ! psr delay        retl        nop /* * Set priority level to a value. * * splx(s) * int s; */	ENTRY(splx)	and	%o0, PSR_PIL, %g1	mov	%psr, %o0	bclr	PSR_PIL, %o0	bset	%g1, %o0	mov	%o0, %psr	nop				! psr delay	retl	nop        PCVAL   =       0       ! offsets in buf structure	SPVAL   =       4	SIGMASK =       8	SIGSTACK =      12	SS_SP      =    0       ! offset in sigstack structure						SS_ONSTACK =    4	.seg	"data"	.global	_fpu_exists_fpu_exists:	.word	1			! assume FPU exists	.seg	"text"	.align	4/* * FPU probe - try a floating point instruction to see if there * really is an FPU in the current configuration. */	ENTRY(fpu_probe)	mov	%psr, %g1		! read psr	set	PSR_EF, %g2		! enable floating-point	bset	%g2, %g1	mov	%g1, %psr		! write psr	nop				! psr delay, three cycles	sethi	%hi(zero), %g2		! wait till the fpu bit is fixed	or	%g2, %lo(zero), %g2	ld	[%g2], %fsr		! This causes less trouble with SAS.	retl				! if no FPU, we get fp_disabled trap	nop				! which will clear the fpu_exists flagzero:	.word	0/* * floating point disabled trap. * if FPU does not exist, emulate instruction * otherwise, enable floating point */	.global _fp_disabled_fp_disabled:	!	! if we get an fp_disabled trap and the FPU is enabled	! then there is not an FPU in the configuration	!	set	PSR_EF, %l5		! FPU enable bit	btst	%l5, %l0		! was the FPU enabled?	sethi	%hi(_fpu_exists), %l6	bz,a	1f			! fp was disabled, fix up state	ld	[%l6 + %lo(_fpu_exists)], %l5	! else clear fpu_exists	!	! fp_disable trap when the FPU is enabled; should only happen	! once from autoconf when there is not an FPU in the board	!	clr	[%l6 + %lo(_fpu_exists)] ! FPU does not exist in configuration	set 	PSR_EF, %l4	bclr	%l4, %l5	mov	%l5, %psr	nop;nop;nop1:	jmp	%l2			! return from trap skip inst	rett	%l2 + 4/* * The number of windows, set by fiximp when machine is booted. */	.seg    "data"	.align  4	.global _nwindows_nwindows:	.word   8	.seg    "text"/* * fiximp() * * Fix the implementation dependent parameters * Find the type of sparc implementation we are running * on and fix the number of windows in the trap vectors. * The last byte of every trap vector must be equal to * the number of windows in the implementation minus one. * Correct the number of save/restores used in flush_windows * to be optimal for this implementation. * The macros SYS_TRAP, and WIN_TRAP depend on it! */fiximp:	mov	%psr, %o1			srl	%o1, 28, %o1		tst	%o1		bnz,a	1f				mov	8, %o1			! implementation 1, sunray 8 windows	mov	7, %o1			! implementation 0, sunrise 7 windows1:	set	_scb, %o2	mov	256, %o3		! number of trap vectors	set	_nwindows, %o4		! variable holding # windows (NW)	st	%o1, [%o4]	sub	%o1, 1, %o1		! last byte of trap vectors get NW-11:	stb	%o1, [%o2 + 15]		! write last byte of trap vectors	subcc	%o3, 1, %o3	bnz	1b	add	%o2, 16, %o2	retl	nop/* * Flush all windows to memory, except for the one we entered in. * We do this by doing NWINDOW-2 saves then the same number of restores. * This leaves the WIM immediately before window entered in. * This is used for context switching. */        ENTRY(flush_windows)        save    %sp, -WINDOWSIZE, %sp        save    %sp, 0, %sp        save    %sp, 0, %sp        save    %sp, 0, %sp        save    %sp, 0, %sp         ! if not a 470 the next two instructions should be nops        .global _flushwin_not470_flushwin_not470:        save    %sp, -WINDOWSIZE, %sp        restore         restore        restore        restore        restore        ret        restore          .seg    "text"        .align  4  /* * _setjmp(buf_ptr) * buf_ptr points to a five word array (jmp_buf). In the first is our * return address, the second, is the callers SP. * The rest is cleared by _setjmp * *              +----------------+ *   %i0->      |      pc        | *              +----------------+ *              |      sp        | *              +----------------+ *              |    sigmask     | *              +----------------+ *              |   stagstack    | *              |   structure    | *              +----------------+ * */           ENTRY(_setjmp)        st      %o7, [%o0 + PCVAL]      ! return pc        st      %sp, [%o0 + SPVAL]      ! save caller's sp        clr     [%o0 + SIGMASK]         ! clear the remainder of the jmp_buf        clr     [%o0 + SIGSTACK + SS_SP]        clr     [%o0 + SIGSTACK + SS_ONSTACK]        retl        clr     %o0 /* * _longjmp(buf_ptr, val) * buf_ptr points to an array which has been initialized by _setjmp. * val is the value we wish to return to _setjmp's caller * * We will flush our registers by doing 6 save instructions. This could be * better done as a kernel call. This is necessary to ensure that the * registers we want to pick up are stored in the stack. Then, we set fp * from the saved fp and make ourselves a stack frame. */        ENTRY(_longjmp)        save    %sp, -WINDOWSIZE, %sp         call    _flush_windows        nop         ld      [%i0 + SPVAL], %fp      ! build new stack frame        sub     %fp, MINFRAME, %sp      ! establish new save area        ld      [%i0 + PCVAL], %i7      ! get new return pc        ret        restore %i1, 0, %o0             ! return (val)

⌨️ 快捷键说明

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