irqasm.S 1.3 KB

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