|  | /* | 
|  | * (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> | 
|  | #include <version.h> | 
|  |  | 
|  | #if !defined(CONFIG_IDENT_STRING) | 
|  | #define CONFIG_IDENT_STRING "" | 
|  | #endif | 
|  |  | 
|  | #define STATUS_INIT	0x8600		/* IE=1, IPRI=2 */ | 
|  |  | 
|  | /************************************************************************* | 
|  | * RESTART | 
|  | ************************************************************************/ | 
|  |  | 
|  | .text | 
|  | .global _start | 
|  |  | 
|  | _start: | 
|  | bsr	0f | 
|  | nop | 
|  | .long	_start | 
|  |  | 
|  | /* GERMS -- The "standard-32" configuration GERMS monitor looks | 
|  | * for the string "Nios" at flash_base + 0xc (actually it only | 
|  | * tests for 'N', 'i'). You can leave support for this in place | 
|  | * as it's only a few words. | 
|  | */ | 
|  | . = _start + 0x000c | 
|  | .string "Nios" | 
|  |  | 
|  | .align 4 | 
|  | 0: | 
|  | /* | 
|  | * Early setup -- set cwp = HI_LIMIT, IPRI = 2, IE = 1 to | 
|  | * enable underflow exceptions. Disable cache. | 
|  | * NOTE: %o7 has return addr -- save in %g7 use later. | 
|  | */ | 
|  | mov	%g7, %o7 | 
|  |  | 
|  | pfx	2			/* WVALID */ | 
|  | rdctl	%g0 | 
|  | lsri	%g0, 1 | 
|  | pfx	%hi(STATUS_INIT) | 
|  | or	%g0, %lo(STATUS_INIT) | 
|  | wrctl	%g0			/* update status */ | 
|  | nop | 
|  |  | 
|  | /* | 
|  | * STACK | 
|  | */ | 
|  | pfx	%hi(CFG_INIT_SP) | 
|  | movi	%sp, %lo(CFG_INIT_SP) | 
|  | pfx	%xhi(CFG_INIT_SP) | 
|  | movhi	%sp, %xlo(CFG_INIT_SP) | 
|  | mov	%fp, %sp | 
|  |  | 
|  | pfx	%hi(4*16) | 
|  | subi	%sp, %lo(4*16)		/* Space for reg window mgmt */ | 
|  |  | 
|  | /* | 
|  | * RELOCATE -- %g7 has return addr from bsr at _start. | 
|  | */ | 
|  | pfx	%hi(__u_boot_cmd_end) | 
|  | movi	%g5, %lo(__u_boot_cmd_end) | 
|  | pfx	%xhi(__u_boot_cmd_end) | 
|  | movhi	%g5, %xlo(__u_boot_cmd_end) /* %g5 <- end address */ | 
|  |  | 
|  | lsli	%g7, 1			/* mem = retaddr << 1 */ | 
|  | mov	%g6, %g7 | 
|  | subi	%g6, 4			/* %g6 <- src addr */ | 
|  | ld	%g7, [%g7]		/* %g7 <- dst addr */ | 
|  |  | 
|  | /* No need to move text sections if we're already located | 
|  | * at the proper address. | 
|  | */ | 
|  | cmp	%g7, %g6 | 
|  | ifs	cc_z | 
|  | br	reloc | 
|  | nop				/* delay slot */ | 
|  |  | 
|  | 1:	cmp	%g7, %g5 | 
|  | skps	cc_nz | 
|  | br	2f | 
|  | nop				/* delay slot */ | 
|  |  | 
|  | ld	%g0, [%g6] | 
|  | addi	%g6, 4			/* src++ */ | 
|  | st	[%g7], %g0 | 
|  | addi	%g7, 4			/* dst++ */ | 
|  | br	1b | 
|  | nop				/* delay slot */ | 
|  | 2: | 
|  |  | 
|  | /* | 
|  | * Jump to relocation address | 
|  | */ | 
|  | pfx	%hi(reloc@h) | 
|  | movi	%g0, %lo(reloc@h) | 
|  | pfx	%xhi(reloc@h) | 
|  | movhi	%g0, %xlo(reloc@h) | 
|  | jmp	%g0 | 
|  | nop				/* delay slot */ | 
|  | reloc: | 
|  |  | 
|  | /* | 
|  | * CLEAR BSS | 
|  | */ | 
|  | pfx	%hi(__bss_end) | 
|  | movi	%g5, %lo(__bss_end) | 
|  | pfx	%xhi(__bss_end) | 
|  | movhi	%g5, %xlo(__bss_end)	/* %g5 <- end address */ | 
|  | pfx	%hi(__bss_start) | 
|  | movi	%g7, %lo(__bss_start) | 
|  | pfx	%xhi(__bss_start) | 
|  | movhi	%g7, %xlo(__bss_start)	/* %g7 <- end address */ | 
|  |  | 
|  | movi	%g0, 0 | 
|  | 3:	cmp	%g7, %g5 | 
|  | skps	cc_nz | 
|  | br	4f | 
|  | nop				/* delay slot */ | 
|  |  | 
|  | st	[%g7], %g0 | 
|  | addi	%g7, 4			/* (delay slot) dst++ */ | 
|  | br	3b | 
|  | nop				/* delay slot */ | 
|  | 4: | 
|  |  | 
|  | /* | 
|  | * INIT VECTOR TABLE | 
|  | */ | 
|  | pfx	%hi(CFG_VECT_BASE) | 
|  | movi	%g0, %lo(CFG_VECT_BASE) | 
|  | pfx	%xhi(CFG_VECT_BASE) | 
|  | movhi	%g0, %xlo(CFG_VECT_BASE)	/* dst */ | 
|  | mov	%l0, %g0 | 
|  |  | 
|  | pfx	%hi(_vectors) | 
|  | movi	%g1, %lo(_vectors) | 
|  | pfx	%xhi(_vectors) | 
|  | movhi	%g1, %xlo(_vectors)	/* src */ | 
|  | bgen	%g2, 6			/* cnt = 64 */ | 
|  |  | 
|  | ldp	%g3, [%l0, 3]		/* bkpt vector */ | 
|  | ldp	%g4, [%l0, 4]		/* single step vector */ | 
|  |  | 
|  | 5:	ld	%g7, [%g1] | 
|  | addi	%g1, 4			/* src++ */ | 
|  | st	[%g0], %g7 | 
|  | addi	%g0, 4			/* dst++ */ | 
|  |  | 
|  | subi	%g2, 1			/* cnt-- */ | 
|  | ifrnz	%g2 | 
|  | br	5b | 
|  | nop				/* delay slot */ | 
|  |  | 
|  | #if defined(CONFIG_ROM_STUBS) | 
|  | /* Restore the breakpoint and single step exception | 
|  | * vectors to their original values. | 
|  | */ | 
|  | stp	[%l0,3], %g3		/* breakpoint */ | 
|  | stp	[%l0,4], %g4		/* single step */ | 
|  | #endif | 
|  |  | 
|  | /* For debug startup convenience ... software breakpoints | 
|  | * set prior to this point may not succeed ;-) | 
|  | */ | 
|  | .global __start | 
|  | __start: | 
|  |  | 
|  | /* | 
|  | * Call board_init -- never returns | 
|  | */ | 
|  | pfx	%hi(board_init@h) | 
|  | movi	%g1, %lo(board_init@h) | 
|  | pfx	%xhi(board_init@h) | 
|  | movhi	%g1, %xlo(board_init@h) | 
|  | call	%g1 | 
|  | nop				/* Delaly slot */ | 
|  | /* NEVER RETURNS */ | 
|  |  | 
|  | /* | 
|  | * dly_clks -- Nios doesn't have a time/clk reference for simple | 
|  | * delay loops, so we do our best by counting instruction cycles. | 
|  | * A control register that counts system clock cycles would be | 
|  | * a handy feature -- hint for Altera ;-) | 
|  | */ | 
|  | .globl dly_clks | 
|  | /* Each loop is 4 instructions as delay slot is always | 
|  | * executed. Each instruction is approximately 4 clocks | 
|  | * (according to some lame info from Altera). So ... | 
|  | * ... each loop is about 16 clocks. | 
|  | */ | 
|  |  | 
|  | dly_clks: | 
|  | lsri	%o0, 4			/* cnt/16 */ | 
|  |  | 
|  | 8:	skprnz	%o0 | 
|  | br	9f | 
|  | subi	%o0, 1			/* cnt--, Delay slot */ | 
|  | br	8b | 
|  | nop | 
|  |  | 
|  | 9:	lret | 
|  | nop				/* Delay slot */ | 
|  |  | 
|  |  | 
|  | .data | 
|  | .globl	version_string | 
|  |  | 
|  | version_string: | 
|  | .ascii U_BOOT_VERSION | 
|  | .ascii " (", __DATE__, " - ", __TIME__, ")" | 
|  | .ascii CONFIG_IDENT_STRING, "\0" |