.set noreorder

.include "hwregs_a.h"

.set ISR_STACK_SIZE, 4096


.section .text

# Global ISR handler of PSn00bSDK

.set at

.type _global_isr, @function
_global_isr:
	
.Lisr_loop:

	#la		$gp, _gp					# Keep restoring GP since it gets
										# changed elsewhere sometimes
	
	lui		$a0, IOBASE					# Get IRQ status
	lw		$v0, IMASK($a0)
	nop
	
	srl		$v0, $s1					# Check IRQ mask bit if set
	andi	$v0, 0x1
	
	beqz	$v0, .Lno_irq				# Don't execute callback if IRQ not enabled
	nop
	
	lw		$v0, ISTAT($a0)
	nop
	srl		$v0, $s1					# Check IRQ status bit if set
	andi	$v0, 0x1
	beqz	$v0, .Lno_irq				# Don't execute callback if no IRQ
	nop
	
	lw		$v1, 0($s0)					# Load IRQ callback function
	nop
	
	lw		$v0, ISTAT($a0)				# Acknowledge the IRQ (by writing a 0 bit)
	li		$a1, 1
	sll		$a1, $s1
	addiu	$a2, $0 , -1
	xor		$a1, $a2
	sw		$a1, ISTAT($a0)
	
	beqz	$v1, .Lno_irq				# Don't execute if callback is not set
	nop

	jalr	$v1							# Call interrupt handler
	nop
	
.Lno_irq:

	addiu	$s0, 4
	
	blt		$s1, 11, .Lisr_loop
	addiu	$s1, 1

	j		ReturnFromException
	nop


.section .data

# Global ISR callback table

.global _irq_func_table
.type _irq_func_table, @object
_irq_func_table:
	.word	0
	.word	0
	.word	0
	.word	0
	.word	0
	.word	0
	.word	0
	.word	0
	.word	0
	.word	0
	.word	0
	.word	0

# Global ISR hook structure
.global _custom_exit
.type _custom_exit, @object
_custom_exit:
	.word _global_isr			# pc
	.word _isr_stack+ISR_STACK_SIZE	# sp
	.word 0						# fp
	.word _irq_func_table		# s0
	.word 0						# s1
	.word 0						# s2
	.word 0						# s3
	.word 0						# s4
	.word 0						# s5
	.word 0						# s6
	.word 0						# s7
	.word _gp					# gp
	
# Global ISR stack
#	.fill 1024
#_custom_exit_stack:
#	.fill 4
.comm _isr_stack, ISR_STACK_SIZE+4
