		.file	"exception.s"

		.section .kdata,"a"
		.align	2
_k_stack:	.space	256, 0
_k_msg1:	.asciiz	"Exception at "
_k_msg2:	.asciiz	"EPC      : "
_k_msg3:	.asciiz	"Cause    : "
_k_msg4:	.asciiz	"Status   : "
_k_msg5:	.asciiz	"BadVAddr : "
_k_crlf:	.asciiz	"\r\n"
_k_hextbl:	.ascii "0123456789ABCDEF"

		.section .ktext,"ax"
		.align	2
		.globl _kputs

		.macro kpush reg
		addiu	$sp, 4
		sw		\reg, 0($sp)
		.endm
		
		.macro kpop reg
		lw		\reg, 0($sp)
		addiu	$sp, -4
		.endm

_exc_handler:

		sw		$sp, _k_stack
		la		$sp, _k_stack
		kpush	$8
		kpush	$9
		kpush	$10
		kpush	$11
		kpush	$12
		kpush	$31

		.set	noreorder
		# Get BadVAddr
		mfc0	$10, $8
		kpush	$10
		# Get Status
		mfc0	$10, $12
		kpush	$10
		# Get Cause
		mfc0	$10, $13
		kpush	$10
		srl		$10, 29
		andi	$11, $10, 4
		# Get EPC
		mfc0	$10, $14
		kpush	$10

		# Get real EPC
		addu	$10, $11
		kpush	$10
		
		# set uart
		la	$26, sys_uart_baud
		addiu	$27, $0, baudrate
		sb	$27, 0($26)

		# Print CRLF
		la		$11, _k_crlf
		jal		_kputs
		nop

		# Print real EPC
		la		$11, _k_msg1
		jal		_kputs
		nop
		kpop	$10
		jal		_kprint_word		
		nop
		la		$11, _k_crlf
		jal		_kputs
		nop
		
		# Print EPC
		la		$11, _k_msg2
		jal		_kputs
		nop
		kpop	$10
		jal		_kprint_word		
		nop
		la		$11, _k_crlf
		jal		_kputs
		nop
		
		# Print Cause
		la		$11, _k_msg3
		jal		_kputs
		nop
		kpop	$10
		jal		_kprint_word		
		nop
		la		$11, _k_crlf
		jal		_kputs
		nop
		
		# Print Status
		la		$11, _k_msg4
		jal		_kputs
		nop
		kpop	$10
		jal		_kprint_word		
		nop
		la		$11, _k_crlf
		jal		_kputs
		nop
		
		# Print BadVAddr
		la		$11, _k_msg5
		jal		_kputs
		nop
		kpop	$10
		jal		_kprint_word		
		nop
		la		$11, _k_crlf
		jal		_kputs
		nop
		
		# Set Error LED and ExcCode LEDs
		# Get Cause
		mfc0	$26, $13
		la 		$27, sys_led_port
		srl		$26, 2
		andi	$26, 0x000F
		or 		$26, $27
		sw 		$26, 0($27)

		# wait for all interrupts = 0
$w4x:	mfc0	$26, $13
		nop
		srl		$26, 8
		andi	$26, 0xFF
		bnez	$26, $w4x
		nop
		
		# Get return address
		mfc0	$26, $14

		kpop	$31
		kpop	$12
		kpop	$11
		kpop	$10
		kpop	$9
		kpop	$8
		lw		$sp, _k_stack

		# Return
		jr	$26
		rfe
		.set	reorder

# word = $10
_kprint_word:
		.set	noreorder
		kpush	$31
		kpush	$10
		srl		$10, 16
		jal		_kprint_halfword
		nop
		kpop	$10
		jal		_kprint_halfword
		nop
		kpop	$31
		jr		$31
		nop
		.set	noreorder
		
# halfword = $10
_kprint_halfword:
		.set	noreorder
		kpush	$31
		kpush	$10
		srl		$10, 8
		jal		_kprint_byte
		nop
		kpop	$10
		jal		_kprint_byte
		nop
		kpop	$31
		jr		$31
		nop
		.set	noreorder
		
# byte = $10
_kprint_byte:
		.set	noreorder
		kpush	$31
		kpush	$10
		srl		$10, 4
		jal		_kprint_nibble
		nop
		kpop	$10
		jal		_kprint_nibble
		nop
		kpop	$31
		jr		$31
		nop
		.set	noreorder
		
_kprint_nibble:
		.set	noreorder
		kpush	$31
		kpush	$10
		la		$12, _k_hextbl
		andi	$10, 0xF
		addu	$12, $10
		lbu		$10, 0($12)
		jal		_ksaus
		nop
		kpop	$10
		kpop	$31
		jr		$31
		nop
		.set	noreorder
		
# char = $10
_ksaus:
		.set	noreorder
		la		$8, sys_uart_stat
		lbu		$8, 0($8)
		la		$9, sys_uart_data
		andi	$8, 0x02
		bnez	$8, _ksaus
		nop
		j		$31
		sb		$10, 0($9)
		.set	reorder
	
_kputs:
		.set	noreorder
		kpush	$11
		kpush	$31
$kpl:	lbu		$10, 0($11)
		addiu	$11, 1
		blez	$10, $kpex
		nop
		jal		_ksaus
		nop
		j		$kpl
		nop
$kpex:	kpop	$31
		kpop	$11
		jr		$31
		nop		
		.set	reorder
	
