mirror of
https://github.com/MPSU/APS.git
synced 2025-09-16 17:40:41 +00:00
ЛР10. Добавлены адреса инструкций в листинге
This commit is contained in:
@@ -246,90 +246,95 @@ _Рисунок 4. Структурная схема контроллера пр
|
|||||||
```asm
|
```asm
|
||||||
_start:
|
_start:
|
||||||
# Инициализируем начальные значения регистров
|
# Инициализируем начальные значения регистров
|
||||||
li sp, 0x00003FFC # устанавливаем указатель на верхушку стека
|
00: li sp, 0x00003FFC # устанавливаем указатель на верхушку стека
|
||||||
|
04: # данная псевдоинструкция будет разбита на две
|
||||||
|
# инструкции: lui и addi
|
||||||
|
|
||||||
|
08: li gp, 0x00000000 # устанавливаем указатель на глобальные данные
|
||||||
|
|
||||||
|
0C: li t0, 0x00000001 # подготавливаем маску прерывания единственного
|
||||||
|
# (нулевого) входа
|
||||||
|
10: csrw mie, t0 # загружаем маску в регистр маски
|
||||||
|
|
||||||
|
14: la t0, interrupt # псевдоинструкция la аналогично li загружает число,
|
||||||
|
18: # только в случае la — это число является адресом
|
||||||
|
# указанного места (адреса обработчика перехвата)
|
||||||
# данная псевдоинструкция будет разбита на две
|
# данная псевдоинструкция будет разбита на две
|
||||||
# инструкции: lui и addi
|
# инструкции: lui и addi
|
||||||
|
|
||||||
li gp, 0x00000000 # устанавливаем указатель на глобальные данные
|
1С: csrw mtvec, t0 # устанавливаем вектор прерывания
|
||||||
|
|
||||||
li t0, 0x00000001 # подготавливаем маску прерывания единственного
|
20: li t0, 0x00001FFC # готовим адрес верхушки стека прерывания
|
||||||
# (нулевого) входа
|
24: # данная псевдоинструкция будет разбита на две
|
||||||
csrw mie, t0 # загружаем маску в регистр маски
|
# инструкции: lui и addi
|
||||||
|
|
||||||
la t0, interrupt # псевдоинструкция la аналогично li загружает число,
|
28: csrw mscratch, t0 # загружаем в указатель на верхушку стека прерывания
|
||||||
# только в случае la — это число является адресом
|
|
||||||
# указанного места (адреса обработчика перехвата)
|
|
||||||
|
|
||||||
csrw mtvec, t0 # устанавливаем вектор прерывания
|
2С: li t0, 1 # начальное значение глобальной переменной
|
||||||
|
30: sw t0, 0(gp) # загружаем переменную в память
|
||||||
|
|
||||||
li t0, 0x00001FFC # готовим адрес верхушки стека прерывания
|
34: li t1, 0 # начальное значение, чтобы в симуляции не было xxx
|
||||||
csrw mscratch, t0 # загружаем в указатель на верхушку стека прерывания
|
38: li t2, 0 # начальное значение, чтобы в симуляции не было xxx
|
||||||
|
|
||||||
li t0, 1 # начальное значение глобальной переменной
|
# Вызов ecall исключительно из хулиганских соображений, поскольку в данной
|
||||||
sw t0, 0(gp) # загружаем переменную в память
|
# микроархитектурной реализации это приведет к появлению illegal_instr и
|
||||||
|
# последующей обработке исключения
|
||||||
|
3С: ecall
|
||||||
|
|
||||||
li t1, 0 # начальное значение, чтобы в симуляции не было xxx
|
|
||||||
li t2, 0 # начальное значение, чтобы в симуляции не было xxx
|
|
||||||
|
|
||||||
# Вызов ecall исключительно из хулиганских соображений,
|
|
||||||
# поскольку в данной микроархитектурной реализации это
|
|
||||||
# приведет к появлению illegal_instr и последующей обработке
|
|
||||||
# исключения
|
|
||||||
ecall
|
|
||||||
# Вызов функции main
|
# Вызов функции main
|
||||||
main:
|
main:
|
||||||
beq x0, x0, main # бесконечный цикл, аналогичный while (1);
|
40: beq x0, x0, main # бесконечный цикл, аналогичный while (1);
|
||||||
|
|
||||||
# ОБРАБОТЧИК ПРЕРЫВАНИЯ
|
# ОБРАБОТЧИК ПРЕРЫВАНИЯ
|
||||||
# Без стороннего вмешательства процессор никогда не перейдет
|
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
|
||||||
# к инструкциям ниже, однако в случае прерывания,
|
# однако в случае прерывания в программный счетчик будет загружен адрес первой
|
||||||
# в программный счетчик будет загружен адрес первой
|
|
||||||
# нижележащей инструкции.
|
# нижележащей инструкции.
|
||||||
|
|
||||||
# Сохраняем используемые регистры на стек
|
# Сохраняем используемые регистры на стек
|
||||||
interrupt:
|
interrupt:
|
||||||
csrrw t0, mscratch, t0 # меняем местами mscratch и t0
|
44: csrrw t0, mscratch, t0 # меняем местами mscratch и t0
|
||||||
sw t1, 0(t0) # сохраняем t1 на стек mscratch
|
48: sw t1, 0(t0) # сохраняем t1 на стек mscratch
|
||||||
sw t2, 4(t0) # сохраняем t2 на стек mscratch
|
4С: sw t2, 4(t0) # сохраняем t2 на стек mscratch
|
||||||
|
|
||||||
# Проверяем произошло ли прерывание
|
# Проверяем произошло ли прерывание
|
||||||
csrr t1, mcause # t1 = mcause
|
50: csrr t1, mcause # t1 = mcause
|
||||||
li t2, 0x10000010 # загружаем в t2 код того, что произошло прерывание
|
54: li t2, 0x10000010 # загружаем в t2 код того, что произошло прерывание
|
||||||
bne t1, t2, exc_handler # если коды не совпадают, переходим к проверке
|
58: # данная псевдоинструкция будет разбита на две
|
||||||
|
# инструкции: lui и addi
|
||||||
|
5C: bne t1, t2, exc_handler # если коды не совпадают, переходим к проверке
|
||||||
# на исключение
|
# на исключение
|
||||||
# Обработчик прерывания
|
# Обработчик прерывания
|
||||||
lw t2, 0(gp) # загружаем переменную из памяти
|
60: lw t2, 0(gp) # загружаем переменную из памяти
|
||||||
addi t2, t2, 3 # прибавляем к значению 3
|
64: addi t2, t2, 3 # прибавляем к значению 3
|
||||||
sw t2, 0(gp) # возвращаем переменную в память
|
68: sw t2, 0(gp) # возвращаем переменную в память
|
||||||
j done # идем возвращать регистры и на выход
|
6C: j done # идем возвращать регистры и на выход
|
||||||
|
|
||||||
exc_handler: # Проверяем произошло ли исключение
|
exc_handler: # Проверяем произошло ли исключение
|
||||||
li t2, 0x0000002 # загружаем в t2 код того, что произошло исключение
|
70: li t2, 0x0000002 # загружаем в t2 код того, что произошло исключение
|
||||||
bne t1, t2, done # если это не оно, то выходим
|
74: bne t1, t2, done # если это не оно, то выходим
|
||||||
|
|
||||||
# Обработчик исключения
|
# Обработчик исключения
|
||||||
csrr t1, mepc # Узнаем значение PC (адреса инструкции,
|
78: csrr t1, mepc # Узнаем значение PC (адреса инструкции,
|
||||||
# вызвавшей исключение)
|
# вызвавшей исключение)
|
||||||
lw t2, 0x0(t1) # Загружаем эту инструкцию в регистр t2
|
7C: lw t2, 0x0(t1) # Загружаем эту инструкцию в регистр t2
|
||||||
# Теоретически мы могли бы после этого
|
# Теоретически мы могли бы после этого
|
||||||
# сделать что-то, в зависимости от этой инструкции.
|
# сделать что-то, в зависимости от этой инструкции.
|
||||||
# Например если это операция умножения — вызвать
|
# Например если это операция умножения — вызвать
|
||||||
# подпрограмму умножения.
|
# подпрограмму умножения.
|
||||||
|
|
||||||
addi t1, t1, 4 # Увеличиваем значение PC на 4, чтобы после
|
80: addi t1, t1, 4 # Увеличиваем значение PC на 4, чтобы после
|
||||||
# возврата не попасть на инструкцию, вызвавшую
|
# возврата не попасть на инструкцию, вызвавшую
|
||||||
# исключение.
|
# исключение.
|
||||||
csrw mepc, t1 # Записываем обновленное значение PC в регистр mepc
|
84: csrw mepc, t1 # Записываем обновленное значение PC в регистр mepc
|
||||||
j done # идем восстанавливать регистры со стека и на выход
|
88: j done # идем восстанавливать регистры со стека и на выход
|
||||||
|
|
||||||
# Возвращаем регистры на места и выходим
|
# Возвращаем регистры на места и выходим
|
||||||
done:
|
done:
|
||||||
lw t1, 0(t0) # возвращаем t1 со стека
|
8C: lw t1, 0(t0) # возвращаем t1 со стека
|
||||||
lw t2, 4(t0) # возвращаем t2 со стека
|
90: lw t2, 4(t0) # возвращаем t2 со стека
|
||||||
csrrw t0, mscratch, t0 # меняем обратно местами t0 и mscratch
|
94: csrrw t0, mscratch, t0 # меняем обратно местами t0 и mscratch
|
||||||
mret # возвращаем управление программе (pc = mepc)
|
98: mret # возвращаем управление программе (pc = mepc)
|
||||||
# что означает возврат в бесконечный цикл
|
# что означает возврат в бесконечный цикл
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Задание
|
## Задание
|
||||||
|
Reference in New Issue
Block a user