uboot/arch/microblaze/cpu/start.S
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007 Michal Simek
   3 * (C) Copyright 2004 Atmark Techno, Inc.
   4 *
   5 * Michal  SIMEK <monstr@monstr.eu>
   6 * Yasushi SHOJI <yashi@atmark-techno.com>
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <asm-offsets.h>
  12#include <config.h>
  13
  14        .text
  15        .global _start
  16_start:
  17        /*
  18         * reserve registers:
  19         * r10: Stores little/big endian offset for vectors
  20         * r2: Stores imm opcode
  21         * r3: Stores brai opcode
  22         */
  23
  24        mts     rmsr, r0        /* disable cache */
  25
  26        addi    r8, r0, __end
  27        mts     rslr, r8
  28#if defined(CONFIG_SPL_BUILD)
  29        addi    r1, r0, CONFIG_SPL_STACK_ADDR
  30        mts     rshr, r1
  31        addi    r1, r1, -4      /* Decrement SP to top of memory */
  32#else
  33#if defined(CONFIG_SYS_MALLOC_F_LEN)
  34        addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
  35#else
  36        addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
  37#endif
  38        mts     rshr, r1
  39        addi    r1, r1, -4      /* Decrement SP to top of memory */
  40
  41        /* Find-out if u-boot is running on BIG/LITTLE endian platform
  42         * There are some steps which is necessary to keep in mind:
  43         * 1. Setup offset value to r6
  44         * 2. Store word offset value to address 0x0
  45         * 3. Load just byte from address 0x0
  46         * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
  47         *     value that's why is on address 0x0
  48         * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
  49         */
  50        addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
  51        lwi     r7, r0, 0x28
  52        swi     r6, r0, 0x28 /* used first unused MB vector */
  53        lbui    r10, r0, 0x28 /* used first unused MB vector */
  54        swi     r7, r0, 0x28
  55
  56        /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
  57        addi    r2, r0, 0xb0000000      /* hex b000 opcode imm */
  58        addi    r3, r0, 0xb8080000      /* hew b808 opcode brai */
  59
  60#ifdef CONFIG_SYS_RESET_ADDRESS
  61        /* reset address */
  62        swi     r2, r0, 0x0     /* reset address - imm opcode */
  63        swi     r3, r0, 0x4     /* reset address - brai opcode */
  64
  65        addik   r6, r0, CONFIG_SYS_RESET_ADDRESS
  66        sw      r6, r1, r0
  67        lhu     r7, r1, r10
  68        rsubi   r8, r10, 0x2
  69        sh      r7, r0, r8
  70        rsubi   r8, r10, 0x6
  71        sh      r6, r0, r8
  72#endif
  73
  74#ifdef CONFIG_SYS_USR_EXCEP
  75        /* user_vector_exception */
  76        swi     r2, r0, 0x8     /* user vector exception - imm opcode */
  77        swi     r3, r0, 0xC     /* user vector exception - brai opcode */
  78
  79        addik   r6, r0, _exception_handler
  80        sw      r6, r1, r0
  81        /*
  82         * BIG ENDIAN memory map for user exception
  83         * 0x8: 0xB000XXXX
  84         * 0xC: 0xB808XXXX
  85         *
  86         * then it is necessary to count address for storing the most significant
  87         * 16bits from _exception_handler address and copy it to
  88         * 0xa address. Big endian use offset in r10=0 that's why is it just
  89         * 0xa address. The same is done for the least significant 16 bits
  90         * for 0xe address.
  91         *
  92         * LITTLE ENDIAN memory map for user exception
  93         * 0x8: 0xXXXX00B0
  94         * 0xC: 0xXXXX08B8
  95         *
  96         * Offset is for little endian setup to 0x2. rsubi instruction decrease
  97         * address value to ensure that points to proper place which is
  98         * 0x8 for the most significant 16 bits and
  99         * 0xC for the least significant 16 bits
 100         */
 101        lhu     r7, r1, r10
 102        rsubi   r8, r10, 0xa
 103        sh      r7, r0, r8
 104        rsubi   r8, r10, 0xe
 105        sh      r6, r0, r8
 106#endif
 107
 108        /* interrupt_handler */
 109        swi     r2, r0, 0x10    /* interrupt - imm opcode */
 110        swi     r3, r0, 0x14    /* interrupt - brai opcode */
 111
 112        addik   r6, r0, _interrupt_handler
 113        sw      r6, r1, r0
 114        lhu     r7, r1, r10
 115        rsubi   r8, r10, 0x12
 116        sh      r7, r0, r8
 117        rsubi   r8, r10, 0x16
 118        sh      r6, r0, r8
 119
 120        /* hardware exception */
 121        swi     r2, r0, 0x20    /* hardware exception - imm opcode */
 122        swi     r3, r0, 0x24    /* hardware exception - brai opcode */
 123
 124        addik   r6, r0, _hw_exception_handler
 125        sw      r6, r1, r0
 126        lhu     r7, r1, r10
 127        rsubi   r8, r10, 0x22
 128        sh      r7, r0, r8
 129        rsubi   r8, r10, 0x26
 130        sh      r6, r0, r8
 131#endif /* BUILD_SPL */
 132
 133        /* Flush cache before enable cache */
 134        addik   r5, r0, 0
 135        addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
 136        bralid r15, flush_cache
 137        nop
 138
 139        /* enable instruction and data cache */
 140        mfs     r12, rmsr
 141        ori     r12, r12, 0x1a0
 142        mts     rmsr, r12
 143
 144clear_bss:
 145        /* clear BSS segments */
 146        addi    r5, r0, __bss_start
 147        addi    r4, r0, __bss_end
 148        cmp     r6, r5, r4
 149        beqi    r6, 3f
 1502:
 151        swi     r0, r5, 0 /* write zero to loc */
 152        addi    r5, r5, 4 /* increment to next loc */
 153        cmp     r6, r5, r4 /* check if we have reach the end */
 154        bnei    r6, 2b
 1553:      /* jumping to board_init */
 156#ifndef CONFIG_SPL_BUILD
 157        or      r5, r0, r0      /* flags - empty */
 158        addi    r31, r0, _gd
 159#if defined(CONFIG_SYS_MALLOC_F_LEN)
 160        addi    r6, r0, CONFIG_SYS_INIT_SP_OFFSET
 161        swi     r6, r31, GD_MALLOC_BASE
 162#endif
 163        brai    board_init_f
 164#else
 165        addi    r31, r0, _gd
 166#if defined(CONFIG_SYS_MALLOC_F_LEN)
 167        addi    r6, r0, CONFIG_SPL_STACK_ADDR
 168        swi     r6, r31, GD_MALLOC_BASE
 169#endif
 170        brai    board_init_r
 171#endif
 1721:      bri     1b
 173
 174 .section .bss
 175.align 4
 176_gd:
 177         .space  GENERATED_GBL_DATA_SIZE
 178
 179#ifndef CONFIG_SPL_BUILD
 180/*
 181 * Read 16bit little endian
 182 */
 183        .text
 184        .global in16
 185        .ent    in16
 186        .align  2
 187in16:   lhu     r3, r0, r5
 188        bslli   r4, r3, 8
 189        bsrli   r3, r3, 8
 190        andi    r4, r4, 0xffff
 191        or      r3, r3, r4
 192        rtsd    r15, 8
 193        sext16  r3, r3
 194        .end    in16
 195
 196/*
 197 * Write 16bit little endian
 198 * first parameter(r5) - address, second(r6) - short value
 199 */
 200        .text
 201        .global out16
 202        .ent    out16
 203        .align  2
 204out16:  bslli   r3, r6, 8
 205        bsrli   r6, r6, 8
 206        andi    r3, r3, 0xffff
 207        or      r3, r3, r6
 208        sh      r3, r0, r5
 209        rtsd    r15, 8
 210        or      r0, r0, r0
 211        .end    out16
 212
 213/*
 214 * Relocate u-boot
 215 */
 216        .text
 217        .global relocate_code
 218        .ent    relocate_code
 219        .align  2
 220relocate_code:
 221        /*
 222         * r5 - start_addr_sp
 223         * r6 - new_gd
 224         * r7 - reloc_addr
 225         */
 226        addi    r1, r5, 0 /* Start to use new SP */
 227        addi    r31, r6, 0 /* Start to use new GD */
 228
 229        add     r23, r0, r7 /* Move reloc addr to r23 */
 230        /* Relocate text and data - r12 temp value */
 231        addi    r21, r0, _start
 232        addi    r22, r0, __end - 4 /* Include BSS too */
 233
 234        rsub    r6, r21, r22
 235        or      r5, r0, r0
 2361:      lw      r12, r21, r5 /* Load u-boot data */
 237        sw      r12, r23, r5 /* Write zero to loc */
 238        cmp     r12, r5, r6 /* Check if we have reach the end */
 239        bneid   r12, 1b
 240        addi    r5, r5, 4 /* Increment to next loc - relocate code */
 241
 242       /* R23 points to the base address. */
 243        add     r23, r0, r7 /* Move reloc addr to r23 */
 244        addi    r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
 245        rsub    r23, r24, r23 /* keep - this is already here gd->reloc_off */
 246
 247        addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
 248        lwi     r7, r0, 0x28
 249        swi     r6, r0, 0x28 /* used first unused MB vector */
 250        lbui    r10, r0, 0x28 /* used first unused MB vector */
 251        swi     r7, r0, 0x28
 252
 253#ifdef CONFIG_SYS_USR_EXCEP
 254        addik   r6, r0, _exception_handler
 255        addk    r6, r6, r23 /* add offset */
 256        sw      r6, r1, r0
 257        lhu     r7, r1, r10
 258        rsubi   r8, r10, 0xa
 259        sh      r7, r0, r8
 260        rsubi   r8, r10, 0xe
 261        sh      r6, r0, r8
 262#endif
 263        addik   r6, r0, _hw_exception_handler
 264        addk    r6, r6, r23 /* add offset */
 265        sw      r6, r1, r0
 266        lhu     r7, r1, r10
 267        rsubi   r8, r10, 0x22
 268        sh      r7, r0, r8
 269        rsubi   r8, r10, 0x26
 270        sh      r6, r0, r8
 271
 272        addik   r6, r0, _interrupt_handler
 273        addk    r6, r6, r23 /* add offset */
 274        sw      r6, r1, r0
 275        lhu     r7, r1, r10
 276        rsubi   r8, r10, 0x12
 277        sh      r7, r0, r8
 278        rsubi   r8, r10, 0x16
 279        sh      r6, r0, r8
 280
 281        /* Check if GOT exist */
 282        addik   r21, r23, _got_start
 283        addik   r22, r23, _got_end
 284        cmpu    r12, r21, r22
 285        beqi    r12, 2f /* No GOT table - jump over */
 286
 287        /* Skip last 3 entries plus 1 because of loop boundary below */
 288        addik   r22, r22, -0x10
 289
 290        /* Relocate the GOT. */
 2913:      lw      r12, r21, r0 /* Load entry */
 292        addk    r12, r12, r23 /* Add reloc offset */
 293        sw      r12, r21, r0 /* Save entry back */
 294
 295        cmpu    r12, r21, r22 /* Check if this cross boundary */
 296        bneid   r12, 3b
 297        addik   r21. r21, 4
 298
 299        /* Update pointer to GOT */
 300        mfs     r20, rpc
 301        addik   r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
 302        addk    r20, r20, r23
 303
 304        /* Flush caches to ensure consistency */
 305        addik   r5, r0, 0
 306        addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
 307        bralid  r15, flush_cache
 308        nop
 309
 3102:      addi    r5, r31, 0 /* gd is initialized in board_r.c */
 311        addi    r6, r0, CONFIG_SYS_TEXT_BASE
 312        addi    r12, r23, board_init_r
 313        bra     r12 /* Jump to relocated code */
 314
 315        .end    relocate_code
 316#endif
 317