OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [common/] [crt0.S] - Rev 11

Go to most recent revision | Compare with Previous | Blame | View Log

/* ################################################################################################# */
/* # << NEORV32 - crt0.S - Application Start-Up Code & Minimal Runtime Environment >>              # */
/* # ********************************************************************************************* # */
/* # The start-up code provides a minimal runtime environment that catches all exceptions and      # */
/* # interrupts and delegates them to the handler functions (installed by user via dedicated       # */
/* # install function from the neorv32 runtime environment library).                               # */
/* # ********************************************************************************************* # */
/* # BSD 3-Clause License                                                                          # */
/* #                                                                                               # */
/* # Copyright (c) 2020, Stephan Nolting. 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.                                                            # */
/* #                                                                                               # */
/* # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  # */
/* #    endorse or promote products derived from this software without specific prior written      # */
/* #    permission.                                                                                # */
/* #                                                                                               # */
/* # 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 HOLDER 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.                                                            # */
/* # ********************************************************************************************* # */
/* # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting # */
/* ################################################################################################# */

  .file "crt0.S"
  .section .text
  .balign 4
  .global _start


  // custom CSRs
  .set CSR_MISPACEBASE, 0xfc4  // CUSTOM (r/-): Base address of instruction memory space (via MEM_ISPACE_BASE generic) */
  .set CSR_MDSPACEBASE, 0xfc5  // CUSTOM (r/-): Base address of data memory space (via MEM_DSPACE_BASE generic) */
  .set CSR_MISPACESIZE, 0xfc6  // CUSTOM (r/-): Total size of instruction memory space in byte (via MEM_ISPACE_SIZE generic) */
  .set CSR_MDSPACESIZE, 0xfc7  // CUSTOM (r/-): Total size of data memory space in byte (via MEM_DSPACE_SIZE generic) */

  // IO region
  .set IO_BEGIN,    0xFFFFFF80  // start of processor-internal IO region
  .set MTIMECMP_LO, 0xFFFFFF98
  .set MTIMECMP_HI, 0xFFFFFF9C


_start:
  .cfi_startproc
  .cfi_undefined ra

// *********************************************************
// Clear register file
// *********************************************************
__crt0_reg_file_clear:
  addi  x0,  x0, 0 // hardwired to zero
  addi  x1,  x0, 0
__crt0_reg_file_init:
  addi  x2,  x1, 0
  addi  x3,  x2, 0
  addi  x4,  x3, 0
  addi  x5,  x4, 0
  addi  x6,  x5, 0
  addi  x7,  x6, 0
  addi  x8,  x7, 0
  addi  x9,  x8, 0
  addi x10,  x9, 0
  addi x11, x10, 0
  addi x12, x11, 0
  addi x13, x12, 0
  addi x14, x13, 0
  addi x15, x14, 0

// the following registers do not exist in rv32e
// "__RISCV_EMBEDDED_CPU__" is automatically defined by the makefiles when
// compiling for a rv32e architecture
#ifndef __RISCV_EMBEDDED_CPU__
  addi x16, x15, 0
  addi x17, x16, 0
  addi x18, x17, 0
  addi x19, x18, 0
  addi x20, x19, 0
  addi x21, x20, 0
  addi x22, x21, 0
  addi x23, x22, 0
  addi x24, x23, 0
  addi x25, x24, 0
  addi x26, x25, 0
  addi x27, x26, 0
  addi x28, x27, 0
  addi x29, x28, 0
  addi x30, x29, 0
  addi x31, x30, 0
#endif


// *********************************************************
// TEST AREA / DANGER ZONE / IDEA-LAB
// *********************************************************
__crt0_tests:
  nop


// *********************************************************
// Setup stack pointer
// *********************************************************
__crt0_stack_pointer_init:
  csrr  x11, CSR_MDSPACEBASE // data memory space base address
  csrr  x12, CSR_MDSPACESIZE // data memory space size
  add   sp, x11, x12
  addi  sp, sp, -4 // stack pointer = last entry
  addi  fp, sp, 0  // frame pointer = stack pointer


// *********************************************************
// Setup global pointer
// *********************************************************
__crt0_global_pointer_init:
  .option push
  .option norelax
  la gp, __global_pointer$
  .option pop


// *********************************************************
// Init exception vector table (2x16 4-byte entries) with dummy handlers
// *********************************************************
__crt0_neorv32_rte_init:
  la    x11, __crt0_neorv32_rte
  csrw  mtvec, x11 // set address of first-level exception handler

  csrr  x11, CSR_MDSPACEBASE // data memory space base address
  la    x12, __crt0_neorv32_rte_dummy_hanlder
  li    x13, 2*16  // number of entries (16xEXC, 16xIRQ)

__crt0_neorv32_rte_init_loop:
  sw  x12,  0(x11) // set dummy handler
  add x11, x11, 4
  add x13, x13, -1
  bne zero, x13, __crt0_neorv32_rte_init_loop


// *********************************************************
// Reset/deactivate IO/peripheral devices
// Devices, that are not implemented, will cause a store access fault
// which is captured but actually ignored due to the dummy handler.
// *********************************************************
__crt0_reset_io:
  li x11, IO_BEGIN // start of processor-internal IO region

__crt0_reset_io_loop:
  sw   zero, 0(x11)
  addi x11, x11, 4
  bne  zero, x11, __crt0_reset_io_loop

  // set mtime_compare to MAX (to prevent an IRQ)
  li x11, -1
  sw x11, MTIMECMP_LO(zero)  
  sw x11, MTIMECMP_HI(zero)


// *********************************************************
// Clear .bss section (byte-wise)
// *********************************************************
__crt0_clear_bss:
  la x11, __crt0_bss_start
  la x12, __crt0_bss_end

__crt0_clear_bss_loop:
  bge  x11, x12, __crt0_clear_bss_loop_end
  sb   zero, 0(x11)
  addi x11, x11, 1
  j    __crt0_clear_bss_loop

__crt0_clear_bss_loop_end:


// *********************************************************
// Copy initialized .data section from ROM to RAM (byte-wise)
// *********************************************************
__crt0_copy_data:
  la x11, __crt0_copy_data_src_begin  // start of data area (copy source)
  la x12, __crt0_copy_data_dst_begin  // start of data area (copy destination)
  la x13, __crt0_copy_data_dst_end    // last address of destination data area

__crt0_copy_data_loop:
  bge  x12, x13,  __crt0_copy_data_loop_end
  lb   x14, 0(x11)
  sb   x14, 0(x12)
  addi x11, x11, 1
  addi x12, x12, 1
  j    __crt0_copy_data_loop

__crt0_copy_data_loop_end:


// *********************************************************
// Call main function (with argc = argv = 0)
// *********************************************************
__crt0_main_entry:

  addi x10, zero, 0 // argc = 0
  addi x11, zero, 0 // argv = 0

  jal ra, main


// *********************************************************
// Go to endless sleep mode if main returns
// *********************************************************
__crt0_this_is_the_end:
  csrrci zero, mstatus, 8 // mstatus: disable global IRQs (MIE)
  wfi
__crt0_this_is_the_end_end:
  j __crt0_this_is_the_end_end // in case Ziscr is not available


// *********************************************************
// NEORV32 runtime environment: First-level exception/interrupt handler
// *********************************************************
__crt0_neorv32_rte:

  // --------------------------------------------
  // full context save
  // --------------------------------------------
#ifndef __RISCV_EMBEDDED_CPU__
  addi  sp, sp, -120
#else
  addi  sp, sp, -56
#endif

  sw    ra,0(sp)
  sw    gp,4(sp)
  sw    tp,8(sp)
  sw    t0,12(sp)
  sw    t1,16(sp)
  sw    t2,20(sp)
  sw    s0,24(sp)
  sw    s1,28(sp)
  sw    a0,32(sp)
  sw    a1,36(sp)
  sw    a2,40(sp)
  sw    a3,44(sp)
  sw    a4,48(sp)
  sw    a5,52(sp)
#ifndef __RISCV_EMBEDDED_CPU__
  sw    a6,56(sp)
  sw    a7,60(sp)
  sw    s2,64(sp)
  sw    s3,68(sp)
  sw    s4,72(sp)
  sw    s5,76(sp)
  sw    s6,80(sp)
  sw    s7,84(sp)
  sw    s8,88(sp)
  sw    s9,92(sp)
  sw    s10,96(sp)
  sw    s11,100(sp)
  sw    t3,104(sp)
  sw    t4,108(sp)
  sw    t5,112(sp)
  sw    t6,116(sp)
#endif


  // --------------------------------------------
  // get cause and prepare jump into vector table
  // --------------------------------------------
  csrr  t0, mcause        // get cause code

  andi  t1, t0, 0x0f      // isolate cause ID
  slli  t1, t1, 2         // make address offset
  csrr  ra, CSR_MDSPACEBASE  // data memory space base address
  add   t1, t1, ra        // get vetor table entry address (EXC vectors)

  csrr  ra, mepc          // get return address

  blt   t0, zero, __crt0_neorv32_rte_is_irq  // branch if this is an INTERRUPT


  // --------------------------------------------
  // compute return address for EXCEPTIONS only
  // --------------------------------------------
__crt0_neorv32_rte_is_exc:

  // check if faulting instruction is compressed and adjust return address

  lh    t0, 0(ra)   // get compressed instruction or lower 16 bits of uncompressed instruction that caused exception
  addi  t2, zero, 3 // mask
  and   t0, t0, t2  // isolate lowest 2 opcode bits (= 11 for uncompressed instructions)

  addi  ra, ra, +2  // only this for compressed instructions
  bne   t0, t2, __crt0_neorv32_rte_execute // jump if compressed instruction
  
  addi  ra, ra, +2  // add another 2 (making +4) for uncompressed instructions
  j __crt0_neorv32_rte_execute


  // --------------------------------------------
  // vector table offset for INTERRUPTS only
  // --------------------------------------------
__crt0_neorv32_rte_is_irq:
  addi  t1, t1, 16*4


  // --------------------------------------------
  // call handler from vector table
  // --------------------------------------------
__crt0_neorv32_rte_execute:
  lw    t0, 0(t1)       // get base address of second-level handler

  // push ra
  addi  sp, sp, -4
  sw    ra, 0(sp)

  jalr  ra, t0          // call second-level handler

  // pop ra
  lw    ra, 0(sp)
  addi  sp, sp, +4

  csrw  mepc, ra


  // --------------------------------------------
  // full context restore
  // --------------------------------------------
  lw    ra,0(sp)
  lw    gp,4(sp)
  lw    tp,8(sp)
  lw    t0,12(sp)
  lw    t1,16(sp)
  lw    t2,20(sp)
  lw    s0,24(sp)
  lw    s1,28(sp)
  lw    a0,32(sp)
  lw    a1,36(sp)
  lw    a2,40(sp)
  lw    a3,44(sp)
  lw    a4,48(sp)
  lw    a5,52(sp)
#ifndef __RISCV_EMBEDDED_CPU__
  lw    a6,56(sp)
  lw    a7,60(sp)
  lw    s2,64(sp)
  lw    s3,68(sp)
  lw    s4,72(sp)
  lw    s5,76(sp)
  lw    s6,80(sp)
  lw    s7,84(sp)
  lw    s8,88(sp)
  lw    s9,92(sp)
  lw    s10,96(sp)
  lw    s11,100(sp)
  lw    t3,104(sp)
  lw    t4,108(sp)
  lw    t5,112(sp)
  lw    t6,116(sp)
#endif

#ifndef __RISCV_EMBEDDED_CPU__
  addi  sp, sp, +120
#else
  addi  sp, sp, +56
#endif


  // --------------------------------------------
  // this is the ONLY place where MRET should be used!
  // --------------------------------------------
  mret


// *********************************************************
// Dummy exception handler: just move on to next instruction
// *********************************************************
__crt0_neorv32_rte_dummy_hanlder:
  ret

  .cfi_endproc
  .end

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.