irqasm.S 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. // Priority for ABC-bus I/O
  17. andi s0,s11,1 << ABC_IRQ
  18. beqz s0,1f
  19. jal irqhandler_abc
  20. sub s11,s11,s0
  21. beqz s11,.L_done
  22. 1:
  23. li s1, 0
  24. .Lirq_loop:
  25. // ctz would make this more efficient...
  26. #if IRQ_VECTORS > 16
  27. slli t0,s11,16
  28. bnez t0,1f
  29. srli s11,s11,16
  30. addi s1,s1,16*4
  31. 1:
  32. #endif
  33. #if IRQ_VECTORS > 8
  34. zext.b t0,s11
  35. bnez t0,2f
  36. srli s11,s11,8
  37. addi s1,s1,8*4
  38. 2:
  39. #endif
  40. #if IRQ_VECTORS > 4
  41. andi t0,s11,15
  42. bnez t0,3f
  43. srli s11,s11,4
  44. addi s1,s1,4*4
  45. 3:
  46. #endif
  47. #if IRQ_VECTORS > 2
  48. andi t0,s11,3
  49. bnez t0,4f
  50. srli s11,s11,2
  51. addi s1,s1,2*4
  52. 4:
  53. #endif
  54. #if IRQ_VECTORS > 1
  55. andi t0,s11,1
  56. bnez t0,5f
  57. srli s11,s11,1
  58. addi s1,s1,1*4
  59. 5:
  60. #endif
  61. // __irq_handler_table must be in the zero page
  62. // However, prevent the linker from incorrectly relaxing
  63. // this instruction.
  64. .option push
  65. .option norelax
  66. lw t0,%lo(__irq_handler_table)(s1)
  67. .option pop
  68. srli a0,s1,2
  69. mv a1,s10
  70. jalr t0
  71. srli s11,s11,1
  72. addi s1,s1,4*1
  73. bnez s11,.Lirq_loop
  74. .L_done:
  75. mret
  76. .type _irq, @function
  77. .size _irq, . - _irq
  78. .option pop