fpu.S 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Author: Lu Zeng <zenglu@loongson.cn>
  4. * Pei Huang <huangpei@loongson.cn>
  5. * Huacai Chen <chenhuacai@loongson.cn>
  6. *
  7. * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  8. */
  9. #include <linux/export.h>
  10. #include <asm/asm.h>
  11. #include <asm/asmmacro.h>
  12. #include <asm/asm-extable.h>
  13. #include <asm/asm-offsets.h>
  14. #include <asm/errno.h>
  15. #include <asm/fpregdef.h>
  16. #include <asm/loongarch.h>
  17. #include <asm/regdef.h>
  18. #include <asm/unwind_hints.h>
  19. #define FPU_REG_WIDTH 8
  20. #define LSX_REG_WIDTH 16
  21. #define LASX_REG_WIDTH 32
  22. .macro EX insn, reg, src, offs
  23. .ex\@: \insn \reg, \src, \offs
  24. _asm_extable .ex\@, .L_fpu_fault
  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. #if defined(CONFIG_CPU_HAS_LBT)
  136. /* TM bit is always 0 if LBT not supported */
  137. andi \tmp0, \tmp0, FPU_CSR_TM
  138. beqz \tmp0, 1f
  139. x86clrtm
  140. 1:
  141. #endif
  142. .endm
  143. .macro sc_restore_fcsr base, tmp0
  144. EX ld.w \tmp0, \base, 0
  145. movgr2fcsr fcsr0, \tmp0
  146. .endm
  147. .macro sc_save_lsx base
  148. #ifdef CONFIG_CPU_HAS_LSX
  149. EX vst $vr0, \base, (0 * LSX_REG_WIDTH)
  150. EX vst $vr1, \base, (1 * LSX_REG_WIDTH)
  151. EX vst $vr2, \base, (2 * LSX_REG_WIDTH)
  152. EX vst $vr3, \base, (3 * LSX_REG_WIDTH)
  153. EX vst $vr4, \base, (4 * LSX_REG_WIDTH)
  154. EX vst $vr5, \base, (5 * LSX_REG_WIDTH)
  155. EX vst $vr6, \base, (6 * LSX_REG_WIDTH)
  156. EX vst $vr7, \base, (7 * LSX_REG_WIDTH)
  157. EX vst $vr8, \base, (8 * LSX_REG_WIDTH)
  158. EX vst $vr9, \base, (9 * LSX_REG_WIDTH)
  159. EX vst $vr10, \base, (10 * LSX_REG_WIDTH)
  160. EX vst $vr11, \base, (11 * LSX_REG_WIDTH)
  161. EX vst $vr12, \base, (12 * LSX_REG_WIDTH)
  162. EX vst $vr13, \base, (13 * LSX_REG_WIDTH)
  163. EX vst $vr14, \base, (14 * LSX_REG_WIDTH)
  164. EX vst $vr15, \base, (15 * LSX_REG_WIDTH)
  165. EX vst $vr16, \base, (16 * LSX_REG_WIDTH)
  166. EX vst $vr17, \base, (17 * LSX_REG_WIDTH)
  167. EX vst $vr18, \base, (18 * LSX_REG_WIDTH)
  168. EX vst $vr19, \base, (19 * LSX_REG_WIDTH)
  169. EX vst $vr20, \base, (20 * LSX_REG_WIDTH)
  170. EX vst $vr21, \base, (21 * LSX_REG_WIDTH)
  171. EX vst $vr22, \base, (22 * LSX_REG_WIDTH)
  172. EX vst $vr23, \base, (23 * LSX_REG_WIDTH)
  173. EX vst $vr24, \base, (24 * LSX_REG_WIDTH)
  174. EX vst $vr25, \base, (25 * LSX_REG_WIDTH)
  175. EX vst $vr26, \base, (26 * LSX_REG_WIDTH)
  176. EX vst $vr27, \base, (27 * LSX_REG_WIDTH)
  177. EX vst $vr28, \base, (28 * LSX_REG_WIDTH)
  178. EX vst $vr29, \base, (29 * LSX_REG_WIDTH)
  179. EX vst $vr30, \base, (30 * LSX_REG_WIDTH)
  180. EX vst $vr31, \base, (31 * LSX_REG_WIDTH)
  181. #endif
  182. .endm
  183. .macro sc_restore_lsx base
  184. #ifdef CONFIG_CPU_HAS_LSX
  185. EX vld $vr0, \base, (0 * LSX_REG_WIDTH)
  186. EX vld $vr1, \base, (1 * LSX_REG_WIDTH)
  187. EX vld $vr2, \base, (2 * LSX_REG_WIDTH)
  188. EX vld $vr3, \base, (3 * LSX_REG_WIDTH)
  189. EX vld $vr4, \base, (4 * LSX_REG_WIDTH)
  190. EX vld $vr5, \base, (5 * LSX_REG_WIDTH)
  191. EX vld $vr6, \base, (6 * LSX_REG_WIDTH)
  192. EX vld $vr7, \base, (7 * LSX_REG_WIDTH)
  193. EX vld $vr8, \base, (8 * LSX_REG_WIDTH)
  194. EX vld $vr9, \base, (9 * LSX_REG_WIDTH)
  195. EX vld $vr10, \base, (10 * LSX_REG_WIDTH)
  196. EX vld $vr11, \base, (11 * LSX_REG_WIDTH)
  197. EX vld $vr12, \base, (12 * LSX_REG_WIDTH)
  198. EX vld $vr13, \base, (13 * LSX_REG_WIDTH)
  199. EX vld $vr14, \base, (14 * LSX_REG_WIDTH)
  200. EX vld $vr15, \base, (15 * LSX_REG_WIDTH)
  201. EX vld $vr16, \base, (16 * LSX_REG_WIDTH)
  202. EX vld $vr17, \base, (17 * LSX_REG_WIDTH)
  203. EX vld $vr18, \base, (18 * LSX_REG_WIDTH)
  204. EX vld $vr19, \base, (19 * LSX_REG_WIDTH)
  205. EX vld $vr20, \base, (20 * LSX_REG_WIDTH)
  206. EX vld $vr21, \base, (21 * LSX_REG_WIDTH)
  207. EX vld $vr22, \base, (22 * LSX_REG_WIDTH)
  208. EX vld $vr23, \base, (23 * LSX_REG_WIDTH)
  209. EX vld $vr24, \base, (24 * LSX_REG_WIDTH)
  210. EX vld $vr25, \base, (25 * LSX_REG_WIDTH)
  211. EX vld $vr26, \base, (26 * LSX_REG_WIDTH)
  212. EX vld $vr27, \base, (27 * LSX_REG_WIDTH)
  213. EX vld $vr28, \base, (28 * LSX_REG_WIDTH)
  214. EX vld $vr29, \base, (29 * LSX_REG_WIDTH)
  215. EX vld $vr30, \base, (30 * LSX_REG_WIDTH)
  216. EX vld $vr31, \base, (31 * LSX_REG_WIDTH)
  217. #endif
  218. .endm
  219. .macro sc_save_lasx base
  220. #ifdef CONFIG_CPU_HAS_LASX
  221. EX xvst $xr0, \base, (0 * LASX_REG_WIDTH)
  222. EX xvst $xr1, \base, (1 * LASX_REG_WIDTH)
  223. EX xvst $xr2, \base, (2 * LASX_REG_WIDTH)
  224. EX xvst $xr3, \base, (3 * LASX_REG_WIDTH)
  225. EX xvst $xr4, \base, (4 * LASX_REG_WIDTH)
  226. EX xvst $xr5, \base, (5 * LASX_REG_WIDTH)
  227. EX xvst $xr6, \base, (6 * LASX_REG_WIDTH)
  228. EX xvst $xr7, \base, (7 * LASX_REG_WIDTH)
  229. EX xvst $xr8, \base, (8 * LASX_REG_WIDTH)
  230. EX xvst $xr9, \base, (9 * LASX_REG_WIDTH)
  231. EX xvst $xr10, \base, (10 * LASX_REG_WIDTH)
  232. EX xvst $xr11, \base, (11 * LASX_REG_WIDTH)
  233. EX xvst $xr12, \base, (12 * LASX_REG_WIDTH)
  234. EX xvst $xr13, \base, (13 * LASX_REG_WIDTH)
  235. EX xvst $xr14, \base, (14 * LASX_REG_WIDTH)
  236. EX xvst $xr15, \base, (15 * LASX_REG_WIDTH)
  237. EX xvst $xr16, \base, (16 * LASX_REG_WIDTH)
  238. EX xvst $xr17, \base, (17 * LASX_REG_WIDTH)
  239. EX xvst $xr18, \base, (18 * LASX_REG_WIDTH)
  240. EX xvst $xr19, \base, (19 * LASX_REG_WIDTH)
  241. EX xvst $xr20, \base, (20 * LASX_REG_WIDTH)
  242. EX xvst $xr21, \base, (21 * LASX_REG_WIDTH)
  243. EX xvst $xr22, \base, (22 * LASX_REG_WIDTH)
  244. EX xvst $xr23, \base, (23 * LASX_REG_WIDTH)
  245. EX xvst $xr24, \base, (24 * LASX_REG_WIDTH)
  246. EX xvst $xr25, \base, (25 * LASX_REG_WIDTH)
  247. EX xvst $xr26, \base, (26 * LASX_REG_WIDTH)
  248. EX xvst $xr27, \base, (27 * LASX_REG_WIDTH)
  249. EX xvst $xr28, \base, (28 * LASX_REG_WIDTH)
  250. EX xvst $xr29, \base, (29 * LASX_REG_WIDTH)
  251. EX xvst $xr30, \base, (30 * LASX_REG_WIDTH)
  252. EX xvst $xr31, \base, (31 * LASX_REG_WIDTH)
  253. #endif
  254. .endm
  255. .macro sc_restore_lasx base
  256. #ifdef CONFIG_CPU_HAS_LASX
  257. EX xvld $xr0, \base, (0 * LASX_REG_WIDTH)
  258. EX xvld $xr1, \base, (1 * LASX_REG_WIDTH)
  259. EX xvld $xr2, \base, (2 * LASX_REG_WIDTH)
  260. EX xvld $xr3, \base, (3 * LASX_REG_WIDTH)
  261. EX xvld $xr4, \base, (4 * LASX_REG_WIDTH)
  262. EX xvld $xr5, \base, (5 * LASX_REG_WIDTH)
  263. EX xvld $xr6, \base, (6 * LASX_REG_WIDTH)
  264. EX xvld $xr7, \base, (7 * LASX_REG_WIDTH)
  265. EX xvld $xr8, \base, (8 * LASX_REG_WIDTH)
  266. EX xvld $xr9, \base, (9 * LASX_REG_WIDTH)
  267. EX xvld $xr10, \base, (10 * LASX_REG_WIDTH)
  268. EX xvld $xr11, \base, (11 * LASX_REG_WIDTH)
  269. EX xvld $xr12, \base, (12 * LASX_REG_WIDTH)
  270. EX xvld $xr13, \base, (13 * LASX_REG_WIDTH)
  271. EX xvld $xr14, \base, (14 * LASX_REG_WIDTH)
  272. EX xvld $xr15, \base, (15 * LASX_REG_WIDTH)
  273. EX xvld $xr16, \base, (16 * LASX_REG_WIDTH)
  274. EX xvld $xr17, \base, (17 * LASX_REG_WIDTH)
  275. EX xvld $xr18, \base, (18 * LASX_REG_WIDTH)
  276. EX xvld $xr19, \base, (19 * LASX_REG_WIDTH)
  277. EX xvld $xr20, \base, (20 * LASX_REG_WIDTH)
  278. EX xvld $xr21, \base, (21 * LASX_REG_WIDTH)
  279. EX xvld $xr22, \base, (22 * LASX_REG_WIDTH)
  280. EX xvld $xr23, \base, (23 * LASX_REG_WIDTH)
  281. EX xvld $xr24, \base, (24 * LASX_REG_WIDTH)
  282. EX xvld $xr25, \base, (25 * LASX_REG_WIDTH)
  283. EX xvld $xr26, \base, (26 * LASX_REG_WIDTH)
  284. EX xvld $xr27, \base, (27 * LASX_REG_WIDTH)
  285. EX xvld $xr28, \base, (28 * LASX_REG_WIDTH)
  286. EX xvld $xr29, \base, (29 * LASX_REG_WIDTH)
  287. EX xvld $xr30, \base, (30 * LASX_REG_WIDTH)
  288. EX xvld $xr31, \base, (31 * LASX_REG_WIDTH)
  289. #endif
  290. .endm
  291. /*
  292. * Save a thread's fp context.
  293. */
  294. SYM_FUNC_START(_save_fp)
  295. fpu_save_csr a0 t1
  296. fpu_save_double a0 t1 # clobbers t1
  297. fpu_save_cc a0 t1 t2 # clobbers t1, t2
  298. jr ra
  299. SYM_FUNC_END(_save_fp)
  300. EXPORT_SYMBOL(_save_fp)
  301. /*
  302. * Restore a thread's fp context.
  303. */
  304. SYM_FUNC_START(_restore_fp)
  305. fpu_restore_double a0 t1 # clobbers t1
  306. fpu_restore_csr a0 t1 t2
  307. fpu_restore_cc a0 t1 t2 # clobbers t1, t2
  308. jr ra
  309. SYM_FUNC_END(_restore_fp)
  310. #ifdef CONFIG_CPU_HAS_LSX
  311. /*
  312. * Save a thread's LSX vector context.
  313. */
  314. SYM_FUNC_START(_save_lsx)
  315. lsx_save_all a0 t1 t2
  316. jr ra
  317. SYM_FUNC_END(_save_lsx)
  318. EXPORT_SYMBOL(_save_lsx)
  319. /*
  320. * Restore a thread's LSX vector context.
  321. */
  322. SYM_FUNC_START(_restore_lsx)
  323. lsx_restore_all a0 t1 t2
  324. jr ra
  325. SYM_FUNC_END(_restore_lsx)
  326. SYM_FUNC_START(_save_lsx_upper)
  327. lsx_save_all_upper a0 t0 t1
  328. jr ra
  329. SYM_FUNC_END(_save_lsx_upper)
  330. SYM_FUNC_START(_restore_lsx_upper)
  331. lsx_restore_all_upper a0 t0 t1
  332. jr ra
  333. SYM_FUNC_END(_restore_lsx_upper)
  334. EXPORT_SYMBOL(_restore_lsx_upper)
  335. SYM_FUNC_START(_init_lsx_upper)
  336. lsx_init_all_upper t1
  337. jr ra
  338. SYM_FUNC_END(_init_lsx_upper)
  339. #endif
  340. #ifdef CONFIG_CPU_HAS_LASX
  341. /*
  342. * Save a thread's LASX vector context.
  343. */
  344. SYM_FUNC_START(_save_lasx)
  345. lasx_save_all a0 t1 t2
  346. jr ra
  347. SYM_FUNC_END(_save_lasx)
  348. EXPORT_SYMBOL(_save_lasx)
  349. /*
  350. * Restore a thread's LASX vector context.
  351. */
  352. SYM_FUNC_START(_restore_lasx)
  353. lasx_restore_all a0 t1 t2
  354. jr ra
  355. SYM_FUNC_END(_restore_lasx)
  356. SYM_FUNC_START(_save_lasx_upper)
  357. lasx_save_all_upper a0 t0 t1
  358. jr ra
  359. SYM_FUNC_END(_save_lasx_upper)
  360. SYM_FUNC_START(_restore_lasx_upper)
  361. lasx_restore_all_upper a0 t0 t1
  362. jr ra
  363. SYM_FUNC_END(_restore_lasx_upper)
  364. EXPORT_SYMBOL(_restore_lasx_upper)
  365. SYM_FUNC_START(_init_lasx_upper)
  366. lasx_init_all_upper t1
  367. jr ra
  368. SYM_FUNC_END(_init_lasx_upper)
  369. #endif
  370. /*
  371. * Load the FPU with signalling NANS. This bit pattern we're using has
  372. * the property that no matter whether considered as single or as double
  373. * precision represents signaling NANS.
  374. *
  375. * The value to initialize fcsr0 to comes in $a0.
  376. */
  377. SYM_FUNC_START(_init_fpu)
  378. li.w t1, CSR_EUEN_FPEN
  379. csrxchg t1, t1, LOONGARCH_CSR_EUEN
  380. movgr2fcsr fcsr0, a0
  381. li.w t1, -1 # SNaN
  382. movgr2fr.d $f0, t1
  383. movgr2fr.d $f1, t1
  384. movgr2fr.d $f2, t1
  385. movgr2fr.d $f3, t1
  386. movgr2fr.d $f4, t1
  387. movgr2fr.d $f5, t1
  388. movgr2fr.d $f6, t1
  389. movgr2fr.d $f7, t1
  390. movgr2fr.d $f8, t1
  391. movgr2fr.d $f9, t1
  392. movgr2fr.d $f10, t1
  393. movgr2fr.d $f11, t1
  394. movgr2fr.d $f12, t1
  395. movgr2fr.d $f13, t1
  396. movgr2fr.d $f14, t1
  397. movgr2fr.d $f15, t1
  398. movgr2fr.d $f16, t1
  399. movgr2fr.d $f17, t1
  400. movgr2fr.d $f18, t1
  401. movgr2fr.d $f19, t1
  402. movgr2fr.d $f20, t1
  403. movgr2fr.d $f21, t1
  404. movgr2fr.d $f22, t1
  405. movgr2fr.d $f23, t1
  406. movgr2fr.d $f24, t1
  407. movgr2fr.d $f25, t1
  408. movgr2fr.d $f26, t1
  409. movgr2fr.d $f27, t1
  410. movgr2fr.d $f28, t1
  411. movgr2fr.d $f29, t1
  412. movgr2fr.d $f30, t1
  413. movgr2fr.d $f31, t1
  414. jr ra
  415. SYM_FUNC_END(_init_fpu)
  416. /*
  417. * a0: fpregs
  418. * a1: fcc
  419. * a2: fcsr
  420. */
  421. SYM_FUNC_START(_save_fp_context)
  422. sc_save_fcc a1 t1 t2
  423. sc_save_fcsr a2 t1
  424. sc_save_fp a0
  425. li.w a0, 0 # success
  426. jr ra
  427. SYM_FUNC_END(_save_fp_context)
  428. /*
  429. * a0: fpregs
  430. * a1: fcc
  431. * a2: fcsr
  432. */
  433. SYM_FUNC_START(_restore_fp_context)
  434. sc_restore_fp a0
  435. sc_restore_fcc a1 t1 t2
  436. sc_restore_fcsr a2 t1
  437. li.w a0, 0 # success
  438. jr ra
  439. SYM_FUNC_END(_restore_fp_context)
  440. /*
  441. * a0: fpregs
  442. * a1: fcc
  443. * a2: fcsr
  444. */
  445. SYM_FUNC_START(_save_lsx_context)
  446. sc_save_fcc a1, t0, t1
  447. sc_save_fcsr a2, t0
  448. sc_save_lsx a0
  449. li.w a0, 0 # success
  450. jr ra
  451. SYM_FUNC_END(_save_lsx_context)
  452. /*
  453. * a0: fpregs
  454. * a1: fcc
  455. * a2: fcsr
  456. */
  457. SYM_FUNC_START(_restore_lsx_context)
  458. sc_restore_lsx a0
  459. sc_restore_fcc a1, t1, t2
  460. sc_restore_fcsr a2, t1
  461. li.w a0, 0 # success
  462. jr ra
  463. SYM_FUNC_END(_restore_lsx_context)
  464. /*
  465. * a0: fpregs
  466. * a1: fcc
  467. * a2: fcsr
  468. */
  469. SYM_FUNC_START(_save_lasx_context)
  470. sc_save_fcc a1, t0, t1
  471. sc_save_fcsr a2, t0
  472. sc_save_lasx a0
  473. li.w a0, 0 # success
  474. jr ra
  475. SYM_FUNC_END(_save_lasx_context)
  476. /*
  477. * a0: fpregs
  478. * a1: fcc
  479. * a2: fcsr
  480. */
  481. SYM_FUNC_START(_restore_lasx_context)
  482. sc_restore_lasx a0
  483. sc_restore_fcc a1, t1, t2
  484. sc_restore_fcsr a2, t1
  485. li.w a0, 0 # success
  486. jr ra
  487. SYM_FUNC_END(_restore_lasx_context)
  488. .L_fpu_fault:
  489. li.w a0, -EFAULT # failure
  490. jr ra
  491. #ifdef CONFIG_CPU_HAS_LBT
  492. STACK_FRAME_NON_STANDARD _restore_fp
  493. #ifdef CONFIG_CPU_HAS_LSX
  494. STACK_FRAME_NON_STANDARD _restore_lsx
  495. #endif
  496. #ifdef CONFIG_CPU_HAS_LASX
  497. STACK_FRAME_NON_STANDARD _restore_lasx
  498. #endif
  499. #endif