/arch/arm26/nwfpe/fpa11.c

https://bitbucket.org/evzijst/gittest · C · 221 lines · 162 code · 24 blank · 35 comment · 20 complexity · 49a6530524e4e4862df248de8eae8978 MD5 · raw file

  1. /*
  2. NetWinder Floating Point Emulator
  3. (c) Rebel.COM, 1998,1999
  4. Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include "fpa11.h"
  18. #include "fpopcode.h"
  19. #include "fpmodule.h"
  20. #include "fpmodule.inl"
  21. #include <linux/compiler.h>
  22. #include <asm/system.h>
  23. /* forward declarations */
  24. unsigned int EmulateCPDO(const unsigned int);
  25. unsigned int EmulateCPDT(const unsigned int);
  26. unsigned int EmulateCPRT(const unsigned int);
  27. /* Reset the FPA11 chip. Called to initialize and reset the emulator. */
  28. void resetFPA11(void)
  29. {
  30. int i;
  31. FPA11 *fpa11 = GET_FPA11();
  32. /* initialize the register type array */
  33. for (i=0;i<=7;i++)
  34. {
  35. fpa11->fType[i] = typeNone;
  36. }
  37. /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
  38. fpa11->fpsr = FP_EMULATOR | BIT_AC;
  39. /* FPCR: set SB, AB and DA bits, clear all others */
  40. #if MAINTAIN_FPCR
  41. fpa11->fpcr = MASK_RESET;
  42. #endif
  43. }
  44. void SetRoundingMode(const unsigned int opcode)
  45. {
  46. #if MAINTAIN_FPCR
  47. FPA11 *fpa11 = GET_FPA11();
  48. fpa11->fpcr &= ~MASK_ROUNDING_MODE;
  49. #endif
  50. switch (opcode & MASK_ROUNDING_MODE)
  51. {
  52. default:
  53. case ROUND_TO_NEAREST:
  54. float_rounding_mode = float_round_nearest_even;
  55. #if MAINTAIN_FPCR
  56. fpa11->fpcr |= ROUND_TO_NEAREST;
  57. #endif
  58. break;
  59. case ROUND_TO_PLUS_INFINITY:
  60. float_rounding_mode = float_round_up;
  61. #if MAINTAIN_FPCR
  62. fpa11->fpcr |= ROUND_TO_PLUS_INFINITY;
  63. #endif
  64. break;
  65. case ROUND_TO_MINUS_INFINITY:
  66. float_rounding_mode = float_round_down;
  67. #if MAINTAIN_FPCR
  68. fpa11->fpcr |= ROUND_TO_MINUS_INFINITY;
  69. #endif
  70. break;
  71. case ROUND_TO_ZERO:
  72. float_rounding_mode = float_round_to_zero;
  73. #if MAINTAIN_FPCR
  74. fpa11->fpcr |= ROUND_TO_ZERO;
  75. #endif
  76. break;
  77. }
  78. }
  79. void SetRoundingPrecision(const unsigned int opcode)
  80. {
  81. #if MAINTAIN_FPCR
  82. FPA11 *fpa11 = GET_FPA11();
  83. fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
  84. #endif
  85. switch (opcode & MASK_ROUNDING_PRECISION)
  86. {
  87. case ROUND_SINGLE:
  88. floatx80_rounding_precision = 32;
  89. #if MAINTAIN_FPCR
  90. fpa11->fpcr |= ROUND_SINGLE;
  91. #endif
  92. break;
  93. case ROUND_DOUBLE:
  94. floatx80_rounding_precision = 64;
  95. #if MAINTAIN_FPCR
  96. fpa11->fpcr |= ROUND_DOUBLE;
  97. #endif
  98. break;
  99. case ROUND_EXTENDED:
  100. floatx80_rounding_precision = 80;
  101. #if MAINTAIN_FPCR
  102. fpa11->fpcr |= ROUND_EXTENDED;
  103. #endif
  104. break;
  105. default: floatx80_rounding_precision = 80;
  106. }
  107. }
  108. void FPA11_CheckInit(void)
  109. {
  110. FPA11 *fpa11 = GET_FPA11();
  111. if (unlikely(fpa11->initflag == 0))
  112. {
  113. resetFPA11();
  114. SetRoundingMode(ROUND_TO_NEAREST);
  115. SetRoundingPrecision(ROUND_EXTENDED);
  116. fpa11->initflag = 1;
  117. }
  118. }
  119. /* Emulate the instruction in the opcode. */
  120. unsigned int EmulateAll(unsigned int opcode)
  121. {
  122. unsigned int nRc = 1, code;
  123. code = opcode & 0x00000f00;
  124. if (code == 0x00000100 || code == 0x00000200)
  125. {
  126. /* For coprocessor 1 or 2 (FPA11) */
  127. code = opcode & 0x0e000000;
  128. if (code == 0x0e000000)
  129. {
  130. if (opcode & 0x00000010)
  131. {
  132. /* Emulate conversion opcodes. */
  133. /* Emulate register transfer opcodes. */
  134. /* Emulate comparison opcodes. */
  135. nRc = EmulateCPRT(opcode);
  136. }
  137. else
  138. {
  139. /* Emulate monadic arithmetic opcodes. */
  140. /* Emulate dyadic arithmetic opcodes. */
  141. nRc = EmulateCPDO(opcode);
  142. }
  143. }
  144. else if (code == 0x0c000000)
  145. {
  146. /* Emulate load/store opcodes. */
  147. /* Emulate load/store multiple opcodes. */
  148. nRc = EmulateCPDT(opcode);
  149. }
  150. else
  151. {
  152. /* Invalid instruction detected. Return FALSE. */
  153. nRc = 0;
  154. }
  155. }
  156. return(nRc);
  157. }
  158. #if 0
  159. unsigned int EmulateAll1(unsigned int opcode)
  160. {
  161. switch ((opcode >> 24) & 0xf)
  162. {
  163. case 0xc:
  164. case 0xd:
  165. if ((opcode >> 20) & 0x1)
  166. {
  167. switch ((opcode >> 8) & 0xf)
  168. {
  169. case 0x1: return PerformLDF(opcode); break;
  170. case 0x2: return PerformLFM(opcode); break;
  171. default: return 0;
  172. }
  173. }
  174. else
  175. {
  176. switch ((opcode >> 8) & 0xf)
  177. {
  178. case 0x1: return PerformSTF(opcode); break;
  179. case 0x2: return PerformSFM(opcode); break;
  180. default: return 0;
  181. }
  182. }
  183. break;
  184. case 0xe:
  185. if (opcode & 0x10)
  186. return EmulateCPDO(opcode);
  187. else
  188. return EmulateCPRT(opcode);
  189. break;
  190. default: return 0;
  191. }
  192. }
  193. #endif