fcnvff.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  3. *
  4. * Floating-point emulation code
  5. * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2, or (at your option)
  10. * any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. /*
  22. * BEGIN_DESC
  23. *
  24. * File:
  25. * @(#) pa/spmath/fcnvff.c $Revision: 1.1 $
  26. *
  27. * Purpose:
  28. * Single Floating-point to Double Floating-point
  29. * Double Floating-point to Single Floating-point
  30. *
  31. * External Interfaces:
  32. * dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status)
  33. * sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status)
  34. *
  35. * Internal Interfaces:
  36. *
  37. * Theory:
  38. * <<please update with a overview of the operation of this file>>
  39. *
  40. * END_DESC
  41. */
  42. #include "float.h"
  43. #include "sgl_float.h"
  44. #include "dbl_float.h"
  45. #include "cnv_float.h"
  46. /*
  47. * Single Floating-point to Double Floating-point
  48. */
  49. /*ARGSUSED*/
  50. int
  51. sgl_to_dbl_fcnvff(
  52. sgl_floating_point *srcptr,
  53. unsigned int *nullptr,
  54. dbl_floating_point *dstptr,
  55. unsigned int *status)
  56. {
  57. register unsigned int src, resultp1, resultp2;
  58. register int src_exponent;
  59. src = *srcptr;
  60. src_exponent = Sgl_exponent(src);
  61. Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */
  62. /*
  63. * Test for NaN or infinity
  64. */
  65. if (src_exponent == SGL_INFINITY_EXPONENT) {
  66. /*
  67. * determine if NaN or infinity
  68. */
  69. if (Sgl_iszero_mantissa(src)) {
  70. /*
  71. * is infinity; want to return double infinity
  72. */
  73. Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
  74. Dbl_copytoptr(resultp1,resultp2,dstptr);
  75. return(NOEXCEPTION);
  76. }
  77. else {
  78. /*
  79. * is NaN; signaling or quiet?
  80. */
  81. if (Sgl_isone_signaling(src)) {
  82. /* trap if INVALIDTRAP enabled */
  83. if (Is_invalidtrap_enabled())
  84. return(INVALIDEXCEPTION);
  85. /* make NaN quiet */
  86. else {
  87. Set_invalidflag();
  88. Sgl_set_quiet(src);
  89. }
  90. }
  91. /*
  92. * NaN is quiet, return as double NaN
  93. */
  94. Dbl_setinfinity_exponent(resultp1);
  95. Sgl_to_dbl_mantissa(src,resultp1,resultp2);
  96. Dbl_copytoptr(resultp1,resultp2,dstptr);
  97. return(NOEXCEPTION);
  98. }
  99. }
  100. /*
  101. * Test for zero or denormalized
  102. */
  103. if (src_exponent == 0) {
  104. /*
  105. * determine if zero or denormalized
  106. */
  107. if (Sgl_isnotzero_mantissa(src)) {
  108. /*
  109. * is denormalized; want to normalize
  110. */
  111. Sgl_clear_signexponent(src);
  112. Sgl_leftshiftby1(src);
  113. Sgl_normalize(src,src_exponent);
  114. Sgl_to_dbl_exponent(src_exponent,resultp1);
  115. Sgl_to_dbl_mantissa(src,resultp1,resultp2);
  116. }
  117. else {
  118. Dbl_setzero_exponentmantissa(resultp1,resultp2);
  119. }
  120. Dbl_copytoptr(resultp1,resultp2,dstptr);
  121. return(NOEXCEPTION);
  122. }
  123. /*
  124. * No special cases, just complete the conversion
  125. */
  126. Sgl_to_dbl_exponent(src_exponent, resultp1);
  127. Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
  128. Dbl_copytoptr(resultp1,resultp2,dstptr);
  129. return(NOEXCEPTION);
  130. }
  131. /*
  132. * Double Floating-point to Single Floating-point
  133. */
  134. /*ARGSUSED*/
  135. int
  136. dbl_to_sgl_fcnvff(
  137. dbl_floating_point *srcptr,
  138. unsigned int *nullptr,
  139. sgl_floating_point *dstptr,
  140. unsigned int *status)
  141. {
  142. register unsigned int srcp1, srcp2, result;
  143. register int src_exponent, dest_exponent, dest_mantissa;
  144. register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
  145. register boolean lsb_odd = FALSE;
  146. boolean is_tiny;
  147. Dbl_copyfromptr(srcptr,srcp1,srcp2);
  148. src_exponent = Dbl_exponent(srcp1);
  149. Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */
  150. /*
  151. * Test for NaN or infinity
  152. */
  153. if (src_exponent == DBL_INFINITY_EXPONENT) {
  154. /*
  155. * determine if NaN or infinity
  156. */
  157. if (Dbl_iszero_mantissa(srcp1,srcp2)) {
  158. /*
  159. * is infinity; want to return single infinity
  160. */
  161. Sgl_setinfinity_exponentmantissa(result);
  162. *dstptr = result;
  163. return(NOEXCEPTION);
  164. }
  165. /*
  166. * is NaN; signaling or quiet?
  167. */
  168. if (Dbl_isone_signaling(srcp1)) {
  169. /* trap if INVALIDTRAP enabled */
  170. if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
  171. else {
  172. Set_invalidflag();
  173. /* make NaN quiet */
  174. Dbl_set_quiet(srcp1);
  175. }
  176. }
  177. /*
  178. * NaN is quiet, return as single NaN
  179. */
  180. Sgl_setinfinity_exponent(result);
  181. Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
  182. if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
  183. *dstptr = result;
  184. return(NOEXCEPTION);
  185. }
  186. /*
  187. * Generate result
  188. */
  189. Dbl_to_sgl_exponent(src_exponent,dest_exponent);
  190. if (dest_exponent > 0) {
  191. Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
  192. stickybit,lsb_odd);
  193. }
  194. else {
  195. if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
  196. Sgl_setzero_exponentmantissa(result);
  197. *dstptr = result;
  198. return(NOEXCEPTION);
  199. }
  200. if (Is_underflowtrap_enabled()) {
  201. Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
  202. guardbit,stickybit,lsb_odd);
  203. }
  204. else {
  205. /* compute result, determine inexact info,
  206. * and set Underflowflag if appropriate
  207. */
  208. Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
  209. dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
  210. is_tiny);
  211. }
  212. }
  213. /*
  214. * Now round result if not exact
  215. */
  216. if (inexact) {
  217. switch (Rounding_mode()) {
  218. case ROUNDPLUS:
  219. if (Sgl_iszero_sign(result)) dest_mantissa++;
  220. break;
  221. case ROUNDMINUS:
  222. if (Sgl_isone_sign(result)) dest_mantissa++;
  223. break;
  224. case ROUNDNEAREST:
  225. if (guardbit) {
  226. if (stickybit || lsb_odd) dest_mantissa++;
  227. }
  228. }
  229. }
  230. Sgl_set_exponentmantissa(result,dest_mantissa);
  231. /*
  232. * check for mantissa overflow after rounding
  233. */
  234. if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
  235. Sgl_isone_hidden(result)) dest_exponent++;
  236. /*
  237. * Test for overflow
  238. */
  239. if (dest_exponent >= SGL_INFINITY_EXPONENT) {
  240. /* trap if OVERFLOWTRAP enabled */
  241. if (Is_overflowtrap_enabled()) {
  242. /*
  243. * Check for gross overflow
  244. */
  245. if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
  246. return(UNIMPLEMENTEDEXCEPTION);
  247. /*
  248. * Adjust bias of result
  249. */
  250. Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
  251. *dstptr = result;
  252. if (inexact)
  253. if (Is_inexacttrap_enabled())
  254. return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
  255. else Set_inexactflag();
  256. return(OVERFLOWEXCEPTION);
  257. }
  258. Set_overflowflag();
  259. inexact = TRUE;
  260. /* set result to infinity or largest number */
  261. Sgl_setoverflow(result);
  262. }
  263. /*
  264. * Test for underflow
  265. */
  266. else if (dest_exponent <= 0) {
  267. /* trap if UNDERFLOWTRAP enabled */
  268. if (Is_underflowtrap_enabled()) {
  269. /*
  270. * Check for gross underflow
  271. */
  272. if (dest_exponent <= -(SGL_WRAP))
  273. return(UNIMPLEMENTEDEXCEPTION);
  274. /*
  275. * Adjust bias of result
  276. */
  277. Sgl_setwrapped_exponent(result,dest_exponent,unfl);
  278. *dstptr = result;
  279. if (inexact)
  280. if (Is_inexacttrap_enabled())
  281. return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
  282. else Set_inexactflag();
  283. return(UNDERFLOWEXCEPTION);
  284. }
  285. /*
  286. * result is denormalized or signed zero
  287. */
  288. if (inexact && is_tiny) Set_underflowflag();
  289. }
  290. else Sgl_set_exponent(result,dest_exponent);
  291. *dstptr = result;
  292. /*
  293. * Trap if inexact trap is enabled
  294. */
  295. if (inexact)
  296. if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  297. else Set_inexactflag();
  298. return(NOEXCEPTION);
  299. }