mirror of
https://github.com/MPSU/APS.git
synced 2025-09-19 10:50:41 +00:00
ЛР14,16. Дополнение startup-файла
- добавлен код восстановления CS-регистра mcause - в более явном виде описано почему в низкоуровневом обработчике на стек сохраняется не весь регистровый файл.
This commit is contained in:
@@ -361,12 +361,10 @@ _endless_loop:
|
|||||||
# В основе кода лежит обработчик из репозитория urv-core:
|
# В основе кода лежит обработчик из репозитория urv-core:
|
||||||
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
|
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
|
||||||
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
|
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
|
||||||
# судя по документу приведенному ниже, обычное ABI подразумевает такое же
|
# в реализации сохраняются только необерегаемые регистры регистрового файла.
|
||||||
# сохранение контекста, что и при программном вызове (EABI подразумевает ещё
|
# Это сделано по причине того, что при вызове высокоуровневого обработчика
|
||||||
# меньшее сохранение контекста), поэтому нет нужды сохранять весь регистровый
|
# прерываний, тот будет обязан сохранить оберегаемые регистры в соответствии
|
||||||
# файл.
|
# с соглашением о вызовах.
|
||||||
# Документ:
|
|
||||||
# https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc
|
|
||||||
_int_handler:
|
_int_handler:
|
||||||
# Данная операция меняет местами регистры sp и mscratch.
|
# Данная операция меняет местами регистры sp и mscratch.
|
||||||
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
|
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
|
||||||
@@ -427,9 +425,11 @@ _int_handler:
|
|||||||
mv a0,sp
|
mv a0,sp
|
||||||
|
|
||||||
lw t1, 72(a0)
|
lw t1, 72(a0)
|
||||||
|
lw t2, 76(a0)
|
||||||
addi sp, sp, 80
|
addi sp, sp, 80
|
||||||
csrw mscratch, sp
|
csrw mscratch, sp
|
||||||
csrw mepc, t1
|
csrw mepc, t1
|
||||||
|
csrw mcause, t2
|
||||||
lw ra, 4(a0)
|
lw ra, 4(a0)
|
||||||
lw sp, 8(a0)
|
lw sp, 8(a0)
|
||||||
lw t0, 12(a0)
|
lw t0, 12(a0)
|
||||||
@@ -453,6 +453,7 @@ _int_handler:
|
|||||||
# Выход из обработчика прерывания
|
# Выход из обработчика прерывания
|
||||||
mret
|
mret
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
_Листинг 2. Пример содержимого файла первичных команд с поясняющими комментариями._
|
_Листинг 2. Пример содержимого файла первичных команд с поясняющими комментариями._
|
||||||
|
@@ -58,12 +58,10 @@ _endless_loop:
|
|||||||
# В основе кода лежит обработчик из репозитория urv-core:
|
# В основе кода лежит обработчик из репозитория urv-core:
|
||||||
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
|
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
|
||||||
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
|
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
|
||||||
# судя по документу приведенному ниже, обычное ABI подразумевает такое же
|
# в реализации сохраняются только необерегаемые регистры регистрового файла.
|
||||||
# сохранение контекста, что и при программном вызове (EABI подразумевает еще
|
# Это сделано по причине того, что при вызове высокоуровневого обработчика
|
||||||
# меньшее сохранение контекста), поэтому нет нужды сохранять весь регистровый
|
# прерываний, тот будет обязан сохранить оберегаемые регистры в соответствии
|
||||||
# файл.
|
# с соглашением о вызовах.
|
||||||
# Документ:
|
|
||||||
# https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc
|
|
||||||
_int_handler:
|
_int_handler:
|
||||||
# Данная операция меняет местами регистры sp и mscratch.
|
# Данная операция меняет местами регистры sp и mscratch.
|
||||||
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
|
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
|
||||||
@@ -103,7 +101,7 @@ _int_handler:
|
|||||||
sw t6, 68(sp)
|
sw t6, 68(sp)
|
||||||
|
|
||||||
# Кроме того, мы сохраняем состояние регистров прерываний на случай, если
|
# Кроме того, мы сохраняем состояние регистров прерываний на случай, если
|
||||||
# произойдет еще одно прерывание.
|
# произойдет ещё одно прерывание.
|
||||||
csrr t0, mscratch
|
csrr t0, mscratch
|
||||||
csrr t1, mepc
|
csrr t1, mepc
|
||||||
csrr a0, mcause
|
csrr a0, mcause
|
||||||
@@ -119,14 +117,16 @@ _int_handler:
|
|||||||
# Восстановление контекста. В первую очередь мы хотим восстановить CS-регистры,
|
# Восстановление контекста. В первую очередь мы хотим восстановить CS-регистры,
|
||||||
# на случай, если происходило вложенное прерывание. Для этого, мы должны
|
# на случай, если происходило вложенное прерывание. Для этого, мы должны
|
||||||
# вернуть исходное значение указателя стека прерываний. Однако его нынешнее
|
# вернуть исходное значение указателя стека прерываний. Однако его нынешнее
|
||||||
# значение нам еще необходимо для восстановления контекста, поэтому мы
|
# значение нам ещё необходимо для восстановления контекста, поэтому мы
|
||||||
# сохраним его в регистр a0, и будем восстанавливаться из него.
|
# сохраним его в регистр a0, и будем восстанавливаться из него.
|
||||||
mv a0,sp
|
mv a0,sp
|
||||||
|
|
||||||
lw t1, 72(a0)
|
lw t1, 72(a0)
|
||||||
|
lw t2, 76(a0)
|
||||||
addi sp, sp, 80
|
addi sp, sp, 80
|
||||||
csrw mscratch, sp
|
csrw mscratch, sp
|
||||||
csrw mepc, t1
|
csrw mepc, t1
|
||||||
|
csrw mcause, t2
|
||||||
lw ra, 4(a0)
|
lw ra, 4(a0)
|
||||||
lw sp, 8(a0)
|
lw sp, 8(a0)
|
||||||
lw t0, 12(a0)
|
lw t0, 12(a0)
|
||||||
|
@@ -41,7 +41,11 @@ _main_call:
|
|||||||
# нулевой элемент которого является именем исполняемого файла,
|
# нулевой элемент которого является именем исполняемого файла,
|
||||||
# Но для простоты реализации оба аргумента всего лишь обнулены.
|
# Но для простоты реализации оба аргумента всего лишь обнулены.
|
||||||
# Это сделано для детерминированного поведения программы в случае,
|
# Это сделано для детерминированного поведения программы в случае,
|
||||||
# если будет пытаться использовать эти аргументы.
|
# если программист будет пытаться использовать эти аргументы.
|
||||||
|
|
||||||
|
# Вызов main.
|
||||||
|
# Для того чтобы программа скомпоновалась, где-то должна быть описана
|
||||||
|
# функция именно с таким именем.
|
||||||
call main
|
call main
|
||||||
# Зацикливание после выхода из функции main
|
# Зацикливание после выхода из функции main
|
||||||
_endless_loop:
|
_endless_loop:
|
||||||
@@ -54,12 +58,10 @@ _endless_loop:
|
|||||||
# В основе кода лежит обработчик из репозитория urv-core:
|
# В основе кода лежит обработчик из репозитория urv-core:
|
||||||
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
|
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
|
||||||
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
|
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
|
||||||
# судя по документу приведенному ниже, обычное ABI подразумевает такое же
|
# в реализации сохраняются только необерегаемые регистры регистрового файла.
|
||||||
# сохранение контекста, что и при программном вызове (EABI подразумевает еще
|
# Это сделано по причине того, что при вызове высокоуровневого обработчика
|
||||||
# меньшее сохранение контекста), поэтому нет нужды сохранять весь регистровый
|
# прерываний, тот будет обязан сохранить оберегаемые регистры в соответствии
|
||||||
# файл.
|
# с соглашением о вызовах.
|
||||||
# Документ:
|
|
||||||
# https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc
|
|
||||||
_int_handler:
|
_int_handler:
|
||||||
# Данная операция меняет местами регистры sp и mscratch.
|
# Данная операция меняет местами регистры sp и mscratch.
|
||||||
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
|
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
|
||||||
@@ -99,7 +101,7 @@ _int_handler:
|
|||||||
sw t6, 68(sp)
|
sw t6, 68(sp)
|
||||||
|
|
||||||
# Кроме того, мы сохраняем состояние регистров прерываний на случай, если
|
# Кроме того, мы сохраняем состояние регистров прерываний на случай, если
|
||||||
# произойдет еще одно прерывание.
|
# произойдет ещё одно прерывание.
|
||||||
csrr t0, mscratch
|
csrr t0, mscratch
|
||||||
csrr t1, mepc
|
csrr t1, mepc
|
||||||
csrr a0, mcause
|
csrr a0, mcause
|
||||||
@@ -107,20 +109,24 @@ _int_handler:
|
|||||||
sw t1, 72(sp)
|
sw t1, 72(sp)
|
||||||
sw a0, 76(sp)
|
sw a0, 76(sp)
|
||||||
|
|
||||||
# Вызов высокоуровневого обработчика прерываний
|
# Вызов высокоуровневого обработчика прерываний.
|
||||||
# call int_handler
|
# Для того чтобы программа скомпоновалась, где-то должна быть описана
|
||||||
|
# функция именно с таким именем.
|
||||||
|
call int_handler
|
||||||
|
|
||||||
# Восстановление контекста. В первую очередь мы хотим восстановить CS-регистры,
|
# Восстановление контекста. В первую очередь мы хотим восстановить CS-регистры,
|
||||||
# на случай, если происходило вложенное прерывание. Для этого, мы должны
|
# на случай, если происходило вложенное прерывание. Для этого, мы должны
|
||||||
# вернуть исходное значение указателя стека прерываний. Однако его нынешнее
|
# вернуть исходное значение указателя стека прерываний. Однако его нынешнее
|
||||||
# значение нам еще необходимо для восстановления контекста, поэтому мы
|
# значение нам ещё необходимо для восстановления контекста, поэтому мы
|
||||||
# сохраним его в регистр a0, и будем восстанавливаться из него.
|
# сохраним его в регистр a0, и будем восстанавливаться из него.
|
||||||
mv a0,sp
|
mv a0,sp
|
||||||
|
|
||||||
lw t1, 72(a0)
|
lw t1, 72(a0)
|
||||||
|
lw t2, 76(a0)
|
||||||
addi sp, sp, 80
|
addi sp, sp, 80
|
||||||
csrw mscratch, sp
|
csrw mscratch, sp
|
||||||
csrw mepc, t1
|
csrw mepc, t1
|
||||||
|
csrw mcause, t2
|
||||||
lw ra, 4(a0)
|
lw ra, 4(a0)
|
||||||
lw sp, 8(a0)
|
lw sp, 8(a0)
|
||||||
lw t0, 12(a0)
|
lw t0, 12(a0)
|
||||||
|
Reference in New Issue
Block a user