12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- #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
- jalr t0
- srli s11,s11,1
- addi s1,s1,4*1
- bnez s11,.Lirq_loop
- mret
- .type _irq, @function
- .size _irq, . - _irq
- .option pop
|