first.S 9.15 KB
/*
 * Copyright (c) 2020, Cobham Gaisler AB
 * All rights reserved.
 *
 * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 "bcc/leon.h"
#include <macros.i>
#include <context.i>

#define MSTATUS_FS 0x00006000

/*
 * Reset trap handler for multi vector trapping
 *
 * This file assumes that a boot loader has performed basic initialization.
 */

        .section        ".text.first"
        .global         _start
        .global         bcc_start_processor

FUNC_BEGIN _start
        .option push
        .option norelax
        la      gp, __global_pointer$
        .option pop

#ifdef __riscv_flen
        li      t0, MSTATUS_FS
        csrs    mstatus, t0
        csrw    fcsr, zero
#endif

        /* Secondary processor may not take exception since no stack yet. */
        la      t0, __bcc_first_mtvec
        csrw    mtvec, t0

        csrr    s0, mhartid
        bnez    s0, .Lstart_on_secondary

        la      t0, __bcc_trap_table
        csrw    mtvec, t0

        call    __bcc_init40

        la      t0, __bcc_crt0
        jalr    t0

.Lstart_on_secondary:
        /* mhartid * 4 */
        sll     t1, s0, 2
        /* Wait for go issued by the boot processor (mhartid == 0) */
        la      t0, __bcc_secondary_go
        add     t0, t1, t0
.Lwait_for_go_again:
        lw      t1, 0(t0)
        fence   iorw, iorw
        bnez    t1, .Lwait_for_go_again

        /*
         * Lets go: pick upp sp and pc
         *
         * t4: address of __bcc_startinfo[mhartid].pc
         * t5: address of __bcc_startinfo[mhartid].sp
         */
        la      t3, __bcc_startinfo
#if __riscv_xlen == 32
        sll     t2, s0, 3
        add     t4, t3, t2
        add     t5, t4, 4
#else
        sll     t2, s0, 4
        add     t4, t3, t2
        add     t5, t4, 8
#endif
        LREG    t6, 0(t4)
        LREG    sp, 0(t5)

        la      t0, __bcc_trap_table
        csrw    mtvec, t0

        csrr    a0, mhartid
        jalr    t6

__bcc_secondary_go:
.rept   16
        /* ebreak instruction */
        .word   0x00100073
.endr
FUNC_END _start

/* This function clears the cpuid entry in __bcc_secondary_go. */
FUNC_BEGIN bcc_start_processor
        /* cpuid * 4 */
        sll     t1, a0, 2
        la      t2, __bcc_secondary_go
        add     t0, t1, t2
        fence   iorw,ow
#ifdef __riscv_atomic
        amoswap.w zero, zero, 0(t0)
#else
        sw      zero, 0(t0)
#endif
        mv      a0, zero
        ret
FUNC_END bcc_start_processor

FUNC_BEGIN __bcc_first_mtvec
        ebreak
FUNC_END __bcc_first_mtvec

FUNC_BEGIN __bcc_trap_table
        csrr    x0, mcause
        addi    sp, sp, -sizeof_isr_ctx
        SREG    x1,  isr_ctx_x1(sp)
# x2 is sp
#        SREG    x2,  isr_ctx_x2(sp)
        SREG    x3,  isr_ctx_x3(sp)
        SREG    x4,  isr_ctx_x4(sp)
        SREG    x5,  isr_ctx_x5(sp)
        SREG    x6,  isr_ctx_x6(sp)
        SREG    x7,  isr_ctx_x7(sp)
        SREG    x8,  isr_ctx_x8(sp)
        SREG    x9,  isr_ctx_x9(sp)
        SREG    x10, isr_ctx_x10(sp)
        SREG    x11, isr_ctx_x11(sp)
        SREG    x12, isr_ctx_x12(sp)
        SREG    x13, isr_ctx_x13(sp)
        SREG    x14, isr_ctx_x14(sp)
        SREG    x15, isr_ctx_x15(sp)
        SREG    x16, isr_ctx_x16(sp)
        SREG    x17, isr_ctx_x17(sp)
        SREG    x18, isr_ctx_x18(sp)
        SREG    x19, isr_ctx_x19(sp)
        SREG    x20, isr_ctx_x20(sp)
        SREG    x21, isr_ctx_x21(sp)
        SREG    x22, isr_ctx_x22(sp)
        SREG    x23, isr_ctx_x23(sp)
        SREG    x24, isr_ctx_x24(sp)
        SREG    x25, isr_ctx_x25(sp)
        SREG    x26, isr_ctx_x26(sp)
        SREG    x27, isr_ctx_x27(sp)
        SREG    x28, isr_ctx_x28(sp)
        SREG    x29, isr_ctx_x29(sp)
        SREG    x30, isr_ctx_x30(sp)
        SREG    x31, isr_ctx_x31(sp)
        csrr    a0, mstatus
        csrr    a1, mepc
        csrr    a2, mcause
        SREG    a0, isr_ctx_mstatus(sp)
        SREG    a1, isr_ctx_mepc(sp)
        SREG    a2, isr_ctx_mcause(sp)
#if defined(__riscv_flen)
        frcsr   t0
        sw      t0,  isr_ctx_fcsr(sp)

        FSREG   f0,  isr_ctx_f0(sp)
        FSREG   f1,  isr_ctx_f1(sp)
        FSREG   f2,  isr_ctx_f2(sp)
        FSREG   f3,  isr_ctx_f3(sp)
        FSREG   f4,  isr_ctx_f4(sp)
        FSREG   f5,  isr_ctx_f5(sp)
        FSREG   f6,  isr_ctx_f6(sp)
        FSREG   f7,  isr_ctx_f7(sp)
        FSREG   f8,  isr_ctx_f8(sp)
        FSREG   f9,  isr_ctx_f9(sp)
        FSREG   f10, isr_ctx_f10(sp)
        FSREG   f11, isr_ctx_f11(sp)
        FSREG   f12, isr_ctx_f12(sp)
        FSREG   f13, isr_ctx_f13(sp)
        FSREG   f14, isr_ctx_f14(sp)
        FSREG   f15, isr_ctx_f15(sp)
        FSREG   f16, isr_ctx_f16(sp)
        FSREG   f17, isr_ctx_f17(sp)
        FSREG   f18, isr_ctx_f18(sp)
        FSREG   f19, isr_ctx_f19(sp)
        FSREG   f20, isr_ctx_f20(sp)
        FSREG   f21, isr_ctx_f21(sp)
        FSREG   f22, isr_ctx_f22(sp)
        FSREG   f23, isr_ctx_f23(sp)
        FSREG   f24, isr_ctx_f24(sp)
        FSREG   f25, isr_ctx_f25(sp)
        FSREG   f26, isr_ctx_f26(sp)
        FSREG   f27, isr_ctx_f27(sp)
        FSREG   f28, isr_ctx_f28(sp)
        FSREG   f29, isr_ctx_f29(sp)
        FSREG   f30, isr_ctx_f30(sp)
        FSREG   f31, isr_ctx_f31(sp)
#endif

        bgez    a2, .Lsync

        call    __bcc_handle_interrupt
        j       .Ldone

.Lsync:
        mv      a3, sp
        /* void __bcc_handle_exception(mstatus, mepc, mcause, frame) */
        call    __bcc_handle_exception

.Ldone:
        LREG    x1,  isr_ctx_x1(sp)
#        LREG    x2,  isr_ctx_x2(sp)
        LREG    x3,  isr_ctx_x3(sp)
        LREG    x4,  isr_ctx_x4(sp)
        LREG    x5,  isr_ctx_x5(sp)
        LREG    x6,  isr_ctx_x6(sp)
        LREG    x7,  isr_ctx_x7(sp)
        LREG    x8,  isr_ctx_x8(sp)
        LREG    x9,  isr_ctx_x9(sp)
        LREG    x10, isr_ctx_x10(sp)
        LREG    x11, isr_ctx_x11(sp)
        LREG    x12, isr_ctx_x12(sp)
        LREG    x13, isr_ctx_x13(sp)
        LREG    x14, isr_ctx_x14(sp)
        LREG    x15, isr_ctx_x15(sp)
        LREG    x16, isr_ctx_x16(sp)
        LREG    x17, isr_ctx_x17(sp)
        LREG    x18, isr_ctx_x18(sp)
        LREG    x19, isr_ctx_x19(sp)
        LREG    x20, isr_ctx_x20(sp)
        LREG    x21, isr_ctx_x21(sp)
        LREG    x22, isr_ctx_x22(sp)
        LREG    x23, isr_ctx_x23(sp)
        LREG    x24, isr_ctx_x24(sp)
        LREG    x25, isr_ctx_x25(sp)
        LREG    x26, isr_ctx_x26(sp)
        LREG    x27, isr_ctx_x27(sp)
        LREG    x28, isr_ctx_x28(sp)
        LREG    x29, isr_ctx_x29(sp)

#if defined(__riscv_flen)
        FLREG   f0,  isr_ctx_f0(sp)
        FLREG   f1,  isr_ctx_f1(sp)
        FLREG   f2,  isr_ctx_f2(sp)
        FLREG   f3,  isr_ctx_f3(sp)
        FLREG   f4,  isr_ctx_f4(sp)
        FLREG   f5,  isr_ctx_f5(sp)
        FLREG   f6,  isr_ctx_f6(sp)
        FLREG   f7,  isr_ctx_f7(sp)
        FLREG   f8,  isr_ctx_f8(sp)
        FLREG   f9,  isr_ctx_f9(sp)
        FLREG   f10, isr_ctx_f10(sp)
        FLREG   f11, isr_ctx_f11(sp)
        FLREG   f12, isr_ctx_f12(sp)
        FLREG   f13, isr_ctx_f13(sp)
        FLREG   f14, isr_ctx_f14(sp)
        FLREG   f15, isr_ctx_f15(sp)
        FLREG   f16, isr_ctx_f16(sp)
        FLREG   f17, isr_ctx_f17(sp)
        FLREG   f18, isr_ctx_f18(sp)
        FLREG   f19, isr_ctx_f19(sp)
        FLREG   f20, isr_ctx_f20(sp)
        FLREG   f21, isr_ctx_f21(sp)
        FLREG   f22, isr_ctx_f22(sp)
        FLREG   f23, isr_ctx_f23(sp)
        FLREG   f24, isr_ctx_f24(sp)
        FLREG   f25, isr_ctx_f25(sp)
        FLREG   f26, isr_ctx_f26(sp)
        FLREG   f27, isr_ctx_f27(sp)
        FLREG   f28, isr_ctx_f28(sp)
        FLREG   f29, isr_ctx_f29(sp)
        FLREG   f30, isr_ctx_f30(sp)
        FLREG   f31, isr_ctx_f31(sp)
        lw      x30, isr_ctx_fcsr(sp)
        fscsr   x30
#endif

        LREG    x30, isr_ctx_mstatus(sp)
        LREG    x31, isr_ctx_mepc(sp)
        csrw    mstatus, x30
        csrw    mepc, x31
        LREG    x30, isr_ctx_x30(sp)
        LREG    x31, isr_ctx_x31(sp)
        addi    sp, sp, sizeof_isr_ctx
        mret
FUNC_END __bcc_trap_table