fpu.S 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Author: Lu Zeng <[email protected]>
  4. * Pei Huang <[email protected]>
  5. * Huacai Chen <[email protected]>
  6. *
  7. * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  8. */
  9. #include <asm/asm.h>
  10. #include <asm/asmmacro.h>
  11. #include <asm/asm-offsets.h>
  12. #include <asm/errno.h>
  13. #include <asm/export.h>
  14. #include <asm/fpregdef.h>
  15. #include <asm/loongarch.h>
  16. #include <asm/regdef.h>
  17. #define FPU_REG_WIDTH 8
  18. #define LSX_REG_WIDTH 16
  19. #define LASX_REG_WIDTH 32
  20. .macro EX insn, reg, src, offs
  21. .ex\@: \insn \reg, \src, \offs
  22. .section __ex_table,"a"
  23. PTR .ex\@, fault
  24. .previous
  25. .endm
  26. .macro sc_save_fp base
  27. EX fst.d $f0, \base, (0 * FPU_REG_WIDTH)
  28. EX fst.d $f1, \base, (1 * FPU_REG_WIDTH)
  29. EX fst.d $f2, \base, (2 * FPU_REG_WIDTH)
  30. EX fst.d $f3, \base, (3 * FPU_REG_WIDTH)
  31. EX fst.d $f4, \base, (4 * FPU_REG_WIDTH)
  32. EX fst.d $f5, \base, (5 * FPU_REG_WIDTH)
  33. EX fst.d $f6, \base, (6 * FPU_REG_WIDTH)
  34. EX fst.d $f7, \base, (7 * FPU_REG_WIDTH)
  35. EX fst.d $f8, \base, (8 * FPU_REG_WIDTH)
  36. EX fst.d $f9, \base, (9 * FPU_REG_WIDTH)
  37. EX fst.d $f10, \base, (10 * FPU_REG_WIDTH)
  38. EX fst.d $f11, \base, (11 * FPU_REG_WIDTH)
  39. EX fst.d $f12, \base, (12 * FPU_REG_WIDTH)
  40. EX fst.d $f13, \base, (13 * FPU_REG_WIDTH)
  41. EX fst.d $f14, \base, (14 * FPU_REG_WIDTH)
  42. EX fst.d $f15, \base, (15 * FPU_REG_WIDTH)
  43. EX fst.d $f16, \base, (16 * FPU_REG_WIDTH)
  44. EX fst.d $f17, \base, (17 * FPU_REG_WIDTH)
  45. EX fst.d $f18, \base, (18 * FPU_REG_WIDTH)
  46. EX fst.d $f19, \base, (19 * FPU_REG_WIDTH)
  47. EX fst.d $f20, \base, (20 * FPU_REG_WIDTH)
  48. EX fst.d $f21, \base, (21 * FPU_REG_WIDTH)
  49. EX fst.d $f22, \base, (22 * FPU_REG_WIDTH)
  50. EX fst.d $f23, \base, (23 * FPU_REG_WIDTH)
  51. EX fst.d $f24, \base, (24 * FPU_REG_WIDTH)
  52. EX fst.d $f25, \base, (25 * FPU_REG_WIDTH)
  53. EX fst.d $f26, \base, (26 * FPU_REG_WIDTH)
  54. EX fst.d $f27, \base, (27 * FPU_REG_WIDTH)
  55. EX fst.d $f28, \base, (28 * FPU_REG_WIDTH)
  56. EX fst.d $f29, \base, (29 * FPU_REG_WIDTH)
  57. EX fst.d $f30, \base, (30 * FPU_REG_WIDTH)
  58. EX fst.d $f31, \base, (31 * FPU_REG_WIDTH)
  59. .endm
  60. .macro sc_restore_fp base
  61. EX fld.d $f0, \base, (0 * FPU_REG_WIDTH)
  62. EX fld.d $f1, \base, (1 * FPU_REG_WIDTH)
  63. EX fld.d $f2, \base, (2 * FPU_REG_WIDTH)
  64. EX fld.d $f3, \base, (3 * FPU_REG_WIDTH)
  65. EX fld.d $f4, \base, (4 * FPU_REG_WIDTH)
  66. EX fld.d $f5, \base, (5 * FPU_REG_WIDTH)
  67. EX fld.d $f6, \base, (6 * FPU_REG_WIDTH)
  68. EX fld.d $f7, \base, (7 * FPU_REG_WIDTH)
  69. EX fld.d $f8, \base, (8 * FPU_REG_WIDTH)
  70. EX fld.d $f9, \base, (9 * FPU_REG_WIDTH)
  71. EX fld.d $f10, \base, (10 * FPU_REG_WIDTH)
  72. EX fld.d $f11, \base, (11 * FPU_REG_WIDTH)
  73. EX fld.d $f12, \base, (12 * FPU_REG_WIDTH)
  74. EX fld.d $f13, \base, (13 * FPU_REG_WIDTH)
  75. EX fld.d $f14, \base, (14 * FPU_REG_WIDTH)
  76. EX fld.d $f15, \base, (15 * FPU_REG_WIDTH)
  77. EX fld.d $f16, \base, (16 * FPU_REG_WIDTH)
  78. EX fld.d $f17, \base, (17 * FPU_REG_WIDTH)
  79. EX fld.d $f18, \base, (18 * FPU_REG_WIDTH)
  80. EX fld.d $f19, \base, (19 * FPU_REG_WIDTH)
  81. EX fld.d $f20, \base, (20 * FPU_REG_WIDTH)
  82. EX fld.d $f21, \base, (21 * FPU_REG_WIDTH)
  83. EX fld.d $f22, \base, (22 * FPU_REG_WIDTH)
  84. EX fld.d $f23, \base, (23 * FPU_REG_WIDTH)
  85. EX fld.d $f24, \base, (24 * FPU_REG_WIDTH)
  86. EX fld.d $f25, \base, (25 * FPU_REG_WIDTH)
  87. EX fld.d $f26, \base, (26 * FPU_REG_WIDTH)
  88. EX fld.d $f27, \base, (27 * FPU_REG_WIDTH)
  89. EX fld.d $f28, \base, (28 * FPU_REG_WIDTH)
  90. EX fld.d $f29, \base, (29 * FPU_REG_WIDTH)
  91. EX fld.d $f30, \base, (30 * FPU_REG_WIDTH)
  92. EX fld.d $f31, \base, (31 * FPU_REG_WIDTH)
  93. .endm
  94. .macro sc_save_fcc base, tmp0, tmp1
  95. movcf2gr \tmp0, $fcc0
  96. move \tmp1, \tmp0
  97. movcf2gr \tmp0, $fcc1
  98. bstrins.d \tmp1, \tmp0, 15, 8
  99. movcf2gr \tmp0, $fcc2
  100. bstrins.d \tmp1, \tmp0, 23, 16
  101. movcf2gr \tmp0, $fcc3
  102. bstrins.d \tmp1, \tmp0, 31, 24
  103. movcf2gr \tmp0, $fcc4
  104. bstrins.d \tmp1, \tmp0, 39, 32
  105. movcf2gr \tmp0, $fcc5
  106. bstrins.d \tmp1, \tmp0, 47, 40
  107. movcf2gr \tmp0, $fcc6
  108. bstrins.d \tmp1, \tmp0, 55, 48
  109. movcf2gr \tmp0, $fcc7
  110. bstrins.d \tmp1, \tmp0, 63, 56
  111. EX st.d \tmp1, \base, 0
  112. .endm
  113. .macro sc_restore_fcc base, tmp0, tmp1
  114. EX ld.d \tmp0, \base, 0
  115. bstrpick.d \tmp1, \tmp0, 7, 0
  116. movgr2cf $fcc0, \tmp1
  117. bstrpick.d \tmp1, \tmp0, 15, 8
  118. movgr2cf $fcc1, \tmp1
  119. bstrpick.d \tmp1, \tmp0, 23, 16
  120. movgr2cf $fcc2, \tmp1
  121. bstrpick.d \tmp1, \tmp0, 31, 24
  122. movgr2cf $fcc3, \tmp1
  123. bstrpick.d \tmp1, \tmp0, 39, 32
  124. movgr2cf $fcc4, \tmp1
  125. bstrpick.d \tmp1, \tmp0, 47, 40
  126. movgr2cf $fcc5, \tmp1
  127. bstrpick.d \tmp1, \tmp0, 55, 48
  128. movgr2cf $fcc6, \tmp1
  129. bstrpick.d \tmp1, \tmp0, 63, 56
  130. movgr2cf $fcc7, \tmp1
  131. .endm
  132. .macro sc_save_fcsr base, tmp0
  133. movfcsr2gr \tmp0, fcsr0
  134. EX st.w \tmp0, \base, 0
  135. .endm
  136. .macro sc_restore_fcsr base, tmp0
  137. EX ld.w \tmp0, \base, 0
  138. movgr2fcsr fcsr0, \tmp0
  139. .endm
  140. /*
  141. * Save a thread's fp context.
  142. */
  143. SYM_FUNC_START(_save_fp)
  144. fpu_save_csr a0 t1
  145. fpu_save_double a0 t1 # clobbers t1
  146. fpu_save_cc a0 t1 t2 # clobbers t1, t2
  147. jr ra
  148. SYM_FUNC_END(_save_fp)
  149. EXPORT_SYMBOL(_save_fp)
  150. /*
  151. * Restore a thread's fp context.
  152. */
  153. SYM_FUNC_START(_restore_fp)
  154. fpu_restore_double a0 t1 # clobbers t1
  155. fpu_restore_csr a0 t1
  156. fpu_restore_cc a0 t1 t2 # clobbers t1, t2
  157. jr ra
  158. SYM_FUNC_END(_restore_fp)
  159. /*
  160. * Load the FPU with signalling NANS. This bit pattern we're using has
  161. * the property that no matter whether considered as single or as double
  162. * precision represents signaling NANS.
  163. *
  164. * The value to initialize fcsr0 to comes in $a0.
  165. */
  166. SYM_FUNC_START(_init_fpu)
  167. li.w t1, CSR_EUEN_FPEN
  168. csrxchg t1, t1, LOONGARCH_CSR_EUEN
  169. movgr2fcsr fcsr0, a0
  170. li.w t1, -1 # SNaN
  171. movgr2fr.d $f0, t1
  172. movgr2fr.d $f1, t1
  173. movgr2fr.d $f2, t1
  174. movgr2fr.d $f3, t1
  175. movgr2fr.d $f4, t1
  176. movgr2fr.d $f5, t1
  177. movgr2fr.d $f6, t1
  178. movgr2fr.d $f7, t1
  179. movgr2fr.d $f8, t1
  180. movgr2fr.d $f9, t1
  181. movgr2fr.d $f10, t1
  182. movgr2fr.d $f11, t1
  183. movgr2fr.d $f12, t1
  184. movgr2fr.d $f13, t1
  185. movgr2fr.d $f14, t1
  186. movgr2fr.d $f15, t1
  187. movgr2fr.d $f16, t1
  188. movgr2fr.d $f17, t1
  189. movgr2fr.d $f18, t1
  190. movgr2fr.d $f19, t1
  191. movgr2fr.d $f20, t1
  192. movgr2fr.d $f21, t1
  193. movgr2fr.d $f22, t1
  194. movgr2fr.d $f23, t1
  195. movgr2fr.d $f24, t1
  196. movgr2fr.d $f25, t1
  197. movgr2fr.d $f26, t1
  198. movgr2fr.d $f27, t1
  199. movgr2fr.d $f28, t1
  200. movgr2fr.d $f29, t1
  201. movgr2fr.d $f30, t1
  202. movgr2fr.d $f31, t1
  203. jr ra
  204. SYM_FUNC_END(_init_fpu)
  205. /*
  206. * a0: fpregs
  207. * a1: fcc
  208. * a2: fcsr
  209. */
  210. SYM_FUNC_START(_save_fp_context)
  211. sc_save_fcc a1 t1 t2
  212. sc_save_fcsr a2 t1
  213. sc_save_fp a0
  214. li.w a0, 0 # success
  215. jr ra
  216. SYM_FUNC_END(_save_fp_context)
  217. /*
  218. * a0: fpregs
  219. * a1: fcc
  220. * a2: fcsr
  221. */
  222. SYM_FUNC_START(_restore_fp_context)
  223. sc_restore_fp a0
  224. sc_restore_fcc a1 t1 t2
  225. sc_restore_fcsr a2 t1
  226. li.w a0, 0 # success
  227. jr ra
  228. SYM_FUNC_END(_restore_fp_context)
  229. SYM_FUNC_START(fault)
  230. li.w a0, -EFAULT # failure
  231. jr ra
  232. SYM_FUNC_END(fault)