cvw/tests/custom/crt0/isr.s
2022-12-18 16:24:26 -06:00

214 lines
4.8 KiB
ArmAsm

.section .text
.global __trap_handler
.type __trap_handler, @function
__trap_handler:
# save the context of the cpu to the top of the current stack
addi sp, sp, -124
sw x1, 0x0(sp)
sw x2, 0x4(sp)
sw x3, 0x8(sp)
sw x4, 0xC(sp)
sw x5, 0x10(sp)
sw x6, 0x14(sp)
sw x7, 0x18(sp)
sw x8, 0x1C(sp)
sw x9, 0x20(sp)
sw x10, 0x24(sp)
sw x11, 0x28(sp)
sw x12, 0x2C(sp)
sw x13, 0x30(sp)
sw x14, 0x34(sp)
sw x15, 0x38(sp)
sw x16, 0x3C(sp)
sw x17, 0x40(sp)
sw x18, 0x44(sp)
sw x19, 0x48(sp)
sw x20, 0x4C(sp)
sw x21, 0x50(sp)
sw x22, 0x54(sp)
sw x23, 0x58(sp)
sw x24, 0x5C(sp)
sw x25, 0x60(sp)
sw x26, 0x64(sp)
sw x27, 0x68(sp)
sw x28, 0x6C(sp)
sw x29, 0x70(sp)
sw x30, 0x74(sp)
sw x31, 0x78(sp)
# figure out what caused the trap.
csrrw t0, mcause, x0
# mcause is {int, 31 bit exception code}
# for this implementation only the lowest 4 bits are used
srli t1, t0, 31 # interrupt flag
andi t2, t0, 0xF # 4 bit cause
slli t1, t1, 5 # shift int flag
or t1, t1, t2 # combine
slli t1, t1, 2 # multiply by 4
la t3, exception_table
add t4, t3, t1
lw t5, 0(t4)
jr t5, 0 # jump to specific ISR
# specific ISR is expected to set epc
restore_st:
# restore register from stack on exit.
lw x1, 0x0(sp)
lw x2, 0x4(sp)
lw x3, 0x8(sp)
lw x4, 0xC(sp)
lw x5, 0x10(sp)
lw x6, 0x14(sp)
lw x7, 0x18(sp)
lw x8, 0x1C(sp)
lw x9, 0x20(sp)
lw x10, 0x24(sp)
lw x11, 0x28(sp)
lw x12, 0x2C(sp)
lw x13, 0x30(sp)
lw x14, 0x34(sp)
lw x15, 0x38(sp)
lw x16, 0x3C(sp)
lw x17, 0x40(sp)
lw x18, 0x44(sp)
lw x19, 0x48(sp)
lw x20, 0x4C(sp)
lw x21, 0x50(sp)
lw x22, 0x54(sp)
lw x23, 0x58(sp)
lw x24, 0x5C(sp)
lw x25, 0x60(sp)
lw x26, 0x64(sp)
lw x27, 0x68(sp)
lw x28, 0x6C(sp)
lw x29, 0x70(sp)
lw x30, 0x74(sp)
lw x31, 0x78(sp)
addi sp, sp, 124
mret
.section .text
.type trap_instr_addr_misalign, @function
trap_instr_addr_misalign:
# fatal error, report error and halt
addi sp, sp, 4
sw ra, 0(sp)
jal fail
lw ra, 0(sp)
la t0, restore_st
jr t0, 0
.section .text
.type trap_m_ecall, @function
trap_m_ecall:
addi sp, sp, -4
sw ra, 0(sp)
# select which system call based on a7.
# for this example we will just define the following.
# not standard with linux or anything.
# 0: execute a call back function
# 1: decrease privilege by 1 (m=>s, s=>u, u=>u)
# 2: increase privilege by 1 (m=>m, s=>m, u=>s)
# check a7
li t0, 1
beq a7, t0, trap_m_decrease_privilege
li t0, 2
beq a7, t0, trap_m_increase_privilege
# call call back function if not zero
la t1, isr_m_ecall_cb_fp
lw t0, 0(t1)
beq t0, x0, trap_m_ecall_skip_cb
jalr ra, t0, 0
trap_m_ecall_skip_cb:
# modify the mepc
csrrw t0, mepc, x0
addi t0, t0, 4
csrrw x0, mepc, t0
lw ra, 0(sp)
addi sp, sp, 4
la t0, restore_st
jr t0, 0
trap_m_decrease_privilege:
# read the mstatus register
csrrw t0, mstatus, x0
# 11 => 01, and 01 => 00.
# this is accomplished by clearing bit 12 and taking the old
# bit 12 as the new bit 11.
li t3, 0x00001800
and t1, t0, t3 # isolates the bits 12 and 11.
# shift right by 1.
srli t2, t1, 1
and t2, t2, t3 # this will clear bit 10.
li t3, ~0x00001800
and t4, t0, t3
or t0, t2, t4
csrrw x0, mstatus, t0
j trap_m_ecall_skip_cb
trap_m_increase_privilege:
# read the mstatus register
csrrw t0, mstatus, x0
# 11 => 01, and 01 => 00.
# this is accomplished by setting bit 11 and taking the old
# bit 11 as the new bit 12.
li t3, 0x00000800
li t4, ~0x00000800
and t1, t0, t3
slli t2, t1, 1 # shift left by 1.
or t2, t2, t3 # bit 11 is always set.
and t1, t0, t5
or t0, t1, t2
csrrw x0, mstatus, t0
j trap_m_ecall_skip_cb
.data
exception_table:
.int trap_instr_addr_misalign
.int trap_instr_addr_misalign #trap_instr_access_fault
.int trap_instr_addr_misalign #trap_illegal_instr
.int trap_instr_addr_misalign #trap_breakpoint
.int trap_instr_addr_misalign #trap_load_addr_misalign
.int trap_instr_addr_misalign #trap_load_access_fault
.int trap_instr_addr_misalign #trap_store_addr_misalign
.int trap_instr_addr_misalign #trap_store_access_fault
.int trap_m_ecall
.int trap_m_ecall
.int restore_st
.int trap_m_ecall
.int trap_instr_addr_misalign #trap_instr_page_fault
.int trap_instr_addr_misalign #trap_load_page_fault
.int restore_st
.int trap_instr_addr_misalign #trap_store_page_fault
#.data
#interrupt_table:
.int trap_instr_addr_misalign #trap_u_software
.int trap_instr_addr_misalign #trap_s_software
.int restore_st
.int trap_instr_addr_misalign #trap_m_software
.int trap_instr_addr_misalign #trap_u_timer
.int trap_instr_addr_misalign #trap_s_timer
.int restore_st
.int trap_instr_addr_misalign #trap_m_timer
.int trap_instr_addr_misalign #trap_u_external
.int trap_instr_addr_misalign #trap_s_external
.int restore_st
.int trap_instr_addr_misalign #trap_m_external
.int restore_st
.int restore_st
.int restore_st
.int restore_st
.section .data
.global isr_m_ecall_cb_fp
isr_m_ecall_cb_fp:
.int 0