blob: f2385656f8f50c6c24ab3694b0b9246d6643e613 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "hw/top_earlgrey/sw/autogen/top_earlgrey_memory.h"
/**
* ROM_EXT Interrupt Vector
*/
.section .vectors, "ax"
.option push
// Disable RISC-V instruction compression: we need all instructions to
// be exactly word wide in the interrupt vector.
.option norvc
// Disable RISC-V linker relaxation, as it can compress instructions at
// link-time, which we also really don't want.
.option norelax
/**
* `_rom_ext_interrupt_vector` is an ibex-compatible interrupt vector.
*
* Interrupt vectors in Ibex have 32 4-byte entries for 32 possible interrupts.
* The vector must be 256-byte aligned, as Ibex's vectoring mechanism
* requires that. This section will be padded with `unimp` (`0xc0001073`) if
* needed depending on the alignment of the next section.
*
* Only the following will be used by Ibex:
* - Exception Handler (Entry 0)
* - Machine Software Interrupt Handler (Entry 3)
* - Machine Timer Interrupt Handler (Entry 7)
* - Machine External Interrupt Handler (Entry 11)
* - Vendor Interrupt Handlers (Entries 16-31)
*
* More information about Ibex's interrupts can be found here:
* https://ibex-core.readthedocs.io/en/latest/03_reference/exception_interrupts.html
*/
.balignl 256, 0xc0001073
.global _rom_ext_interrupt_vector
.type _rom_ext_interrupt_vector, @function
_rom_ext_interrupt_vector:
// Entry 0: exception handler.
j rom_ext_exception_handler
// Entries 1-30: interrupt handlers.
.rept 30
j rom_ext_interrupt_handler
.endr
// Entry 31: non-maskable interrupt handler.
j rom_ext_nmi_handler
.size _rom_ext_interrupt_vector, .-_rom_ext_interrupt_vector
// Re-enable compressed instructions, linker relaxation.
.option pop
// -----------------------------------------------------------------------------
/**
* ROM_EXT runtime initialization code.
*/
/**
* NOTE: The "ax" flag below is necessary to ensure that this section
* is allocated executable space in ROM by the linker.
*/
.section .crt, "ax"
/**
* Entry point.
*
* This symbol is jumped to from `rom_boot` using the `entry_point` field
* of the manifest.
*/
.balign 4
.global _rom_ext_start_boot
.type _rom_ext_start_boot, @function
_rom_ext_start_boot:
/**
* Set up the global pointer `gp`.
*
* Linker relaxations are disabled until the global pointer is setup below,
* because otherwise some sequences may be turned into `gp`-relative
* sequences, which is incorrect when `gp` is not initialized.
*/
.option push
.option norelax
la gp, __global_pointer$
.option pop
/**
* Disable Interrupts.
*
* We cannot disable exceptions, or Ibex's non-maskable interrupts (interrupt
* 31), so we still need to be careful.
*/
// Clear `MIE` field of `mstatus` (disable interrupts globally).
csrci mstatus, 0x8
/**
* Clear all the machine-defined interrupts, `MEIE`, `MTIE`, and `MSIE` fields
* of `mie`.
*/
li t0, 0xFFFF0888
csrc mie, t0
/**
* Set up the stack pointer.
*
* In RISC-V, the stack grows downwards, so we load the address of the highest
* word in the stack into sp. We don't load in `_stack_end`, as that points
* beyond the end of RAM, and we always want it to be valid to dereference
* `sp`, and we need this to be 128-bit (16-byte) aligned to meet the psABI.
*
* If an exception fires, the handler is conventionaly only allowed to clobber
* memory at addresses below `sp`.
*/
la sp, (_stack_end - 16)
/**
* Setup C Runtime
*/
/**
* Initialize the `.data` section in RAM from ROM.
*/
la a0, _data_start
la a1, _data_end
la a2, _data_init_start
call crt_section_copy
/**
* Initialize the `.bss` section.
*
* We do this despite zeroing all of SRAM above, so that we still zero `.bss`
* once we've enabled SRAM scrambling.
*/
la a0, _bss_start
la a1, _bss_end
call crt_section_clear
// Re-clobber all of the temporary registers.
li t0, 0x0
li t1, 0x0
li t2, 0x0
li t3, 0x0
li t4, 0x0
li t5, 0x0
li t6, 0x0
// Re-clobber all of the argument registers.
li a0, 0x0
li a1, 0x0
li a2, 0x0
li a3, 0x0
li a4, 0x0
li a5, 0x0
li a6, 0x0
li a7, 0x0
/**
* Set well-defined interrupt/exception handlers
*
* The lowest two bits should be `0b01` to ensure we use vectored interrupts.
* We set the handlers only after making sure that we can execute some code,
* i.e. `crt_section_copy` and `crt_section_clear`, to avoid a double-fault
* condition. Any exceptions and interrupts occuring before this line will be
* handled by the ROM.
*/
la t0, (_rom_ext_interrupt_vector + 1)
csrw mtvec, t0
/**
* Jump to C Code
*/
tail rom_ext_main
.size _rom_ext_start_boot, .-_rom_ext_start_boot