root/sys/arch/amiga/stand/bootblock/boot/bbstart.s
/* $NetBSD: bbstart.s,v 1.15 2022/04/29 07:12:41 rin Exp $ */

/*-
 * Copyright (c) 1996 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Ignatios Souvatzis.
 *
 * 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 "elf2bb.h"

#define LVOAllocMem     -0x0c6
#define LVODoIO         -0x1c8
#define LVOCacheClearU  -0x27c

#define IOcmd   28
#define IOerr   31
#define IOlen   36
#define IObuf   40
#define IOoff   44

#define Cmd_Rd  2

        .text
#if defined(_PRIMARY_BOOT) || defined(AUTOLOAD)
Lzero:  .asciz "DOS"                    | "DOS type"
#else
Lzero:  .ascii  "BOOT"                  | Secondary Boot
#endif
        /*
         * We put the relocator version here, for elf2bb, which replaces
         * it with the bootblock checksum.
         */
Chksum: .long RELVER_RELATIVE_BYTES_FORWARD
Filesz: .long 8192                      | dummy

/*
 * Entry point from Kickstart.
 * A1 points to an IOrequest, A6 points to ExecBase, we have a stack.
 * _must_ be at offset 12.
 */
ENTRY_NOPROFILE(start)
#ifdef AUTOLOAD
        jra     Lautoload
#else
        jra     Lrelocate
#endif

Lreltab:
        .word 0                 | elf2bb puts the reloc table address here

        .globl _C_LABEL(default_command)
_C_LABEL(default_command):
        .asciz  "netbsd -ASn2"
        .org    (_C_LABEL(default_command)+32)

#ifdef AUTOLOAD
/*
 * autoload
 */
Lautoload:
        movl    %a6,%sp@-                       |SysBase
        movl    %a1,%sp@-                       |IORequest

        movl    #AUTOLOAD,%d0           |Howmuch
        movl    %d0,%a1@(IOlen)         | for the actual read...
        movl    #0x10001,%d1            |MEMF_CLEAR|MEMF_PUBLIC
        jsr     %a6@(LVOAllocMem)
        movl    %sp@+,%a1                       |IORequest
        movl    %sp@+,%a6                       |SysBase
        orl     %d0,%d0
        jne     Lgotmem
        movql   #1,%d0
        rts

Lgotmem:
        movl    %d0,%sp@-                       |Address
        movl    %a1@(IOoff),%sp@-               |Old offset
        movl    %a1,%sp@-
        movl    %a6,%sp@-

/* we've set IOlen above */
        movl    %d0,%a1@(IObuf)
        movw    #Cmd_Rd,%a1@(IOcmd)
        jsr     %a6@(LVODoIO)

        movl    %sp@+,%a6
        movl    %sp@+,%a1
        movl    %sp@+,%a1@(IOoff)

        tstb    %a1@(IOerr)
        jne     Lioerr
        addl    #Lrelocate-Lzero,%sp@

        movl    %a6,%sp@-
        jsr     %a6@(LVOCacheClearU)
        movl    %sp@+,%a6
        rts
Lioerr:
        movql   #1,%d0
        addql   #4,%sp
        rts
#endif

/*
 * Relocate ourselves, at the same time clearing the relocation table
 * (in case it overlaps with BSS).
 *
 * Register usage:
 * A2: points into the reloc table, located at our end.
 * A0: pointer to the longword to relocate.
 * D0: word offset of longword to relocate
 * D1: points to our start.
 *
 * Table has relative byte offsets, if a byte offset is zero, it is
 * followed by an absolute word offset. If this is zero, too, table
 * end is reached.
 */

Lrelocate:
        lea     %pc@(Lzero),%a0
        movl    %a0,%d1

        /*
         * Here, we cannot use
         *      movw    %pc@(Lreltab),%a2
         * "movw" against An is synonym for "movea.w", which carries out
         * sign extension. This breaks things when reltab >= 0x8000.
         */
        movq    #0,%d0
        movw    %pc@(Lreltab),%d0
        movl    %d0,%a2

        addl    %d1,%a2
        jra     Loopend
        
Loopw:
        clrw    %a2@+
Loopb:
        addl    %d0,%a0
        addl    %d1,%a0@
Loopend:
        movq    #0,%d0
        movb    %a2@,%d0
        clrb    %a2@+   | bfclr %a2@+{0:8} is still two shorts
        tstb    %d0     | we could save one short by using casb %d0,d0,%a2@+
        jne     Loopb

        movw    %a2@,%d0
        jne     Loopw

Lendtab:
        movl    %a6,%sp@-
        jsr     %a6@(LVOCacheClearU)
        movl    %sp@+,%a6

/* We are relocated. Now it is safe to initialize _SysBase: */

        movl    %a6,_C_LABEL(SysBase)

#ifndef _PRIMARY_BOOT
        movl    %a5,%sp@-               | Console info
#endif
        movl    %a1,%sp@-
        bsr     _C_LABEL(pain)
#ifdef _PRIMARY_BOOT
        addql   #4,%sp
#else
        addql   #8,%sp
#endif

Lerr:
        movq    #1,%d0
        rts

        .comm _C_LABEL(SysBase),4