#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