ldstfp.S 4.0 KB

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