// vi:ft=asm:

.global __riscv64_entry
.global __riscv64_ap_entry

.macro LOAD_PCREL label, reg, sym
\label: auipc \reg, %pcrel_hi(\sym)
        addi \reg, \reg, %pcrel_lo(\label)
.endm

.pushsection .text.entry
__riscv64_entry:
    .ascii  "MZ"                    // Magic 0
    j       __riscv64_real_entry    // Jump to real entry (if entered by non-Linux bootloader)
    .long   0
    .quad   0x200000                // Offset from RAM start
    .quad   __kernel_size           // Image size
    .quad   0                       // Kernel flags
    .long   0x2                     // Header version
    .long   0
    .quad   0
    .ascii  "RISCV\x00\x00\x00"     // Magic 1
    .ascii  "RSC\x05"               // Magic 2
    .long 0

__riscv64_real_entry:
    csrw satp, zero
    mv tp, zero

    // a0 - bootstrap HART ID
    // a1 - device tree blob
    LOAD_PCREL .L00, s0, __riscv64_entry
    mv s1, a0
    mv s2, a1

    //// Zero the .bss
    LOAD_PCREL .L01, t0, __bss_start
    LOAD_PCREL .L02, t1, __bss_end
1:  bgeu t0, t1, 2f
    sd zero, (t0)
    addi t0, t0, 8
    j 1b
2:

    //// Store boot parameters
    LOAD_PCREL .L03, t0, {kernel_load_base}
    LOAD_PCREL .L04, t1, {boot_hart_id}
    LOAD_PCREL .L05, t2, {dtb_address}
    sd s0, (t0)
    sd s1, (t1)
    sd s2, (t2)

    //// Setup a stack
    LOAD_PCREL .L06, sp, {boot_stack_bottom} + {boot_stack_size}

    //// Relocate the kernel
    mv a0, s0
    LOAD_PCREL .L07, a1, __rela_start
    LOAD_PCREL .L08, a2, __rela_end
    jal {relocate_kernel}

    //// Enter S-mode kernel
    j {bsp_smode_entry}
.popsection // .text.entry

.pushsection .text
__riscv64_ap_entry:
    // a1 - context struct
    csrw satp, zero
    mv tp, zero

    // Setup stack and enter Rust code
    ld sp, (a1)
    mv a0, a1
    mv a1, sp
    j {ap_smode_entry}
.popsection // .text
