URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
[/] [neorv32/] [trunk/] [sw/] [common/] [crt0.S] - Rev 74
Compare with Previous | Blame | View Log
/* ################################################################################################# *//* # << NEORV32 - crt0.S - Start-Up Code >> # *//* # ********************************************************************************************* # *//* # BSD 3-Clause License # *//* # # *//* # Copyright (c) 2022, 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.crt0.balign 4.global _start.global __crt0_main_exit_start:.cfi_startproc.cfi_undefined ra// ************************************************************************************************// This is the very first instruction that is executed after hardware reset. It ensures that x0 is// written at least once - the CPU HW will ensure it is always set to zero on any write access.//// Furthermore, we have to disable ALL interrupts, which is required if this code is part of a// program uploaded by the on-chip debugger (potentionally taking control from the bootloader).// We setup a new stack pointer here and WE DO NOT WANT TO trap to an outdated trap handler with// a modified stack pointer.// ************************************************************************************************csrrci zero, mstatus, (1<<3) // disable global interrupt flag and write "anything" to x0// ************************************************************************************************// Setup pointers using linker script symbols// ************************************************************************************************__crt0_pointer_init:.option push.option norelaxla sp, __crt0_stack_begin // stack pointerla gp, __global_pointer$ // global pointer.option pop// ************************************************************************************************// Setup CPU core CSRs (some of them DO NOT have a dedicated// reset and need to be explicitly initialized)// ************************************************************************************************__crt0_cpu_csr_init:la x10, __crt0_dummy_trap_handler // configure early-boot trap handlercsrw mtvec, x10csrw mepc, x10 // just to init mepccsrw mstatus, zero // clear all control flags, also disable global IRQcsrw mie, zero // absolutely no interrupt sources, thankscsrw mip, zero // clear all pending interruptscsrw 0x320, zero // stop all counters; use "mcountinhibit" literal address for lagacy toolchain compatibilitycsrw mcounteren, zero // no access from less-privileged modes to counter CSRscsrw mcycle, zero // reset cycle countercsrw mcycleh, zerocsrw minstret, zero // reset instructions-retired countercsrw minstreth, zero// ************************************************************************************************// Initialize integer register file (lower half)// ************************************************************************************************__crt0_reg_file_clear://addi x0, x0, 0 // hardwired to zeroaddi x1, x0, 0//addi x2, x0, 0 // stack pointer sp//addi x3, x0, 0 // global pointer gpaddi x4, x0, 0addi x5, x0, 0addi x6, x0, 0addi x7, x0, 0//addi x8, x0, 0 // implicitly initialized within crt0//addi x9, x0, 0 // implicitly initialized within crt0//addi x10, x0, 0 // implicitly initialized within crt0//addi x11, x0, 0 // implicitly initialized within crt0//addi x12, x0, 0 // implicitly initialized within crt0//addi x13, x0, 0 // implicitly initialized within crt0//addi x14, x0, 0 // implicitly initialized within crt0//addi x15, x0, 0 // implicitly initialized within crt0// ************************************************************************************************// Initialize integer register file (upper half, if no E extension)// ************************************************************************************************#ifndef __riscv_32e// do not do this if compiling bootloader (to save some program space)#ifndef make_bootloaderaddi x16, x0, 0addi x17, x0, 0addi x18, x0, 0addi x19, x0, 0addi x20, x0, 0addi x21, x0, 0addi x22, x0, 0addi x23, x0, 0addi x24, x0, 0addi x25, x0, 0addi x26, x0, 0addi x27, x0, 0addi x28, x0, 0addi x29, x0, 0addi x30, x0, 0addi x31, x0, 0#endif#endif// ************************************************************************************************// Reset/deactivate IO/peripheral devices// Devices, that are not implemented, will cause a store bus access fault// that is catched (but not further processed) by the dummy trap handler.// ************************************************************************************************__crt0_reset_io:la x8, __crt0_io_space_begin // start of processor-internal IO regionla x9, __crt0_io_space_end // end of processor-internal IO region__crt0_reset_io_loop:sw zero, 0(x8)addi x8, x8, 4bne x8, x9, __crt0_reset_io_loop// ************************************************************************************************// 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_endlb x14, 0(x11)sb x14, 0(x12)addi x11, x11, 1addi x12, x12, 1j __crt0_copy_data_loop__crt0_copy_data_loop_end:// ************************************************************************************************// Clear .bss section (byte-wise)// ************************************************************************************************__crt0_clear_bss:la x14, __crt0_bss_startla x15, __crt0_bss_end__crt0_clear_bss_loop:bge x14, x15, __crt0_clear_bss_loop_endsb zero, 0(x14)addi x14, x14, 1j __crt0_clear_bss_loop__crt0_clear_bss_loop_end:// ************************************************************************************************// Setup arguments and call main function// ************************************************************************************************__crt0_main_entry:addi a0, zero, 0 // a0 = argc = 0addi a1, zero, 0 // a1 = argv = 0jal ra, main // call actual app's main function, this "should" not return__crt0_main_exit: // main's "return" and "exit" will arrive herecsrw mscratch, a0 // backup main's return code to mscratch (for debugger)// ************************************************************************************************// call "after main" handler (if there is any) if main really returns// ************************************************************************************************#ifndef make_bootloader // after_main handler not supported for bootloader__crt0_main_aftermath:.weak __neorv32_crt0_after_mainla ra, __neorv32_crt0_after_mainbeqz ra, __crt0_main_aftermath_end // check if an aftermath handler has been specifiedjalr ra // execute handler with main's return code still in a0__crt0_main_aftermath_end:#endif// ************************************************************************************************// go to endless sleep mode// ************************************************************************************************__crt0_shutdown:csrci mstatus, 8 // disable global IRQs (clear mstatus.mie)wfi // go to sleep modej . // endless loop// ************************************************************************************************// dummy trap handler (for exceptions & IRQs during very early boot stage)// does nothing but trying to move on to the next instruction// ************************************************************************************************.balign 4__crt0_dummy_trap_handler:addi sp, sp, -8sw x8, 0(sp)sw x9, 4(sp)csrr x8, mcauseblt x8, zero, __crt0_dummy_trap_handler_irq // skip mepc modification if interruptcsrr x8, mepc__crt0_dummy_trap_handler_exc_c_check: // is compressed instruction?lh x9, 0(x8) // get compressed instruction or lower 16 bits of uncompressed instruction that caused exceptionandi x9, x9, 3 // mask: isolate lowest 2 opcode bits (= 11 for uncompressed instructions)addi x8, x8, +2 // only this for compressed instructionscsrw mepc, x8 // set return address when compressed instructionaddi x8, zero, 3bne x8, x9, __crt0_dummy_trap_handler_irq // jump if compressed instruction__crt0_dummy_trap_handler_exc_uncrompressed: // is uncompressed instruction!csrr x8, mepcaddi x8, x8, +2 // add another 2 (making +4) for uncompressed instructionscsrw mepc, x8__crt0_dummy_trap_handler_irq:lw x8, 0(sp)lw x9, 4(sp)addi sp, sp, +8mret.cfi_endproc.end
