xref: /rk3399_rockchip-uboot/arch/mips/cpu/start.S (revision c3e72ab80135a19ac6eb2585b69de0acf19b87c1)
1eef88dfbSDaniel Schwierzeck/*
2eef88dfbSDaniel Schwierzeck *  Startup Code for MIPS32 CPU-core
3eef88dfbSDaniel Schwierzeck *
4eef88dfbSDaniel Schwierzeck *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
5eef88dfbSDaniel Schwierzeck *
6eef88dfbSDaniel Schwierzeck * SPDX-License-Identifier:	GPL-2.0+
7eef88dfbSDaniel Schwierzeck */
8eef88dfbSDaniel Schwierzeck
9eef88dfbSDaniel Schwierzeck#include <asm-offsets.h>
10eef88dfbSDaniel Schwierzeck#include <config.h>
11eef88dfbSDaniel Schwierzeck#include <asm/asm.h>
12eef88dfbSDaniel Schwierzeck#include <asm/regdef.h>
13eef88dfbSDaniel Schwierzeck#include <asm/mipsregs.h>
14eef88dfbSDaniel Schwierzeck
15eef88dfbSDaniel Schwierzeck#ifndef CONFIG_SYS_INIT_SP_ADDR
16eef88dfbSDaniel Schwierzeck#define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_SDRAM_BASE + \
17eef88dfbSDaniel Schwierzeck				CONFIG_SYS_INIT_SP_OFFSET)
18eef88dfbSDaniel Schwierzeck#endif
19eef88dfbSDaniel Schwierzeck
20eef88dfbSDaniel Schwierzeck#ifdef CONFIG_32BIT
21eef88dfbSDaniel Schwierzeck# define MIPS_RELOC	3
22eef88dfbSDaniel Schwierzeck# define STATUS_SET	0
23eef88dfbSDaniel Schwierzeck#endif
24eef88dfbSDaniel Schwierzeck
25eef88dfbSDaniel Schwierzeck#ifdef CONFIG_64BIT
26eef88dfbSDaniel Schwierzeck# ifdef CONFIG_SYS_LITTLE_ENDIAN
27eef88dfbSDaniel Schwierzeck#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
28eef88dfbSDaniel Schwierzeck	(((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym))
29eef88dfbSDaniel Schwierzeck# else
30eef88dfbSDaniel Schwierzeck#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
31eef88dfbSDaniel Schwierzeck	((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24)
32eef88dfbSDaniel Schwierzeck# endif
33eef88dfbSDaniel Schwierzeck# define MIPS_RELOC	MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03)
34eef88dfbSDaniel Schwierzeck# define STATUS_SET	ST0_KX
35eef88dfbSDaniel Schwierzeck#endif
36eef88dfbSDaniel Schwierzeck
37eef88dfbSDaniel Schwierzeck	.set noreorder
38eef88dfbSDaniel Schwierzeck
3965d297afSDaniel Schwierzeck	.macro init_wr sel
4065d297afSDaniel Schwierzeck	MTC0	zero, CP0_WATCHLO,\sel
4165d297afSDaniel Schwierzeck	mtc0	t1, CP0_WATCHHI,\sel
4265d297afSDaniel Schwierzeck	mfc0	t0, CP0_WATCHHI,\sel
4365d297afSDaniel Schwierzeck	bgez	t0, wr_done
4465d297afSDaniel Schwierzeck	 nop
4565d297afSDaniel Schwierzeck	.endm
46eef88dfbSDaniel Schwierzeck
47345490fcSDaniel Schwierzeck	.macro uhi_mips_exception
48345490fcSDaniel Schwierzeck	move	k0, t9		# preserve t9 in k0
49345490fcSDaniel Schwierzeck	move	k1, a0		# preserve a0 in k1
50345490fcSDaniel Schwierzeck	li	t9, 15		# UHI exception operation
51345490fcSDaniel Schwierzeck	li	a0, 0		# Use hard register context
52345490fcSDaniel Schwierzeck	sdbbp	1		# Invoke UHI operation
53345490fcSDaniel Schwierzeck	.endm
54345490fcSDaniel Schwierzeck
55*c3e72ab8SDaniel Schwierzeck	.macro setup_stack_gd
56*c3e72ab8SDaniel Schwierzeck	li	t0, -16
57*c3e72ab8SDaniel Schwierzeck	PTR_LI	t1, CONFIG_SYS_INIT_SP_ADDR
58*c3e72ab8SDaniel Schwierzeck	and	sp, t1, t0		# force 16 byte alignment
59*c3e72ab8SDaniel Schwierzeck	PTR_SUBU \
60*c3e72ab8SDaniel Schwierzeck		sp, sp, GD_SIZE		# reserve space for gd
61*c3e72ab8SDaniel Schwierzeck	and	sp, sp, t0		# force 16 byte alignment
62*c3e72ab8SDaniel Schwierzeck	move	k0, sp			# save gd pointer
63*c3e72ab8SDaniel Schwierzeck#ifdef CONFIG_SYS_MALLOC_F_LEN
64*c3e72ab8SDaniel Schwierzeck	li	t2, CONFIG_SYS_MALLOC_F_LEN
65*c3e72ab8SDaniel Schwierzeck	PTR_SUBU \
66*c3e72ab8SDaniel Schwierzeck		sp, sp, t2		# reserve space for early malloc
67*c3e72ab8SDaniel Schwierzeck	and	sp, sp, t0		# force 16 byte alignment
68*c3e72ab8SDaniel Schwierzeck#endif
69*c3e72ab8SDaniel Schwierzeck	move	fp, sp
70*c3e72ab8SDaniel Schwierzeck
71*c3e72ab8SDaniel Schwierzeck	/* Clear gd */
72*c3e72ab8SDaniel Schwierzeck	move	t0, k0
73*c3e72ab8SDaniel Schwierzeck1:
74*c3e72ab8SDaniel Schwierzeck	PTR_S	zero, 0(t0)
75*c3e72ab8SDaniel Schwierzeck	blt	t0, t1, 1b
76*c3e72ab8SDaniel Schwierzeck	 PTR_ADDIU t0, PTRSIZE
77*c3e72ab8SDaniel Schwierzeck
78*c3e72ab8SDaniel Schwierzeck#ifdef CONFIG_SYS_MALLOC_F_LEN
79*c3e72ab8SDaniel Schwierzeck	PTR_S	sp, GD_MALLOC_BASE(k0)	# gd->malloc_base offset
80*c3e72ab8SDaniel Schwierzeck#endif
81*c3e72ab8SDaniel Schwierzeck	.endm
82*c3e72ab8SDaniel Schwierzeck
8311349298SDaniel SchwierzeckENTRY(_start)
84a187559eSBin Meng	/* U-Boot entry point */
85eef88dfbSDaniel Schwierzeck	b	reset
8665d297afSDaniel Schwierzeck	 mtc0	zero, CP0_COUNT	# clear cp0 count for most accurate boot timing
87eef88dfbSDaniel Schwierzeck
88eef88dfbSDaniel Schwierzeck#if defined(CONFIG_SYS_XWAY_EBU_BOOTCFG)
89eef88dfbSDaniel Schwierzeck	/*
90eef88dfbSDaniel Schwierzeck	 * Almost all Lantiq XWAY SoC devices have an external bus unit (EBU) to
91eef88dfbSDaniel Schwierzeck	 * access external NOR flashes. If the board boots from NOR flash the
92eef88dfbSDaniel Schwierzeck	 * internal BootROM does a blind read at address 0xB0000010 to read the
93eef88dfbSDaniel Schwierzeck	 * initial configuration for that EBU in order to access the flash
94eef88dfbSDaniel Schwierzeck	 * device with correct parameters. This config option is board-specific.
95eef88dfbSDaniel Schwierzeck	 */
96af3971f8SDaniel Schwierzeck	.org 0x10
97eef88dfbSDaniel Schwierzeck	.word CONFIG_SYS_XWAY_EBU_BOOTCFG
98eef88dfbSDaniel Schwierzeck	.word 0x0
99af3971f8SDaniel Schwierzeck#endif
100af3971f8SDaniel Schwierzeck#if defined(CONFIG_MALTA)
101eef88dfbSDaniel Schwierzeck	/*
102eef88dfbSDaniel Schwierzeck	 * Linux expects the Board ID here.
103eef88dfbSDaniel Schwierzeck	 */
104af3971f8SDaniel Schwierzeck	.org 0x10
105eef88dfbSDaniel Schwierzeck	.word 0x00000420	# 0x420 (Malta Board with CoreLV)
106eef88dfbSDaniel Schwierzeck	.word 0x00000000
107eef88dfbSDaniel Schwierzeck#endif
108eef88dfbSDaniel Schwierzeck
109af3971f8SDaniel Schwierzeck#if defined(CONFIG_ROM_EXCEPTION_VECTORS)
110345490fcSDaniel Schwierzeck	/*
111345490fcSDaniel Schwierzeck	 * Exception vector entry points. When running from ROM, an exception
112345490fcSDaniel Schwierzeck	 * cannot be handled. Halt execution and transfer control to debugger,
113345490fcSDaniel Schwierzeck	 * if one is attached.
114345490fcSDaniel Schwierzeck	 */
115eef88dfbSDaniel Schwierzeck	.org 0x200
116eef88dfbSDaniel Schwierzeck	/* TLB refill, 32 bit task */
117345490fcSDaniel Schwierzeck	uhi_mips_exception
118eef88dfbSDaniel Schwierzeck
119eef88dfbSDaniel Schwierzeck	.org 0x280
120eef88dfbSDaniel Schwierzeck	/* XTLB refill, 64 bit task */
121345490fcSDaniel Schwierzeck	uhi_mips_exception
122eef88dfbSDaniel Schwierzeck
123eef88dfbSDaniel Schwierzeck	.org 0x300
124eef88dfbSDaniel Schwierzeck	/* Cache error exception */
125345490fcSDaniel Schwierzeck	uhi_mips_exception
126eef88dfbSDaniel Schwierzeck
127eef88dfbSDaniel Schwierzeck	.org 0x380
128eef88dfbSDaniel Schwierzeck	/* General exception */
129345490fcSDaniel Schwierzeck	uhi_mips_exception
130eef88dfbSDaniel Schwierzeck
131eef88dfbSDaniel Schwierzeck	.org 0x400
132eef88dfbSDaniel Schwierzeck	/* Catch interrupt exceptions */
133345490fcSDaniel Schwierzeck	uhi_mips_exception
134eef88dfbSDaniel Schwierzeck
135eef88dfbSDaniel Schwierzeck	.org 0x480
136eef88dfbSDaniel Schwierzeck	/* EJTAG debug exception */
137eef88dfbSDaniel Schwierzeck1:	b	1b
138eef88dfbSDaniel Schwierzeck	 nop
139eef88dfbSDaniel Schwierzeck
140af3971f8SDaniel Schwierzeck	.org 0x500
141af3971f8SDaniel Schwierzeck#endif
142af3971f8SDaniel Schwierzeck
143eef88dfbSDaniel Schwierzeckreset:
14431d36f74SPaul Burton#if __mips_isa_rev >= 6
14531d36f74SPaul Burton	mfc0	t0, CP0_CONFIG, 5
14631d36f74SPaul Burton	and	t0, t0, MIPS_CONF5_VP
14731d36f74SPaul Burton	beqz	t0, 1f
14831d36f74SPaul Burton	 nop
14931d36f74SPaul Burton
15031d36f74SPaul Burton	b	2f
15131d36f74SPaul Burton	 mfc0	t0, CP0_GLOBALNUMBER
15231d36f74SPaul Burton#endif
15331d36f74SPaul Burton
15431d36f74SPaul Burton1:	mfc0	t0, CP0_EBASE
15531d36f74SPaul Burton	and	t0, t0, EBASE_CPUNUM
15631d36f74SPaul Burton
15731d36f74SPaul Burton	/* Hang if this isn't the first CPU in the system */
15831d36f74SPaul Burton2:	beqz	t0, 4f
15931d36f74SPaul Burton	 nop
16031d36f74SPaul Burton3:	wait
16131d36f74SPaul Burton	b	3b
16231d36f74SPaul Burton	 nop
163eef88dfbSDaniel Schwierzeck
16465d297afSDaniel Schwierzeck	/* Init CP0 Status */
16565d297afSDaniel Schwierzeck4:	mfc0	t0, CP0_STATUS
16665d297afSDaniel Schwierzeck	and	t0, ST0_IMPL
16765d297afSDaniel Schwierzeck	or	t0, ST0_BEV | ST0_ERL | STATUS_SET
16865d297afSDaniel Schwierzeck	mtc0	t0, CP0_STATUS
16965d297afSDaniel Schwierzeck
17065d297afSDaniel Schwierzeck	/*
17165d297afSDaniel Schwierzeck	 * Check whether CP0 Config1 is implemented. If not continue
17265d297afSDaniel Schwierzeck	 * with legacy Watch register initialization.
17365d297afSDaniel Schwierzeck	 */
17465d297afSDaniel Schwierzeck	mfc0	t0, CP0_CONFIG
17565d297afSDaniel Schwierzeck	bgez	t0, wr_legacy
17665d297afSDaniel Schwierzeck	 nop
17765d297afSDaniel Schwierzeck
17865d297afSDaniel Schwierzeck	/*
17965d297afSDaniel Schwierzeck	 * Check WR bit in CP0 Config1 to determine if Watch registers
18065d297afSDaniel Schwierzeck	 * are implemented.
18165d297afSDaniel Schwierzeck	 */
18265d297afSDaniel Schwierzeck	mfc0	t0, CP0_CONFIG, 1
18365d297afSDaniel Schwierzeck	andi	t0, (1 << 3)
18465d297afSDaniel Schwierzeck	beqz	t0, wr_done
18565d297afSDaniel Schwierzeck	 nop
18665d297afSDaniel Schwierzeck
18765d297afSDaniel Schwierzeck	/* Clear Watch Status bits and disable watch exceptions */
18865d297afSDaniel Schwierzeck	li	t1, 0x7		# Clear I, R and W conditions
18965d297afSDaniel Schwierzeck	init_wr	0
19065d297afSDaniel Schwierzeck	init_wr	1
19165d297afSDaniel Schwierzeck	init_wr	2
19265d297afSDaniel Schwierzeck	init_wr	3
19365d297afSDaniel Schwierzeck	init_wr	4
19465d297afSDaniel Schwierzeck	init_wr	5
19565d297afSDaniel Schwierzeck	init_wr	6
19665d297afSDaniel Schwierzeck	init_wr	7
19765d297afSDaniel Schwierzeck	b	wr_done
19865d297afSDaniel Schwierzeck	 nop
19965d297afSDaniel Schwierzeck
20065d297afSDaniel Schwierzeckwr_legacy:
20165d297afSDaniel Schwierzeck	MTC0	zero, CP0_WATCHLO
202e26e8dc8SDaniel Schwierzeck	mtc0	zero, CP0_WATCHHI
203eef88dfbSDaniel Schwierzeck
20465d297afSDaniel Schwierzeckwr_done:
20565d297afSDaniel Schwierzeck	/* Clear WP, IV and SW interrupts */
206eef88dfbSDaniel Schwierzeck	mtc0	zero, CP0_CAUSE
207eef88dfbSDaniel Schwierzeck
20865d297afSDaniel Schwierzeck	/* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */
209eef88dfbSDaniel Schwierzeck	mtc0	zero, CP0_COMPARE
210eef88dfbSDaniel Schwierzeck
211eef88dfbSDaniel Schwierzeck#ifndef CONFIG_SKIP_LOWLEVEL_INIT
2124f9226b4SPaul Burton	mfc0	t0, CP0_CONFIG
2134f9226b4SPaul Burton	and	t0, t0, MIPS_CONF_IMPL
2144f9226b4SPaul Burton	or	t0, t0, CONF_CM_UNCACHED
215eef88dfbSDaniel Schwierzeck	mtc0	t0, CP0_CONFIG
216c5b8412dSPaul Burton	ehb
217eef88dfbSDaniel Schwierzeck#endif
218eef88dfbSDaniel Schwierzeck
219eef88dfbSDaniel Schwierzeck	/*
220eef88dfbSDaniel Schwierzeck	 * Initialize $gp, force pointer sized alignment of bal instruction to
221eef88dfbSDaniel Schwierzeck	 * forbid the compiler to put nop's between bal and _gp. This is
222eef88dfbSDaniel Schwierzeck	 * required to keep _gp and ra aligned to 8 byte.
223eef88dfbSDaniel Schwierzeck	 */
224eef88dfbSDaniel Schwierzeck	.align	PTRLOG
225eef88dfbSDaniel Schwierzeck	bal	1f
226eef88dfbSDaniel Schwierzeck	 nop
227eef88dfbSDaniel Schwierzeck	PTR	_gp
228eef88dfbSDaniel Schwierzeck1:
229eef88dfbSDaniel Schwierzeck	PTR_L	gp, 0(ra)
230eef88dfbSDaniel Schwierzeck
231b2b135d9SPaul Burton#ifdef CONFIG_MIPS_CM
232b2b135d9SPaul Burton	PTR_LA	t9, mips_cm_map
233b2b135d9SPaul Burton	jalr	t9
234b2b135d9SPaul Burton	 nop
235b2b135d9SPaul Burton#endif
236b2b135d9SPaul Burton
237eef88dfbSDaniel Schwierzeck#ifndef CONFIG_SKIP_LOWLEVEL_INIT
238f8981277SPaul Burton# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
239eef88dfbSDaniel Schwierzeck	/* Initialize any external memory */
240eef88dfbSDaniel Schwierzeck	PTR_LA	t9, lowlevel_init
241eef88dfbSDaniel Schwierzeck	jalr	t9
242eef88dfbSDaniel Schwierzeck	 nop
243f8981277SPaul Burton# endif
244eef88dfbSDaniel Schwierzeck
245eef88dfbSDaniel Schwierzeck	/* Initialize caches... */
246eef88dfbSDaniel Schwierzeck	PTR_LA	t9, mips_cache_reset
247eef88dfbSDaniel Schwierzeck	jalr	t9
248eef88dfbSDaniel Schwierzeck	 nop
249f8981277SPaul Burton
250f8981277SPaul Burton# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
251f8981277SPaul Burton	/* Initialize any external memory */
252f8981277SPaul Burton	PTR_LA	t9, lowlevel_init
253f8981277SPaul Burton	jalr	t9
254f8981277SPaul Burton	 nop
255f8981277SPaul Burton# endif
256eef88dfbSDaniel Schwierzeck#endif
257eef88dfbSDaniel Schwierzeck
258*c3e72ab8SDaniel Schwierzeck	/* Set up initial stack and global data */
259*c3e72ab8SDaniel Schwierzeck	setup_stack_gd
260e26e8dc8SDaniel Schwierzeck
261a6279099SPurna Chandra Mandal	move	a0, zero		# a0 <-- boot_flags = 0
262eef88dfbSDaniel Schwierzeck	PTR_LA	t9, board_init_f
263345490fcSDaniel Schwierzeck
264eef88dfbSDaniel Schwierzeck	jr	t9
265eef88dfbSDaniel Schwierzeck	 move	ra, zero
266eef88dfbSDaniel Schwierzeck
26711349298SDaniel Schwierzeck	END(_start)
26811349298SDaniel Schwierzeck
269eef88dfbSDaniel Schwierzeck/*
270eef88dfbSDaniel Schwierzeck * void relocate_code (addr_sp, gd, addr_moni)
271eef88dfbSDaniel Schwierzeck *
272eef88dfbSDaniel Schwierzeck * This "function" does not return, instead it continues in RAM
273eef88dfbSDaniel Schwierzeck * after relocating the monitor code.
274eef88dfbSDaniel Schwierzeck *
275eef88dfbSDaniel Schwierzeck * a0 = addr_sp
276eef88dfbSDaniel Schwierzeck * a1 = gd
277eef88dfbSDaniel Schwierzeck * a2 = destination address
278eef88dfbSDaniel Schwierzeck */
27911349298SDaniel SchwierzeckENTRY(relocate_code)
280eef88dfbSDaniel Schwierzeck	move	sp, a0			# set new stack pointer
281eef88dfbSDaniel Schwierzeck	move	fp, sp
282eef88dfbSDaniel Schwierzeck
283eef88dfbSDaniel Schwierzeck	move	s0, a1			# save gd in s0
284eef88dfbSDaniel Schwierzeck	move	s2, a2			# save destination address in s2
285eef88dfbSDaniel Schwierzeck
286eef88dfbSDaniel Schwierzeck	PTR_LI	t0, CONFIG_SYS_MONITOR_BASE
287eef88dfbSDaniel Schwierzeck	PTR_SUB	s1, s2, t0		# s1 <-- relocation offset
288eef88dfbSDaniel Schwierzeck
289d263cda5SPaul Burton	PTR_LA	t2, __image_copy_end
290eef88dfbSDaniel Schwierzeck	move	t1, a2
291eef88dfbSDaniel Schwierzeck
292eef88dfbSDaniel Schwierzeck	/*
293eef88dfbSDaniel Schwierzeck	 * t0 = source address
294eef88dfbSDaniel Schwierzeck	 * t1 = target address
295eef88dfbSDaniel Schwierzeck	 * t2 = source end address
296eef88dfbSDaniel Schwierzeck	 */
297eef88dfbSDaniel Schwierzeck1:
298e26e8dc8SDaniel Schwierzeck	PTR_L	t3, 0(t0)
299e26e8dc8SDaniel Schwierzeck	PTR_S	t3, 0(t1)
300e26e8dc8SDaniel Schwierzeck	PTR_ADDU t0, PTRSIZE
301eef88dfbSDaniel Schwierzeck	blt	t0, t2, 1b
302e26e8dc8SDaniel Schwierzeck	 PTR_ADDU t1, PTRSIZE
303eef88dfbSDaniel Schwierzeck
304eef88dfbSDaniel Schwierzeck	/*
305eef88dfbSDaniel Schwierzeck	 * Now we want to update GOT.
306eef88dfbSDaniel Schwierzeck	 *
307eef88dfbSDaniel Schwierzeck	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
308eef88dfbSDaniel Schwierzeck	 * generated by GNU ld. Skip these reserved entries from relocation.
309eef88dfbSDaniel Schwierzeck	 */
310d263cda5SPaul Burton	PTR_LA	t3, num_got_entries
311d263cda5SPaul Burton	PTR_LA	t8, _GLOBAL_OFFSET_TABLE_
312eef88dfbSDaniel Schwierzeck	PTR_ADD	t8, s1			# t8 now holds relocated _G_O_T_
3139f8ac824SPaul Burton	PTR_ADDIU t8, t8, 2 * PTRSIZE	# skipping first two entries
314eef88dfbSDaniel Schwierzeck	PTR_LI	t2, 2
315eef88dfbSDaniel Schwierzeck1:
316eef88dfbSDaniel Schwierzeck	PTR_L	t1, 0(t8)
317eef88dfbSDaniel Schwierzeck	beqz	t1, 2f
318eef88dfbSDaniel Schwierzeck	 PTR_ADD t1, s1
319eef88dfbSDaniel Schwierzeck	PTR_S	t1, 0(t8)
320eef88dfbSDaniel Schwierzeck2:
3219f8ac824SPaul Burton	PTR_ADDIU t2, 1
322eef88dfbSDaniel Schwierzeck	blt	t2, t3, 1b
3239f8ac824SPaul Burton	 PTR_ADDIU t8, PTRSIZE
324eef88dfbSDaniel Schwierzeck
325eef88dfbSDaniel Schwierzeck	/* Update dynamic relocations */
326d263cda5SPaul Burton	PTR_LA	t1, __rel_dyn_start
327d263cda5SPaul Burton	PTR_LA	t2, __rel_dyn_end
328eef88dfbSDaniel Schwierzeck
329eef88dfbSDaniel Schwierzeck	b	2f			# skip first reserved entry
3309f8ac824SPaul Burton	 PTR_ADDIU t1, 2 * PTRSIZE
331eef88dfbSDaniel Schwierzeck
332eef88dfbSDaniel Schwierzeck1:
333eef88dfbSDaniel Schwierzeck	lw	t8, -4(t1)		# t8 <-- relocation info
334eef88dfbSDaniel Schwierzeck
335eef88dfbSDaniel Schwierzeck	PTR_LI	t3, MIPS_RELOC
336eef88dfbSDaniel Schwierzeck	bne	t8, t3, 2f		# skip non-MIPS_RELOC entries
337eef88dfbSDaniel Schwierzeck	 nop
338eef88dfbSDaniel Schwierzeck
339eef88dfbSDaniel Schwierzeck	PTR_L	t3, -(2 * PTRSIZE)(t1)	# t3 <-- location to fix up in FLASH
340eef88dfbSDaniel Schwierzeck
341eef88dfbSDaniel Schwierzeck	PTR_L	t8, 0(t3)		# t8 <-- original pointer
342eef88dfbSDaniel Schwierzeck	PTR_ADD	t8, s1			# t8 <-- adjusted pointer
343eef88dfbSDaniel Schwierzeck
344eef88dfbSDaniel Schwierzeck	PTR_ADD	t3, s1			# t3 <-- location to fix up in RAM
345eef88dfbSDaniel Schwierzeck	PTR_S	t8, 0(t3)
346eef88dfbSDaniel Schwierzeck
347eef88dfbSDaniel Schwierzeck2:
348eef88dfbSDaniel Schwierzeck	blt	t1, t2, 1b
3499f8ac824SPaul Burton	 PTR_ADDIU t1, 2 * PTRSIZE	# each rel.dyn entry is 2*PTRSIZE bytes
350eef88dfbSDaniel Schwierzeck
351eef88dfbSDaniel Schwierzeck	/*
352d263cda5SPaul Burton	 * Flush caches to ensure our newly modified instructions are visible
353d263cda5SPaul Burton	 * to the instruction cache. We're still running with the old GOT, so
354d263cda5SPaul Burton	 * apply the reloc offset to the start address.
355d263cda5SPaul Burton	 */
356d263cda5SPaul Burton	PTR_LA	a0, __text_start
357d263cda5SPaul Burton	PTR_LA	a1, __text_end
358d263cda5SPaul Burton	PTR_SUB	a1, a1, a0
359d263cda5SPaul Burton	PTR_LA	t9, flush_cache
360d263cda5SPaul Burton	jalr	t9
361d263cda5SPaul Burton	 PTR_ADD	a0, s1
362d263cda5SPaul Burton
363d263cda5SPaul Burton	PTR_ADD	gp, s1			# adjust gp
364d263cda5SPaul Burton
365d263cda5SPaul Burton	/*
366eef88dfbSDaniel Schwierzeck	 * Clear BSS
367eef88dfbSDaniel Schwierzeck	 *
368eef88dfbSDaniel Schwierzeck	 * GOT is now relocated. Thus __bss_start and __bss_end can be
369eef88dfbSDaniel Schwierzeck	 * accessed directly via $gp.
370eef88dfbSDaniel Schwierzeck	 */
371eef88dfbSDaniel Schwierzeck	PTR_LA	t1, __bss_start		# t1 <-- __bss_start
372eef88dfbSDaniel Schwierzeck	PTR_LA	t2, __bss_end		# t2 <-- __bss_end
373eef88dfbSDaniel Schwierzeck
374eef88dfbSDaniel Schwierzeck1:
375eef88dfbSDaniel Schwierzeck	PTR_S	zero, 0(t1)
376eef88dfbSDaniel Schwierzeck	blt	t1, t2, 1b
3779f8ac824SPaul Burton	 PTR_ADDIU t1, PTRSIZE
378eef88dfbSDaniel Schwierzeck
379eef88dfbSDaniel Schwierzeck	move	a0, s0			# a0 <-- gd
380eef88dfbSDaniel Schwierzeck	move	a1, s2
381eef88dfbSDaniel Schwierzeck	PTR_LA	t9, board_init_r
382eef88dfbSDaniel Schwierzeck	jr	t9
383eef88dfbSDaniel Schwierzeck	 move	ra, zero
384eef88dfbSDaniel Schwierzeck
38511349298SDaniel Schwierzeck	END(relocate_code)
386