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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
/*
* Startup Code for MIPS32 XBURST CPU-core
*
* Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
*
* 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>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/cacheops.h>
.set noreorder
.globl _start
.text
_start:
/* Initialize $gp */
bal 1f
nop
.word _gp
1:
lw gp, 0(ra)
/* Set up temporary stack */
li sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
la t9, board_init_f
jr t9
nop
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
* a0 = addr_sp
* a1 = gd
* a2 = destination address
*/
.globl relocate_code
.ent relocate_code
relocate_code:
move sp, a0 # set new stack pointer
li t0, CONFIG_SYS_MONITOR_BASE
sub t6, a2, t0 # t6 <-- relocation offset
la t3, in_ram
lw t2, -12(t3) # t2 <-- __image_copy_end
move t1, a2
add gp, t6 # adjust gp
/*
* t0 = source address
* t1 = target address
* t2 = source end address
*/
1:
lw t3, 0(t0)
sw t3, 0(t1)
addu t0, 4
blt t0, t2, 1b
addu t1, 4
/* If caches were enabled, we would have to flush them here. */
/* flush d-cache */
li t0, KSEG0
addi t1, t0, CONFIG_SYS_DCACHE_SIZE
2:
cache INDEX_WRITEBACK_INV_D, 0(t0)
bne t0, t1, 2b
addi t0, CONFIG_SYS_CACHELINE_SIZE
sync
/* flush i-cache */
li t0, KSEG0
addi t1, t0, CONFIG_SYS_ICACHE_SIZE
3:
cache INDEX_INVALIDATE_I, 0(t0)
bne t0, t1, 3b
addi t0, CONFIG_SYS_CACHELINE_SIZE
/* Invalidate BTB */
mfc0 t0, CP0_CONFIG, 7
nop
ori t0, 2
mtc0 t0, CP0_CONFIG, 7
nop
/* Jump to where we've relocated ourselves */
addi t0, a2, in_ram - _start
jr t0
nop
.word __rel_dyn_end
.word __rel_dyn_start
.word __image_copy_end
.word _GLOBAL_OFFSET_TABLE_
.word num_got_entries
in_ram:
/*
* Now we want to update GOT.
*
* GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
* generated by GNU ld. Skip these reserved entries from relocation.
*/
lw t3, -4(t0) # t3 <-- num_got_entries
lw t4, -8(t0) # t4 <-- _GLOBAL_OFFSET_TABLE_
add t4, t6 # t4 now holds relocated _G_O_T_
addi t4, t4, 8 # skipping first two entries
li t2, 2
1:
lw t1, 0(t4)
beqz t1, 2f
add t1, t6
sw t1, 0(t4)
2:
addi t2, 1
blt t2, t3, 1b
addi t4, 4
/* Update dynamic relocations */
lw t1, -16(t0) # t1 <-- __rel_dyn_start
lw t2, -20(t0) # t2 <-- __rel_dyn_end
b 2f # skip first reserved entry
addi t1, 8
1:
lw t3, -4(t1) # t3 <-- relocation info
sub t3, 3
bnez t3, 2f # skip non R_MIPS_REL32 entries
nop
lw t3, -8(t1) # t3 <-- location to fix up in FLASH
lw t4, 0(t3) # t4 <-- original pointer
add t4, t6 # t4 <-- adjusted pointer
add t3, t6 # t3 <-- location to fix up in RAM
sw t4, 0(t3)
2:
blt t1, t2, 1b
addi t1, 8 # each rel.dyn entry is 8 bytes
/*
* Clear BSS
*
* GOT is now relocated. Thus __bss_start and __bss_end can be
* accessed directly via $gp.
*/
la t1, __bss_start # t1 <-- __bss_start
la t2, __bss_end # t2 <-- __bss_end
1:
sw zero, 0(t1)
blt t1, t2, 1b
addi t1, 4
move a0, a1 # a0 <-- gd
la t9, board_init_r
jr t9
move a1, a2
.end relocate_code
|