summaryrefslogtreecommitdiffstats
path: root/arch/nios2/cpu/start.S
blob: 42520d7ccb6821902dabee2b72e4bc8d5a6f4e3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 * (C) Copyright 2004, 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.
 *
 */

#include <config.h>
#include <asm-generic/memory_layout.h>

/*************************************************************************
 * RESTART
 ************************************************************************/

.section ".text_entry","ax"

_start:
	wrctl   status, r0      /* Disable interrupts */
	/* ICACHE INIT -- only the icache line at the reset address
	 * is invalidated at reset. So the init must stay within
	 * the cache line size (8 words). If GERMS is used, we'll
	 * just be invalidating the cache a second time. If cache
	 * is not implemented initi behaves as nop.
	 */
	ori     r4, r0, %lo(ICACHE_LINE_SIZE)
	movhi   r5, %hi(ICACHE_SIZE)
	ori     r5, r5, %lo(ICACHE_SIZE)
0:	initi   r5
	sub     r5, r5, r4
	bgt     r5, r0, 0b
	br      _except_end   /* Skip the tramp */

	/* EXCEPTION TRAMPOLINE -- the following gets copied
	 * to the exception address (below), but is otherwise at the
	 * default exception vector offset (0x0020).
	 */
_except_start:
	movhi   et, %hi(_exception)
	ori     et, et, %lo(_exception)
	jmp     et
_except_end:

	/* INTERRUPTS -- for now, all interrupts masked and globally
	 * disabled.
	 */
	wrctl   ienable, r0  /* All disabled */

	/* DCACHE INIT -- if dcache not implemented, initd behaves as
	 * nop.
	 */
	movhi   r4, %hi(DCACHE_LINE_SIZE)
	ori     r4, r4, %lo(DCACHE_LINE_SIZE)
	movhi   r5, %hi(DCACHE_SIZE)
	ori     r5, r5, %lo(DCACHE_SIZE)
	mov     r6, r0
1:	initd   0(r6)
	add     r6, r6, r4
	bltu    r6, r5, 1b

	/* RELOCATE CODE, DATA & COMMAND TABLE -- the following code
	 * assumes code, data and the command table are all
	 * contiguous. This lets us relocate everything as a single
	 * block. Make sure the linker script matches this ;-)
	 */
	nextpc  r4
_cur:	movhi   r5, %hi(_cur - _start)
	ori     r5, r5, %lo(_cur - _start)
	sub     r4, r4, r5                 /* r4 <- cur _start */
	mov     r8, r4
	movhi   r5, %hi(_start)
	ori     r5, r5, %lo(_start)        /* r5 <- linked _start */
	beq     r4, r5, 3f

	movhi   r6, %hi(_edata)
	ori     r6, r6, %lo(_edata)
2:	ldwio   r7, 0(r4)
	addi    r4, r4, 4
	stwio   r7, 0(r5)
	addi    r5, r5, 4
	bne     r5, r6, 2b
3:

	/* ZERO BSS/SBSS -- bss and sbss are assumed to be adjacent
	 * and between __bss_start and _end.
	 */
	 movhi  r5, %hi(__bss_start)
	 ori    r5, r5, %lo(__bss_start)
	 movhi  r6, %hi(_end)
	 ori    r6, r6, %lo(_end)
	 beq    r5, r6, 5f

4:	stwio   r0, 0(r5)
	 addi   r5, r5, 4
	 bne    r5, r6, 4b
5:

	/* JUMP TO RELOC ADDR */
	movhi   r4, %hi(_reloc)
	ori     r4, r4, %lo(_reloc)
	jmp     r4
_reloc:

	/* COPY EXCEPTION TRAMPOLINE -- copy the tramp to the
	 * exception address. Define CONFIG_ROM_STUBS to prevent
	 * the copy (e.g. exception in flash or in other
	 * softare/firmware component).
	 */
#if !defined(CONFIG_ROM_STUBS)
	movhi   r4, %hi(_except_start)
	ori     r4, r4, %lo(_except_start)
	movhi   r5, %hi(_except_end)
	ori     r5, r5, %lo(_except_end)
	movhi   r6, %hi(EXCEPTION_ADDR)
	ori     r6, r6, %lo(EXCEPTION_ADDR)
	beq     r4, r6, 7f                  /* Skip if at proper addr */

6:	ldwio   r7, 0(r4)
	stwio   r7, 0(r6)
	addi    r4, r4, 4
	addi    r6, r6, 4
	bne     r4, r5, 6b
7:
#endif

	/* STACK INIT -- zero top two words for call back chain.
	 */
	movhi   sp, %hi(STACK_BASE)
	ori     sp, sp, %lo(STACK_BASE)
	addi    sp, sp, -8
	stw     r0, 0(sp)
	stw     r0, 4(sp)
	mov     fp, sp

        /* Set the global pointer */
	movhi   r26, %hi(_gp)
	ori     r26, r26, %lo(_gp)

	/*
	 * Call board_init -- never returns
	 */
	movhi   r4, %hi(start_barebox@h)
	ori     r4, r4, %lo(start_barebox@h)
	callr   r4

	/* NEVER RETURNS -- but branch to the _start just
	 * in case ;-)
	 */
	br      _start