ldstfp.S 6.0 KB

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