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

📄 traps.s.svn-base

📁 u-boot for S3c2443 processor
💻 SVN-BASE
字号:
/* * (C) Copyright 2003, Psyent Corporation <www.psyent.com> * Scott McNutt <smcnutt@psyent.com> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <config.h>/************************************************************************* * Register window underflow * * The register window underflow exception occurs whenever the lowest * valid register window is in use (CWP=LO_LIMIT) and a save instruction * is issued. The save moves CWP below LO_LIMIT, %sp is set as normal, * then the exception is generated prior to executing the instruction * after the save. ************************************************************************/	.text	.global _cwp_lolimit	.align	4_cwp_lolimit:	/* Sixteen words are always allocated by the compiler in every	 * procedure's stack frame, always starting at %sp, for saving	 * 'in' and 'local' registers on a window overflow.	 *	 * Save the 'global' and 'in' regs on stack. They are restored	 * at cwp = HI_LIMIT. The 'local' regs aren't in-use at this point.	 */	sts	[%sp,0], %g0		/* Save 'global' regs*/	sts	[%sp,1], %g1	sts	[%sp,2], %g2	sts	[%sp,3], %g3	sts	[%sp,4], %g4	sts	[%sp,5], %g5	sts	[%sp,6], %g6	sts	[%sp,7], %g7	sts	[%sp,8], %i0		/* Save 'in' regs */	sts	[%sp,9], %i1	sts	[%sp,10], %i2	sts	[%sp,11], %i3	sts	[%sp,12], %i4	sts	[%sp,13], %i5	sts	[%sp,14], %i6	sts	[%sp,15], %i7	/* Save current %sp and return address in a global so they are	 * available at cwp = HI_LIMIT ... where the 'global'/'in' regs	 * are restored. NOTE: %sp changes with cwp.	 */	mov	%g7, %o7	mov	%g6, %sp	/* Get LO_LIMIT/HI_LIMIT to know where to start & stop. Note: in	 * the underflow exception, cwp is __NOT__ guaranteed to be zero.	 * If the OCI debug module is enabled the reset value for LO_LIMIT	 * is 2, not 1 -- so cwp can be 1 or 0.	 */	pfx	2			/* WVALID */	rdctl	%g1	mov	%g2, %g1	pfx	0	and	%g1, 0x1f		/* g1 <- LO_LIMIT */	lsri	%g2, 5	pfx	0	and	%g2,0x1f		/* g2 <- HI_LIMIT */	/* Set istatus so cwp = HI_LIMIT after tret	 */	movi	%g5, 0x1f	lsli	%g5, 4	not	%g5			/* mask to clr cwp */	pfx	1			/* istatus */	rdctl	%g0	and	%g0, %g5		/* clear cwp field */	mov	%g4, %g2	lsli	%g4, 4	or	%g0, %g4		/* cwp = HI_LIMIT */	pfx	1	wrctl	%g0			/* update istatus */	/* Now move up the register file, saving as we go. When loop	 * is first entered, %g1 is at LO_LIMIT.	 */0:	restore				/* cwp++ */	sts	[%sp,0], %l0		/* Save "local" regs*/	sts	[%sp,1], %l1	sts	[%sp,2], %l2	sts	[%sp,3], %l3	sts	[%sp,4], %l4	sts	[%sp,5], %l5	sts	[%sp,6], %l6	sts	[%sp,7], %l7	sts	[%sp,8], %i0		/* Save 'in' regs */	sts	[%sp,9], %i1	sts	[%sp,10], %i2	sts	[%sp,11], %i3	sts	[%sp,12], %i4	sts	[%sp,13], %i5	sts	[%sp,14], %i6	sts	[%sp,15], %i7	cmp	%g1, %g2		/* cwp == HI_LIMIT ? */	skps	cc_ne			/* if so, we're done */	br	1f	nop				/* delay slot */	inc	%g1			/* g1 <- cwp++ */	br	0b	nop				/* delay slot */	/* At this point cwp = HI_LIMIT, so the global/in regs that were	 * in place when the underflow occurred must be restored using	 * the original stack pointer (saved in g6).	 */1:	mov	%o7, %g7		/* restore return addr */	mov	%sp, %g6		/* Restore original sp */	lds	%g0, [%sp,0]		/* Restore 'global' regs*/	lds	%g1, [%sp,1]	lds	%g2, [%sp,2]	lds	%g3, [%sp,3]	lds	%g4, [%sp,4]	lds	%g5, [%sp,5]	lds	%g6, [%sp,6]	lds	%g7, [%sp,7]	lds	%i0, [%sp,8]		/* Restore 'in' regs*/	lds	%i1, [%sp,9]	lds	%i2, [%sp,10]	lds	%i3, [%sp,11]	lds	%i4, [%sp,12]	lds	%i5, [%sp,13]	lds	%i6, [%sp,14]	lds	%i7, [%sp,15]	tret	%o7			/* All done *//************************************************************************* * Register window overflow * * The register window overflow exception occurs whenever the highest * valid register window is in use (cwp = HI_LIMIT) and a restore * instruction is issued. Control is transferred to the overflow handler * before the instruction following restore is executed. * * When a register window overflow exception is taken, the exception * handler sees cwp at HI_LIMIT. ************************************************************************/	.text	.global _cwp_hilimit	.align	4_cwp_hilimit:	/* Save 'global'/'in' regs on the stack -- will restore when cwp	 * is at LO_LIMIT. Locals don't need saving as they are going away.	 */	sts	[%sp,0], %g0		/* Save "global" regs*/	sts	[%sp,1], %g1	sts	[%sp,2], %g2	sts	[%sp,3], %g3	sts	[%sp,4], %g4	sts	[%sp,5], %g5	sts	[%sp,6], %g6	sts	[%sp,7], %g7	sts	[%sp,8], %i0		/* Save 'in' regs */	sts	[%sp,9], %i1	sts	[%sp,10], %i2	sts	[%sp,11], %i3	sts	[%sp,12], %i4	sts	[%sp,13], %i5	sts	[%sp,14], %i6	sts	[%sp,15], %i7	/* The current %sp must be available in global to restore regs	 * saved on stack. Need return addr as well ;-)	 */	mov	%g7, %o7	mov	%g6, %sp	/* Get HI_LIMIT & LO_LIMIT	 */	pfx	2			/* WVALID */	rdctl	%g1	mov	%g2, %g1	pfx	0	and	%g1, 0x1f		/* g1 <- LO_LIMIT */	lsri	%g2, 5	pfx	0	and	%g2,0x1f		/* g2 <- HI_LIMIT */	/* Set istatus so cwp = LO_LIMIT after tret	 */	movi	%g5, 0x1f	lsli	%g5, 4	not	%g5			/* mask to clr cwp */	pfx	1			/* istatus */	rdctl	%g0	and	%g0, %g5		/* clear cwp field */	mov	%g4, %g1		/* g4 <- LO_LIMIT */	lsli	%g4, 4	or	%g0, %g4		/* cwp = LO_LIMIT */	pfx	1	wrctl	%g0			/* update istatus */	/* Move to cwp = LO_LIMIT-1 and restore 'in' regs.	 */	subi	%g4,(1 << 4)		/* g4 <- LO_LIMIT - 1 */	rdctl	%g0	and	%g0, %g5		/* clear cwp field */	or	%g0, %g4		/* cwp = LO_LIMIT - 1 */	wrctl	%g0			/* update status */	nop	mov	%sp, %g6		/* Restore sp */	lds	%i0, [%sp,8]		/* Restore 'in' regs */	lds	%i1, [%sp,9]	lds	%i2, [%sp,10]	lds	%i3, [%sp,11]	lds	%i4, [%sp,12]	lds	%i5, [%sp,13]	lds	%i6, [%sp,14]		/* sp in next window */	lds	%i7, [%sp,15]	/* Starting at LO_LIMIT-1, move up the register file, restoring	 * along the way.	 */0:	restore				/* cwp++ */	lds	%l0, [%sp,0]		/* Restore 'local' regs*/	lds	%l1, [%sp,1]	lds	%l2, [%sp,2]	lds	%l3, [%sp,3]	lds	%l4, [%sp,4]	lds	%l5, [%sp,5]	lds	%l6, [%sp,6]	lds	%l7, [%sp,7]	lds	%i0, [%sp,8]		/* Restore 'in' regs */	lds	%i1, [%sp,9]	lds	%i2, [%sp,10]	lds	%i3, [%sp,11]	lds	%i4, [%sp,12]	lds	%i5, [%sp,13]	lds	%i6, [%sp,14]		/* sp in next window */	lds	%i7, [%sp,15]	cmp	%g1, %g2		/* cwp == HI_LIMIT ? */	skps	cc_ne			/* if so, we're done */	br	1f	nop				/* delay slot */	inc	%g1			/* cwp++ */	br	0b	nop				/* delay slot */	/* All windows have been updated at this point, but the globals	 * still need to be restored. Go to cwp = LO_LIMIT-1 to get	 * some registers to use.	 */1:	rdctl	%g0	and	%g0, %g5		/* clear cwp field */	or	%g0, %g4		/* cwp = LO_LIMIT - 1 */	wrctl	%g0			/* update status */	nop	/* Now there are some registers available to use in restoring	 * the globals.	 */	mov	%sp, %g6	mov	%o7, %g7	lds	%g0, [%sp,0]		/* Restore "global" regs*/	lds	%g1, [%sp,1]	lds	%g2, [%sp,2]	lds	%g3, [%sp,3]	lds	%g4, [%sp,4]	lds	%g5, [%sp,5]	lds	%g6, [%sp,6]	lds	%g7, [%sp,7]	/* The tret moves istatus -> status. istatus was already set for	 * cwp = LO_LIMIT.	 */	tret	%o7			/* done *//************************************************************************* * Default exception handler * * The default handler passes control to external_interrupt(). So trap * or hardware interrupt hanlders can be installed using the familiar * irq_install_handler(). * * Here, the stack is fixed-up and cwp is incremented prior to calling * external_interrupt(). This lets the underflow and overflow handlers * operate normally during the exception. ************************************************************************/	.text	.global _def_xhandler	.align	4_def_xhandler:	/* Allocate some stack space: 16 words at %sp to accomodate	 * a reg window underflow, 8 words to save interrupted task's	 * 'out' regs (which are now the 'in' regs), 8 words to preserve	 * the 'global' regs and 3 words to save the return address,	 * status and istatus. istatus must be saved in the event an	 * underflow occurs in a dispatched handler. status is saved so	 * a handler can access it on stack.	 */	pfx	%hi((16+16+3) * 4)	subi	%fp, %lo((16+16+3) * 4)	mov	%sp, %fp	/* Save the 'global' regs and the interrupted task's 'out' regs	 * (our 'in' regs) along with the return addr, status & istatus.	 * First 16 words are for underflow exception.	 */	rdctl	%l0			/* status */	pfx	1			/* istatus */	rdctl	%l1	sts	[%sp,16+0], %g0		/* Save 'global' regs*/	sts	[%sp,16+1], %g1	sts	[%sp,16+2], %g2	sts	[%sp,16+3], %g3	sts	[%sp,16+4], %g4	sts	[%sp,16+5], %g5	sts	[%sp,16+6], %g6	sts	[%sp,16+7], %g7	sts	[%sp,16+8], %i0		/* Save 'in' regs */	sts	[%sp,16+9], %i1	sts	[%sp,16+10], %i2	sts	[%sp,16+11], %i3	sts	[%sp,16+12], %i4	sts	[%sp,16+13], %i5	sts	[%sp,16+14], %i6	sts	[%sp,16+15], %i7	sts	[%sp,16+16], %l0	/* status */	sts	[%sp,16+17], %l1	/* istatus */	sts	[%sp,16+18], %o7	/* return addr */	/* Move to cwp+1 ... this guarantees cwp is at or above LO_LIMIT.	 * Need to set IPRI=3 and IE=1 to enable underflow exceptions.	 * NOTE: only the 'out' regs have been saved ... can't touch	 * the 'in' or 'local' here.	 */	restore				/* cwp++ */	rdctl	%o0			/* o0 <- status */	pfx	%hi(0x7e00)	movi	%o1, %lo(0x7e00)	not	%o1	and	%o0, %o1		/* clear IPRI */	pfx	%hi(0x8600)	movi	%o1, %lo(0x8600)	or	%o0, %o1		/* IPRI=3, IE=1 */	wrctl	%o0			/* o0 -> status */	nop	/* It's ok to call a C routine now since cwp >= LO_LIMIT,	 * interrupt task's registers are/will be preserved, and	 * underflow exceptions can be handled.	 */	pfx	%hi(external_interrupt@h)	movi	%o1, %lo(external_interrupt@h)	pfx	%xhi(external_interrupt@h)	movhi	%o1, %xlo(external_interrupt@h)	bgen	%o0, 4+2		/* 16 * 4 */	add	%o0, %sp		/* Ptr to regs */	call	%o1	nop	/* Move back to the exception register window, restore the 'out'	 * registers, then return from exception.	 */	rdctl	%o0			/* o0 <- status */	subi	%o0, 16	wrctl	%o0			/* cwp-- */	nop	mov	%sp, %fp	lds	%g0, [%sp,16+0]		/* Restore 'global' regs*/	lds	%g1, [%sp,16+1]	lds	%g2, [%sp,16+2]	lds	%g3, [%sp,16+3]	lds	%g4, [%sp,16+4]	lds	%g5, [%sp,16+5]	lds	%g6, [%sp,16+6]	lds	%g7, [%sp,16+7]	lds	%i0, [%sp,16+8]		/* Restore 'in' regs*/	lds	%i1, [%sp,16+9]	lds	%i2, [%sp,16+10]	lds	%i3, [%sp,16+11]	lds	%i4, [%sp,16+12]	lds	%i5, [%sp,16+13]	lds	%i6, [%sp,16+14]	lds	%i7, [%sp,16+15]	lds	%l0, [%sp,16+16]	/* status */	lds	%l1, [%sp,16+17]	/* istatus */	lds	%o7, [%sp,16+18]	/* return addr */	pfx	1	wrctl	%l1			/* restore istatus */	pfx	%hi((16+16+3) * 4)	addi	%sp, %lo((16+16+3) * 4)	mov	%fp, %sp	tret	%o7			/* Done *//************************************************************************* * Timebase Timer Interrupt -- This has identical structure to above, * but calls timer_interrupt().  Doing it this way keeps things similar * to other architectures (e.g. ppc). ************************************************************************/	.text	.global _timebase_int	.align	4_timebase_int:	/* Allocate  stack space.	 */	pfx	%hi((16+16+3) * 4)	subi	%fp, %lo((16+16+3) * 4)	mov	%sp, %fp	/* Save the 'global' regs & 'out' regs (our 'in' regs)	 */	rdctl	%l0			/* status */	pfx	1			/* istatus */	rdctl	%l1	sts	[%sp,16+0], %g0		/* Save 'global' regs*/	sts	[%sp,16+1], %g1	sts	[%sp,16+2], %g2	sts	[%sp,16+3], %g3	sts	[%sp,16+4], %g4	sts	[%sp,16+5], %g5	sts	[%sp,16+6], %g6	sts	[%sp,16+7], %g7	sts	[%sp,16+8], %i0		/* Save 'in' regs */	sts	[%sp,16+9], %i1	sts	[%sp,16+10], %i2	sts	[%sp,16+11], %i3	sts	[%sp,16+12], %i4	sts	[%sp,16+13], %i5	sts	[%sp,16+14], %i6	sts	[%sp,16+15], %i7	sts	[%sp,16+16], %l0	/* status */	sts	[%sp,16+17], %l1	/* istatus */	sts	[%sp,16+18], %o7	/* return addr */	/* Move to cwp+1.	 */	restore				/* cwp++ */	rdctl	%o0			/* o0 <- status */	pfx	%hi(0x7e00)	movi	%o1, %lo(0x7e00)	not	%o1	and	%o0, %o1		/* clear IPRI */	pfx	%hi(0x8600)	movi	%o1, %lo(0x8600)	or	%o0, %o1		/* IPRI=3, IE=1 */	wrctl	%o0			/* o0 -> status */	nop	/* Call timer_interrupt()	 */	pfx	%hi(timer_interrupt@h)	movi	%o1, %lo(timer_interrupt@h)	pfx	%xhi(timer_interrupt@h)	movhi	%o1, %xlo(timer_interrupt@h)	bgen	%o0, 4+2		/* 16 * 4 */	add	%o0, %sp		/* Ptr to regs */	call	%o1	nop	/* Move back to the exception register window, restore the 'out'	 * registers, then return from exception.	 */	rdctl	%o0			/* o0 <- status */	subi	%o0, 16	wrctl	%o0			/* cwp-- */	nop	mov	%sp, %fp	lds	%g0, [%sp,16+0]		/* Restore 'global' regs*/	lds	%g1, [%sp,16+1]	lds	%g2, [%sp,16+2]	lds	%g3, [%sp,16+3]	lds	%g4, [%sp,16+4]	lds	%g5, [%sp,16+5]	lds	%g6, [%sp,16+6]	lds	%g7, [%sp,16+7]	lds	%i0, [%sp,16+8]		/* Restore 'in' regs*/	lds	%i1, [%sp,16+9]	lds	%i2, [%sp,16+10]	lds	%i3, [%sp,16+11]	lds	%i4, [%sp,16+12]	lds	%i5, [%sp,16+13]	lds	%i6, [%sp,16+14]	lds	%i7, [%sp,16+15]	lds	%l0, [%sp,16+16]	/* status */	lds	%l1, [%sp,16+17]	/* istatus */	lds	%o7, [%sp,16+18]	/* return addr */	pfx	1	wrctl	%l1			/* restore istatus */	pfx	%hi((16+16+3) * 4)	addi	%sp, %lo((16+16+3) * 4)	mov	%fp, %sp	tret	%o7			/* Done */

⌨️ 快捷键说明

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