irqasm.S 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #include "picorv32.h"
  2. // The IRQ dispatch code is written in assembly to make
  3. // better use of the register bank switching: can simply
  4. // use the saved registers here, no saving needed.
  5. // registers need to be
  6. .pushsection ".init.irq","ax"
  7. .globl _irq
  8. _irq:
  9. addqxi sp,sp,0
  10. // s10 contains the IRQ return address, s11 the mask of
  11. // IRQs to be handled.
  12. li s1, 0
  13. .Lirq_loop:
  14. // ctz would make this more efficient...
  15. slli t0,s11,16
  16. bnez t0,1f
  17. srli s11,s11,16
  18. addi s1,s1,16*4
  19. 1:
  20. zext.b t0,s11
  21. bnez t0,2f
  22. srli s11,s11,8
  23. addi s1,s1,8*4
  24. 2:
  25. andi t0,s11,15
  26. bnez t0,3f
  27. srli s11,s11,4
  28. addi s1,s1,4*4
  29. 3:
  30. andi t0,s11,3
  31. bnez t0,4f
  32. srli s11,s11,2
  33. addi s1,s1,2*4
  34. 4:
  35. andi t0,s11,1
  36. bnez t0,5f
  37. srli s11,s11,1
  38. addi s1,s1,1*4
  39. 5:
  40. // __irq_handler_table must be in the zero page
  41. // However, prevent the linker from incorrectly relaxing
  42. // this instruction.
  43. .option push
  44. .option norelax
  45. lw t0,%lo(__irq_handler_table)(s1)
  46. .option pop
  47. srli a0,s1,2
  48. jalr t0
  49. srli s11,s11,1
  50. addi s1,s1,4*1
  51. bnez s11,.Lirq_loop
  52. mret
  53. .type _irq, @function
  54. .size _irq, . - _irq