checkasm.S 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /****************************************************************************
  2. * Copyright © 2022 Rémi Denis-Courmont.
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
  19. *****************************************************************************/
  20. #include "libavutil/riscv/asm.S"
  21. #if (__riscv_xlen == 64)
  22. const fail_s_reg
  23. .asciz "callee-saved integer register clobbered"
  24. endconst
  25. const fail_fs_reg
  26. .asciz "callee-saved floating-point register clobbered"
  27. endconst
  28. const fail_rsvd_reg
  29. .asciz "unallocatable register clobbered"
  30. endconst
  31. .section .tbss, "waT"
  32. .align 3
  33. .hidden checked_func
  34. .hidden saved_regs
  35. checked_func:
  36. .quad 0
  37. saved_regs:
  38. /* Space to spill RA, SP, GP, TP, S0-S11 and FS0-FS11 */
  39. .rept 4 + 12 + 12
  40. .quad 0
  41. .endr
  42. func checkasm_set_function
  43. lpad 0
  44. la.tls.ie t0, checked_func
  45. add t0, tp, t0
  46. sd a0, (t0)
  47. ret
  48. endfunc
  49. func checkasm_get_wrapper, v
  50. lpad 0
  51. addi sp, sp, -16
  52. sd fp, (sp)
  53. sd ra, 8(sp)
  54. addi fp, sp, 16
  55. call av_get_cpu_flags
  56. andi t0, a0, 8 /* AV_CPU_FLAG_RVV_I32 */
  57. lla a0, 3f
  58. beqz t0, 1f
  59. lla a0, 2f
  60. 1:
  61. ld ra, 8(sp)
  62. ld fp, (sp)
  63. addi sp, sp, 16
  64. ret
  65. .option norvc
  66. .align 2
  67. 2: /* <-- Entry point with the Vector extension --> */
  68. lpad 0
  69. /* Clobber the vectors */
  70. vsetvli t0, zero, e32, m8, ta, ma
  71. li t0, 0xdeadbeef
  72. vmv.v.x v0, t0
  73. vmv.v.x v8, t0
  74. vmv.v.x v16, t0
  75. vmv.v.x v24, t0
  76. /* Clobber the vector configuration */
  77. li t0, 0 /* Vector length: zero */
  78. li t2, -4 /* Vector type: illegal */
  79. vsetvl zero, t0, t2
  80. csrwi vxrm, 3 /* Rounding mode: round-to-odd */
  81. csrwi vxsat, 1 /* Saturation: encountered */
  82. .align 2
  83. 3: /* <-- Entry point without the Vector extension --> */
  84. lpad 0
  85. /* Save RA, unallocatable and callee-saved registers */
  86. la.tls.ie t0, saved_regs
  87. add t0, tp, t0
  88. sd ra, (t0)
  89. sd sp, 8(t0)
  90. sd gp, 16(t0)
  91. sd tp, 24(t0)
  92. .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  93. sd s\n, (32 + (16 * \n))(t0)
  94. fsd fs\n, (40 + (16 * \n))(t0)
  95. .endr
  96. /* Clobber the stack space right below SP */
  97. li t0, 0xdeadbeef1badf00d
  98. .rept 16
  99. addi sp, sp, -16
  100. sd t0, (sp)
  101. sd t0, 8(sp)
  102. .endr
  103. addi sp, sp, 256
  104. /* Clobber the saved and temporary registers */
  105. .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  106. .if (\n > 1 && \n < 7)
  107. mv t\n, t0
  108. .endif
  109. fmv.d.x ft\n, t0
  110. mv s\n, t0
  111. fmv.d.x fs\n, t0
  112. .endr
  113. /* Call the tested function */
  114. la.tls.ie t0, checked_func
  115. add t0, tp, t0
  116. ld t3, (t0)
  117. sd zero, (t0)
  118. jalr t3
  119. /* Check special register values */
  120. la.tls.ie t0, saved_regs
  121. add t0, tp, t0
  122. ld t1, 8(t0)
  123. bne t1, sp, 5f
  124. ld t1, 16(t0)
  125. bne t1, gp, 5f
  126. ld t1, 24(t0) // If TP was corrupted, we probably will have...
  127. bne t1, tp, 5f // ...already crashed before we even get here.
  128. /* Check value of saved registers */
  129. li t0, 0xdeadbeef1badf00d
  130. .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  131. bne t0, s\n, 6f
  132. #ifdef __riscv_float_abi_double
  133. /* TODO: check float ABI single too */
  134. fmv.x.d t1, fs\n
  135. bne t0, t1, 7f
  136. #endif
  137. .endr
  138. 4:
  139. /* Restore RA and saved registers */
  140. la.tls.ie t0, saved_regs
  141. add t0, tp, t0
  142. ld ra, (t0)
  143. .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  144. ld s\n, (32 + (16 * \n))(t0)
  145. fld fs\n, (40 + (16 * \n))(t0)
  146. .endr
  147. ret
  148. 5:
  149. lla a0, fail_rsvd_reg
  150. call checkasm_fail_func
  151. tail abort /* The test harness would probably crash anyway */
  152. 6:
  153. lla a0, fail_s_reg
  154. call checkasm_fail_func
  155. j 4b
  156. 7:
  157. lla a0, fail_fs_reg
  158. call checkasm_fail_func
  159. j 4b
  160. endfunc
  161. #endif