ЛР10. Добавлены адреса инструкций в листинге

This commit is contained in:
Andrei Solodovnikov
2023-11-14 21:52:18 +03:00
parent 12ed407140
commit 188389d8ba

View File

@@ -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)
# что означает возврат в бесконечный цикл # что означает возврат в бесконечный цикл
``` ```
## Задание ## Задание