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