u-boot-brain/arch/mips/cpu/mips32/start.S
Daniel Schwierzeck 696a3b2a53 MIPS: start.S: optimize BSS initialization
Get the start and end address for clearing BSS from the newly
introduced symbols __bss_start and __bss_end. After GOT is
relocated, those symbols are already pointing to the correct
addresses.

Also optimize the loop by moving the address incrementation
to the delay slot to avoid the initial sub instruction.

Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
2013-02-12 22:22:13 +01:00

251 lines
5.0 KiB
ArmAsm

/*
* Startup Code for MIPS32 CPU-core
*
* Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
*
* 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 <asm-offsets.h>
#include <config.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#ifndef CONFIG_SYS_MIPS_CACHE_MODE
#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
#endif
/*
* For the moment disable interrupts, mark the kernel mode and
* set ST0_KX so that the CPU does not spit fire when using
* 64-bit addresses.
*/
.macro setup_c0_status set clr
.set push
mfc0 t0, CP0_STATUS
or t0, ST0_CU0 | \set | 0x1f | \clr
xor t0, 0x1f | \clr
mtc0 t0, CP0_STATUS
.set noreorder
sll zero, 3 # ehb
.set pop
.endm
.set noreorder
.globl _start
.text
_start:
/* U-boot entry point */
b reset
nop
.org 0x10
#ifdef CONFIG_SYS_XWAY_EBU_BOOTCFG
/*
* Almost all Lantiq XWAY SoC devices have an external bus unit (EBU) to
* access external NOR flashes. If the board boots from NOR flash the
* internal BootROM does a blind read at address 0xB0000010 to read the
* initial configuration for that EBU in order to access the flash
* device with correct parameters. This config option is board-specific.
*/
.word CONFIG_SYS_XWAY_EBU_BOOTCFG
.word 0x0
#endif
.org 0x200
/* TLB refill, 32 bit task */
1: b 1b
nop
.org 0x280
/* XTLB refill, 64 bit task */
1: b 1b
nop
.org 0x300
/* Cache error exception */
1: b 1b
nop
.org 0x380
/* General exception */
1: b 1b
nop
.org 0x400
/* Catch interrupt exceptions */
1: b 1b
nop
.org 0x480
/* EJTAG debug exception */
1: b 1b
nop
.align 4
reset:
/* Clear watch registers */
mtc0 zero, CP0_WATCHLO
mtc0 zero, CP0_WATCHHI
/* WP(Watch Pending), SW0/1 should be cleared */
mtc0 zero, CP0_CAUSE
setup_c0_status 0 0
/* Init Timer */
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/* CONFIG0 register */
li t0, CONF_CM_UNCACHED
mtc0 t0, CP0_CONFIG
#endif
/* Initialize $gp */
bal 1f
nop
.word _gp
1:
lw gp, 0(ra)
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/* Initialize any external memory */
la t9, lowlevel_init
jalr t9
nop
/* Initialize caches... */
la t9, mips_cache_reset
jalr t9
nop
/* ... and enable them */
li t0, CONFIG_SYS_MIPS_CACHE_MODE
mtc0 t0, CP0_CONFIG
#endif
/* 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
move s0, a1 # save gd in s0
move s2, a2 # save destination address in s2
li t0, CONFIG_SYS_MONITOR_BASE
sub s1, s2, t0 # s1 <-- relocation offset
la t3, in_ram
lw t2, -12(t3) # t2 <-- uboot_end_data
move t1, a2
add gp, s1 # 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. */
sub a1, t1, s2 # a1 <-- size
la t9, flush_cache
jalr t9
move a0, s2 # a0 <-- destination address
/* Jump to where we've relocated ourselves */
addi t0, s2, in_ram - _start
jr t0
nop
.word _GLOBAL_OFFSET_TABLE_
.word uboot_end_data
.word uboot_end
.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, -16(t0) # t4 <-- _GLOBAL_OFFSET_TABLE_
add t4, s1 # 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, s1
sw t1, 0(t4)
2:
addi t2, 1
blt t2, t3, 1b
addi t4, 4
/*
* 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, s0 # a0 <-- gd
la t9, board_init_r
jr t9
move a1, s2
.end relocate_code