blob: 091efa41820d80bf5fb2226578d272b093b5a577 [file] [log] [blame]
#include "encoding.h"
#define STACK_SIZE (90 * XLEN / 8)
#if XLEN == 64
# define LREG ld
# define SREG sd
# define REGBYTES 8
#else
# define LREG lw
# define SREG sw
# define REGBYTES 4
#endif
.section .text.entry
.globl _start
_start:
j handle_reset
nmi_vector:
j nmi_vector
trap_vector:
j trap_entry
handle_reset:
// If misa doesn't exist (or is following an old spec where it has a
// different number), skip the next block.
la t0, 3f
csrw mtvec, t0
csrwi mstatus, 0
// make sure these registers exist by seeing if either S or U bits
// are set before attempting to zero them out.
csrr t1, misa
addi t2, x0, 1
slli t2, t2, 20 // U_EXTENSION
and t2, t1, t2
bne x0, t2, 1f
addi t2, x0, 1
slli t2, t2, 18 // S_EXTENSION
and t2, t1, t2
bne x0, t2, 1f
j 2f
1:
csrwi mideleg, 0
csrwi medeleg, 0
2:
csrwi mie, 0
3:
la t0, trap_entry
csrw mtvec, t0
csrwi mstatus, 0
# initialize global pointer
.option push
.option norelax
la gp, __global_pointer$
.option pop
# Initialize stack pointer.
la sp, stack_bottom
# Give each hart STACK_SIZE of stack.
# Assume hart IDs are contiguous and start at 0.
li t1, STACK_SIZE
csrr t0, CSR_MHARTID
# Don't use mul instruction because not all harts support it.
addi t0, t0, 1
1:
add sp, sp, t1
addi t0, t0, -1
bnez t0, 1b
# Catch trap in case trigger module is not implemented
la t2, 2f
csrrw t2, mtvec, t2
# Clear all hardware triggers
li t0, ~0
1:
addi t0, t0, 1
csrw CSR_TSELECT, t0
csrw CSR_TDATA1, zero
csrr t1, CSR_TSELECT
beq t0, t1, 1b
.p2align 2
2:
# Restore mtvec
csrw mtvec, t2
#ifdef MULTICORE
csrr t0, CSR_MHARTID
bnez t0, wait_until_initialized
#endif
la t0, __bss_start
la t1, __bss_end
1:
bge t0, t1, 2f
sb zero, 0(t0)
addi t0, t0, 1
j 1b
2:
#ifdef MULTICORE
la t0, initialized
li t1, 1
sw t1, 0(t0)
wait_until_initialized: # Wait for hart 0 to perform initialization.
la t0, initialized
1:
lw t1, 0(t0)
beqz t1, 1b
#endif
# perform the rest of initialization in C
j _init
.align 2
trap_entry:
addi sp, sp, -32*REGBYTES
SREG x1, 1*REGBYTES(sp)
SREG x2, 2*REGBYTES(sp)
SREG x3, 3*REGBYTES(sp)
SREG x4, 4*REGBYTES(sp)
SREG x5, 5*REGBYTES(sp)
SREG x6, 6*REGBYTES(sp)
SREG x7, 7*REGBYTES(sp)
SREG x8, 8*REGBYTES(sp)
SREG x9, 9*REGBYTES(sp)
SREG x10, 10*REGBYTES(sp)
SREG x11, 11*REGBYTES(sp)
SREG x12, 12*REGBYTES(sp)
SREG x13, 13*REGBYTES(sp)
SREG x14, 14*REGBYTES(sp)
SREG x15, 15*REGBYTES(sp)
#ifndef RV32E
SREG x16, 16*REGBYTES(sp)
SREG x17, 17*REGBYTES(sp)
SREG x18, 18*REGBYTES(sp)
SREG x19, 19*REGBYTES(sp)
SREG x20, 20*REGBYTES(sp)
SREG x21, 21*REGBYTES(sp)
SREG x22, 22*REGBYTES(sp)
SREG x23, 23*REGBYTES(sp)
SREG x24, 24*REGBYTES(sp)
SREG x25, 25*REGBYTES(sp)
SREG x26, 26*REGBYTES(sp)
SREG x27, 27*REGBYTES(sp)
SREG x28, 28*REGBYTES(sp)
SREG x29, 29*REGBYTES(sp)
SREG x30, 30*REGBYTES(sp)
SREG x31, 31*REGBYTES(sp)
#endif
csrr a0, mcause
csrr a1, mepc
mv a2, sp
jal handle_trap
csrw mepc, a0
# Remain in M-mode after mret
li t0, MSTATUS_MPP
csrs mstatus, t0
LREG x1, 1*REGBYTES(sp)
LREG x2, 2*REGBYTES(sp)
LREG x3, 3*REGBYTES(sp)
LREG x4, 4*REGBYTES(sp)
LREG x5, 5*REGBYTES(sp)
LREG x6, 6*REGBYTES(sp)
LREG x7, 7*REGBYTES(sp)
LREG x8, 8*REGBYTES(sp)
LREG x9, 9*REGBYTES(sp)
LREG x10, 10*REGBYTES(sp)
LREG x11, 11*REGBYTES(sp)
LREG x12, 12*REGBYTES(sp)
LREG x13, 13*REGBYTES(sp)
LREG x14, 14*REGBYTES(sp)
LREG x15, 15*REGBYTES(sp)
#ifndef RV32E
LREG x16, 16*REGBYTES(sp)
LREG x17, 17*REGBYTES(sp)
LREG x18, 18*REGBYTES(sp)
LREG x19, 19*REGBYTES(sp)
LREG x20, 20*REGBYTES(sp)
LREG x21, 21*REGBYTES(sp)
LREG x22, 22*REGBYTES(sp)
LREG x23, 23*REGBYTES(sp)
LREG x24, 24*REGBYTES(sp)
LREG x25, 25*REGBYTES(sp)
LREG x26, 26*REGBYTES(sp)
LREG x27, 27*REGBYTES(sp)
LREG x28, 28*REGBYTES(sp)
LREG x29, 29*REGBYTES(sp)
LREG x30, 30*REGBYTES(sp)
LREG x31, 31*REGBYTES(sp)
#endif
addi sp, sp, 32*REGBYTES
mret
loop_forever:
j loop_forever
// Fill the stack with data so we can see if it was overrun.
.section .data
.align 4
stack_bottom:
.fill NHARTS * STACK_SIZE/4, 4, 0x22446688
stack_top:
initialized:
.word 0