root/arch/nios2/boot/compressed/head.S
/*
 * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
 *
 * Based on arch/nios2/kernel/head.S
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 */

/*
 *  This code can be loaded anywhere, eg FLASH ROM as reset vector,
 *  as long as output does not overlap it.
 */

#include <linux/linkage.h>
#include <asm/cache.h>

        .text
        .set noat
ENTRY(_start)
        wrctl   status, r0              /* disable interrupt */
        /* invalidate all instruction cache */
        movia   r1, NIOS2_ICACHE_SIZE
        movui   r2, NIOS2_ICACHE_LINE_SIZE
1:      initi   r1
        sub     r1, r1, r2
        bgt     r1, r0, 1b
        /* invalidate all data cache */
        movia   r1, NIOS2_DCACHE_SIZE
        movui   r2, NIOS2_DCACHE_LINE_SIZE
1:      initd   0(r1)
        sub     r1, r1, r2
        bgt     r1, r0, 1b

        nextpc  r1                      /* Find out where we are */
chkadr:
        movia   r2, chkadr
        beq     r1, r2, finish_move     /* We are running in correct address,
                                           done */
        /* move code, r1: src, r2: dest, r3: last dest */
        addi    r1, r1, (_start - chkadr)       /* Source */
        movia   r2, _start              /* Destination */
        movia   r3, __bss_start         /* End of copy */
1:      ldw     r8, 0(r1)               /* load a word from [r1] */
        stw     r8, 0(r2)               /* stort a word to dest [r2] */
        addi    r1, r1, 4               /* inc the src addr */
        addi    r2, r2, 4               /* inc the dest addr */
        blt     r2, r3, 1b
        /* flush the data cache after moving */
        movia   r1, NIOS2_DCACHE_SIZE
        movui   r2, NIOS2_DCACHE_LINE_SIZE
1:      flushd  0(r1)
        sub     r1, r1, r2
        bgt     r1, r0, 1b
        movia   r1, finish_move
        jmp     r1                      /* jmp to linked address */

finish_move:
        /* zero out the .bss segment (uninitialized common data) */
        movia   r2, __bss_start         /* presume nothing is between */
        movia   r1, _end                /* the .bss and _end. */
1:      stb     r0, 0(r2)
        addi    r2, r2, 1
        bne     r1, r2, 1b
        /*
         * set up the stack pointer, some where higher than _end.
         * The stack space must be greater than 32K for decompress.
         */
        movia   sp, 0x10000
        add     sp, sp, r1
        /* save args passed from u-boot, maybe */
        addi    sp, sp, -16
        stw     r4, 0(sp)
        stw     r5, 4(sp)
        stw     r6, 8(sp)
        stw     r7, 12(sp)
        /* decompress the kernel */
        call    decompress_kernel
        /* pass saved args to kernel */
        ldw     r4, 0(sp)
        ldw     r5, 4(sp)
        ldw     r6, 8(sp)
        ldw     r7, 12(sp)

        /* flush all data cache after decompressing */
        movia   r1, NIOS2_DCACHE_SIZE
        movui   r2, NIOS2_DCACHE_LINE_SIZE
1:      flushd  0(r1)
        sub     r1, r1, r2
        bgt     r1, r0, 1b
        /* flush all instruction cache */
        movia   r1, NIOS2_ICACHE_SIZE
        movui   r2, NIOS2_ICACHE_LINE_SIZE
1:      flushi  r1
        sub     r1, r1, r2
        bgt     r1, r0, 1b
        flushp
        /* jump to start real kernel */
        movia   r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE)
        jmp     r1

        .balign 512
fake_headers_as_bzImage:
        .short  0
        .ascii  "HdrS"
        .short  0x0202
        .short  0
        .short  0
        .byte   0x00, 0x10
        .short  0
        .byte   0
        .byte   1
        .byte   0x00, 0x80
        .long   0
        .long   0