fcnvfx.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  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/fcnvfx.c $Revision: 1.1 $
  26. *
  27. * Purpose:
  28. * Single Floating-point to Single Fixed-point
  29. * Single Floating-point to Double Fixed-point
  30. * Double Floating-point to Single Fixed-point
  31. * Double Floating-point to Double Fixed-point
  32. *
  33. * External Interfaces:
  34. * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
  35. * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
  36. * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
  37. * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
  38. *
  39. * Internal Interfaces:
  40. *
  41. * Theory:
  42. * <<please update with a overview of the operation of this file>>
  43. *
  44. * END_DESC
  45. */
  46. #include "float.h"
  47. #include "sgl_float.h"
  48. #include "dbl_float.h"
  49. #include "cnv_float.h"
  50. /*
  51. * Single Floating-point to Single Fixed-point
  52. */
  53. /*ARGSUSED*/
  54. int
  55. sgl_to_sgl_fcnvfx(
  56. sgl_floating_point *srcptr,
  57. sgl_floating_point *nullptr,
  58. int *dstptr,
  59. sgl_floating_point *status)
  60. {
  61. register unsigned int src, temp;
  62. register int src_exponent, result;
  63. register boolean inexact = FALSE;
  64. src = *srcptr;
  65. src_exponent = Sgl_exponent(src) - SGL_BIAS;
  66. /*
  67. * Test for overflow
  68. */
  69. if (src_exponent > SGL_FX_MAX_EXP) {
  70. /* check for MININT */
  71. if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
  72. Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
  73. if (Sgl_iszero_sign(src)) result = 0x7fffffff;
  74. else result = 0x80000000;
  75. if (Is_invalidtrap_enabled()) {
  76. return(INVALIDEXCEPTION);
  77. }
  78. Set_invalidflag();
  79. *dstptr = result;
  80. return(NOEXCEPTION);
  81. }
  82. }
  83. /*
  84. * Generate result
  85. */
  86. if (src_exponent >= 0) {
  87. temp = src;
  88. Sgl_clear_signexponent_set_hidden(temp);
  89. Int_from_sgl_mantissa(temp,src_exponent);
  90. if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
  91. else result = Sgl_all(temp);
  92. /* check for inexact */
  93. if (Sgl_isinexact_to_fix(src,src_exponent)) {
  94. inexact = TRUE;
  95. /* round result */
  96. switch (Rounding_mode()) {
  97. case ROUNDPLUS:
  98. if (Sgl_iszero_sign(src)) result++;
  99. break;
  100. case ROUNDMINUS:
  101. if (Sgl_isone_sign(src)) result--;
  102. break;
  103. case ROUNDNEAREST:
  104. if (Sgl_isone_roundbit(src,src_exponent)) {
  105. if (Sgl_isone_stickybit(src,src_exponent)
  106. || (Sgl_isone_lowmantissa(temp)))
  107. if (Sgl_iszero_sign(src)) result++;
  108. else result--;
  109. }
  110. }
  111. }
  112. }
  113. else {
  114. result = 0;
  115. /* check for inexact */
  116. if (Sgl_isnotzero_exponentmantissa(src)) {
  117. inexact = TRUE;
  118. /* round result */
  119. switch (Rounding_mode()) {
  120. case ROUNDPLUS:
  121. if (Sgl_iszero_sign(src)) result++;
  122. break;
  123. case ROUNDMINUS:
  124. if (Sgl_isone_sign(src)) result--;
  125. break;
  126. case ROUNDNEAREST:
  127. if (src_exponent == -1)
  128. if (Sgl_isnotzero_mantissa(src))
  129. if (Sgl_iszero_sign(src)) result++;
  130. else result--;
  131. }
  132. }
  133. }
  134. *dstptr = result;
  135. if (inexact) {
  136. if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  137. else Set_inexactflag();
  138. }
  139. return(NOEXCEPTION);
  140. }
  141. /*
  142. * Single Floating-point to Double Fixed-point
  143. */
  144. /*ARGSUSED*/
  145. int
  146. sgl_to_dbl_fcnvfx(
  147. sgl_floating_point *srcptr,
  148. unsigned int *nullptr,
  149. dbl_integer *dstptr,
  150. unsigned int *status)
  151. {
  152. register int src_exponent, resultp1;
  153. register unsigned int src, temp, resultp2;
  154. register boolean inexact = FALSE;
  155. src = *srcptr;
  156. src_exponent = Sgl_exponent(src) - SGL_BIAS;
  157. /*
  158. * Test for overflow
  159. */
  160. if (src_exponent > DBL_FX_MAX_EXP) {
  161. /* check for MININT */
  162. if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
  163. Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
  164. if (Sgl_iszero_sign(src)) {
  165. resultp1 = 0x7fffffff;
  166. resultp2 = 0xffffffff;
  167. }
  168. else {
  169. resultp1 = 0x80000000;
  170. resultp2 = 0;
  171. }
  172. if (Is_invalidtrap_enabled()) {
  173. return(INVALIDEXCEPTION);
  174. }
  175. Set_invalidflag();
  176. Dint_copytoptr(resultp1,resultp2,dstptr);
  177. return(NOEXCEPTION);
  178. }
  179. Dint_set_minint(resultp1,resultp2);
  180. Dint_copytoptr(resultp1,resultp2,dstptr);
  181. return(NOEXCEPTION);
  182. }
  183. /*
  184. * Generate result
  185. */
  186. if (src_exponent >= 0) {
  187. temp = src;
  188. Sgl_clear_signexponent_set_hidden(temp);
  189. Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
  190. if (Sgl_isone_sign(src)) {
  191. Dint_setone_sign(resultp1,resultp2);
  192. }
  193. /* check for inexact */
  194. if (Sgl_isinexact_to_fix(src,src_exponent)) {
  195. inexact = TRUE;
  196. /* round result */
  197. switch (Rounding_mode()) {
  198. case ROUNDPLUS:
  199. if (Sgl_iszero_sign(src)) {
  200. Dint_increment(resultp1,resultp2);
  201. }
  202. break;
  203. case ROUNDMINUS:
  204. if (Sgl_isone_sign(src)) {
  205. Dint_decrement(resultp1,resultp2);
  206. }
  207. break;
  208. case ROUNDNEAREST:
  209. if (Sgl_isone_roundbit(src,src_exponent))
  210. if (Sgl_isone_stickybit(src,src_exponent) ||
  211. (Dint_isone_lowp2(resultp2)))
  212. if (Sgl_iszero_sign(src)) {
  213. Dint_increment(resultp1,resultp2);
  214. }
  215. else {
  216. Dint_decrement(resultp1,resultp2);
  217. }
  218. }
  219. }
  220. }
  221. else {
  222. Dint_setzero(resultp1,resultp2);
  223. /* check for inexact */
  224. if (Sgl_isnotzero_exponentmantissa(src)) {
  225. inexact = TRUE;
  226. /* round result */
  227. switch (Rounding_mode()) {
  228. case ROUNDPLUS:
  229. if (Sgl_iszero_sign(src)) {
  230. Dint_increment(resultp1,resultp2);
  231. }
  232. break;
  233. case ROUNDMINUS:
  234. if (Sgl_isone_sign(src)) {
  235. Dint_decrement(resultp1,resultp2);
  236. }
  237. break;
  238. case ROUNDNEAREST:
  239. if (src_exponent == -1)
  240. if (Sgl_isnotzero_mantissa(src))
  241. if (Sgl_iszero_sign(src)) {
  242. Dint_increment(resultp1,resultp2);
  243. }
  244. else {
  245. Dint_decrement(resultp1,resultp2);
  246. }
  247. }
  248. }
  249. }
  250. Dint_copytoptr(resultp1,resultp2,dstptr);
  251. if (inexact) {
  252. if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  253. else Set_inexactflag();
  254. }
  255. return(NOEXCEPTION);
  256. }
  257. /*
  258. * Double Floating-point to Single Fixed-point
  259. */
  260. /*ARGSUSED*/
  261. int
  262. dbl_to_sgl_fcnvfx(
  263. dbl_floating_point *srcptr,
  264. unsigned int *nullptr,
  265. int *dstptr,
  266. unsigned int *status)
  267. {
  268. register unsigned int srcp1,srcp2, tempp1,tempp2;
  269. register int src_exponent, result;
  270. register boolean inexact = FALSE;
  271. Dbl_copyfromptr(srcptr,srcp1,srcp2);
  272. src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
  273. /*
  274. * Test for overflow
  275. */
  276. if (src_exponent > SGL_FX_MAX_EXP) {
  277. /* check for MININT */
  278. if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
  279. if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
  280. else result = 0x80000000;
  281. if (Is_invalidtrap_enabled()) {
  282. return(INVALIDEXCEPTION);
  283. }
  284. Set_invalidflag();
  285. *dstptr = result;
  286. return(NOEXCEPTION);
  287. }
  288. }
  289. /*
  290. * Generate result
  291. */
  292. if (src_exponent >= 0) {
  293. tempp1 = srcp1;
  294. tempp2 = srcp2;
  295. Dbl_clear_signexponent_set_hidden(tempp1);
  296. Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
  297. if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
  298. result = -Dbl_allp1(tempp1);
  299. else result = Dbl_allp1(tempp1);
  300. /* check for inexact */
  301. if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
  302. inexact = TRUE;
  303. /* round result */
  304. switch (Rounding_mode()) {
  305. case ROUNDPLUS:
  306. if (Dbl_iszero_sign(srcp1)) result++;
  307. break;
  308. case ROUNDMINUS:
  309. if (Dbl_isone_sign(srcp1)) result--;
  310. break;
  311. case ROUNDNEAREST:
  312. if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
  313. if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
  314. (Dbl_isone_lowmantissap1(tempp1)))
  315. if (Dbl_iszero_sign(srcp1)) result++;
  316. else result--;
  317. }
  318. /* check for overflow */
  319. if ((Dbl_iszero_sign(srcp1) && result < 0) ||
  320. (Dbl_isone_sign(srcp1) && result > 0)) {
  321. if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
  322. else result = 0x80000000;
  323. if (Is_invalidtrap_enabled()) {
  324. return(INVALIDEXCEPTION);
  325. }
  326. Set_invalidflag();
  327. *dstptr = result;
  328. return(NOEXCEPTION);
  329. }
  330. }
  331. }
  332. else {
  333. result = 0;
  334. /* check for inexact */
  335. if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
  336. inexact = TRUE;
  337. /* round result */
  338. switch (Rounding_mode()) {
  339. case ROUNDPLUS:
  340. if (Dbl_iszero_sign(srcp1)) result++;
  341. break;
  342. case ROUNDMINUS:
  343. if (Dbl_isone_sign(srcp1)) result--;
  344. break;
  345. case ROUNDNEAREST:
  346. if (src_exponent == -1)
  347. if (Dbl_isnotzero_mantissa(srcp1,srcp2))
  348. if (Dbl_iszero_sign(srcp1)) result++;
  349. else result--;
  350. }
  351. }
  352. }
  353. *dstptr = result;
  354. if (inexact) {
  355. if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  356. else Set_inexactflag();
  357. }
  358. return(NOEXCEPTION);
  359. }
  360. /*
  361. * Double Floating-point to Double Fixed-point
  362. */
  363. /*ARGSUSED*/
  364. int
  365. dbl_to_dbl_fcnvfx(
  366. dbl_floating_point *srcptr,
  367. unsigned int *nullptr,
  368. dbl_integer *dstptr,
  369. unsigned int *status)
  370. {
  371. register int src_exponent, resultp1;
  372. register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
  373. register boolean inexact = FALSE;
  374. Dbl_copyfromptr(srcptr,srcp1,srcp2);
  375. src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
  376. /*
  377. * Test for overflow
  378. */
  379. if (src_exponent > DBL_FX_MAX_EXP) {
  380. /* check for MININT */
  381. if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
  382. Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
  383. if (Dbl_iszero_sign(srcp1)) {
  384. resultp1 = 0x7fffffff;
  385. resultp2 = 0xffffffff;
  386. }
  387. else {
  388. resultp1 = 0x80000000;
  389. resultp2 = 0;
  390. }
  391. if (Is_invalidtrap_enabled()) {
  392. return(INVALIDEXCEPTION);
  393. }
  394. Set_invalidflag();
  395. Dint_copytoptr(resultp1,resultp2,dstptr);
  396. return(NOEXCEPTION);
  397. }
  398. }
  399. /*
  400. * Generate result
  401. */
  402. if (src_exponent >= 0) {
  403. tempp1 = srcp1;
  404. tempp2 = srcp2;
  405. Dbl_clear_signexponent_set_hidden(tempp1);
  406. Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
  407. resultp2);
  408. if (Dbl_isone_sign(srcp1)) {
  409. Dint_setone_sign(resultp1,resultp2);
  410. }
  411. /* check for inexact */
  412. if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
  413. inexact = TRUE;
  414. /* round result */
  415. switch (Rounding_mode()) {
  416. case ROUNDPLUS:
  417. if (Dbl_iszero_sign(srcp1)) {
  418. Dint_increment(resultp1,resultp2);
  419. }
  420. break;
  421. case ROUNDMINUS:
  422. if (Dbl_isone_sign(srcp1)) {
  423. Dint_decrement(resultp1,resultp2);
  424. }
  425. break;
  426. case ROUNDNEAREST:
  427. if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
  428. if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
  429. (Dint_isone_lowp2(resultp2)))
  430. if (Dbl_iszero_sign(srcp1)) {
  431. Dint_increment(resultp1,resultp2);
  432. }
  433. else {
  434. Dint_decrement(resultp1,resultp2);
  435. }
  436. }
  437. }
  438. }
  439. else {
  440. Dint_setzero(resultp1,resultp2);
  441. /* check for inexact */
  442. if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
  443. inexact = TRUE;
  444. /* round result */
  445. switch (Rounding_mode()) {
  446. case ROUNDPLUS:
  447. if (Dbl_iszero_sign(srcp1)) {
  448. Dint_increment(resultp1,resultp2);
  449. }
  450. break;
  451. case ROUNDMINUS:
  452. if (Dbl_isone_sign(srcp1)) {
  453. Dint_decrement(resultp1,resultp2);
  454. }
  455. break;
  456. case ROUNDNEAREST:
  457. if (src_exponent == -1)
  458. if (Dbl_isnotzero_mantissa(srcp1,srcp2))
  459. if (Dbl_iszero_sign(srcp1)) {
  460. Dint_increment(resultp1,resultp2);
  461. }
  462. else {
  463. Dint_decrement(resultp1,resultp2);
  464. }
  465. }
  466. }
  467. }
  468. Dint_copytoptr(resultp1,resultp2,dstptr);
  469. if (inexact) {
  470. if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
  471. else Set_inexactflag();
  472. }
  473. return(NOEXCEPTION);
  474. }