/arch/arm/nwfpe/fpa11_cpdt.c

https://bitbucket.org/evzijst/gittest · C · 392 lines · 315 code · 56 blank · 21 comment · 41 complexity · d741d66346e32ff704d112369e8c0b9e MD5 · raw file

  1. /*
  2. NetWinder Floating Point Emulator
  3. (c) Rebel.com, 1998-1999
  4. (c) Philip Blundell, 1998, 2001
  5. Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include <linux/config.h>
  19. #include "fpa11.h"
  20. #include "softfloat.h"
  21. #include "fpopcode.h"
  22. #include "fpmodule.h"
  23. #include "fpmodule.inl"
  24. #include <asm/uaccess.h>
  25. static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
  26. {
  27. FPA11 *fpa11 = GET_FPA11();
  28. fpa11->fType[Fn] = typeSingle;
  29. get_user(fpa11->fpreg[Fn].fSingle, pMem);
  30. }
  31. static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
  32. {
  33. FPA11 *fpa11 = GET_FPA11();
  34. unsigned int *p;
  35. p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
  36. fpa11->fType[Fn] = typeDouble;
  37. #ifdef __ARMEB__
  38. get_user(p[0], &pMem[0]); /* sign & exponent */
  39. get_user(p[1], &pMem[1]);
  40. #else
  41. get_user(p[0], &pMem[1]);
  42. get_user(p[1], &pMem[0]); /* sign & exponent */
  43. #endif
  44. }
  45. #ifdef CONFIG_FPE_NWFPE_XP
  46. static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
  47. {
  48. FPA11 *fpa11 = GET_FPA11();
  49. unsigned int *p;
  50. p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
  51. fpa11->fType[Fn] = typeExtended;
  52. get_user(p[0], &pMem[0]); /* sign & exponent */
  53. get_user(p[1], &pMem[2]); /* ls bits */
  54. get_user(p[2], &pMem[1]); /* ms bits */
  55. }
  56. #endif
  57. static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
  58. {
  59. FPA11 *fpa11 = GET_FPA11();
  60. register unsigned int *p;
  61. unsigned long x;
  62. p = (unsigned int *) &(fpa11->fpreg[Fn]);
  63. get_user(x, &pMem[0]);
  64. fpa11->fType[Fn] = (x >> 14) & 0x00000003;
  65. switch (fpa11->fType[Fn]) {
  66. case typeSingle:
  67. case typeDouble:
  68. {
  69. get_user(p[0], &pMem[2]); /* Single */
  70. get_user(p[1], &pMem[1]); /* double msw */
  71. p[2] = 0; /* empty */
  72. }
  73. break;
  74. #ifdef CONFIG_FPE_NWFPE_XP
  75. case typeExtended:
  76. {
  77. get_user(p[1], &pMem[2]);
  78. get_user(p[2], &pMem[1]); /* msw */
  79. p[0] = (x & 0x80003fff);
  80. }
  81. break;
  82. #endif
  83. }
  84. }
  85. static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
  86. {
  87. FPA11 *fpa11 = GET_FPA11();
  88. union {
  89. float32 f;
  90. unsigned int i[1];
  91. } val;
  92. switch (fpa11->fType[Fn]) {
  93. case typeDouble:
  94. val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
  95. break;
  96. #ifdef CONFIG_FPE_NWFPE_XP
  97. case typeExtended:
  98. val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
  99. break;
  100. #endif
  101. default:
  102. val.f = fpa11->fpreg[Fn].fSingle;
  103. }
  104. put_user(val.i[0], pMem);
  105. }
  106. static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
  107. {
  108. FPA11 *fpa11 = GET_FPA11();
  109. union {
  110. float64 f;
  111. unsigned int i[2];
  112. } val;
  113. switch (fpa11->fType[Fn]) {
  114. case typeSingle:
  115. val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
  116. break;
  117. #ifdef CONFIG_FPE_NWFPE_XP
  118. case typeExtended:
  119. val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
  120. break;
  121. #endif
  122. default:
  123. val.f = fpa11->fpreg[Fn].fDouble;
  124. }
  125. #ifdef __ARMEB__
  126. put_user(val.i[0], &pMem[0]); /* msw */
  127. put_user(val.i[1], &pMem[1]); /* lsw */
  128. #else
  129. put_user(val.i[1], &pMem[0]); /* msw */
  130. put_user(val.i[0], &pMem[1]); /* lsw */
  131. #endif
  132. }
  133. #ifdef CONFIG_FPE_NWFPE_XP
  134. static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
  135. {
  136. FPA11 *fpa11 = GET_FPA11();
  137. union {
  138. floatx80 f;
  139. unsigned int i[3];
  140. } val;
  141. switch (fpa11->fType[Fn]) {
  142. case typeSingle:
  143. val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
  144. break;
  145. case typeDouble:
  146. val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
  147. break;
  148. default:
  149. val.f = fpa11->fpreg[Fn].fExtended;
  150. }
  151. put_user(val.i[0], &pMem[0]); /* sign & exp */
  152. put_user(val.i[1], &pMem[2]);
  153. put_user(val.i[2], &pMem[1]); /* msw */
  154. }
  155. #endif
  156. static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
  157. {
  158. FPA11 *fpa11 = GET_FPA11();
  159. register unsigned int nType, *p;
  160. p = (unsigned int *) &(fpa11->fpreg[Fn]);
  161. nType = fpa11->fType[Fn];
  162. switch (nType) {
  163. case typeSingle:
  164. case typeDouble:
  165. {
  166. put_user(p[0], &pMem[2]); /* single */
  167. put_user(p[1], &pMem[1]); /* double msw */
  168. put_user(nType << 14, &pMem[0]);
  169. }
  170. break;
  171. #ifdef CONFIG_FPE_NWFPE_XP
  172. case typeExtended:
  173. {
  174. put_user(p[2], &pMem[1]); /* msw */
  175. put_user(p[1], &pMem[2]);
  176. put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
  177. }
  178. break;
  179. #endif
  180. }
  181. }
  182. unsigned int PerformLDF(const unsigned int opcode)
  183. {
  184. unsigned int __user *pBase, *pAddress, *pFinal;
  185. unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
  186. pBase = (unsigned int __user *) readRegister(getRn(opcode));
  187. if (REG_PC == getRn(opcode)) {
  188. pBase += 2;
  189. write_back = 0;
  190. }
  191. pFinal = pBase;
  192. if (BIT_UP_SET(opcode))
  193. pFinal += getOffset(opcode);
  194. else
  195. pFinal -= getOffset(opcode);
  196. if (PREINDEXED(opcode))
  197. pAddress = pFinal;
  198. else
  199. pAddress = pBase;
  200. switch (opcode & MASK_TRANSFER_LENGTH) {
  201. case TRANSFER_SINGLE:
  202. loadSingle(getFd(opcode), pAddress);
  203. break;
  204. case TRANSFER_DOUBLE:
  205. loadDouble(getFd(opcode), pAddress);
  206. break;
  207. #ifdef CONFIG_FPE_NWFPE_XP
  208. case TRANSFER_EXTENDED:
  209. loadExtended(getFd(opcode), pAddress);
  210. break;
  211. #endif
  212. default:
  213. nRc = 0;
  214. }
  215. if (write_back)
  216. writeRegister(getRn(opcode), (unsigned long) pFinal);
  217. return nRc;
  218. }
  219. unsigned int PerformSTF(const unsigned int opcode)
  220. {
  221. unsigned int __user *pBase, *pAddress, *pFinal;
  222. unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
  223. SetRoundingMode(ROUND_TO_NEAREST);
  224. pBase = (unsigned int __user *) readRegister(getRn(opcode));
  225. if (REG_PC == getRn(opcode)) {
  226. pBase += 2;
  227. write_back = 0;
  228. }
  229. pFinal = pBase;
  230. if (BIT_UP_SET(opcode))
  231. pFinal += getOffset(opcode);
  232. else
  233. pFinal -= getOffset(opcode);
  234. if (PREINDEXED(opcode))
  235. pAddress = pFinal;
  236. else
  237. pAddress = pBase;
  238. switch (opcode & MASK_TRANSFER_LENGTH) {
  239. case TRANSFER_SINGLE:
  240. storeSingle(getFd(opcode), pAddress);
  241. break;
  242. case TRANSFER_DOUBLE:
  243. storeDouble(getFd(opcode), pAddress);
  244. break;
  245. #ifdef CONFIG_FPE_NWFPE_XP
  246. case TRANSFER_EXTENDED:
  247. storeExtended(getFd(opcode), pAddress);
  248. break;
  249. #endif
  250. default:
  251. nRc = 0;
  252. }
  253. if (write_back)
  254. writeRegister(getRn(opcode), (unsigned long) pFinal);
  255. return nRc;
  256. }
  257. unsigned int PerformLFM(const unsigned int opcode)
  258. {
  259. unsigned int __user *pBase, *pAddress, *pFinal;
  260. unsigned int i, Fd, write_back = WRITE_BACK(opcode);
  261. pBase = (unsigned int __user *) readRegister(getRn(opcode));
  262. if (REG_PC == getRn(opcode)) {
  263. pBase += 2;
  264. write_back = 0;
  265. }
  266. pFinal = pBase;
  267. if (BIT_UP_SET(opcode))
  268. pFinal += getOffset(opcode);
  269. else
  270. pFinal -= getOffset(opcode);
  271. if (PREINDEXED(opcode))
  272. pAddress = pFinal;
  273. else
  274. pAddress = pBase;
  275. Fd = getFd(opcode);
  276. for (i = getRegisterCount(opcode); i > 0; i--) {
  277. loadMultiple(Fd, pAddress);
  278. pAddress += 3;
  279. Fd++;
  280. if (Fd == 8)
  281. Fd = 0;
  282. }
  283. if (write_back)
  284. writeRegister(getRn(opcode), (unsigned long) pFinal);
  285. return 1;
  286. }
  287. unsigned int PerformSFM(const unsigned int opcode)
  288. {
  289. unsigned int __user *pBase, *pAddress, *pFinal;
  290. unsigned int i, Fd, write_back = WRITE_BACK(opcode);
  291. pBase = (unsigned int __user *) readRegister(getRn(opcode));
  292. if (REG_PC == getRn(opcode)) {
  293. pBase += 2;
  294. write_back = 0;
  295. }
  296. pFinal = pBase;
  297. if (BIT_UP_SET(opcode))
  298. pFinal += getOffset(opcode);
  299. else
  300. pFinal -= getOffset(opcode);
  301. if (PREINDEXED(opcode))
  302. pAddress = pFinal;
  303. else
  304. pAddress = pBase;
  305. Fd = getFd(opcode);
  306. for (i = getRegisterCount(opcode); i > 0; i--) {
  307. storeMultiple(Fd, pAddress);
  308. pAddress += 3;
  309. Fd++;
  310. if (Fd == 8)
  311. Fd = 0;
  312. }
  313. if (write_back)
  314. writeRegister(getRn(opcode), (unsigned long) pFinal);
  315. return 1;
  316. }
  317. unsigned int EmulateCPDT(const unsigned int opcode)
  318. {
  319. unsigned int nRc = 0;
  320. if (LDF_OP(opcode)) {
  321. nRc = PerformLDF(opcode);
  322. } else if (LFM_OP(opcode)) {
  323. nRc = PerformLFM(opcode);
  324. } else if (STF_OP(opcode)) {
  325. nRc = PerformSTF(opcode);
  326. } else if (SFM_OP(opcode)) {
  327. nRc = PerformSFM(opcode);
  328. } else {
  329. nRc = 0;
  330. }
  331. return nRc;
  332. }