diff options
Diffstat (limited to 'arch/mips/cpu/mips64/start.S')
-rw-r--r-- | arch/mips/cpu/mips64/start.S | 148 |
1 files changed, 82 insertions, 66 deletions
diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S index 2b8d531e73..dc7ce07ce7 100644 --- a/arch/mips/cpu/mips64/start.S +++ b/arch/mips/cpu/mips64/start.S @@ -31,6 +31,14 @@ #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT #endif +#ifdef CONFIG_SYS_LITTLE_ENDIAN +#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \ + (((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym)) +#else +#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \ + ((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24) +#endif + /* * For the moment disable interrupts, mark the kernel mode and * set ST0_KX so that the CPU does not spit fire when using @@ -52,40 +60,40 @@ .globl _start .text _start: - .org 0x000 + /* U-boot entry point */ b reset nop - .org 0x080 - b romReserved - nop - .org 0x100 - b romReserved - nop - .org 0x180 - b romReserved - nop + .org 0x200 - b romReserved + /* TLB refill, 32 bit task */ +1: b 1b nop + .org 0x280 - b romReserved + /* XTLB refill, 64 bit task */ +1: b 1b nop + .org 0x300 - b romReserved + /* Cache error exception */ +1: b 1b nop + .org 0x380 - b romReserved + /* General exception */ +1: b 1b + nop + + .org 0x400 + /* Catch interrupt exceptions */ +1: b 1b nop + .org 0x480 - b romReserved + /* EJTAG debug exception */ +1: b 1b nop - /* - * We hope there are no more reserved vectors! - * 128 * 8 == 1024 == 0x400 - * so this is address R_VEC+0x400 == 0xbfc00400 - */ - .org 0x500 .align 4 reset: @@ -137,8 +145,7 @@ reset: #endif /* Set up temporary stack */ - dli t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET - dla sp, 0(t0) + dli sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET dla t9, board_init_f jr t9 @@ -159,58 +166,45 @@ reset: relocate_code: move sp, a0 # set new stack pointer + move s0, a1 # save gd in s0 + move s2, a2 # save destination address in s2 + dli t0, CONFIG_SYS_MONITOR_BASE + dsub s1, s2, t0 # s1 <-- relocation offset + dla t3, in_ram - ld t2, -24(t3) # t2 <-- uboot_end_data + ld t2, -24(t3) # t2 <-- __image_copy_end move t1, a2 - move s2, a2 # s2 <-- destination address - /* - * Fix $gp: - * - * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address - */ - move t8, gp - dsub gp, CONFIG_SYS_MONITOR_BASE - dadd gp, a2 # gp now adjusted - dsub s1, gp, t8 # s1 <-- relocation offset + dadd gp, s1 # adjust gp /* * t0 = source address * t1 = target address * t2 = source end address */ - - /* - * Save destination address and size for dlater usage in flush_cache() - */ - move s0, a1 # save gd in s0 - move a0, t1 # a0 <-- destination addr - dsub a1, t2, t0 # a1 <-- size - 1: lw t3, 0(t0) sw t3, 0(t1) daddu t0, 4 - ble t0, t2, 1b + blt t0, t2, 1b daddu t1, 4 /* If caches were enabled, we would have to flush them here. */ - - /* a0 & a1 are already set up for flush_cache(start, size) */ + dsub a1, t1, s2 # a1 <-- size dla t9, flush_cache jalr t9 - nop + move a0, s2 # a0 <-- destination address /* Jump to where we've relocated ourselves */ daddi t0, s2, in_ram - _start jr t0 nop - .dword _gp + .dword __rel_dyn_end + .dword __rel_dyn_start + .dword __image_copy_end .dword _GLOBAL_OFFSET_TABLE_ - .dword uboot_end_data - .dword uboot_end .dword num_got_entries in_ram: @@ -221,10 +215,8 @@ in_ram: * generated by GNU ld. Skip these reserved entries from relocation. */ ld t3, -8(t0) # t3 <-- num_got_entries - ld t8, -32(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_ - ld t9, -40(t0) # t9 <-- _gp - dsub t8, t9 # compute offset - dadd t8, t8, gp # t8 now holds relocated _G_O_T_ + ld t8, -16(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_ + dadd t8, s1 # t8 now holds relocated _G_O_T_ daddi t8, t8, 16 # skipping first two entries dli t2, 2 1: @@ -237,17 +229,45 @@ in_ram: blt t2, t3, 1b daddi t8, 8 - /* Clear BSS */ - ld t1, -24(t0) # t1 <-- uboot_end_data - ld t2, -16(t0) # t2 <-- uboot_end - dadd t1, s1 # adjust pointers - dadd t2, s1 + /* Update dynamic relocations */ + ld t1, -32(t0) # t1 <-- __rel_dyn_start + ld t2, -40(t0) # t2 <-- __rel_dyn_end + + b 2f # skip first reserved entry + daddi t1, 16 - dsub t1, 8 1: - daddi t1, 8 - bltl t1, t2, 1b - sd zero, 0(t1) + lw t8, -4(t1) # t8 <-- relocation info + + dli t3, MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03) + bne t8, t3, 2f # skip non R_MIPS_REL32 entries + nop + + ld t3, -16(t1) # t3 <-- location to fix up in FLASH + + ld t8, 0(t3) # t8 <-- original pointer + dadd t8, s1 # t8 <-- adjusted pointer + + dadd t3, s1 # t3 <-- location to fix up in RAM + sd t8, 0(t3) + +2: + blt t1, t2, 1b + daddi t1, 16 # each rel.dyn entry is 16 bytes + + /* + * Clear BSS + * + * GOT is now relocated. Thus __bss_start and __bss_end can be + * accessed directly via $gp. + */ + dla t1, __bss_start # t1 <-- __bss_start + dla t2, __bss_end # t2 <-- __bss_end + +1: + sd zero, 0(t1) + blt t1, t2, 1b + daddi t1, 8 move a0, s0 # a0 <-- gd dla t9, board_init_r @@ -255,7 +275,3 @@ in_ram: move a1, s2 .end relocate_code - - /* Exception handlers */ -romReserved: - b romReserved |