irqasm.S 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "compiler.h"
  2. #include "picorv32.h"
  3. #include "ioregs.h"
  4. // The IRQ dispatch code is written in assembly to make
  5. // better use of the register bank switching: can simply
  6. // use the saved registers here, no saving needed.
  7. // registers need to be
  8. .pushsection ".init.irq","ax"
  9. .balign 4
  10. .globl _irq
  11. .option push
  12. .option norvc // Alignment matters more here
  13. _irq:
  14. addqxi sp,sp,0
  15. // s10 contains the IRQ return address, s11 the mask of
  16. // IRQs to be handled.
  17. // Send EOI for all interrupts (previously done in hardware)
  18. sw s11,SYS_EOI(zero)
  19. // Fast dispatch for the ABC-bus interrupt handler
  20. andi s0,s11,1 << ABC_IRQ
  21. beqz s0,1f
  22. jal irqhandler_abc_0
  23. sub s11,s11,s0
  24. beqz s11,.L_done
  25. 1:
  26. li s1, 0
  27. .Lirq_loop:
  28. // ctz would make this more efficient...
  29. #if IRQ_VECTORS > 16
  30. slli t0,s11,16
  31. bnez t0,1f
  32. srli s11,s11,16
  33. addi s1,s1,16*4
  34. 1:
  35. #endif
  36. #if IRQ_VECTORS > 8
  37. zext.b t0,s11
  38. bnez t0,2f
  39. srli s11,s11,8
  40. addi s1,s1,8*4
  41. 2:
  42. #endif
  43. #if IRQ_VECTORS > 4
  44. andi t0,s11,15
  45. bnez t0,3f
  46. srli s11,s11,4
  47. addi s1,s1,4*4
  48. 3:
  49. #endif
  50. #if IRQ_VECTORS > 2
  51. andi t0,s11,3
  52. bnez t0,4f
  53. srli s11,s11,2
  54. addi s1,s1,2*4
  55. 4:
  56. #endif
  57. #if IRQ_VECTORS > 1
  58. andi t0,s11,1
  59. bnez t0,5f
  60. srli s11,s11,1
  61. addi s1,s1,1*4
  62. 5:
  63. #endif
  64. srli a0,s1,2 // Vector number
  65. mv a1,s10 // PC (including the rvc flag)
  66. .option norelax // ld will mess up trying to relax this instruction
  67. jalr s1,%lo(__irq_handler_table) // Must be in zero page
  68. .option relax
  69. srli s11,s11,1
  70. addi s1,s1,4*1
  71. bnez s11,.Lirq_loop
  72. .L_done:
  73. mret
  74. .type _irq, @function
  75. .size _irq, . - _irq
  76. .option pop
  77. // Debug functions to read and write x-registers from interrupt
  78. // mode by register number
  79. .pushsection ".text.hot.rdxreg","ax"
  80. .globl rdxreg
  81. .balign 4
  82. rdxreg:
  83. la a3,_xreg_smc
  84. lw a2,8(a3) // addqxi a0,zero,0
  85. andi a0,a0,31
  86. slli a0,a0,15 // rs1
  87. or a2,a2,a0
  88. sw a2,(a3)
  89. jr a3
  90. .type rdxreg, @function
  91. .size rdxreg, . - rdxreg
  92. .popsection
  93. .pushsection ".text.hot.wrxreg","ax"
  94. .globl wrxreg
  95. .balign 4
  96. wrxreg:
  97. la a3,_xreg_smc
  98. lw a2,12(a3) // addxqi zero,a1,0
  99. andi a0,a0,31
  100. slli a0,a0,7 // rd
  101. or a2,a2,a0
  102. sw a2,(a3)
  103. jr a3
  104. .type wrxreg, @function
  105. .size wrxreg, . - wrxreg
  106. .popsection
  107. __rwtext
  108. .balign 4
  109. .option norvc
  110. _xreg_smc:
  111. nop
  112. ret
  113. addqxi a0,zero,0
  114. addxqi zero,a1,0
  115. .type _xreg_smc, @function
  116. .size _xreg_smc, . - _xreg_smc