irqasm.S 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  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. .balign 4
  8. .globl _irq
  9. .option push
  10. .option norvc // Alignment matters more here
  11. _irq:
  12. addqxi sp,sp,0
  13. // s10 contains the IRQ return address, s11 the mask of
  14. // IRQs to be handled.
  15. li s1, 0
  16. .Lirq_loop:
  17. // ctz would make this more efficient...
  18. slli t0,s11,16
  19. bnez t0,1f
  20. srli s11,s11,16
  21. addi s1,s1,16*4
  22. 1:
  23. zext.b t0,s11
  24. bnez t0,2f
  25. srli s11,s11,8
  26. addi s1,s1,8*4
  27. 2:
  28. andi t0,s11,15
  29. bnez t0,3f
  30. srli s11,s11,4
  31. addi s1,s1,4*4
  32. 3:
  33. andi t0,s11,3
  34. bnez t0,4f
  35. srli s11,s11,2
  36. addi s1,s1,2*4
  37. 4:
  38. andi t0,s11,1
  39. bnez t0,5f
  40. srli s11,s11,1
  41. addi s1,s1,1*4
  42. 5:
  43. // __irq_handler_table must be in the zero page
  44. // However, prevent the linker from incorrectly relaxing
  45. // this instruction.
  46. .option push
  47. .option norelax
  48. lw t0,%lo(__irq_handler_table)(s1)
  49. .option pop
  50. srli a0,s1,2
  51. jalr t0
  52. srli s11,s11,1
  53. addi s1,s1,4*1
  54. bnez s11,.Lirq_loop
  55. mret
  56. .type _irq, @function
  57. .size _irq, . - _irq
  58. .option pop