mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
146 lines
7.3 KiB
ArmAsm
146 lines
7.3 KiB
ArmAsm
/* -----------------------------------------------------------------------------
|
||
* Project Name : Architectures of Processor Systems (APS) lab work
|
||
* Organization : National Research University of Electronic Technology (MIET)
|
||
* Department : Institute of Microdevices and Control Systems
|
||
* Author(s) : Andrei Solodovnikov
|
||
* Email(s) : hepoh@org.miet.ru
|
||
|
||
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
|
||
* ------------------------------------------------------------------------------
|
||
*/
|
||
.section .boot
|
||
|
||
.global _start
|
||
_start:
|
||
la gp, _gbl_ptr # Инициализация глобального указателя
|
||
la sp, _stack_ptr # Инициализация указателя на стек
|
||
|
||
# Инициализация (зануление) сегмента bss
|
||
la t0, _bss_start
|
||
la t1, _bss_end
|
||
_bss_init_loop:
|
||
blt t1, t0, _irq_config
|
||
sw zero, 0(t0)
|
||
addi t0, t0, 4
|
||
j _bss_init_loop
|
||
|
||
# Настройка вектора (mtvec) и маски (mie) прерываний, а также указателя на стек
|
||
# прерываний (mscratch).
|
||
_irq_config:
|
||
la t0, _int_handler
|
||
li t1, -1 # -1 (все биты равны 1) означает, что разрешены все прерывания
|
||
la t2, _trap_stack_ptr
|
||
csrw mtvec, t0
|
||
csrw mie, t1
|
||
csrw mscratch, t2
|
||
|
||
# Вызов функции main
|
||
_main_call:
|
||
li a0, 0 # Передача аргументов argc и argv в main. Формально, argc должен
|
||
li a1, 0 # быть больше нуля, а argv должен указывать на массив строк,
|
||
# нулевой элемент которого является именем исполняемого файла,
|
||
# Но для простоты реализации оба аргумента всего лишь обнулены.
|
||
# Это сделано для детерминированного поведения программы в случае,
|
||
# если будет пытаться использовать эти аргументы.
|
||
call main
|
||
# Зацикливание после выхода из функции main
|
||
_endless_loop:
|
||
j _endless_loop
|
||
|
||
# Низкоуровневый обработчик прерывания отвечает за:
|
||
# * Сохранение и восстановление контекста;
|
||
# * Вызов высокоуровневого обработчика с передачей id источника прерывания в
|
||
# качестве аргумента.
|
||
# В основе кода лежит обработчик из репозитория urv-core:
|
||
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
|
||
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
|
||
# судя по документу приведенному ниже, обычное ABI подразумевает такое же
|
||
# сохранение контекста, что и при программном вызове (EABI подразумевает еще
|
||
# меньшее сохранение контекста), поэтому нет нужды сохранять весь регистровый
|
||
# файл.
|
||
# Документ:
|
||
# https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc
|
||
_int_handler:
|
||
# Данная операция меняет местами регистры sp и mscratch.
|
||
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
|
||
# программного стека оказывается в регистре mscratch.
|
||
csrrw sp,mscratch,sp
|
||
|
||
# Далее мы поднимаемся по стеку прерываний и сохраняем все регистры.
|
||
addi sp,sp,-80 # Указатель на стек должен быть выровнен до 16 байт, поэтому
|
||
# поднимаемся вверх не на 76, а на 80.
|
||
sw ra,4(sp)
|
||
# Мы хотим убедиться, что очередное прерывание не наложит стек прерываний на
|
||
# программный стек, поэтому записываем в освободившийся регистр низ
|
||
# программного стека, и проверяем что приподнятый указатель на верхушку
|
||
# стека прерываний не залез в программный стек.
|
||
# В случае, если это произошло (произошло переполнение стека прерываний),
|
||
# мы хотим остановить работу процессора, чтобы не потерять данные, которые
|
||
# могут помочь нам в отладке этой ситуации.
|
||
la ra, _stack_ptr
|
||
blt sp, ra, _endless_loop
|
||
|
||
sw t0,12(sp) # Мы перепрыгнули через смещение 8, поскольку там должен
|
||
# лежать регистр sp, который ранее сохранили в mscratch.
|
||
# Мы запишем его на стек чуть позже.
|
||
sw t1,16(sp)
|
||
sw t2,20(sp)
|
||
sw a0,24(sp)
|
||
sw a1,28(sp)
|
||
sw a2,32(sp)
|
||
sw a3,36(sp)
|
||
sw a4,40(sp)
|
||
sw a5,44(sp)
|
||
sw a6,48(sp)
|
||
sw a7,52(sp)
|
||
sw t3,56(sp)
|
||
sw t4,60(sp)
|
||
sw t5,64(sp)
|
||
sw t6,68(sp)
|
||
|
||
# Кроме того, мы сохраняем состояние регистров прерываний на случай, если
|
||
# произойдет еще одно прерывание.
|
||
csrr t0,mscratch
|
||
csrr t1,mepc
|
||
csrr a0,mcause
|
||
sw t0,8(sp)
|
||
sw t1,72(sp)
|
||
sw a0,76(sp)
|
||
|
||
# Вызов высокоуровневого обработчика прерываний
|
||
# call int_handler
|
||
|
||
# Восстановление контекста. В первую очередь мы хотим восстановить CS-регистры,
|
||
# на случай, если происходило вложенное прерывание. Для этого, мы должны
|
||
# вернуть исходное значение указателя стека прерываний. Однако его нынешнее
|
||
# значение нам еще необходимо для восстановления контекста, поэтому мы
|
||
# сохраним его в регистр a0, и будем восстанавливаться из него.
|
||
mv a0,sp
|
||
|
||
lw t1,72(a0)
|
||
addi sp,sp,80
|
||
csrw mscratch,sp
|
||
csrw mepc,t1
|
||
lw ra,4(a0)
|
||
lw sp,8(a0)
|
||
lw t0,12(a0)
|
||
lw t1,16(a0)
|
||
lw t2,20(a0)
|
||
lw a1,28(a0) # Мы пропустили a0, потому что сейчас он используется в
|
||
# качестве указателя на верхушку стека и не может быть
|
||
# восстановлен.
|
||
lw a2,32(a0)
|
||
lw a3,36(a0)
|
||
lw a4,40(a0)
|
||
lw a5,44(a0)
|
||
lw a6,48(a0)
|
||
lw a7,52(a0)
|
||
lw t3,56(a0)
|
||
lw t4,60(a0)
|
||
lw t5,64(a0)
|
||
lw t6,68(a0)
|
||
lw a0,40(a0)
|
||
|
||
# Выход из обработчика прерывания
|
||
mret
|