xref: /rk3399_rockchip-uboot/arch/mips/cpu/start.S (revision 0d159d6852e2bafc453206a327e267124704a30e)
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
55c3e72ab8SDaniel Schwierzeck	.macro setup_stack_gd
56c3e72ab8SDaniel Schwierzeck	li	t0, -16
57c3e72ab8SDaniel Schwierzeck	PTR_LI	t1, CONFIG_SYS_INIT_SP_ADDR
58c3e72ab8SDaniel Schwierzeck	and	sp, t1, t0		# force 16 byte alignment
59c3e72ab8SDaniel Schwierzeck	PTR_SUBU \
60c3e72ab8SDaniel Schwierzeck		sp, sp, GD_SIZE		# reserve space for gd
61c3e72ab8SDaniel Schwierzeck	and	sp, sp, t0		# force 16 byte alignment
62c3e72ab8SDaniel Schwierzeck	move	k0, sp			# save gd pointer
63c3e72ab8SDaniel Schwierzeck#ifdef CONFIG_SYS_MALLOC_F_LEN
64c3e72ab8SDaniel Schwierzeck	li	t2, CONFIG_SYS_MALLOC_F_LEN
65c3e72ab8SDaniel Schwierzeck	PTR_SUBU \
66c3e72ab8SDaniel Schwierzeck		sp, sp, t2		# reserve space for early malloc
67c3e72ab8SDaniel Schwierzeck	and	sp, sp, t0		# force 16 byte alignment
68c3e72ab8SDaniel Schwierzeck#endif
69c3e72ab8SDaniel Schwierzeck	move	fp, sp
70c3e72ab8SDaniel Schwierzeck
71c3e72ab8SDaniel Schwierzeck	/* Clear gd */
72c3e72ab8SDaniel Schwierzeck	move	t0, k0
73c3e72ab8SDaniel Schwierzeck1:
74c3e72ab8SDaniel Schwierzeck	PTR_S	zero, 0(t0)
75c3e72ab8SDaniel Schwierzeck	blt	t0, t1, 1b
76c3e72ab8SDaniel Schwierzeck	 PTR_ADDIU t0, PTRSIZE
77c3e72ab8SDaniel Schwierzeck
78c3e72ab8SDaniel Schwierzeck#ifdef CONFIG_SYS_MALLOC_F_LEN
79c3e72ab8SDaniel Schwierzeck	PTR_S	sp, GD_MALLOC_BASE(k0)	# gd->malloc_base offset
80c3e72ab8SDaniel Schwierzeck#endif
81c3e72ab8SDaniel Schwierzeck	.endm
82c3e72ab8SDaniel 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
237924ad866SDaniel Schwierzeck#ifdef CONFIG_MIPS_INIT_STACK_IN_SRAM
238924ad866SDaniel Schwierzeck	/* Set up initial stack and global data */
239924ad866SDaniel Schwierzeck	setup_stack_gd
240*0d159d68SDaniel Schwierzeck
241*0d159d68SDaniel Schwierzeck# ifdef CONFIG_DEBUG_UART
242*0d159d68SDaniel Schwierzeck	/* Earliest point to set up debug uart */
243*0d159d68SDaniel Schwierzeck	PTR_LA	t9, debug_uart_init
244*0d159d68SDaniel Schwierzeck	jalr	t9
245*0d159d68SDaniel Schwierzeck	 nop
246*0d159d68SDaniel Schwierzeck# endif
247924ad866SDaniel Schwierzeck#endif
248924ad866SDaniel Schwierzeck
249eef88dfbSDaniel Schwierzeck#ifndef CONFIG_SKIP_LOWLEVEL_INIT
250f8981277SPaul Burton# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
251eef88dfbSDaniel Schwierzeck	/* Initialize any external memory */
252eef88dfbSDaniel Schwierzeck	PTR_LA	t9, lowlevel_init
253eef88dfbSDaniel Schwierzeck	jalr	t9
254eef88dfbSDaniel Schwierzeck	 nop
255f8981277SPaul Burton# endif
256eef88dfbSDaniel Schwierzeck
257eef88dfbSDaniel Schwierzeck	/* Initialize caches... */
258eef88dfbSDaniel Schwierzeck	PTR_LA	t9, mips_cache_reset
259eef88dfbSDaniel Schwierzeck	jalr	t9
260eef88dfbSDaniel Schwierzeck	 nop
261f8981277SPaul Burton
262f8981277SPaul Burton# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
263f8981277SPaul Burton	/* Initialize any external memory */
264f8981277SPaul Burton	PTR_LA	t9, lowlevel_init
265f8981277SPaul Burton	jalr	t9
266f8981277SPaul Burton	 nop
267f8981277SPaul Burton# endif
268eef88dfbSDaniel Schwierzeck#endif
269eef88dfbSDaniel Schwierzeck
270924ad866SDaniel Schwierzeck#ifndef CONFIG_MIPS_INIT_STACK_IN_SRAM
271c3e72ab8SDaniel Schwierzeck	/* Set up initial stack and global data */
272c3e72ab8SDaniel Schwierzeck	setup_stack_gd
273*0d159d68SDaniel Schwierzeck
274*0d159d68SDaniel Schwierzeck# ifdef CONFIG_DEBUG_UART
275*0d159d68SDaniel Schwierzeck	/* Earliest point to set up debug uart */
276*0d159d68SDaniel Schwierzeck	PTR_LA	t9, debug_uart_init
277*0d159d68SDaniel Schwierzeck	jalr	t9
278*0d159d68SDaniel Schwierzeck	 nop
279*0d159d68SDaniel Schwierzeck# endif
280924ad866SDaniel Schwierzeck#endif
281e26e8dc8SDaniel Schwierzeck
282a6279099SPurna Chandra Mandal	move	a0, zero		# a0 <-- boot_flags = 0
283eef88dfbSDaniel Schwierzeck	PTR_LA	t9, board_init_f
284345490fcSDaniel Schwierzeck
285eef88dfbSDaniel Schwierzeck	jr	t9
286eef88dfbSDaniel Schwierzeck	 move	ra, zero
287eef88dfbSDaniel Schwierzeck
28811349298SDaniel Schwierzeck	END(_start)
28911349298SDaniel Schwierzeck
290eef88dfbSDaniel Schwierzeck/*
291eef88dfbSDaniel Schwierzeck * void relocate_code (addr_sp, gd, addr_moni)
292eef88dfbSDaniel Schwierzeck *
293eef88dfbSDaniel Schwierzeck * This "function" does not return, instead it continues in RAM
294eef88dfbSDaniel Schwierzeck * after relocating the monitor code.
295eef88dfbSDaniel Schwierzeck *
296eef88dfbSDaniel Schwierzeck * a0 = addr_sp
297eef88dfbSDaniel Schwierzeck * a1 = gd
298eef88dfbSDaniel Schwierzeck * a2 = destination address
299eef88dfbSDaniel Schwierzeck */
30011349298SDaniel SchwierzeckENTRY(relocate_code)
301eef88dfbSDaniel Schwierzeck	move	sp, a0			# set new stack pointer
302eef88dfbSDaniel Schwierzeck	move	fp, sp
303eef88dfbSDaniel Schwierzeck
304eef88dfbSDaniel Schwierzeck	move	s0, a1			# save gd in s0
305eef88dfbSDaniel Schwierzeck	move	s2, a2			# save destination address in s2
306eef88dfbSDaniel Schwierzeck
307eef88dfbSDaniel Schwierzeck	PTR_LI	t0, CONFIG_SYS_MONITOR_BASE
308eef88dfbSDaniel Schwierzeck	PTR_SUB	s1, s2, t0		# s1 <-- relocation offset
309eef88dfbSDaniel Schwierzeck
310d263cda5SPaul Burton	PTR_LA	t2, __image_copy_end
311eef88dfbSDaniel Schwierzeck	move	t1, a2
312eef88dfbSDaniel Schwierzeck
313eef88dfbSDaniel Schwierzeck	/*
314eef88dfbSDaniel Schwierzeck	 * t0 = source address
315eef88dfbSDaniel Schwierzeck	 * t1 = target address
316eef88dfbSDaniel Schwierzeck	 * t2 = source end address
317eef88dfbSDaniel Schwierzeck	 */
318eef88dfbSDaniel Schwierzeck1:
319e26e8dc8SDaniel Schwierzeck	PTR_L	t3, 0(t0)
320e26e8dc8SDaniel Schwierzeck	PTR_S	t3, 0(t1)
321e26e8dc8SDaniel Schwierzeck	PTR_ADDU t0, PTRSIZE
322eef88dfbSDaniel Schwierzeck	blt	t0, t2, 1b
323e26e8dc8SDaniel Schwierzeck	 PTR_ADDU t1, PTRSIZE
324eef88dfbSDaniel Schwierzeck
325eef88dfbSDaniel Schwierzeck	/*
326eef88dfbSDaniel Schwierzeck	 * Now we want to update GOT.
327eef88dfbSDaniel Schwierzeck	 *
328eef88dfbSDaniel Schwierzeck	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
329eef88dfbSDaniel Schwierzeck	 * generated by GNU ld. Skip these reserved entries from relocation.
330eef88dfbSDaniel Schwierzeck	 */
331d263cda5SPaul Burton	PTR_LA	t3, num_got_entries
332d263cda5SPaul Burton	PTR_LA	t8, _GLOBAL_OFFSET_TABLE_
333eef88dfbSDaniel Schwierzeck	PTR_ADD	t8, s1			# t8 now holds relocated _G_O_T_
3349f8ac824SPaul Burton	PTR_ADDIU t8, t8, 2 * PTRSIZE	# skipping first two entries
335eef88dfbSDaniel Schwierzeck	PTR_LI	t2, 2
336eef88dfbSDaniel Schwierzeck1:
337eef88dfbSDaniel Schwierzeck	PTR_L	t1, 0(t8)
338eef88dfbSDaniel Schwierzeck	beqz	t1, 2f
339eef88dfbSDaniel Schwierzeck	 PTR_ADD t1, s1
340eef88dfbSDaniel Schwierzeck	PTR_S	t1, 0(t8)
341eef88dfbSDaniel Schwierzeck2:
3429f8ac824SPaul Burton	PTR_ADDIU t2, 1
343eef88dfbSDaniel Schwierzeck	blt	t2, t3, 1b
3449f8ac824SPaul Burton	 PTR_ADDIU t8, PTRSIZE
345eef88dfbSDaniel Schwierzeck
346eef88dfbSDaniel Schwierzeck	/* Update dynamic relocations */
347d263cda5SPaul Burton	PTR_LA	t1, __rel_dyn_start
348d263cda5SPaul Burton	PTR_LA	t2, __rel_dyn_end
349eef88dfbSDaniel Schwierzeck
350eef88dfbSDaniel Schwierzeck	b	2f			# skip first reserved entry
3519f8ac824SPaul Burton	 PTR_ADDIU t1, 2 * PTRSIZE
352eef88dfbSDaniel Schwierzeck
353eef88dfbSDaniel Schwierzeck1:
354eef88dfbSDaniel Schwierzeck	lw	t8, -4(t1)		# t8 <-- relocation info
355eef88dfbSDaniel Schwierzeck
356eef88dfbSDaniel Schwierzeck	PTR_LI	t3, MIPS_RELOC
357eef88dfbSDaniel Schwierzeck	bne	t8, t3, 2f		# skip non-MIPS_RELOC entries
358eef88dfbSDaniel Schwierzeck	 nop
359eef88dfbSDaniel Schwierzeck
360eef88dfbSDaniel Schwierzeck	PTR_L	t3, -(2 * PTRSIZE)(t1)	# t3 <-- location to fix up in FLASH
361eef88dfbSDaniel Schwierzeck
362eef88dfbSDaniel Schwierzeck	PTR_L	t8, 0(t3)		# t8 <-- original pointer
363eef88dfbSDaniel Schwierzeck	PTR_ADD	t8, s1			# t8 <-- adjusted pointer
364eef88dfbSDaniel Schwierzeck
365eef88dfbSDaniel Schwierzeck	PTR_ADD	t3, s1			# t3 <-- location to fix up in RAM
366eef88dfbSDaniel Schwierzeck	PTR_S	t8, 0(t3)
367eef88dfbSDaniel Schwierzeck
368eef88dfbSDaniel Schwierzeck2:
369eef88dfbSDaniel Schwierzeck	blt	t1, t2, 1b
3709f8ac824SPaul Burton	 PTR_ADDIU t1, 2 * PTRSIZE	# each rel.dyn entry is 2*PTRSIZE bytes
371eef88dfbSDaniel Schwierzeck
372eef88dfbSDaniel Schwierzeck	/*
373d263cda5SPaul Burton	 * Flush caches to ensure our newly modified instructions are visible
374d263cda5SPaul Burton	 * to the instruction cache. We're still running with the old GOT, so
375d263cda5SPaul Burton	 * apply the reloc offset to the start address.
376d263cda5SPaul Burton	 */
377d263cda5SPaul Burton	PTR_LA	a0, __text_start
378d263cda5SPaul Burton	PTR_LA	a1, __text_end
379d263cda5SPaul Burton	PTR_SUB	a1, a1, a0
380d263cda5SPaul Burton	PTR_LA	t9, flush_cache
381d263cda5SPaul Burton	jalr	t9
382d263cda5SPaul Burton	 PTR_ADD	a0, s1
383d263cda5SPaul Burton
384d263cda5SPaul Burton	PTR_ADD	gp, s1			# adjust gp
385d263cda5SPaul Burton
386d263cda5SPaul Burton	/*
387eef88dfbSDaniel Schwierzeck	 * Clear BSS
388eef88dfbSDaniel Schwierzeck	 *
389eef88dfbSDaniel Schwierzeck	 * GOT is now relocated. Thus __bss_start and __bss_end can be
390eef88dfbSDaniel Schwierzeck	 * accessed directly via $gp.
391eef88dfbSDaniel Schwierzeck	 */
392eef88dfbSDaniel Schwierzeck	PTR_LA	t1, __bss_start		# t1 <-- __bss_start
393eef88dfbSDaniel Schwierzeck	PTR_LA	t2, __bss_end		# t2 <-- __bss_end
394eef88dfbSDaniel Schwierzeck
395eef88dfbSDaniel Schwierzeck1:
396eef88dfbSDaniel Schwierzeck	PTR_S	zero, 0(t1)
397eef88dfbSDaniel Schwierzeck	blt	t1, t2, 1b
3989f8ac824SPaul Burton	 PTR_ADDIU t1, PTRSIZE
399eef88dfbSDaniel Schwierzeck
400eef88dfbSDaniel Schwierzeck	move	a0, s0			# a0 <-- gd
401eef88dfbSDaniel Schwierzeck	move	a1, s2
402eef88dfbSDaniel Schwierzeck	PTR_LA	t9, board_init_r
403eef88dfbSDaniel Schwierzeck	jr	t9
404eef88dfbSDaniel Schwierzeck	 move	ra, zero
405eef88dfbSDaniel Schwierzeck
40611349298SDaniel Schwierzeck	END(relocate_code)
407