checkasm.S 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. la.tls.ie t0, checked_func
  44. add t0, tp, t0
  45. sd a0, (t0)
  46. ret
  47. endfunc
  48. func checkasm_get_wrapper, v
  49. addi sp, sp, -16
  50. sd fp, (sp)
  51. sd ra, 8(sp)
  52. addi fp, sp, 16
  53. call av_get_cpu_flags
  54. andi t0, a0, 8 /* AV_CPU_FLAG_RVV_I32 */
  55. lla a0, 3f
  56. beqz t0, 1f
  57. lla a0, 2f
  58. 1:
  59. ld ra, 8(sp)
  60. ld fp, (sp)
  61. addi sp, sp, 16
  62. ret
  63. 2: /* <-- Entry point with the Vector extension --> */
  64. /* Clobber the vectors */
  65. vsetvli t0, zero, e32, m8, ta, ma
  66. li t0, 0xdeadbeef
  67. vmv.v.x v0, t0
  68. vmv.v.x v8, t0
  69. vmv.v.x v16, t0
  70. vmv.v.x v24, t0
  71. /* Clobber the vector configuration */
  72. li t0, 0 /* Vector length: zero */
  73. li t1, -1 << 31 /* Vector type: illegal */
  74. vsetvl zero, t0, t1
  75. csrwi vxrm, 3 /* Rounding mode: round-to-odd */
  76. csrwi vxsat, 1 /* Saturation: encountered */
  77. 3: /* <-- Entry point without the Vector extension --> */
  78. /* Save RA, unallocatable and callee-saved registers */
  79. la.tls.ie t0, saved_regs
  80. add t0, tp, t0
  81. sd ra, (t0)
  82. sd sp, 8(t0)
  83. sd gp, 16(t0)
  84. sd tp, 24(t0)
  85. .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  86. sd s\n, (32 + (16 * \n))(t0)
  87. fsd fs\n, (40 + (16 * \n))(t0)
  88. .endr
  89. /* Clobber the stack space right below SP */
  90. li t0, 0xdeadbeef1badf00d
  91. .rept 16
  92. addi sp, sp, -16
  93. sd t0, (sp)
  94. sd t0, 8(sp)
  95. .endr
  96. addi sp, sp, 256
  97. /* Clobber the saved and temporary registers */
  98. .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  99. .if (\n > 0 && \n < 7)
  100. mv t\n, t0
  101. .endif
  102. fmv.d.x ft\n, t0
  103. mv s\n, t0
  104. fmv.d.x fs\n, t0
  105. .endr
  106. /* Call the tested function */
  107. la.tls.ie t0, checked_func
  108. add t0, tp, t0
  109. ld t1, (t0)
  110. sd zero, (t0)
  111. jalr t1
  112. /* Check special register values */
  113. la.tls.ie t0, saved_regs
  114. add t0, tp, t0
  115. ld t1, 8(t0)
  116. bne t1, sp, 5f
  117. ld t1, 16(t0)
  118. bne t1, gp, 5f
  119. ld t1, 24(t0) // If TP was corrupted, we probably will have...
  120. bne t1, tp, 5f // ...already crashed before we even get here.
  121. /* Check value of saved registers */
  122. li t0, 0xdeadbeef1badf00d
  123. .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  124. bne t0, s\n, 6f
  125. #ifdef __riscv_float_abi_double
  126. /* TODO: check float ABI single too */
  127. fmv.x.d t1, fs\n
  128. bne t0, t1, 7f
  129. #endif
  130. .endr
  131. 4:
  132. /* Restore RA and saved registers */
  133. la.tls.ie t0, saved_regs
  134. add t0, tp, t0
  135. ld ra, (t0)
  136. .irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
  137. ld s\n, (32 + (16 * \n))(t0)
  138. fld fs\n, (40 + (16 * \n))(t0)
  139. .endr
  140. ret
  141. 5:
  142. lla a0, fail_rsvd_reg
  143. call checkasm_fail_func
  144. tail abort /* The test harness would probably crash anyway */
  145. 6:
  146. lla a0, fail_s_reg
  147. call checkasm_fail_func
  148. j 4b
  149. 7:
  150. lla a0, fail_fs_reg
  151. call checkasm_fail_func
  152. j 4b
  153. endfunc
  154. #endif