ldstfp.S 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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 <linux/errno.h>
  18. #ifdef CONFIG_PPC_FPU
  19. #define STKFRM (PPC_MIN_STKFRM + 16)
  20. .macro extab instr,handler
  21. .section __ex_table,"a"
  22. PPC_LONG \instr,\handler
  23. .previous
  24. .endm
  25. .macro inst32 op
  26. reg = 0
  27. .rept 32
  28. 20: \op reg,0,r4
  29. b 3f
  30. extab 20b,99f
  31. reg = reg + 1
  32. .endr
  33. .endm
  34. /* Get the contents of frN into fr0; N is in r3. */
  35. _GLOBAL(get_fpr)
  36. mflr r0
  37. rlwinm r3,r3,3,0xf8
  38. bcl 20,31,1f
  39. blr /* fr0 is already in fr0 */
  40. nop
  41. reg = 1
  42. .rept 31
  43. fmr fr0,reg
  44. blr
  45. reg = reg + 1
  46. .endr
  47. 1: mflr r5
  48. add r5,r3,r5
  49. mtctr r5
  50. mtlr r0
  51. bctr
  52. /* Put the contents of fr0 into frN; N is in r3. */
  53. _GLOBAL(put_fpr)
  54. mflr r0
  55. rlwinm r3,r3,3,0xf8
  56. bcl 20,31,1f
  57. blr /* fr0 is already in fr0 */
  58. nop
  59. reg = 1
  60. .rept 31
  61. fmr reg,fr0
  62. blr
  63. reg = reg + 1
  64. .endr
  65. 1: mflr r5
  66. add r5,r3,r5
  67. mtctr r5
  68. mtlr r0
  69. bctr
  70. /* Load FP reg N from float at *p. N is in r3, p in r4. */
  71. _GLOBAL(do_lfs)
  72. PPC_STLU r1,-STKFRM(r1)
  73. mflr r0
  74. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  75. mfmsr r6
  76. ori r7,r6,MSR_FP
  77. cmpwi cr7,r3,0
  78. MTMSRD(r7)
  79. isync
  80. beq cr7,1f
  81. stfd fr0,STKFRM-16(r1)
  82. 1: li r9,-EFAULT
  83. 2: lfs fr0,0(r4)
  84. li r9,0
  85. 3: bl put_fpr
  86. beq cr7,4f
  87. lfd fr0,STKFRM-16(r1)
  88. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  89. mtlr r0
  90. MTMSRD(r6)
  91. isync
  92. mr r3,r9
  93. addi r1,r1,STKFRM
  94. blr
  95. extab 2b,3b
  96. /* Load FP reg N from double at *p. N is in r3, p in r4. */
  97. _GLOBAL(do_lfd)
  98. PPC_STLU r1,-STKFRM(r1)
  99. mflr r0
  100. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  101. mfmsr r6
  102. ori r7,r6,MSR_FP
  103. cmpwi cr7,r3,0
  104. MTMSRD(r7)
  105. isync
  106. beq cr7,1f
  107. stfd fr0,STKFRM-16(r1)
  108. 1: li r9,-EFAULT
  109. 2: lfd fr0,0(r4)
  110. li r9,0
  111. 3: beq cr7,4f
  112. bl put_fpr
  113. lfd fr0,STKFRM-16(r1)
  114. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  115. mtlr r0
  116. MTMSRD(r6)
  117. isync
  118. mr r3,r9
  119. addi r1,r1,STKFRM
  120. blr
  121. extab 2b,3b
  122. /* Store FP reg N to float at *p. N is in r3, p in r4. */
  123. _GLOBAL(do_stfs)
  124. PPC_STLU r1,-STKFRM(r1)
  125. mflr r0
  126. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  127. mfmsr r6
  128. ori r7,r6,MSR_FP
  129. cmpwi cr7,r3,0
  130. MTMSRD(r7)
  131. isync
  132. beq cr7,1f
  133. stfd fr0,STKFRM-16(r1)
  134. bl get_fpr
  135. 1: li r9,-EFAULT
  136. 2: stfs fr0,0(r4)
  137. li r9,0
  138. 3: beq cr7,4f
  139. lfd fr0,STKFRM-16(r1)
  140. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  141. mtlr r0
  142. MTMSRD(r6)
  143. isync
  144. mr r3,r9
  145. addi r1,r1,STKFRM
  146. blr
  147. extab 2b,3b
  148. /* Store FP reg N to double at *p. N is in r3, p in r4. */
  149. _GLOBAL(do_stfd)
  150. PPC_STLU r1,-STKFRM(r1)
  151. mflr r0
  152. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  153. mfmsr r6
  154. ori r7,r6,MSR_FP
  155. cmpwi cr7,r3,0
  156. MTMSRD(r7)
  157. isync
  158. beq cr7,1f
  159. stfd fr0,STKFRM-16(r1)
  160. bl get_fpr
  161. 1: li r9,-EFAULT
  162. 2: stfd fr0,0(r4)
  163. li r9,0
  164. 3: beq cr7,4f
  165. lfd fr0,STKFRM-16(r1)
  166. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  167. mtlr r0
  168. MTMSRD(r6)
  169. isync
  170. mr r3,r9
  171. addi r1,r1,STKFRM
  172. blr
  173. extab 2b,3b
  174. #ifdef CONFIG_ALTIVEC
  175. /* Get the contents of vrN into v0; N is in r3. */
  176. _GLOBAL(get_vr)
  177. mflr r0
  178. rlwinm r3,r3,3,0xf8
  179. bcl 20,31,1f
  180. blr /* v0 is already in v0 */
  181. nop
  182. reg = 1
  183. .rept 31
  184. vor v0,reg,reg /* assembler doesn't know vmr? */
  185. blr
  186. reg = reg + 1
  187. .endr
  188. 1: mflr r5
  189. add r5,r3,r5
  190. mtctr r5
  191. mtlr r0
  192. bctr
  193. /* Put the contents of v0 into vrN; N is in r3. */
  194. _GLOBAL(put_vr)
  195. mflr r0
  196. rlwinm r3,r3,3,0xf8
  197. bcl 20,31,1f
  198. blr /* v0 is already in v0 */
  199. nop
  200. reg = 1
  201. .rept 31
  202. vor reg,v0,v0
  203. blr
  204. reg = reg + 1
  205. .endr
  206. 1: mflr r5
  207. add r5,r3,r5
  208. mtctr r5
  209. mtlr r0
  210. bctr
  211. /* Load vector reg N from *p. N is in r3, p in r4. */
  212. _GLOBAL(do_lvx)
  213. PPC_STLU r1,-STKFRM(r1)
  214. mflr r0
  215. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  216. mfmsr r6
  217. oris r7,r6,MSR_VEC@h
  218. cmpwi cr7,r3,0
  219. li r8,STKFRM-16
  220. MTMSRD(r7)
  221. isync
  222. beq cr7,1f
  223. stvx v0,r1,r8
  224. 1: li r9,-EFAULT
  225. 2: lvx v0,0,r4
  226. li r9,0
  227. 3: beq cr7,4f
  228. bl put_vr
  229. lvx v0,r1,r8
  230. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  231. mtlr r0
  232. MTMSRD(r6)
  233. isync
  234. mr r3,r9
  235. addi r1,r1,STKFRM
  236. blr
  237. extab 2b,3b
  238. /* Store vector reg N to *p. N is in r3, p in r4. */
  239. _GLOBAL(do_stvx)
  240. PPC_STLU r1,-STKFRM(r1)
  241. mflr r0
  242. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  243. mfmsr r6
  244. oris r7,r6,MSR_VEC@h
  245. cmpwi cr7,r3,0
  246. li r8,STKFRM-16
  247. MTMSRD(r7)
  248. isync
  249. beq cr7,1f
  250. stvx v0,r1,r8
  251. bl get_vr
  252. 1: li r9,-EFAULT
  253. 2: stvx v0,0,r4
  254. li r9,0
  255. 3: beq cr7,4f
  256. lvx v0,r1,r8
  257. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  258. mtlr r0
  259. MTMSRD(r6)
  260. isync
  261. mr r3,r9
  262. addi r1,r1,STKFRM
  263. blr
  264. extab 2b,3b
  265. #endif /* CONFIG_ALTIVEC */
  266. #ifdef CONFIG_VSX
  267. /* Get the contents of vsN into vs0; N is in r3. */
  268. _GLOBAL(get_vsr)
  269. mflr r0
  270. rlwinm r3,r3,3,0x1f8
  271. bcl 20,31,1f
  272. blr /* vs0 is already in vs0 */
  273. nop
  274. reg = 1
  275. .rept 63
  276. XXLOR(0,reg,reg)
  277. blr
  278. reg = reg + 1
  279. .endr
  280. 1: mflr r5
  281. add r5,r3,r5
  282. mtctr r5
  283. mtlr r0
  284. bctr
  285. /* Put the contents of vs0 into vsN; N is in r3. */
  286. _GLOBAL(put_vsr)
  287. mflr r0
  288. rlwinm r3,r3,3,0x1f8
  289. bcl 20,31,1f
  290. blr /* v0 is already in v0 */
  291. nop
  292. reg = 1
  293. .rept 63
  294. XXLOR(reg,0,0)
  295. blr
  296. reg = reg + 1
  297. .endr
  298. 1: mflr r5
  299. add r5,r3,r5
  300. mtctr r5
  301. mtlr r0
  302. bctr
  303. /* Load VSX reg N from vector doubleword *p. N is in r3, p in r4. */
  304. _GLOBAL(do_lxvd2x)
  305. PPC_STLU r1,-STKFRM(r1)
  306. mflr r0
  307. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  308. mfmsr r6
  309. oris r7,r6,MSR_VSX@h
  310. cmpwi cr7,r3,0
  311. li r8,STKFRM-16
  312. MTMSRD(r7)
  313. isync
  314. beq cr7,1f
  315. STXVD2X(0,R1,R8)
  316. 1: li r9,-EFAULT
  317. 2: LXVD2X(0,R0,R4)
  318. li r9,0
  319. 3: beq cr7,4f
  320. bl put_vsr
  321. LXVD2X(0,R1,R8)
  322. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  323. mtlr r0
  324. MTMSRD(r6)
  325. isync
  326. mr r3,r9
  327. addi r1,r1,STKFRM
  328. blr
  329. extab 2b,3b
  330. /* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */
  331. _GLOBAL(do_stxvd2x)
  332. PPC_STLU r1,-STKFRM(r1)
  333. mflr r0
  334. PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
  335. mfmsr r6
  336. oris r7,r6,MSR_VSX@h
  337. cmpwi cr7,r3,0
  338. li r8,STKFRM-16
  339. MTMSRD(r7)
  340. isync
  341. beq cr7,1f
  342. STXVD2X(0,R1,R8)
  343. bl get_vsr
  344. 1: li r9,-EFAULT
  345. 2: STXVD2X(0,R0,R4)
  346. li r9,0
  347. 3: beq cr7,4f
  348. LXVD2X(0,R1,R8)
  349. 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
  350. mtlr r0
  351. MTMSRD(r6)
  352. isync
  353. mr r3,r9
  354. addi r1,r1,STKFRM
  355. blr
  356. extab 2b,3b
  357. #endif /* CONFIG_VSX */
  358. #endif /* CONFIG_PPC_FPU */