op-common.h 25 KB

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