fpu.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /* fpu.c --- FPU emulator for stand-alone RX simulator.
  2. Copyright (C) 2008-2022 Free Software Foundation, Inc.
  3. Contributed by Red Hat, Inc.
  4. This file is part of the GNU simulators.
  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 3 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, see <http://www.gnu.org/licenses/>. */
  15. /* This must come before any other includes. */
  16. #include "defs.h"
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include "cpu.h"
  20. #include "fpu.h"
  21. /* FPU encodings are as follows:
  22. S EXPONENT MANTISSA
  23. 1 12345678 12345678901234567890123
  24. 0 00000000 00000000000000000000000 +0
  25. 1 00000000 00000000000000000000000 -0
  26. X 00000000 00000000000000000000001 Denormals
  27. X 00000000 11111111111111111111111
  28. X 00000001 XXXXXXXXXXXXXXXXXXXXXXX Normals
  29. X 11111110 XXXXXXXXXXXXXXXXXXXXXXX
  30. 0 11111111 00000000000000000000000 +Inf
  31. 1 11111111 00000000000000000000000 -Inf
  32. X 11111111 0XXXXXXXXXXXXXXXXXXXXXX SNaN (X != 0)
  33. X 11111111 1XXXXXXXXXXXXXXXXXXXXXX QNaN (X != 0)
  34. */
  35. #define trace 0
  36. #define tprintf if (trace) printf
  37. /* Some magic numbers. */
  38. #define PLUS_MAX 0x7f7fffffUL
  39. #define MINUS_MAX 0xff7fffffUL
  40. #define PLUS_INF 0x7f800000UL
  41. #define MINUS_INF 0xff800000UL
  42. #define PLUS_ZERO 0x00000000UL
  43. #define MINUS_ZERO 0x80000000UL
  44. #define FP_RAISE(e) fp_raise(FPSWBITS_C##e)
  45. static void
  46. fp_raise (int mask)
  47. {
  48. regs.r_fpsw |= mask;
  49. if (mask != FPSWBITS_CE)
  50. {
  51. if (regs.r_fpsw & (mask << FPSW_CESH))
  52. regs.r_fpsw |= (mask << FPSW_CFSH);
  53. if (regs.r_fpsw & FPSWBITS_FMASK)
  54. regs.r_fpsw |= FPSWBITS_FSUM;
  55. else
  56. regs.r_fpsw &= ~FPSWBITS_FSUM;
  57. }
  58. }
  59. /* We classify all numbers as one of these. They correspond to the
  60. rows/colums in the exception tables. */
  61. typedef enum {
  62. FP_NORMAL,
  63. FP_PZERO,
  64. FP_NZERO,
  65. FP_PINFINITY,
  66. FP_NINFINITY,
  67. FP_DENORMAL,
  68. FP_QNAN,
  69. FP_SNAN
  70. } FP_Type;
  71. #if defined DEBUG0
  72. static const char *fpt_names[] = {
  73. "Normal", "+0", "-0", "+Inf", "-Inf", "Denormal", "QNaN", "SNaN"
  74. };
  75. #endif
  76. #define EXP_BIAS 127
  77. #define EXP_ZERO -127
  78. #define EXP_INF 128
  79. #define MANT_BIAS 0x00080000UL
  80. typedef struct {
  81. int exp;
  82. unsigned int mant; /* 24 bits */
  83. char type;
  84. char sign;
  85. fp_t orig_value;
  86. } FP_Parts;
  87. static void
  88. fp_explode (fp_t f, FP_Parts *p)
  89. {
  90. int exp, mant, sign;
  91. exp = ((f & 0x7f800000UL) >> 23);
  92. mant = f & 0x007fffffUL;
  93. sign = f & 0x80000000UL;
  94. /*printf("explode: %08x %x %2x %6x\n", f, sign, exp, mant);*/
  95. p->sign = sign ? -1 : 1;
  96. p->exp = exp - EXP_BIAS;
  97. p->orig_value = f;
  98. p->mant = mant | 0x00800000UL;
  99. if (p->exp == EXP_ZERO)
  100. {
  101. if (regs.r_fpsw & FPSWBITS_DN)
  102. mant = 0;
  103. if (mant)
  104. p->type = FP_DENORMAL;
  105. else
  106. {
  107. p->mant = 0;
  108. p->type = sign ? FP_NZERO : FP_PZERO;
  109. }
  110. }
  111. else if (p->exp == EXP_INF)
  112. {
  113. if (mant == 0)
  114. p->type = sign ? FP_NINFINITY : FP_PINFINITY;
  115. else if (mant & 0x00400000UL)
  116. p->type = FP_QNAN;
  117. else
  118. p->type = FP_SNAN;
  119. }
  120. else
  121. p->type = FP_NORMAL;
  122. }
  123. static fp_t
  124. fp_implode (FP_Parts *p)
  125. {
  126. int exp, mant;
  127. exp = p->exp + EXP_BIAS;
  128. mant = p->mant;
  129. /*printf("implode: exp %d mant 0x%x\n", exp, mant);*/
  130. if (p->type == FP_NORMAL)
  131. {
  132. while (mant
  133. && exp > 0
  134. && mant < 0x00800000UL)
  135. {
  136. mant <<= 1;
  137. exp --;
  138. }
  139. while (mant > 0x00ffffffUL)
  140. {
  141. mant >>= 1;
  142. exp ++;
  143. }
  144. if (exp < 0)
  145. {
  146. /* underflow */
  147. exp = 0;
  148. mant = 0;
  149. FP_RAISE (E);
  150. }
  151. if (exp >= 255)
  152. {
  153. /* overflow */
  154. exp = 255;
  155. mant = 0;
  156. FP_RAISE (O);
  157. }
  158. }
  159. mant &= 0x007fffffUL;
  160. exp &= 0xff;
  161. mant |= exp << 23;
  162. if (p->sign < 0)
  163. mant |= 0x80000000UL;
  164. return mant;
  165. }
  166. typedef union {
  167. unsigned long long ll;
  168. double d;
  169. } U_d_ll;
  170. static int checked_format = 0;
  171. /* We assume a double format like this:
  172. S[1] E[11] M[52]
  173. */
  174. static double
  175. fp_to_double (FP_Parts *p)
  176. {
  177. U_d_ll u;
  178. if (!checked_format)
  179. {
  180. u.d = 1.5;
  181. if (u.ll != 0x3ff8000000000000ULL)
  182. abort ();
  183. u.d = -225;
  184. if (u.ll != 0xc06c200000000000ULL)
  185. abort ();
  186. u.d = 10.1;
  187. if (u.ll != 0x4024333333333333ULL)
  188. abort ();
  189. checked_format = 1;
  190. }
  191. u.ll = 0;
  192. if (p->sign < 0)
  193. u.ll |= (1ULL << 63);
  194. /* Make sure a zero encoding stays a zero. */
  195. if (p->exp != -EXP_BIAS)
  196. u.ll |= ((unsigned long long)p->exp + 1023ULL) << 52;
  197. u.ll |= (unsigned long long) (p->mant & 0x007fffffUL) << (52 - 23);
  198. return u.d;
  199. }
  200. static void
  201. double_to_fp (double d, FP_Parts *p)
  202. {
  203. int exp;
  204. U_d_ll u;
  205. int sign;
  206. u.d = d;
  207. sign = (u.ll & 0x8000000000000000ULL) ? 1 : 0;
  208. exp = u.ll >> 52;
  209. exp = (exp & 0x7ff);
  210. if (exp == 0)
  211. {
  212. /* A generated denormal should show up as an underflow, not
  213. here. */
  214. if (sign)
  215. fp_explode (MINUS_ZERO, p);
  216. else
  217. fp_explode (PLUS_ZERO, p);
  218. return;
  219. }
  220. exp = exp - 1023;
  221. if ((exp + EXP_BIAS) > 254)
  222. {
  223. FP_RAISE (O);
  224. switch (regs.r_fpsw & FPSWBITS_RM)
  225. {
  226. case FPRM_NEAREST:
  227. if (sign)
  228. fp_explode (MINUS_INF, p);
  229. else
  230. fp_explode (PLUS_INF, p);
  231. break;
  232. case FPRM_ZERO:
  233. if (sign)
  234. fp_explode (MINUS_MAX, p);
  235. else
  236. fp_explode (PLUS_MAX, p);
  237. break;
  238. case FPRM_PINF:
  239. if (sign)
  240. fp_explode (MINUS_MAX, p);
  241. else
  242. fp_explode (PLUS_INF, p);
  243. break;
  244. case FPRM_NINF:
  245. if (sign)
  246. fp_explode (MINUS_INF, p);
  247. else
  248. fp_explode (PLUS_MAX, p);
  249. break;
  250. }
  251. return;
  252. }
  253. if ((exp + EXP_BIAS) < 1)
  254. {
  255. if (sign)
  256. fp_explode (MINUS_ZERO, p);
  257. else
  258. fp_explode (PLUS_ZERO, p);
  259. FP_RAISE (U);
  260. }
  261. p->sign = sign ? -1 : 1;
  262. p->exp = exp;
  263. p->mant = u.ll >> (52-23) & 0x007fffffUL;
  264. p->mant |= 0x00800000UL;
  265. p->type = FP_NORMAL;
  266. if (u.ll & 0x1fffffffULL)
  267. {
  268. switch (regs.r_fpsw & FPSWBITS_RM)
  269. {
  270. case FPRM_NEAREST:
  271. if (u.ll & 0x10000000ULL)
  272. p->mant ++;
  273. break;
  274. case FPRM_ZERO:
  275. break;
  276. case FPRM_PINF:
  277. if (sign == 1)
  278. p->mant ++;
  279. break;
  280. case FPRM_NINF:
  281. if (sign == -1)
  282. p->mant ++;
  283. break;
  284. }
  285. FP_RAISE (X);
  286. }
  287. }
  288. typedef enum {
  289. eNR, /* Use the normal result. */
  290. ePZ, eNZ, /* +- zero */
  291. eSZ, /* signed zero - XOR signs of ops together. */
  292. eRZ, /* +- zero depending on rounding mode. */
  293. ePI, eNI, /* +- Infinity */
  294. eSI, /* signed infinity - XOR signs of ops together. */
  295. eQN, eSN, /* Quiet/Signalling NANs */
  296. eIn, /* Invalid. */
  297. eUn, /* Unimplemented. */
  298. eDZ, /* Divide-by-zero. */
  299. eLT, /* less than */
  300. eGT, /* greater than */
  301. eEQ, /* equal to */
  302. } FP_ExceptionCases;
  303. #if defined DEBUG0
  304. static const char *ex_names[] = {
  305. "NR", "PZ", "NZ", "SZ", "RZ", "PI", "NI", "SI", "QN", "SN", "IN", "Un", "DZ", "LT", "GT", "EQ"
  306. };
  307. #endif
  308. /* This checks for all exceptional cases (not all FP exceptions) and
  309. returns TRUE if it is providing the result in *c. If it returns
  310. FALSE, the caller should do the "normal" operation. */
  311. static int
  312. check_exceptions (FP_Parts *a, FP_Parts *b, fp_t *c,
  313. FP_ExceptionCases ex_tab[5][5],
  314. FP_ExceptionCases *case_ret)
  315. {
  316. FP_ExceptionCases fpec;
  317. if (a->type == FP_SNAN
  318. || b->type == FP_SNAN)
  319. fpec = eIn;
  320. else if (a->type == FP_QNAN
  321. || b->type == FP_QNAN)
  322. fpec = eQN;
  323. else if (a->type == FP_DENORMAL
  324. || b->type == FP_DENORMAL)
  325. fpec = eUn;
  326. else
  327. fpec = ex_tab[(int)(a->type)][(int)(b->type)];
  328. /*printf("%s %s -> %s\n", fpt_names[(int)(a->type)], fpt_names[(int)(b->type)], ex_names[(int)(fpec)]);*/
  329. if (case_ret)
  330. *case_ret = fpec;
  331. switch (fpec)
  332. {
  333. case eNR: /* Use the normal result. */
  334. return 0;
  335. case ePZ: /* + zero */
  336. *c = 0x00000000;
  337. return 1;
  338. case eNZ: /* - zero */
  339. *c = 0x80000000;
  340. return 1;
  341. case eSZ: /* signed zero */
  342. *c = (a->sign == b->sign) ? PLUS_ZERO : MINUS_ZERO;
  343. return 1;
  344. case eRZ: /* +- zero depending on rounding mode. */
  345. if ((regs.r_fpsw & FPSWBITS_RM) == FPRM_NINF)
  346. *c = 0x80000000;
  347. else
  348. *c = 0x00000000;
  349. return 1;
  350. case ePI: /* + Infinity */
  351. *c = 0x7F800000;
  352. return 1;
  353. case eNI: /* - Infinity */
  354. *c = 0xFF800000;
  355. return 1;
  356. case eSI: /* sign Infinity */
  357. *c = (a->sign == b->sign) ? PLUS_INF : MINUS_INF;
  358. return 1;
  359. case eQN: /* Quiet NANs */
  360. if (a->type == FP_QNAN)
  361. *c = a->orig_value;
  362. else
  363. *c = b->orig_value;
  364. return 1;
  365. case eSN: /* Signalling NANs */
  366. if (a->type == FP_SNAN)
  367. *c = a->orig_value;
  368. else
  369. *c = b->orig_value;
  370. FP_RAISE (V);
  371. return 1;
  372. case eIn: /* Invalid. */
  373. FP_RAISE (V);
  374. if (a->type == FP_SNAN)
  375. *c = a->orig_value | 0x00400000;
  376. else if (b->type == FP_SNAN)
  377. *c = b->orig_value | 0x00400000;
  378. else
  379. *c = 0x7fc00000;
  380. return 1;
  381. case eUn: /* Unimplemented. */
  382. FP_RAISE (E);
  383. return 1;
  384. case eDZ: /* Division-by-zero. */
  385. *c = (a->sign == b->sign) ? PLUS_INF : MINUS_INF;
  386. FP_RAISE (Z);
  387. return 1;
  388. default:
  389. return 0;
  390. }
  391. }
  392. #define CHECK_EXCEPTIONS(FPPa, FPPb, fpc, ex_tab) \
  393. if (check_exceptions (&FPPa, &FPPb, &fpc, ex_tab, 0)) \
  394. return fpc;
  395. /* For each operation, we have two tables of how nonnormal cases are
  396. handled. The DN=0 case is first, followed by the DN=1 case, with
  397. each table using the following layout: */
  398. static FP_ExceptionCases ex_add_tab[5][5] = {
  399. /* N +0 -0 +In -In */
  400. { eNR, eNR, eNR, ePI, eNI }, /* Normal */
  401. { eNR, ePZ, eRZ, ePI, eNI }, /* +0 */
  402. { eNR, eRZ, eNZ, ePI, eNI }, /* -0 */
  403. { ePI, ePI, ePI, ePI, eIn }, /* +Inf */
  404. { eNI, eNI, eNI, eIn, eNI }, /* -Inf */
  405. };
  406. fp_t
  407. rxfp_add (fp_t fa, fp_t fb)
  408. {
  409. FP_Parts a, b, c;
  410. fp_t rv;
  411. double da, db;
  412. fp_explode (fa, &a);
  413. fp_explode (fb, &b);
  414. CHECK_EXCEPTIONS (a, b, rv, ex_add_tab);
  415. da = fp_to_double (&a);
  416. db = fp_to_double (&b);
  417. tprintf("%g + %g = %g\n", da, db, da+db);
  418. double_to_fp (da+db, &c);
  419. rv = fp_implode (&c);
  420. return rv;
  421. }
  422. static FP_ExceptionCases ex_sub_tab[5][5] = {
  423. /* N +0 -0 +In -In */
  424. { eNR, eNR, eNR, eNI, ePI }, /* Normal */
  425. { eNR, eRZ, ePZ, eNI, ePI }, /* +0 */
  426. { eNR, eNZ, eRZ, eNI, ePI }, /* -0 */
  427. { ePI, ePI, ePI, eIn, ePI }, /* +Inf */
  428. { eNI, eNI, eNI, eNI, eIn }, /* -Inf */
  429. };
  430. fp_t
  431. rxfp_sub (fp_t fa, fp_t fb)
  432. {
  433. FP_Parts a, b, c;
  434. fp_t rv;
  435. double da, db;
  436. fp_explode (fa, &a);
  437. fp_explode (fb, &b);
  438. CHECK_EXCEPTIONS (a, b, rv, ex_sub_tab);
  439. da = fp_to_double (&a);
  440. db = fp_to_double (&b);
  441. tprintf("%g - %g = %g\n", da, db, da-db);
  442. double_to_fp (da-db, &c);
  443. rv = fp_implode (&c);
  444. return rv;
  445. }
  446. static FP_ExceptionCases ex_mul_tab[5][5] = {
  447. /* N +0 -0 +In -In */
  448. { eNR, eNR, eNR, eSI, eSI }, /* Normal */
  449. { eNR, ePZ, eNZ, eIn, eIn }, /* +0 */
  450. { eNR, eNZ, ePZ, eIn, eIn }, /* -0 */
  451. { eSI, eIn, eIn, ePI, eNI }, /* +Inf */
  452. { eSI, eIn, eIn, eNI, ePI }, /* -Inf */
  453. };
  454. fp_t
  455. rxfp_mul (fp_t fa, fp_t fb)
  456. {
  457. FP_Parts a, b, c;
  458. fp_t rv;
  459. double da, db;
  460. fp_explode (fa, &a);
  461. fp_explode (fb, &b);
  462. CHECK_EXCEPTIONS (a, b, rv, ex_mul_tab);
  463. da = fp_to_double (&a);
  464. db = fp_to_double (&b);
  465. tprintf("%g x %g = %g\n", da, db, da*db);
  466. double_to_fp (da*db, &c);
  467. rv = fp_implode (&c);
  468. return rv;
  469. }
  470. static FP_ExceptionCases ex_div_tab[5][5] = {
  471. /* N +0 -0 +In -In */
  472. { eNR, eDZ, eDZ, eSZ, eSZ }, /* Normal */
  473. { eSZ, eIn, eIn, ePZ, eNZ }, /* +0 */
  474. { eSZ, eIn, eIn, eNZ, ePZ }, /* -0 */
  475. { eSI, ePI, eNI, eIn, eIn }, /* +Inf */
  476. { eSI, eNI, ePI, eIn, eIn }, /* -Inf */
  477. };
  478. fp_t
  479. rxfp_div (fp_t fa, fp_t fb)
  480. {
  481. FP_Parts a, b, c;
  482. fp_t rv;
  483. double da, db;
  484. fp_explode (fa, &a);
  485. fp_explode (fb, &b);
  486. CHECK_EXCEPTIONS (a, b, rv, ex_div_tab);
  487. da = fp_to_double (&a);
  488. db = fp_to_double (&b);
  489. tprintf("%g / %g = %g\n", da, db, da/db);
  490. double_to_fp (da/db, &c);
  491. rv = fp_implode (&c);
  492. return rv;
  493. }
  494. static FP_ExceptionCases ex_cmp_tab[5][5] = {
  495. /* N +0 -0 +In -In */
  496. { eNR, eNR, eNR, eLT, eGT }, /* Normal */
  497. { eNR, eEQ, eEQ, eLT, eGT }, /* +0 */
  498. { eNR, eEQ, eEQ, eLT, eGT }, /* -0 */
  499. { eGT, eGT, eGT, eEQ, eGT }, /* +Inf */
  500. { eLT, eLT, eLT, eLT, eEQ }, /* -Inf */
  501. };
  502. void
  503. rxfp_cmp (fp_t fa, fp_t fb)
  504. {
  505. FP_Parts a, b;
  506. fp_t c;
  507. FP_ExceptionCases reason;
  508. int flags = 0;
  509. double da, db;
  510. fp_explode (fa, &a);
  511. fp_explode (fb, &b);
  512. if (check_exceptions (&a, &b, &c, ex_cmp_tab, &reason))
  513. {
  514. if (reason == eQN)
  515. {
  516. /* Special case - incomparable. */
  517. set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, FLAGBIT_O);
  518. return;
  519. }
  520. return;
  521. }
  522. switch (reason)
  523. {
  524. case eEQ:
  525. flags = FLAGBIT_Z;
  526. break;
  527. case eLT:
  528. flags = FLAGBIT_S;
  529. break;
  530. case eGT:
  531. flags = 0;
  532. break;
  533. case eNR:
  534. da = fp_to_double (&a);
  535. db = fp_to_double (&b);
  536. tprintf("fcmp: %g cmp %g\n", da, db);
  537. if (da < db)
  538. flags = FLAGBIT_S;
  539. else if (da == db)
  540. flags = FLAGBIT_Z;
  541. else
  542. flags = 0;
  543. break;
  544. default:
  545. abort();
  546. }
  547. set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, flags);
  548. }
  549. long
  550. rxfp_ftoi (fp_t fa, int round_mode)
  551. {
  552. FP_Parts a;
  553. fp_t rv;
  554. int sign;
  555. int whole_bits, frac_bits;
  556. fp_explode (fa, &a);
  557. sign = fa & 0x80000000UL;
  558. switch (a.type)
  559. {
  560. case FP_NORMAL:
  561. break;
  562. case FP_PZERO:
  563. case FP_NZERO:
  564. return 0;
  565. case FP_PINFINITY:
  566. FP_RAISE (V);
  567. return 0x7fffffffL;
  568. case FP_NINFINITY:
  569. FP_RAISE (V);
  570. return 0x80000000L;
  571. case FP_DENORMAL:
  572. FP_RAISE (E);
  573. return 0;
  574. case FP_QNAN:
  575. case FP_SNAN:
  576. FP_RAISE (V);
  577. return sign ? 0x80000000U : 0x7fffffff;
  578. }
  579. if (a.exp >= 31)
  580. {
  581. FP_RAISE (V);
  582. return sign ? 0x80000000U : 0x7fffffff;
  583. }
  584. a.exp -= 23;
  585. if (a.exp <= -25)
  586. {
  587. /* Less than 0.49999 */
  588. frac_bits = a.mant;
  589. whole_bits = 0;
  590. }
  591. else if (a.exp < 0)
  592. {
  593. frac_bits = a.mant << (32 + a.exp);
  594. whole_bits = a.mant >> (-a.exp);
  595. }
  596. else
  597. {
  598. frac_bits = 0;
  599. whole_bits = a.mant << a.exp;
  600. }
  601. if (frac_bits)
  602. {
  603. switch (round_mode & 3)
  604. {
  605. case FPRM_NEAREST:
  606. if (frac_bits & 0x80000000UL)
  607. whole_bits ++;
  608. break;
  609. case FPRM_ZERO:
  610. break;
  611. case FPRM_PINF:
  612. if (!sign)
  613. whole_bits ++;
  614. break;
  615. case FPRM_NINF:
  616. if (sign)
  617. whole_bits ++;
  618. break;
  619. }
  620. }
  621. rv = sign ? -whole_bits : whole_bits;
  622. return rv;
  623. }
  624. fp_t
  625. rxfp_itof (long fa, int round_mode)
  626. {
  627. fp_t rv;
  628. int sign = 0;
  629. unsigned int frac_bits;
  630. volatile unsigned int whole_bits;
  631. FP_Parts a = {0};
  632. if (fa == 0)
  633. return PLUS_ZERO;
  634. if (fa < 0)
  635. {
  636. fa = -fa;
  637. sign = 1;
  638. a.sign = -1;
  639. }
  640. else
  641. a.sign = 1;
  642. whole_bits = fa;
  643. a.exp = 31;
  644. while (! (whole_bits & 0x80000000UL))
  645. {
  646. a.exp --;
  647. whole_bits <<= 1;
  648. }
  649. frac_bits = whole_bits & 0xff;
  650. whole_bits = whole_bits >> 8;
  651. if (frac_bits)
  652. {
  653. /* We must round */
  654. switch (round_mode & 3)
  655. {
  656. case FPRM_NEAREST:
  657. if (frac_bits & 0x80)
  658. whole_bits ++;
  659. break;
  660. case FPRM_ZERO:
  661. break;
  662. case FPRM_PINF:
  663. if (!sign)
  664. whole_bits ++;
  665. break;
  666. case FPRM_NINF:
  667. if (sign)
  668. whole_bits ++;
  669. break;
  670. }
  671. }
  672. a.mant = whole_bits;
  673. if (whole_bits & 0xff000000UL)
  674. {
  675. a.mant >>= 1;
  676. a.exp ++;
  677. }
  678. rv = fp_implode (&a);
  679. return rv;
  680. }