#include "picorv32.h"
#include "iodevs.h"


	// The IRQ dispatch code is written in assembly to make
	// better use of the register bank switching: can simply
	// use the saved registers here, no saving needed.
	// registers need to be
	.pushsection ".init.irq","ax"
	.balign 4
	.globl _irq
	.option push
	.option norvc	// Alignment matters more here
_irq:
	addqxi sp,sp,0
	// s10 contains the IRQ return address, s11 the mask of
	// IRQs to be handled.

	// Priority for ABC-bus I/O
	andi s0,s11,1 << ABC_IRQ
	beqz s0,1f
	jal irqhandler_abc
	sub s11,s11,s0
	beqz s11,.L_done
1:

	li s1, 0
.Lirq_loop:
	// ctz would make this more efficient...
#if IRQ_VECTORS > 16
	slli t0,s11,16
	bnez t0,1f
	srli s11,s11,16
	addi s1,s1,16*4
1:
#endif
#if IRQ_VECTORS > 8
	zext.b t0,s11
	bnez t0,2f
	srli s11,s11,8
	addi s1,s1,8*4
2:
#endif
#if IRQ_VECTORS > 4
	andi t0,s11,15
	bnez t0,3f
	srli s11,s11,4
	addi s1,s1,4*4
3:
#endif
#if IRQ_VECTORS > 2
	andi t0,s11,3
	bnez t0,4f
	srli s11,s11,2
	addi s1,s1,2*4
4:
#endif
#if IRQ_VECTORS > 1
	andi t0,s11,1
	bnez t0,5f
	srli s11,s11,1
	addi s1,s1,1*4
5:
#endif
	// __irq_handler_table must be in the zero page
	// However, prevent the linker from incorrectly relaxing
	// this instruction.
	.option push
	.option norelax
	lw t0,%lo(__irq_handler_table)(s1)
	.option pop
	srli a0,s1,2
	mv   a1,s10
	jalr t0
	srli s11,s11,1
	addi s1,s1,4*1
	bnez s11,.Lirq_loop

.L_done:
	mret
	.type _irq, @function
	.size _irq, . - _irq
	.option pop
