#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. 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 mret .type _irq, @function .size _irq, . - _irq .option pop