root/sys/arch/mvmeppc/stand/libsa/srt0.S
/*      $NetBSD: srt0.S,v 1.5 2014/08/07 13:56:57 joerg Exp $   */

/*-
 * Copyright (c) 2002 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Steve C. Woodford.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <machine/asm.h>
#include <machine/psl.h>
#include <powerpc/spr.h>
#include <powerpc/oea/spr.h>

#define STACK_SIZE      8192

/*
 * The main entry point when loaded by PPC-Bug.
 *
 * There are two possible entry conditions here:
 *
 *   1) We were booted in `PReP' mode, either from disk or the network.
 *      In this case, we have no control over the load address so we
 *      have to relocate ourselves to the appropriate place.
 *      The firmware passes us the following registers:
 *
 *        %r1  -> Temporary stack
 *        %r3  -> Residual Data
 *        %r4  -> The address we were loaded to
 *        %r5  -> Zero
 *
 *   2) We were booted over the network in Non-PReP mode. In this case,
 *      the load address is usually set using PPC-Bug's "niot" command,
 *      but we won't depend on it so relocation may be required. The
 *      firmware passes us the following registers:
 *
 *        %r1  -> Temporary stack
 *        %r3  -> CLUN of the network device we booted from
 *        %r4  -> DLUN of the network device we booted from
 *        %r5  -> Non-zero
 *        %r6  -> Base address of network device
 *        %r7  -> Execution address of loaded program
 *        %r8  -> Address of IP-address data structure
 *        %r9  -> Pointer to start of filename string
 *        %r10 -> Pointer to end+1 of filename string
 *        %r11 -> Pointer to start of argument string
 *        %r12 -> Pointer to end+1 of argument string
 *
 * The obvious way to distinguish between the two boot modes is by
 * checking the value of %r5.
 */
ENTRY(_start)
        bl      1f
1:      xor     %r0,%r0,%r0

        /* First, switch off Instruction and Data caches. */
        mfspr   %r13,SPR_HID0
        LDCONST(%r14, HID0_DCE|HID0_ICE)
        andc    %r13,%r13,%r14
        sync
        mtspr   SPR_HID0,%r13


        /*
         * All registers now available. Let's see if we need to relocate
         */
        LDCONST(%r13,_C_LABEL(_start))  /* Where we'd like to be */
        LDCONST(%r14,_C_LABEL(edata))   /* End of data section */
        LDCONST(%r15,0x3)
        add     %r14,%r14,%r15
        andc    %r14,%r14,%r15          /* Rounded up to the nearest 32-bits */
        sub     %r15,%r14,%r13          /* Our size, in bytes */
        mflr    %r16                    /* Get address we were loaded to */
        subi    %r16,%r16,0x4           /* Correct for branch */
        cmpw    %r13,%r16               /* Do we need to relocate? */
        beq     _ASM_LABEL(clrbss)      /* No relocation necessary */
        li      %r17,0x4
        bgt     1f                      /* Relocate using forward copy? */

        /* Nope. Need to copy in reverse in case of overlap */
        mr      %r13,%r14               /* dest -> end */
        add     %r16,%r16,%r15          /* src + size */
        subi    %r17,%r17,0x8           /* Increment is -4 */

        /*
         * Do the relocation
         *  %r13  -> dest
         *  %r15  -> number of bytes
         *  %r16  -> src
         *  %r17  -> Increment (+4 or -4)
         */
1:      srwi    %r15,%r15,0x2           /* Convert length to 32-bit words */
        mtctr   %r15                    /* Save in counter register */

2:      lwz     %r15,0(%r16)
        stw     %r15,0(%r13)
        add     %r16,%r16,%r17
        add     %r13,%r13,%r17
        bdnz    2b

        /* Now do an absolute jump to the relocated code */
        LDCONST(%r13,_ASM_LABEL(clrbss))
        mtlr    %r13
        blr

ASENTRY(clrbss)
        LDCONST(%r13,_C_LABEL(edata))   /* End of the data section */
        LDCONST(%r14,_C_LABEL(end))     /* End of BSS */
        LDCONST(%r15,0x3)
        add     %r14,%r14,%r15
        andc    %r14,%r14,%r15          /* Round-up end of BSS to 32-bits */
        sub     %r15,%r14,%r13          /* r15 == length of BSS */
        srwi    %r15,%r15,0x2
        mtctr   %r15                    /* CTR == # of 32-bit words in BSS */
1:      stw     %r0,0(%r13)             /* Clear BSS */
        addi    %r13,%r13,4
        bdnz    1b

        /* Fix up our own stack */
        LDCONST(%r1,stack)
        addi    %r1,%r1,STACK_SIZE-0x10
        LDCONST(%r13,0x0f)
        andc    %r1,%r1,%r13

        /*
         * Copy the arguments passed in from Bug into bug_bootinfo
         *
         * See bugsyscalls.h for details.
         */
        LDCONST(%r13,_C_LABEL(bug_bootinfo))
        stw     %r5,0x00(%r13)
        stw     %r3,0x04(%r13)
        stw     %r4,0x08(%r13)
        stw     %r6,0x0c(%r13)
        stw     %r7,0x10(%r13)
        stw     %r8,0x14(%r13)
        stw     %r9,0x18(%r13)
        stw     %r10,0x1c(%r13)
        stw     %r11,0x20(%r13)
        stw     %r12,0x24(%r13)

        mr      %r3,%r13
        bl      _C_LABEL(main)          /* void main(void) */
        /* FALLTHROUGH */

/*
 * Return to the debugger, either because main() returned or via panic().
 */
ENTRY(_rtt)
        addi    %r10,0,0x0063
        sc
1:      nop
        b       1b

        /*
         * C code runs on this stack.
         */
        .comm   stack,STACK_SIZE,4
        .comm   errno,4,4
        .comm   debug,4,4