op-common.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. /* Software floating-point emulation. Common operations.
  2. Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Richard Henderson (rth@cygnus.com),
  5. Jakub Jelinek (jj@ultra.linux.cz),
  6. David S. Miller (davem@redhat.com) and
  7. Peter Maydell (pmaydell@chiark.greenend.org.uk).
  8. The GNU C Library is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU Library General Public License as
  10. published by the Free Software Foundation; either version 2 of the
  11. License, or (at your option) any later version.
  12. The GNU C Library 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 GNU
  15. Library General Public License for more details.
  16. You should have received a copy of the GNU Library General Public
  17. License along with the GNU C Library; see the file COPYING.LIB. If
  18. not, write to the Free Software Foundation, Inc.,
  19. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  20. #ifndef __MATH_EMU_OP_COMMON_H__
  21. #define __MATH_EMU_OP_COMMON_H__
  22. #define _FP_DECL(wc, X) \
  23. _FP_I_TYPE X##_c=0, X##_s=0, X##_e=0; \
  24. _FP_FRAC_DECL_##wc(X)
  25. /*
  26. * Finish truly unpacking a native fp value by classifying the kind
  27. * of fp value and normalizing both the exponent and the fraction.
  28. */
  29. #define _FP_UNPACK_CANONICAL(fs, wc, X) \
  30. do { \
  31. switch (X##_e) \
  32. { \
  33. default: \
  34. _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
  35. _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
  36. X##_e -= _FP_EXPBIAS_##fs; \
  37. X##_c = FP_CLS_NORMAL; \
  38. break; \
  39. \
  40. case 0: \
  41. if (_FP_FRAC_ZEROP_##wc(X)) \
  42. X##_c = FP_CLS_ZERO; \
  43. else \
  44. { \
  45. /* a denormalized number */ \
  46. _FP_I_TYPE _shift; \
  47. _FP_FRAC_CLZ_##wc(_shift, X); \
  48. _shift -= _FP_FRACXBITS_##fs; \
  49. _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
  50. X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
  51. X##_c = FP_CLS_NORMAL; \
  52. FP_SET_EXCEPTION(FP_EX_DENORM); \
  53. if (FP_DENORM_ZERO) \
  54. { \
  55. FP_SET_EXCEPTION(FP_EX_INEXACT); \
  56. X##_c = FP_CLS_ZERO; \
  57. } \
  58. } \
  59. break; \
  60. \
  61. case _FP_EXPMAX_##fs: \
  62. if (_FP_FRAC_ZEROP_##wc(X)) \
  63. X##_c = FP_CLS_INF; \
  64. else \
  65. { \
  66. X##_c = FP_CLS_NAN; \
  67. /* Check for signaling NaN */ \
  68. if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
  69. FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_SNAN); \
  70. } \
  71. break; \
  72. } \
  73. } while (0)
  74. /*
  75. * Before packing the bits back into the native fp result, take care
  76. * of such mundane things as rounding and overflow. Also, for some
  77. * kinds of fp values, the original parts may not have been fully
  78. * extracted -- but that is ok, we can regenerate them now.
  79. */
  80. #define _FP_PACK_CANONICAL(fs, wc, X) \
  81. do { \
  82. switch (X##_c) \
  83. { \
  84. case FP_CLS_NORMAL: \
  85. X##_e += _FP_EXPBIAS_##fs; \
  86. if (X##_e > 0) \
  87. { \
  88. _FP_ROUND(wc, X); \
  89. if (_FP_FRAC_OVERP_##wc(fs, X)) \
  90. { \
  91. _FP_FRAC_CLEAR_OVERP_##wc(fs, X); \
  92. X##_e++; \
  93. } \
  94. _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
  95. if (X##_e >= _FP_EXPMAX_##fs) \
  96. { \
  97. /* overflow */ \
  98. switch (FP_ROUNDMODE) \
  99. { \
  100. case FP_RND_NEAREST: \
  101. X##_c = FP_CLS_INF; \
  102. break; \
  103. case FP_RND_PINF: \
  104. if (!X##_s) X##_c = FP_CLS_INF; \
  105. break; \
  106. case FP_RND_MINF: \
  107. if (X##_s) X##_c = FP_CLS_INF; \
  108. break; \
  109. } \
  110. if (X##_c == FP_CLS_INF) \
  111. { \
  112. /* Overflow to infinity */ \
  113. X##_e = _FP_EXPMAX_##fs; \
  114. _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
  115. } \
  116. else \
  117. { \
  118. /* Overflow to maximum normal */ \
  119. X##_e = _FP_EXPMAX_##fs - 1; \
  120. _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
  121. } \
  122. FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
  123. FP_SET_EXCEPTION(FP_EX_INEXACT); \
  124. } \
  125. } \
  126. else \
  127. { \
  128. /* we've got a denormalized number */ \
  129. X##_e = -X##_e + 1; \
  130. if (X##_e <= _FP_WFRACBITS_##fs) \
  131. { \
  132. _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
  133. if (_FP_FRAC_HIGH_##fs(X) \
  134. & (_FP_OVERFLOW_##fs >> 1)) \
  135. { \
  136. X##_e = 1; \
  137. _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
  138. } \
  139. else \
  140. { \
  141. _FP_ROUND(wc, X); \
  142. if (_FP_FRAC_HIGH_##fs(X) \
  143. & (_FP_OVERFLOW_##fs >> 1)) \
  144. { \
  145. X##_e = 1; \
  146. _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
  147. FP_SET_EXCEPTION(FP_EX_INEXACT); \
  148. } \
  149. else \
  150. { \
  151. X##_e = 0; \
  152. _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
  153. } \
  154. } \
  155. if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \
  156. (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
  157. FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
  158. } \
  159. else \
  160. { \
  161. /* underflow to zero */ \
  162. X##_e = 0; \
  163. if (!_FP_FRAC_ZEROP_##wc(X)) \
  164. { \
  165. _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
  166. _FP_ROUND(wc, X); \
  167. _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \
  168. } \
  169. FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
  170. } \
  171. } \
  172. break; \
  173. \
  174. case FP_CLS_ZERO: \
  175. X##_e = 0; \
  176. _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
  177. break; \
  178. \
  179. case FP_CLS_INF: \
  180. X##_e = _FP_EXPMAX_##fs; \
  181. _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
  182. break; \
  183. \
  184. case FP_CLS_NAN: \
  185. X##_e = _FP_EXPMAX_##fs; \
  186. if (!_FP_KEEPNANFRACP) \
  187. { \
  188. _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
  189. X##_s = _FP_NANSIGN_##fs; \
  190. } \
  191. else \
  192. _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
  193. break; \
  194. } \
  195. } while (0)
  196. /* This one accepts raw argument and not cooked, returns
  197. * 1 if X is a signaling NaN.
  198. */
  199. #define _FP_ISSIGNAN(fs, wc, X) \
  200. ({ \
  201. int __ret = 0; \
  202. if (X##_e == _FP_EXPMAX_##fs) \
  203. { \
  204. if (!_FP_FRAC_ZEROP_##wc(X) \
  205. && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
  206. __ret = 1; \
  207. } \
  208. __ret; \
  209. })
  210. /*
  211. * Main addition routine. The input values should be cooked.
  212. */
  213. #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
  214. do { \
  215. switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
  216. { \
  217. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
  218. { \
  219. /* shift the smaller number so that its exponent matches the larger */ \
  220. _FP_I_TYPE diff = X##_e - Y##_e; \
  221. \
  222. if (diff < 0) \
  223. { \
  224. diff = -diff; \
  225. if (diff <= _FP_WFRACBITS_##fs) \
  226. _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \
  227. else if (!_FP_FRAC_ZEROP_##wc(X)) \
  228. _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
  229. R##_e = Y##_e; \
  230. } \
  231. else \
  232. { \
  233. if (diff > 0) \
  234. { \
  235. if (diff <= _FP_WFRACBITS_##fs) \
  236. _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \
  237. else if (!_FP_FRAC_ZEROP_##wc(Y)) \
  238. _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
  239. } \
  240. R##_e = X##_e; \
  241. } \
  242. \
  243. R##_c = FP_CLS_NORMAL; \
  244. \
  245. if (X##_s == Y##_s) \
  246. { \
  247. R##_s = X##_s; \
  248. _FP_FRAC_ADD_##wc(R, X, Y); \
  249. if (_FP_FRAC_OVERP_##wc(fs, R)) \
  250. { \
  251. _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
  252. R##_e++; \
  253. } \
  254. } \
  255. else \
  256. { \
  257. R##_s = X##_s; \
  258. _FP_FRAC_SUB_##wc(R, X, Y); \
  259. if (_FP_FRAC_ZEROP_##wc(R)) \
  260. { \
  261. /* return an exact zero */ \
  262. if (FP_ROUNDMODE == FP_RND_MINF) \
  263. R##_s |= Y##_s; \
  264. else \
  265. R##_s &= Y##_s; \
  266. R##_c = FP_CLS_ZERO; \
  267. } \
  268. else \
  269. { \
  270. if (_FP_FRAC_NEGP_##wc(R)) \
  271. { \
  272. _FP_FRAC_SUB_##wc(R, Y, X); \
  273. R##_s = Y##_s; \
  274. } \
  275. \
  276. /* renormalize after subtraction */ \
  277. _FP_FRAC_CLZ_##wc(diff, R); \
  278. diff -= _FP_WFRACXBITS_##fs; \
  279. if (diff) \
  280. { \
  281. R##_e -= diff; \
  282. _FP_FRAC_SLL_##wc(R, diff); \
  283. } \
  284. } \
  285. } \
  286. break; \
  287. } \
  288. \
  289. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
  290. _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \
  291. break; \
  292. \
  293. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
  294. R##_e = X##_e; \
  295. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
  296. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
  297. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
  298. _FP_FRAC_COPY_##wc(R, X); \
  299. R##_s = X##_s; \
  300. R##_c = X##_c; \
  301. break; \
  302. \
  303. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
  304. R##_e = Y##_e; \
  305. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
  306. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
  307. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
  308. _FP_FRAC_COPY_##wc(R, Y); \
  309. R##_s = Y##_s; \
  310. R##_c = Y##_c; \
  311. break; \
  312. \
  313. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
  314. if (X##_s != Y##_s) \
  315. { \
  316. /* +INF + -INF => NAN */ \
  317. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  318. R##_s = _FP_NANSIGN_##fs; \
  319. R##_c = FP_CLS_NAN; \
  320. FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI); \
  321. break; \
  322. } \
  323. /* FALLTHRU */ \
  324. \
  325. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
  326. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
  327. R##_s = X##_s; \
  328. R##_c = FP_CLS_INF; \
  329. break; \
  330. \
  331. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
  332. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
  333. R##_s = Y##_s; \
  334. R##_c = FP_CLS_INF; \
  335. break; \
  336. \
  337. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
  338. /* make sure the sign is correct */ \
  339. if (FP_ROUNDMODE == FP_RND_MINF) \
  340. R##_s = X##_s | Y##_s; \
  341. else \
  342. R##_s = X##_s & Y##_s; \
  343. R##_c = FP_CLS_ZERO; \
  344. break; \
  345. \
  346. default: \
  347. abort(); \
  348. } \
  349. } while (0)
  350. #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
  351. #define _FP_SUB(fs, wc, R, X, Y) \
  352. do { \
  353. if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \
  354. _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
  355. } while (0)
  356. /*
  357. * Main negation routine. FIXME -- when we care about setting exception
  358. * bits reliably, this will not do. We should examine all of the fp classes.
  359. */
  360. #define _FP_NEG(fs, wc, R, X) \
  361. do { \
  362. _FP_FRAC_COPY_##wc(R, X); \
  363. R##_c = X##_c; \
  364. R##_e = X##_e; \
  365. R##_s = 1 ^ X##_s; \
  366. } while (0)
  367. /*
  368. * Main multiplication routine. The input values should be cooked.
  369. */
  370. #define _FP_MUL(fs, wc, R, X, Y) \
  371. do { \
  372. R##_s = X##_s ^ Y##_s; \
  373. switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
  374. { \
  375. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
  376. R##_c = FP_CLS_NORMAL; \
  377. R##_e = X##_e + Y##_e + 1; \
  378. \
  379. _FP_MUL_MEAT_##fs(R,X,Y); \
  380. \
  381. if (_FP_FRAC_OVERP_##wc(fs, R)) \
  382. _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
  383. else \
  384. R##_e--; \
  385. break; \
  386. \
  387. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
  388. _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
  389. break; \
  390. \
  391. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
  392. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
  393. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
  394. R##_s = X##_s; \
  395. \
  396. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
  397. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
  398. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
  399. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
  400. _FP_FRAC_COPY_##wc(R, X); \
  401. R##_c = X##_c; \
  402. break; \
  403. \
  404. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
  405. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
  406. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
  407. R##_s = Y##_s; \
  408. \
  409. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
  410. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
  411. _FP_FRAC_COPY_##wc(R, Y); \
  412. R##_c = Y##_c; \
  413. break; \
  414. \
  415. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
  416. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
  417. R##_s = _FP_NANSIGN_##fs; \
  418. R##_c = FP_CLS_NAN; \
  419. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  420. FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\
  421. break; \
  422. \
  423. default: \
  424. abort(); \
  425. } \
  426. } while (0)
  427. /*
  428. * Main division routine. The input values should be cooked.
  429. */
  430. #define _FP_DIV(fs, wc, R, X, Y) \
  431. do { \
  432. R##_s = X##_s ^ Y##_s; \
  433. switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
  434. { \
  435. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
  436. R##_c = FP_CLS_NORMAL; \
  437. R##_e = X##_e - Y##_e; \
  438. \
  439. _FP_DIV_MEAT_##fs(R,X,Y); \
  440. break; \
  441. \
  442. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
  443. _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
  444. break; \
  445. \
  446. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
  447. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
  448. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
  449. R##_s = X##_s; \
  450. _FP_FRAC_COPY_##wc(R, X); \
  451. R##_c = X##_c; \
  452. break; \
  453. \
  454. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
  455. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
  456. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
  457. R##_s = Y##_s; \
  458. _FP_FRAC_COPY_##wc(R, Y); \
  459. R##_c = Y##_c; \
  460. break; \
  461. \
  462. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
  463. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
  464. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
  465. R##_c = FP_CLS_ZERO; \
  466. break; \
  467. \
  468. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
  469. FP_SET_EXCEPTION(FP_EX_DIVZERO); \
  470. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
  471. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
  472. R##_c = FP_CLS_INF; \
  473. break; \
  474. \
  475. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
  476. R##_s = _FP_NANSIGN_##fs; \
  477. R##_c = FP_CLS_NAN; \
  478. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  479. FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\
  480. break; \
  481. \
  482. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
  483. R##_s = _FP_NANSIGN_##fs; \
  484. R##_c = FP_CLS_NAN; \
  485. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  486. FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\
  487. break; \
  488. \
  489. default: \
  490. abort(); \
  491. } \
  492. } while (0)
  493. /*
  494. * Main differential comparison routine. The inputs should be raw not
  495. * cooked. The return is -1,0,1 for normal values, 2 otherwise.
  496. */
  497. #define _FP_CMP(fs, wc, ret, X, Y, un) \
  498. do { \
  499. /* NANs are unordered */ \
  500. if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
  501. || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
  502. { \
  503. ret = un; \
  504. } \
  505. else \
  506. { \
  507. int __is_zero_x; \
  508. int __is_zero_y; \
  509. \
  510. __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
  511. __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
  512. \
  513. if (__is_zero_x && __is_zero_y) \
  514. ret = 0; \
  515. else if (__is_zero_x) \
  516. ret = Y##_s ? 1 : -1; \
  517. else if (__is_zero_y) \
  518. ret = X##_s ? -1 : 1; \
  519. else if (X##_s != Y##_s) \
  520. ret = X##_s ? -1 : 1; \
  521. else if (X##_e > Y##_e) \
  522. ret = X##_s ? -1 : 1; \
  523. else if (X##_e < Y##_e) \
  524. ret = X##_s ? 1 : -1; \
  525. else if (_FP_FRAC_GT_##wc(X, Y)) \
  526. ret = X##_s ? -1 : 1; \
  527. else if (_FP_FRAC_GT_##wc(Y, X)) \
  528. ret = X##_s ? 1 : -1; \
  529. else \
  530. ret = 0; \
  531. } \
  532. } while (0)
  533. /* Simplification for strict equality. */
  534. #define _FP_CMP_EQ(fs, wc, ret, X, Y) \
  535. do { \
  536. /* NANs are unordered */ \
  537. if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
  538. || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
  539. { \
  540. ret = 1; \
  541. } \
  542. else \
  543. { \
  544. ret = !(X##_e == Y##_e \
  545. && _FP_FRAC_EQ_##wc(X, Y) \
  546. && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
  547. } \
  548. } while (0)
  549. /*
  550. * Main square root routine. The input value should be cooked.
  551. */
  552. #define _FP_SQRT(fs, wc, R, X) \
  553. do { \
  554. _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
  555. _FP_W_TYPE q; \
  556. switch (X##_c) \
  557. { \
  558. case FP_CLS_NAN: \
  559. _FP_FRAC_COPY_##wc(R, X); \
  560. R##_s = X##_s; \
  561. R##_c = FP_CLS_NAN; \
  562. break; \
  563. case FP_CLS_INF: \
  564. if (X##_s) \
  565. { \
  566. R##_s = _FP_NANSIGN_##fs; \
  567. R##_c = FP_CLS_NAN; /* NAN */ \
  568. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  569. FP_SET_EXCEPTION(FP_EX_INVALID); \
  570. } \
  571. else \
  572. { \
  573. R##_s = 0; \
  574. R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
  575. } \
  576. break; \
  577. case FP_CLS_ZERO: \
  578. R##_s = X##_s; \
  579. R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
  580. break; \
  581. case FP_CLS_NORMAL: \
  582. R##_s = 0; \
  583. if (X##_s) \
  584. { \
  585. R##_c = FP_CLS_NAN; /* sNAN */ \
  586. R##_s = _FP_NANSIGN_##fs; \
  587. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  588. FP_SET_EXCEPTION(FP_EX_INVALID); \
  589. break; \
  590. } \
  591. R##_c = FP_CLS_NORMAL; \
  592. if (X##_e & 1) \
  593. _FP_FRAC_SLL_##wc(X, 1); \
  594. R##_e = X##_e >> 1; \
  595. _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
  596. _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
  597. q = _FP_OVERFLOW_##fs >> 1; \
  598. _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
  599. } \
  600. } while (0)
  601. /*
  602. * Convert from FP to integer
  603. */
  604. /* RSIGNED can have following values:
  605. * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
  606. * the result is either 0 or (2^rsize)-1 depending on the sign in such case.
  607. * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
  608. * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
  609. * on the sign in such case.
  610. * 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
  611. * set plus the result is truncated to fit into destination.
  612. * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
  613. * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
  614. * on the sign in such case.
  615. */
  616. #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
  617. do { \
  618. switch (X##_c) \
  619. { \
  620. case FP_CLS_NORMAL: \
  621. if (X##_e < 0) \
  622. { \
  623. FP_SET_EXCEPTION(FP_EX_INEXACT); \
  624. case FP_CLS_ZERO: \
  625. r = 0; \
  626. } \
  627. else if (X##_e >= rsize - (rsigned > 0 || X##_s) \
  628. || (!rsigned && X##_s)) \
  629. { /* overflow */ \
  630. case FP_CLS_NAN: \
  631. case FP_CLS_INF: \
  632. if (rsigned == 2) \
  633. { \
  634. if (X##_c != FP_CLS_NORMAL \
  635. || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs) \
  636. r = 0; \
  637. else \
  638. { \
  639. _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
  640. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  641. } \
  642. } \
  643. else if (rsigned) \
  644. { \
  645. r = 1; \
  646. r <<= rsize - 1; \
  647. r -= 1 - X##_s; \
  648. } \
  649. else \
  650. { \
  651. r = 0; \
  652. if (X##_s) \
  653. r = ~r; \
  654. } \
  655. FP_SET_EXCEPTION(FP_EX_INVALID); \
  656. } \
  657. else \
  658. { \
  659. if (_FP_W_TYPE_SIZE*wc < rsize) \
  660. { \
  661. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  662. r <<= X##_e - _FP_WFRACBITS_##fs; \
  663. } \
  664. else \
  665. { \
  666. if (X##_e >= _FP_WFRACBITS_##fs) \
  667. _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
  668. else if (X##_e < _FP_WFRACBITS_##fs - 1) \
  669. { \
  670. _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \
  671. _FP_WFRACBITS_##fs); \
  672. if (_FP_FRAC_LOW_##wc(X) & 1) \
  673. FP_SET_EXCEPTION(FP_EX_INEXACT); \
  674. _FP_FRAC_SRL_##wc(X, 1); \
  675. } \
  676. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  677. } \
  678. if (rsigned && X##_s) \
  679. r = -r; \
  680. } \
  681. break; \
  682. } \
  683. } while (0)
  684. #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \
  685. do { \
  686. r = 0; \
  687. switch (X##_c) \
  688. { \
  689. case FP_CLS_NORMAL: \
  690. if (X##_e >= _FP_FRACBITS_##fs - 1) \
  691. { \
  692. if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs) \
  693. { \
  694. if (X##_e >= _FP_WFRACBITS_##fs - 1) \
  695. { \
  696. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  697. r <<= X##_e - _FP_WFRACBITS_##fs + 1; \
  698. } \
  699. else \
  700. { \
  701. _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e \
  702. + _FP_FRACBITS_##fs - 1); \
  703. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  704. } \
  705. } \
  706. } \
  707. else \
  708. { \
  709. if (X##_e <= -_FP_WORKBITS - 1) \
  710. _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
  711. else \
  712. _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e, \
  713. _FP_WFRACBITS_##fs); \
  714. _FP_ROUND(wc, X); \
  715. _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
  716. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  717. } \
  718. if (rsigned && X##_s) \
  719. r = -r; \
  720. if (X##_e >= rsize - (rsigned > 0 || X##_s) \
  721. || (!rsigned && X##_s)) \
  722. { /* overflow */ \
  723. case FP_CLS_NAN: \
  724. case FP_CLS_INF: \
  725. if (!rsigned) \
  726. { \
  727. r = 0; \
  728. if (X##_s) \
  729. r = ~r; \
  730. } \
  731. else if (rsigned != 2) \
  732. { \
  733. r = 1; \
  734. r <<= rsize - 1; \
  735. r -= 1 - X##_s; \
  736. } \
  737. FP_SET_EXCEPTION(FP_EX_INVALID); \
  738. } \
  739. break; \
  740. case FP_CLS_ZERO: \
  741. break; \
  742. } \
  743. } while (0)
  744. #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
  745. do { \
  746. if (r) \
  747. { \
  748. unsigned rtype ur_; \
  749. X##_c = FP_CLS_NORMAL; \
  750. \
  751. if ((X##_s = (r < 0))) \
  752. ur_ = (unsigned rtype) -r; \
  753. else \
  754. ur_ = (unsigned rtype) r; \
  755. if (rsize <= _FP_W_TYPE_SIZE) \
  756. __FP_CLZ(X##_e, ur_); \
  757. else \
  758. __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
  759. (_FP_W_TYPE)ur_); \
  760. if (rsize < _FP_W_TYPE_SIZE) \
  761. X##_e -= (_FP_W_TYPE_SIZE - rsize); \
  762. X##_e = rsize - X##_e - 1; \
  763. \
  764. if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e) \
  765. __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
  766. _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
  767. if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0) \
  768. _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
  769. } \
  770. else \
  771. { \
  772. X##_c = FP_CLS_ZERO, X##_s = 0; \
  773. } \
  774. } while (0)
  775. #define FP_CONV(dfs,sfs,dwc,swc,D,S) \
  776. do { \
  777. _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
  778. D##_e = S##_e; \
  779. D##_c = S##_c; \
  780. D##_s = S##_s; \
  781. } while (0)
  782. /*
  783. * Helper primitives.
  784. */
  785. /* Count leading zeros in a word. */
  786. #ifndef __FP_CLZ
  787. #if _FP_W_TYPE_SIZE < 64
  788. /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
  789. #define __FP_CLZ(r, x) \
  790. do { \
  791. _FP_W_TYPE _t = (x); \
  792. r = _FP_W_TYPE_SIZE - 1; \
  793. if (_t > 0xffff) r -= 16; \
  794. if (_t > 0xffff) _t >>= 16; \
  795. if (_t > 0xff) r -= 8; \
  796. if (_t > 0xff) _t >>= 8; \
  797. if (_t & 0xf0) r -= 4; \
  798. if (_t & 0xf0) _t >>= 4; \
  799. if (_t & 0xc) r -= 2; \
  800. if (_t & 0xc) _t >>= 2; \
  801. if (_t & 0x2) r -= 1; \
  802. } while (0)
  803. #else /* not _FP_W_TYPE_SIZE < 64 */
  804. #define __FP_CLZ(r, x) \
  805. do { \
  806. _FP_W_TYPE _t = (x); \
  807. r = _FP_W_TYPE_SIZE - 1; \
  808. if (_t > 0xffffffff) r -= 32; \
  809. if (_t > 0xffffffff) _t >>= 32; \
  810. if (_t > 0xffff) r -= 16; \
  811. if (_t > 0xffff) _t >>= 16; \
  812. if (_t > 0xff) r -= 8; \
  813. if (_t > 0xff) _t >>= 8; \
  814. if (_t & 0xf0) r -= 4; \
  815. if (_t & 0xf0) _t >>= 4; \
  816. if (_t & 0xc) r -= 2; \
  817. if (_t & 0xc) _t >>= 2; \
  818. if (_t & 0x2) r -= 1; \
  819. } while (0)
  820. #endif /* not _FP_W_TYPE_SIZE < 64 */
  821. #endif /* ndef __FP_CLZ */
  822. #define _FP_DIV_HELP_imm(q, r, n, d) \
  823. do { \
  824. q = n / d, r = n % d; \
  825. } while (0)
  826. #endif /* __MATH_EMU_OP_COMMON_H__ */