ldstfp.S 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * Floating-point, VMX/Altivec and VSX loads and stores
  4. * for use in instruction emulation.
  5. *
  6. * Copyright 2010 Paul Mackerras, IBM Corp. <[email protected]>
  7. */
  8. #include <asm/processor.h>
  9. #include <asm/ppc_asm.h>
  10. #include <asm/ppc-opcode.h>
  11. #include <asm/reg.h>
  12. #include <asm/asm-offsets.h>
  13. #include <asm/asm-compat.h>
  14. #include <linux/errno.h>
  15. #define STKFRM (PPC_MIN_STKFRM + 16)
  16. /* Get the contents of frN into *p; N is in r3 and p is in r4. */
  17. _GLOBAL(get_fpr)
  18. mflr r0
  19. mfmsr r6
  20. ori r7, r6, MSR_FP
  21. MTMSRD(r7)
  22. isync
  23. rlwinm r3,r3,3,0xf8
  24. bcl 20,31,1f
  25. reg = 0
  26. .rept 32
  27. stfd reg, 0(r4)
  28. b 2f
  29. reg = reg + 1
  30. .endr
  31. 1: mflr r5
  32. add r5,r3,r5
  33. mtctr r5
  34. mtlr r0
  35. bctr
  36. 2: MTMSRD(r6)
  37. isync
  38. blr
  39. /* Put the contents of *p into frN; N is in r3 and p is in r4. */
  40. _GLOBAL(put_fpr)
  41. mflr r0
  42. mfmsr r6
  43. ori r7, r6, MSR_FP
  44. MTMSRD(r7)
  45. isync
  46. rlwinm r3,r3,3,0xf8
  47. bcl 20,31,1f
  48. reg = 0
  49. .rept 32
  50. lfd reg, 0(r4)
  51. b 2f
  52. reg = reg + 1
  53. .endr
  54. 1: mflr r5
  55. add r5,r3,r5
  56. mtctr r5
  57. mtlr r0
  58. bctr
  59. 2: MTMSRD(r6)
  60. isync
  61. blr
  62. #ifdef CONFIG_ALTIVEC
  63. /* Get the contents of vrN into *p; N is in r3 and p is in r4. */
  64. _GLOBAL(get_vr)
  65. mflr r0
  66. mfmsr r6
  67. oris r7, r6, MSR_VEC@h
  68. MTMSRD(r7)
  69. isync
  70. rlwinm r3,r3,3,0xf8
  71. bcl 20,31,1f
  72. reg = 0
  73. .rept 32
  74. stvx reg, 0, r4
  75. b 2f
  76. reg = reg + 1
  77. .endr
  78. 1: mflr r5
  79. add r5,r3,r5
  80. mtctr r5
  81. mtlr r0
  82. bctr
  83. 2: MTMSRD(r6)
  84. isync
  85. blr
  86. /* Put the contents of *p into vrN; N is in r3 and p is in r4. */
  87. _GLOBAL(put_vr)
  88. mflr r0
  89. mfmsr r6
  90. oris r7, r6, MSR_VEC@h
  91. MTMSRD(r7)
  92. isync
  93. rlwinm r3,r3,3,0xf8
  94. bcl 20,31,1f
  95. reg = 0
  96. .rept 32
  97. lvx reg, 0, r4
  98. b 2f
  99. reg = reg + 1
  100. .endr
  101. 1: mflr r5
  102. add r5,r3,r5
  103. mtctr r5
  104. mtlr r0
  105. bctr
  106. 2: MTMSRD(r6)
  107. isync
  108. blr
  109. #endif /* CONFIG_ALTIVEC */
  110. #ifdef CONFIG_VSX
  111. /* Get the contents of vsN into vs0; N is in r3. */
  112. _GLOBAL(get_vsr)
  113. mflr r0
  114. rlwinm r3,r3,3,0x1f8
  115. bcl 20,31,1f
  116. blr /* vs0 is already in vs0 */
  117. nop
  118. reg = 1
  119. .rept 63
  120. XXLOR(0,reg,reg)
  121. blr
  122. reg = reg + 1
  123. .endr
  124. 1: mflr r5
  125. add r5,r3,r5
  126. mtctr r5
  127. mtlr r0
  128. bctr
  129. /* Put the contents of vs0 into vsN; N is in r3. */
  130. _GLOBAL(put_vsr)
  131. mflr r0
  132. rlwinm r3,r3,3,0x1f8
  133. bcl 20,31,1f
  134. blr /* v0 is already in v0 */
  135. nop
  136. reg = 1
  137. .rept 63
  138. XXLOR(reg,0,0)
  139. blr
  140. reg = reg + 1
  141. .endr
  142. 1: mflr r5
  143. add r5,r3,r5
  144. mtctr r5
  145. mtlr r0
  146. bctr
  147. /* Load VSX reg N from vector doubleword *p. N is in r3, p in r4. */
  148. _GLOBAL(load_vsrn)
  149. PPC_STLU r1,-STKFRM(r1)
  150. mflr r0
  151. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  152. mfmsr r6
  153. oris r7,r6,MSR_VSX@h
  154. cmpwi cr7,r3,0
  155. li r8,STKFRM-16
  156. MTMSRD(r7)
  157. isync
  158. beq cr7,1f
  159. STXVD2X(0,R1,R8)
  160. 1: LXVD2X(0,R0,R4)
  161. #ifdef __LITTLE_ENDIAN__
  162. XXSWAPD(0,0)
  163. #endif
  164. beq cr7,4f
  165. bl put_vsr
  166. LXVD2X(0,R1,R8)
  167. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  168. mtlr r0
  169. MTMSRD(r6)
  170. isync
  171. addi r1,r1,STKFRM
  172. blr
  173. /* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */
  174. _GLOBAL(store_vsrn)
  175. PPC_STLU r1,-STKFRM(r1)
  176. mflr r0
  177. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  178. mfmsr r6
  179. oris r7,r6,MSR_VSX@h
  180. li r8,STKFRM-16
  181. MTMSRD(r7)
  182. isync
  183. STXVD2X(0,R1,R8)
  184. bl get_vsr
  185. #ifdef __LITTLE_ENDIAN__
  186. XXSWAPD(0,0)
  187. #endif
  188. STXVD2X(0,R0,R4)
  189. LXVD2X(0,R1,R8)
  190. PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  191. mtlr r0
  192. MTMSRD(r6)
  193. isync
  194. mr r3,r9
  195. addi r1,r1,STKFRM
  196. blr
  197. #endif /* CONFIG_VSX */
  198. /* Convert single-precision to double, without disturbing FPRs. */
  199. /* conv_sp_to_dp(float *sp, double *dp) */
  200. _GLOBAL(conv_sp_to_dp)
  201. mfmsr r6
  202. ori r7, r6, MSR_FP
  203. MTMSRD(r7)
  204. isync
  205. stfd fr0, -16(r1)
  206. lfs fr0, 0(r3)
  207. stfd fr0, 0(r4)
  208. lfd fr0, -16(r1)
  209. MTMSRD(r6)
  210. isync
  211. blr
  212. /* Convert single-precision to double, without disturbing FPRs. */
  213. /* conv_sp_to_dp(double *dp, float *sp) */
  214. _GLOBAL(conv_dp_to_sp)
  215. mfmsr r6
  216. ori r7, r6, MSR_FP
  217. MTMSRD(r7)
  218. isync
  219. stfd fr0, -16(r1)
  220. lfd fr0, 0(r3)
  221. stfs fr0, 0(r4)
  222. lfd fr0, -16(r1)
  223. MTMSRD(r6)
  224. isync
  225. blr