fpu.S 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * FPU helper code to use FPU operations from inside the kernel
  3. *
  4. * Copyright (C) 2010 Alexander Graf (agraf@suse.de)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. *
  11. */
  12. #include <asm/reg.h>
  13. #include <asm/page.h>
  14. #include <asm/mmu.h>
  15. #include <asm/pgtable.h>
  16. #include <asm/cputable.h>
  17. #include <asm/cache.h>
  18. #include <asm/thread_info.h>
  19. #include <asm/ppc_asm.h>
  20. #include <asm/asm-offsets.h>
  21. /* Instructions operating on single parameters */
  22. /*
  23. * Single operation with one input operand
  24. *
  25. * R3 = (double*)&fpscr
  26. * R4 = (short*)&result
  27. * R5 = (short*)&param1
  28. */
  29. #define FPS_ONE_IN(name) \
  30. _GLOBAL(fps_ ## name); \
  31. lfd 0,0(r3); /* load up fpscr value */ \
  32. MTFSF_L(0); \
  33. lfs 0,0(r5); \
  34. \
  35. name 0,0; \
  36. \
  37. stfs 0,0(r4); \
  38. mffs 0; \
  39. stfd 0,0(r3); /* save new fpscr value */ \
  40. blr
  41. /*
  42. * Single operation with two input operands
  43. *
  44. * R3 = (double*)&fpscr
  45. * R4 = (short*)&result
  46. * R5 = (short*)&param1
  47. * R6 = (short*)&param2
  48. */
  49. #define FPS_TWO_IN(name) \
  50. _GLOBAL(fps_ ## name); \
  51. lfd 0,0(r3); /* load up fpscr value */ \
  52. MTFSF_L(0); \
  53. lfs 0,0(r5); \
  54. lfs 1,0(r6); \
  55. \
  56. name 0,0,1; \
  57. \
  58. stfs 0,0(r4); \
  59. mffs 0; \
  60. stfd 0,0(r3); /* save new fpscr value */ \
  61. blr
  62. /*
  63. * Single operation with three input operands
  64. *
  65. * R3 = (double*)&fpscr
  66. * R4 = (short*)&result
  67. * R5 = (short*)&param1
  68. * R6 = (short*)&param2
  69. * R7 = (short*)&param3
  70. */
  71. #define FPS_THREE_IN(name) \
  72. _GLOBAL(fps_ ## name); \
  73. lfd 0,0(r3); /* load up fpscr value */ \
  74. MTFSF_L(0); \
  75. lfs 0,0(r5); \
  76. lfs 1,0(r6); \
  77. lfs 2,0(r7); \
  78. \
  79. name 0,0,1,2; \
  80. \
  81. stfs 0,0(r4); \
  82. mffs 0; \
  83. stfd 0,0(r3); /* save new fpscr value */ \
  84. blr
  85. FPS_ONE_IN(fres)
  86. FPS_ONE_IN(frsqrte)
  87. FPS_ONE_IN(fsqrts)
  88. FPS_TWO_IN(fadds)
  89. FPS_TWO_IN(fdivs)
  90. FPS_TWO_IN(fmuls)
  91. FPS_TWO_IN(fsubs)
  92. FPS_THREE_IN(fmadds)
  93. FPS_THREE_IN(fmsubs)
  94. FPS_THREE_IN(fnmadds)
  95. FPS_THREE_IN(fnmsubs)
  96. FPS_THREE_IN(fsel)
  97. /* Instructions operating on double parameters */
  98. /*
  99. * Beginning of double instruction processing
  100. *
  101. * R3 = (double*)&fpscr
  102. * R4 = (u32*)&cr
  103. * R5 = (double*)&result
  104. * R6 = (double*)&param1
  105. * R7 = (double*)&param2 [load_two]
  106. * R8 = (double*)&param3 [load_three]
  107. * LR = instruction call function
  108. */
  109. fpd_load_three:
  110. lfd 2,0(r8) /* load param3 */
  111. fpd_load_two:
  112. lfd 1,0(r7) /* load param2 */
  113. fpd_load_one:
  114. lfd 0,0(r6) /* load param1 */
  115. fpd_load_none:
  116. lfd 3,0(r3) /* load up fpscr value */
  117. MTFSF_L(3)
  118. lwz r6, 0(r4) /* load cr */
  119. mtcr r6
  120. blr
  121. /*
  122. * End of double instruction processing
  123. *
  124. * R3 = (double*)&fpscr
  125. * R4 = (u32*)&cr
  126. * R5 = (double*)&result
  127. * LR = caller of instruction call function
  128. */
  129. fpd_return:
  130. mfcr r6
  131. stfd 0,0(r5) /* save result */
  132. mffs 0
  133. stfd 0,0(r3) /* save new fpscr value */
  134. stw r6,0(r4) /* save new cr value */
  135. blr
  136. /*
  137. * Double operation with no input operand
  138. *
  139. * R3 = (double*)&fpscr
  140. * R4 = (u32*)&cr
  141. * R5 = (double*)&result
  142. */
  143. #define FPD_NONE_IN(name) \
  144. _GLOBAL(fpd_ ## name); \
  145. mflr r12; \
  146. bl fpd_load_none; \
  147. mtlr r12; \
  148. \
  149. name. 0; /* call instruction */ \
  150. b fpd_return
  151. /*
  152. * Double operation with one input operand
  153. *
  154. * R3 = (double*)&fpscr
  155. * R4 = (u32*)&cr
  156. * R5 = (double*)&result
  157. * R6 = (double*)&param1
  158. */
  159. #define FPD_ONE_IN(name) \
  160. _GLOBAL(fpd_ ## name); \
  161. mflr r12; \
  162. bl fpd_load_one; \
  163. mtlr r12; \
  164. \
  165. name. 0,0; /* call instruction */ \
  166. b fpd_return
  167. /*
  168. * Double operation with two input operands
  169. *
  170. * R3 = (double*)&fpscr
  171. * R4 = (u32*)&cr
  172. * R5 = (double*)&result
  173. * R6 = (double*)&param1
  174. * R7 = (double*)&param2
  175. * R8 = (double*)&param3
  176. */
  177. #define FPD_TWO_IN(name) \
  178. _GLOBAL(fpd_ ## name); \
  179. mflr r12; \
  180. bl fpd_load_two; \
  181. mtlr r12; \
  182. \
  183. name. 0,0,1; /* call instruction */ \
  184. b fpd_return
  185. /*
  186. * CR Double operation with two input operands
  187. *
  188. * R3 = (double*)&fpscr
  189. * R4 = (u32*)&cr
  190. * R5 = (double*)&param1
  191. * R6 = (double*)&param2
  192. * R7 = (double*)&param3
  193. */
  194. #define FPD_TWO_IN_CR(name) \
  195. _GLOBAL(fpd_ ## name); \
  196. lfd 1,0(r6); /* load param2 */ \
  197. lfd 0,0(r5); /* load param1 */ \
  198. lfd 3,0(r3); /* load up fpscr value */ \
  199. MTFSF_L(3); \
  200. lwz r6, 0(r4); /* load cr */ \
  201. mtcr r6; \
  202. \
  203. name 0,0,1; /* call instruction */ \
  204. mfcr r6; \
  205. mffs 0; \
  206. stfd 0,0(r3); /* save new fpscr value */ \
  207. stw r6,0(r4); /* save new cr value */ \
  208. blr
  209. /*
  210. * Double operation with three input operands
  211. *
  212. * R3 = (double*)&fpscr
  213. * R4 = (u32*)&cr
  214. * R5 = (double*)&result
  215. * R6 = (double*)&param1
  216. * R7 = (double*)&param2
  217. * R8 = (double*)&param3
  218. */
  219. #define FPD_THREE_IN(name) \
  220. _GLOBAL(fpd_ ## name); \
  221. mflr r12; \
  222. bl fpd_load_three; \
  223. mtlr r12; \
  224. \
  225. name. 0,0,1,2; /* call instruction */ \
  226. b fpd_return
  227. FPD_ONE_IN(fsqrts)
  228. FPD_ONE_IN(frsqrtes)
  229. FPD_ONE_IN(fres)
  230. FPD_ONE_IN(frsp)
  231. FPD_ONE_IN(fctiw)
  232. FPD_ONE_IN(fctiwz)
  233. FPD_ONE_IN(fsqrt)
  234. FPD_ONE_IN(fre)
  235. FPD_ONE_IN(frsqrte)
  236. FPD_ONE_IN(fneg)
  237. FPD_ONE_IN(fabs)
  238. FPD_TWO_IN(fadds)
  239. FPD_TWO_IN(fsubs)
  240. FPD_TWO_IN(fdivs)
  241. FPD_TWO_IN(fmuls)
  242. FPD_TWO_IN_CR(fcmpu)
  243. FPD_TWO_IN(fcpsgn)
  244. FPD_TWO_IN(fdiv)
  245. FPD_TWO_IN(fadd)
  246. FPD_TWO_IN(fmul)
  247. FPD_TWO_IN_CR(fcmpo)
  248. FPD_TWO_IN(fsub)
  249. FPD_THREE_IN(fmsubs)
  250. FPD_THREE_IN(fmadds)
  251. FPD_THREE_IN(fnmsubs)
  252. FPD_THREE_IN(fnmadds)
  253. FPD_THREE_IN(fsel)
  254. FPD_THREE_IN(fmsub)
  255. FPD_THREE_IN(fmadd)
  256. FPD_THREE_IN(fnmsub)
  257. FPD_THREE_IN(fnmadd)
  258. _GLOBAL(kvm_cvt_fd)
  259. lfs 0,0(r3)
  260. stfd 0,0(r4)
  261. blr
  262. _GLOBAL(kvm_cvt_df)
  263. lfd 0,0(r3)
  264. stfs 0,0(r4)
  265. blr