forked from Github_Repos/cvw
		
	
		
			
				
	
	
		
			214 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			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
 |