#include "compiler.h"
#include "sections.h"
#include "picorv32.h"
#include "ioregs.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.

	.pushsection ".init.irq","ax"
	.balign 4
	.globl _irq
	.option push
	.option norvc		// Just messes up alignment
	.option arch, +zbb	// Enable the ctz instruction
_irq:
	// s11 contains the mask of IRQs to be handled.

.Lirq_loop:
	ctz a0,s11	// Vector number
	slli t1,a0,2	// Table index
	.option norelax	// Relaxing this instruction will do bad things
	lw ra,%lo(__irq_handler_table)(t1)
	.option relax
	jalr ra

	// Strip the lowest set bit of s11 - the interrupt just handled
	addi t1,s11,-1
	and  s11,s11,t1

	// Check for newly arrived higher priority interrupts; this
	// avoids priority inversion. This will also send EOI (really
	// INTACK) for those interrupts.
	pollirq s11,zero,s11
	bnez s11,.Lirq_loop
	mret

	.type _irq, @function
	.size _irq, . - _irq
	.option pop
