op-common.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  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 truely 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); \
  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. _FP_ROUND(wc, X); \
  134. if (_FP_FRAC_HIGH_##fs(X) \
  135. & (_FP_OVERFLOW_##fs >> 1)) \
  136. { \
  137. X##_e = 1; \
  138. _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
  139. FP_SET_EXCEPTION(FP_EX_INEXACT); \
  140. } \
  141. else \
  142. { \
  143. X##_e = 0; \
  144. _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
  145. } \
  146. if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \
  147. (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
  148. FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
  149. } \
  150. else \
  151. { \
  152. /* underflow to zero */ \
  153. X##_e = 0; \
  154. if (!_FP_FRAC_ZEROP_##wc(X)) \
  155. { \
  156. _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
  157. _FP_ROUND(wc, X); \
  158. _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \
  159. } \
  160. FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
  161. } \
  162. } \
  163. break; \
  164. \
  165. case FP_CLS_ZERO: \
  166. X##_e = 0; \
  167. _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
  168. break; \
  169. \
  170. case FP_CLS_INF: \
  171. X##_e = _FP_EXPMAX_##fs; \
  172. _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
  173. break; \
  174. \
  175. case FP_CLS_NAN: \
  176. X##_e = _FP_EXPMAX_##fs; \
  177. if (!_FP_KEEPNANFRACP) \
  178. { \
  179. _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
  180. X##_s = _FP_NANSIGN_##fs; \
  181. } \
  182. else \
  183. _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
  184. break; \
  185. } \
  186. } while (0)
  187. /* This one accepts raw argument and not cooked, returns
  188. * 1 if X is a signaling NaN.
  189. */
  190. #define _FP_ISSIGNAN(fs, wc, X) \
  191. ({ \
  192. int __ret = 0; \
  193. if (X##_e == _FP_EXPMAX_##fs) \
  194. { \
  195. if (!_FP_FRAC_ZEROP_##wc(X) \
  196. && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
  197. __ret = 1; \
  198. } \
  199. __ret; \
  200. })
  201. /*
  202. * Main addition routine. The input values should be cooked.
  203. */
  204. #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
  205. do { \
  206. switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
  207. { \
  208. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
  209. { \
  210. /* shift the smaller number so that its exponent matches the larger */ \
  211. _FP_I_TYPE diff = X##_e - Y##_e; \
  212. \
  213. if (diff < 0) \
  214. { \
  215. diff = -diff; \
  216. if (diff <= _FP_WFRACBITS_##fs) \
  217. _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \
  218. else if (!_FP_FRAC_ZEROP_##wc(X)) \
  219. _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
  220. R##_e = Y##_e; \
  221. } \
  222. else \
  223. { \
  224. if (diff > 0) \
  225. { \
  226. if (diff <= _FP_WFRACBITS_##fs) \
  227. _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \
  228. else if (!_FP_FRAC_ZEROP_##wc(Y)) \
  229. _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
  230. } \
  231. R##_e = X##_e; \
  232. } \
  233. \
  234. R##_c = FP_CLS_NORMAL; \
  235. \
  236. if (X##_s == Y##_s) \
  237. { \
  238. R##_s = X##_s; \
  239. _FP_FRAC_ADD_##wc(R, X, Y); \
  240. if (_FP_FRAC_OVERP_##wc(fs, R)) \
  241. { \
  242. _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
  243. R##_e++; \
  244. } \
  245. } \
  246. else \
  247. { \
  248. R##_s = X##_s; \
  249. _FP_FRAC_SUB_##wc(R, X, Y); \
  250. if (_FP_FRAC_ZEROP_##wc(R)) \
  251. { \
  252. /* return an exact zero */ \
  253. if (FP_ROUNDMODE == FP_RND_MINF) \
  254. R##_s |= Y##_s; \
  255. else \
  256. R##_s &= Y##_s; \
  257. R##_c = FP_CLS_ZERO; \
  258. } \
  259. else \
  260. { \
  261. if (_FP_FRAC_NEGP_##wc(R)) \
  262. { \
  263. _FP_FRAC_SUB_##wc(R, Y, X); \
  264. R##_s = Y##_s; \
  265. } \
  266. \
  267. /* renormalize after subtraction */ \
  268. _FP_FRAC_CLZ_##wc(diff, R); \
  269. diff -= _FP_WFRACXBITS_##fs; \
  270. if (diff) \
  271. { \
  272. R##_e -= diff; \
  273. _FP_FRAC_SLL_##wc(R, diff); \
  274. } \
  275. } \
  276. } \
  277. break; \
  278. } \
  279. \
  280. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
  281. _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \
  282. break; \
  283. \
  284. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
  285. R##_e = X##_e; \
  286. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
  287. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
  288. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
  289. _FP_FRAC_COPY_##wc(R, X); \
  290. R##_s = X##_s; \
  291. R##_c = X##_c; \
  292. break; \
  293. \
  294. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
  295. R##_e = Y##_e; \
  296. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
  297. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
  298. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
  299. _FP_FRAC_COPY_##wc(R, Y); \
  300. R##_s = Y##_s; \
  301. R##_c = Y##_c; \
  302. break; \
  303. \
  304. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
  305. if (X##_s != Y##_s) \
  306. { \
  307. /* +INF + -INF => NAN */ \
  308. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  309. R##_s = _FP_NANSIGN_##fs; \
  310. R##_c = FP_CLS_NAN; \
  311. FP_SET_EXCEPTION(FP_EX_INVALID); \
  312. break; \
  313. } \
  314. /* FALLTHRU */ \
  315. \
  316. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
  317. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
  318. R##_s = X##_s; \
  319. R##_c = FP_CLS_INF; \
  320. break; \
  321. \
  322. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
  323. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
  324. R##_s = Y##_s; \
  325. R##_c = FP_CLS_INF; \
  326. break; \
  327. \
  328. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
  329. /* make sure the sign is correct */ \
  330. if (FP_ROUNDMODE == FP_RND_MINF) \
  331. R##_s = X##_s | Y##_s; \
  332. else \
  333. R##_s = X##_s & Y##_s; \
  334. R##_c = FP_CLS_ZERO; \
  335. break; \
  336. \
  337. default: \
  338. abort(); \
  339. } \
  340. } while (0)
  341. #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
  342. #define _FP_SUB(fs, wc, R, X, Y) \
  343. do { \
  344. if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \
  345. _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
  346. } while (0)
  347. /*
  348. * Main negation routine. FIXME -- when we care about setting exception
  349. * bits reliably, this will not do. We should examine all of the fp classes.
  350. */
  351. #define _FP_NEG(fs, wc, R, X) \
  352. do { \
  353. _FP_FRAC_COPY_##wc(R, X); \
  354. R##_c = X##_c; \
  355. R##_e = X##_e; \
  356. R##_s = 1 ^ X##_s; \
  357. } while (0)
  358. /*
  359. * Main multiplication routine. The input values should be cooked.
  360. */
  361. #define _FP_MUL(fs, wc, R, X, Y) \
  362. do { \
  363. R##_s = X##_s ^ Y##_s; \
  364. switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
  365. { \
  366. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
  367. R##_c = FP_CLS_NORMAL; \
  368. R##_e = X##_e + Y##_e + 1; \
  369. \
  370. _FP_MUL_MEAT_##fs(R,X,Y); \
  371. \
  372. if (_FP_FRAC_OVERP_##wc(fs, R)) \
  373. _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
  374. else \
  375. R##_e--; \
  376. break; \
  377. \
  378. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
  379. _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
  380. break; \
  381. \
  382. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
  383. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
  384. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
  385. R##_s = X##_s; \
  386. \
  387. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
  388. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
  389. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
  390. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
  391. _FP_FRAC_COPY_##wc(R, X); \
  392. R##_c = X##_c; \
  393. break; \
  394. \
  395. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
  396. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
  397. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
  398. R##_s = Y##_s; \
  399. \
  400. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
  401. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
  402. _FP_FRAC_COPY_##wc(R, Y); \
  403. R##_c = Y##_c; \
  404. break; \
  405. \
  406. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
  407. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
  408. R##_s = _FP_NANSIGN_##fs; \
  409. R##_c = FP_CLS_NAN; \
  410. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  411. FP_SET_EXCEPTION(FP_EX_INVALID); \
  412. break; \
  413. \
  414. default: \
  415. abort(); \
  416. } \
  417. } while (0)
  418. /*
  419. * Main division routine. The input values should be cooked.
  420. */
  421. #define _FP_DIV(fs, wc, R, X, Y) \
  422. do { \
  423. R##_s = X##_s ^ Y##_s; \
  424. switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
  425. { \
  426. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
  427. R##_c = FP_CLS_NORMAL; \
  428. R##_e = X##_e - Y##_e; \
  429. \
  430. _FP_DIV_MEAT_##fs(R,X,Y); \
  431. break; \
  432. \
  433. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
  434. _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
  435. break; \
  436. \
  437. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
  438. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
  439. case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
  440. R##_s = X##_s; \
  441. _FP_FRAC_COPY_##wc(R, X); \
  442. R##_c = X##_c; \
  443. break; \
  444. \
  445. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
  446. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
  447. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
  448. R##_s = Y##_s; \
  449. _FP_FRAC_COPY_##wc(R, Y); \
  450. R##_c = Y##_c; \
  451. break; \
  452. \
  453. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
  454. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
  455. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
  456. R##_c = FP_CLS_ZERO; \
  457. break; \
  458. \
  459. case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
  460. FP_SET_EXCEPTION(FP_EX_DIVZERO); \
  461. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
  462. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
  463. R##_c = FP_CLS_INF; \
  464. break; \
  465. \
  466. case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
  467. case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
  468. R##_s = _FP_NANSIGN_##fs; \
  469. R##_c = FP_CLS_NAN; \
  470. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  471. FP_SET_EXCEPTION(FP_EX_INVALID); \
  472. break; \
  473. \
  474. default: \
  475. abort(); \
  476. } \
  477. } while (0)
  478. /*
  479. * Main differential comparison routine. The inputs should be raw not
  480. * cooked. The return is -1,0,1 for normal values, 2 otherwise.
  481. */
  482. #define _FP_CMP(fs, wc, ret, X, Y, un) \
  483. do { \
  484. /* NANs are unordered */ \
  485. if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
  486. || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
  487. { \
  488. ret = un; \
  489. } \
  490. else \
  491. { \
  492. int __is_zero_x; \
  493. int __is_zero_y; \
  494. \
  495. __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
  496. __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
  497. \
  498. if (__is_zero_x && __is_zero_y) \
  499. ret = 0; \
  500. else if (__is_zero_x) \
  501. ret = Y##_s ? 1 : -1; \
  502. else if (__is_zero_y) \
  503. ret = X##_s ? -1 : 1; \
  504. else if (X##_s != Y##_s) \
  505. ret = X##_s ? -1 : 1; \
  506. else if (X##_e > Y##_e) \
  507. ret = X##_s ? -1 : 1; \
  508. else if (X##_e < Y##_e) \
  509. ret = X##_s ? 1 : -1; \
  510. else if (_FP_FRAC_GT_##wc(X, Y)) \
  511. ret = X##_s ? -1 : 1; \
  512. else if (_FP_FRAC_GT_##wc(Y, X)) \
  513. ret = X##_s ? 1 : -1; \
  514. else \
  515. ret = 0; \
  516. } \
  517. } while (0)
  518. /* Simplification for strict equality. */
  519. #define _FP_CMP_EQ(fs, wc, ret, X, Y) \
  520. do { \
  521. /* NANs are unordered */ \
  522. if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
  523. || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
  524. { \
  525. ret = 1; \
  526. } \
  527. else \
  528. { \
  529. ret = !(X##_e == Y##_e \
  530. && _FP_FRAC_EQ_##wc(X, Y) \
  531. && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
  532. } \
  533. } while (0)
  534. /*
  535. * Main square root routine. The input value should be cooked.
  536. */
  537. #define _FP_SQRT(fs, wc, R, X) \
  538. do { \
  539. _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
  540. _FP_W_TYPE q; \
  541. switch (X##_c) \
  542. { \
  543. case FP_CLS_NAN: \
  544. _FP_FRAC_COPY_##wc(R, X); \
  545. R##_s = X##_s; \
  546. R##_c = FP_CLS_NAN; \
  547. break; \
  548. case FP_CLS_INF: \
  549. if (X##_s) \
  550. { \
  551. R##_s = _FP_NANSIGN_##fs; \
  552. R##_c = FP_CLS_NAN; /* NAN */ \
  553. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  554. FP_SET_EXCEPTION(FP_EX_INVALID); \
  555. } \
  556. else \
  557. { \
  558. R##_s = 0; \
  559. R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
  560. } \
  561. break; \
  562. case FP_CLS_ZERO: \
  563. R##_s = X##_s; \
  564. R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
  565. break; \
  566. case FP_CLS_NORMAL: \
  567. R##_s = 0; \
  568. if (X##_s) \
  569. { \
  570. R##_c = FP_CLS_NAN; /* sNAN */ \
  571. R##_s = _FP_NANSIGN_##fs; \
  572. _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
  573. FP_SET_EXCEPTION(FP_EX_INVALID); \
  574. break; \
  575. } \
  576. R##_c = FP_CLS_NORMAL; \
  577. if (X##_e & 1) \
  578. _FP_FRAC_SLL_##wc(X, 1); \
  579. R##_e = X##_e >> 1; \
  580. _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
  581. _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
  582. q = _FP_OVERFLOW_##fs >> 1; \
  583. _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
  584. } \
  585. } while (0)
  586. /*
  587. * Convert from FP to integer
  588. */
  589. /* RSIGNED can have following values:
  590. * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
  591. * the result is either 0 or (2^rsize)-1 depending on the sign in such case.
  592. * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
  593. * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
  594. * on the sign in such case.
  595. * 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
  596. * set plus the result is truncated to fit into destination.
  597. * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
  598. * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
  599. * on the sign in such case.
  600. */
  601. #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
  602. do { \
  603. switch (X##_c) \
  604. { \
  605. case FP_CLS_NORMAL: \
  606. if (X##_e < 0) \
  607. { \
  608. FP_SET_EXCEPTION(FP_EX_INEXACT); \
  609. case FP_CLS_ZERO: \
  610. r = 0; \
  611. } \
  612. else if (X##_e >= rsize - (rsigned > 0 || X##_s) \
  613. || (!rsigned && X##_s)) \
  614. { /* overflow */ \
  615. case FP_CLS_NAN: \
  616. case FP_CLS_INF: \
  617. if (rsigned == 2) \
  618. { \
  619. if (X##_c != FP_CLS_NORMAL \
  620. || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs) \
  621. r = 0; \
  622. else \
  623. { \
  624. _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
  625. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  626. } \
  627. } \
  628. else if (rsigned) \
  629. { \
  630. r = 1; \
  631. r <<= rsize - 1; \
  632. r -= 1 - X##_s; \
  633. } \
  634. else \
  635. { \
  636. r = 0; \
  637. if (X##_s) \
  638. r = ~r; \
  639. } \
  640. FP_SET_EXCEPTION(FP_EX_INVALID); \
  641. } \
  642. else \
  643. { \
  644. if (_FP_W_TYPE_SIZE*wc < rsize) \
  645. { \
  646. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  647. r <<= X##_e - _FP_WFRACBITS_##fs; \
  648. } \
  649. else \
  650. { \
  651. if (X##_e >= _FP_WFRACBITS_##fs) \
  652. _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
  653. else if (X##_e < _FP_WFRACBITS_##fs - 1) \
  654. { \
  655. _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \
  656. _FP_WFRACBITS_##fs); \
  657. if (_FP_FRAC_LOW_##wc(X) & 1) \
  658. FP_SET_EXCEPTION(FP_EX_INEXACT); \
  659. _FP_FRAC_SRL_##wc(X, 1); \
  660. } \
  661. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  662. } \
  663. if (rsigned && X##_s) \
  664. r = -r; \
  665. } \
  666. break; \
  667. } \
  668. } while (0)
  669. #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \
  670. do { \
  671. r = 0; \
  672. switch (X##_c) \
  673. { \
  674. case FP_CLS_NORMAL: \
  675. if (X##_e >= _FP_FRACBITS_##fs - 1) \
  676. { \
  677. if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs) \
  678. { \
  679. if (X##_e >= _FP_WFRACBITS_##fs - 1) \
  680. { \
  681. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  682. r <<= X##_e - _FP_WFRACBITS_##fs + 1; \
  683. } \
  684. else \
  685. { \
  686. _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e \
  687. + _FP_FRACBITS_##fs - 1); \
  688. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  689. } \
  690. } \
  691. } \
  692. else \
  693. { \
  694. if (X##_e <= -_FP_WORKBITS - 1) \
  695. _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
  696. else \
  697. _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e, \
  698. _FP_WFRACBITS_##fs); \
  699. _FP_ROUND(wc, X); \
  700. _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
  701. _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
  702. } \
  703. if (rsigned && X##_s) \
  704. r = -r; \
  705. if (X##_e >= rsize - (rsigned > 0 || X##_s) \
  706. || (!rsigned && X##_s)) \
  707. { /* overflow */ \
  708. case FP_CLS_NAN: \
  709. case FP_CLS_INF: \
  710. if (!rsigned) \
  711. { \
  712. r = 0; \
  713. if (X##_s) \
  714. r = ~r; \
  715. } \
  716. else if (rsigned != 2) \
  717. { \
  718. r = 1; \
  719. r <<= rsize - 1; \
  720. r -= 1 - X##_s; \
  721. } \
  722. FP_SET_EXCEPTION(FP_EX_INVALID); \
  723. } \
  724. break; \
  725. case FP_CLS_ZERO: \
  726. break; \
  727. } \
  728. } while (0)
  729. #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
  730. do { \
  731. if (r) \
  732. { \
  733. unsigned rtype ur_; \
  734. X##_c = FP_CLS_NORMAL; \
  735. \
  736. if ((X##_s = (r < 0))) \
  737. ur_ = (unsigned rtype) -r; \
  738. else \
  739. ur_ = (unsigned rtype) r; \
  740. if (rsize <= _FP_W_TYPE_SIZE) \
  741. __FP_CLZ(X##_e, ur_); \
  742. else \
  743. __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
  744. (_FP_W_TYPE)ur_); \
  745. if (rsize < _FP_W_TYPE_SIZE) \
  746. X##_e -= (_FP_W_TYPE_SIZE - rsize); \
  747. X##_e = rsize - X##_e - 1; \
  748. \
  749. if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \
  750. __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
  751. _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
  752. if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0) \
  753. _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
  754. } \
  755. else \
  756. { \
  757. X##_c = FP_CLS_ZERO, X##_s = 0; \
  758. } \
  759. } while (0)
  760. #define FP_CONV(dfs,sfs,dwc,swc,D,S) \
  761. do { \
  762. _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
  763. D##_e = S##_e; \
  764. D##_c = S##_c; \
  765. D##_s = S##_s; \
  766. } while (0)
  767. /*
  768. * Helper primitives.
  769. */
  770. /* Count leading zeros in a word. */
  771. #ifndef __FP_CLZ
  772. #if _FP_W_TYPE_SIZE < 64
  773. /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
  774. #define __FP_CLZ(r, x) \
  775. do { \
  776. _FP_W_TYPE _t = (x); \
  777. r = _FP_W_TYPE_SIZE - 1; \
  778. if (_t > 0xffff) r -= 16; \
  779. if (_t > 0xffff) _t >>= 16; \
  780. if (_t > 0xff) r -= 8; \
  781. if (_t > 0xff) _t >>= 8; \
  782. if (_t & 0xf0) r -= 4; \
  783. if (_t & 0xf0) _t >>= 4; \
  784. if (_t & 0xc) r -= 2; \
  785. if (_t & 0xc) _t >>= 2; \
  786. if (_t & 0x2) r -= 1; \
  787. } while (0)
  788. #else /* not _FP_W_TYPE_SIZE < 64 */
  789. #define __FP_CLZ(r, x) \
  790. do { \
  791. _FP_W_TYPE _t = (x); \
  792. r = _FP_W_TYPE_SIZE - 1; \
  793. if (_t > 0xffffffff) r -= 32; \
  794. if (_t > 0xffffffff) _t >>= 32; \
  795. if (_t > 0xffff) r -= 16; \
  796. if (_t > 0xffff) _t >>= 16; \
  797. if (_t > 0xff) r -= 8; \
  798. if (_t > 0xff) _t >>= 8; \
  799. if (_t & 0xf0) r -= 4; \
  800. if (_t & 0xf0) _t >>= 4; \
  801. if (_t & 0xc) r -= 2; \
  802. if (_t & 0xc) _t >>= 2; \
  803. if (_t & 0x2) r -= 1; \
  804. } while (0)
  805. #endif /* not _FP_W_TYPE_SIZE < 64 */
  806. #endif /* ndef __FP_CLZ */
  807. #define _FP_DIV_HELP_imm(q, r, n, d) \
  808. do { \
  809. q = n / d, r = n % d; \
  810. } while (0)
  811. #endif /* __MATH_EMU_OP_COMMON_H__ */