mathinline.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /* Definitions of inline math functions implemented by the m68881/2.
  2. Copyright (C) 1991,92,93,94,96,97,98,99,2000,2002, 2003, 2004
  3. Free Software Foundation, Inc.
  4. This file is part of the GNU C Library.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library 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 GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, write to the Free
  15. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  16. 02111-1307 USA. */
  17. #ifdef __GNUC__
  18. #ifdef __USE_ISOC99
  19. /* GCC 3.1 and up have builtins that actually can be used. */
  20. # if !__GNUC_PREREQ (3,1)
  21. /* ISO C99 defines some macros to perform unordered comparisons. The
  22. m68k FPU supports this with special opcodes and we should use them.
  23. These must not be inline functions since we have to be able to handle
  24. all floating-point types. */
  25. # undef isgreater
  26. # undef isgreaterequal
  27. # undef isless
  28. # undef islessequal
  29. # undef islessgreater
  30. # undef isunordered
  31. # define isgreater(x, y) \
  32. __extension__ \
  33. ({ char __result; \
  34. __asm__ ("fcmp%.x %2,%1; fsogt %0" \
  35. : "=dm" (__result) : "f" (x), "f" (y)); \
  36. __result != 0; })
  37. # define isgreaterequal(x, y) \
  38. __extension__ \
  39. ({ char __result; \
  40. __asm__ ("fcmp%.x %2,%1; fsoge %0" \
  41. : "=dm" (__result) : "f" (x), "f" (y)); \
  42. __result != 0; })
  43. # define isless(x, y) \
  44. __extension__ \
  45. ({ char __result; \
  46. __asm__ ("fcmp%.x %2,%1; fsolt %0" \
  47. : "=dm" (__result) : "f" (x), "f" (y)); \
  48. __result != 0; })
  49. # define islessequal(x, y) \
  50. __extension__ \
  51. ({ char __result; \
  52. __asm__ ("fcmp%.x %2,%1; fsole %0" \
  53. : "=dm" (__result) : "f" (x), "f" (y)); \
  54. __result != 0; })
  55. # define islessgreater(x, y) \
  56. __extension__ \
  57. ({ char __result; \
  58. __asm__ ("fcmp%.x %2,%1; fsogl %0" \
  59. : "=dm" (__result) : "f" (x), "f" (y)); \
  60. __result != 0; })
  61. # define isunordered(x, y) \
  62. __extension__ \
  63. ({ char __result; \
  64. __asm__ ("fcmp%.x %2,%1; fsun %0" \
  65. : "=dm" (__result) : "f" (x), "f" (y)); \
  66. __result != 0; })
  67. # endif /* GCC 3.1 */
  68. #endif
  69. #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
  70. || defined __LIBC_INTERNAL_MATH_INLINES
  71. #ifdef __LIBC_INTERNAL_MATH_INLINES
  72. /* This is used when defining the functions themselves. Define them with
  73. __ names, and with `static inline' instead of `extern inline' so the
  74. bodies will always be used, never an external function call. */
  75. # define __m81_u(x) __CONCAT(__,x)
  76. # define __m81_inline static __inline
  77. #else
  78. # define __m81_u(x) x
  79. # ifdef __cplusplus
  80. # define __m81_inline __inline
  81. # else
  82. # define __m81_inline extern __inline
  83. # endif
  84. # define __M81_MATH_INLINES 1
  85. #endif
  86. /* Define a const math function. */
  87. #define __m81_defun(rettype, func, args) \
  88. __m81_inline rettype __attribute__((__const__)) \
  89. __m81_u(func) args
  90. /* Define the three variants of a math function that has a direct
  91. implementation in the m68k fpu. FUNC is the name for C (which will be
  92. suffixed with f and l for the float and long double version, resp). OP
  93. is the name of the fpu operation (without leading f). */
  94. #if defined __USE_MISC || defined __USE_ISOC99
  95. # define __inline_mathop(func, op) \
  96. __inline_mathop1(double, func, op) \
  97. __inline_mathop1(float, __CONCAT(func,f), op) \
  98. __inline_mathop1(long double, __CONCAT(func,l), op)
  99. #else
  100. # define __inline_mathop(func, op) \
  101. __inline_mathop1(double, func, op)
  102. #endif
  103. #define __inline_mathop1(float_type,func, op) \
  104. __m81_defun (float_type, func, (float_type __mathop_x)) \
  105. { \
  106. float_type __result; \
  107. __asm__("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\
  108. return __result; \
  109. }
  110. __inline_mathop(__atan, atan)
  111. __inline_mathop(__cos, cos)
  112. __inline_mathop(__sin, sin)
  113. __inline_mathop(__tan, tan)
  114. __inline_mathop(__tanh, tanh)
  115. __inline_mathop(__fabs, abs)
  116. #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
  117. __inline_mathop(__rint, int)
  118. __inline_mathop(__expm1, etoxm1)
  119. __inline_mathop(__log1p, lognp1)
  120. #endif
  121. #ifdef __USE_MISC
  122. __inline_mathop(__significand, getman)
  123. #endif
  124. #ifdef __USE_ISOC99
  125. __inline_mathop(__trunc, intrz)
  126. #endif
  127. #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
  128. __inline_mathop(atan, atan)
  129. __inline_mathop(cos, cos)
  130. __inline_mathop(sin, sin)
  131. __inline_mathop(tan, tan)
  132. __inline_mathop(tanh, tanh)
  133. # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
  134. __inline_mathop(rint, int)
  135. __inline_mathop(expm1, etoxm1)
  136. __inline_mathop(log1p, lognp1)
  137. # endif
  138. # ifdef __USE_MISC
  139. __inline_mathop(significand, getman)
  140. # endif
  141. # ifdef __USE_ISOC99
  142. __inline_mathop(trunc, intrz)
  143. # endif
  144. #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
  145. /* This macro contains the definition for the rest of the inline
  146. functions, using FLOAT_TYPE as the domain type and S as the suffix
  147. for the function names. */
  148. #define __inline_functions(float_type, s) \
  149. __m81_defun (float_type, __CONCAT(__floor,s), (float_type __x)) \
  150. { \
  151. float_type __result; \
  152. unsigned long int __ctrl_reg; \
  153. __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
  154. /* Set rounding towards negative infinity. */ \
  155. __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
  156. : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \
  157. /* Convert X to an integer, using -Inf rounding. */ \
  158. __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
  159. /* Restore the previous rounding mode. */ \
  160. __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
  161. : "dmi" (__ctrl_reg)); \
  162. return __result; \
  163. } \
  164. \
  165. __m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) \
  166. { \
  167. float_type __result; \
  168. unsigned long int __ctrl_reg; \
  169. __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
  170. /* Set rounding towards positive infinity. */ \
  171. __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
  172. : "dmi" (__ctrl_reg | 0x30)); \
  173. /* Convert X to an integer, using +Inf rounding. */ \
  174. __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
  175. /* Restore the previous rounding mode. */ \
  176. __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
  177. : "dmi" (__ctrl_reg)); \
  178. return __result; \
  179. }
  180. __inline_functions(double,)
  181. #if defined __USE_MISC || defined __USE_ISOC99
  182. __inline_functions(float,f)
  183. __inline_functions(long double,l)
  184. #endif
  185. #undef __inline_functions
  186. #ifdef __USE_MISC
  187. # define __inline_functions(float_type, s) \
  188. __m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) \
  189. { \
  190. /* There is no branch-condition for infinity, \
  191. so we must extract and examine the condition codes manually. */ \
  192. unsigned long int __fpsr; \
  193. __asm__("ftst%.x %1\n" \
  194. "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
  195. return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \
  196. } \
  197. \
  198. __m81_defun (int, __CONCAT(__finite,s), (float_type __value)) \
  199. { \
  200. /* There is no branch-condition for infinity, so we must extract and \
  201. examine the condition codes manually. */ \
  202. unsigned long int __fpsr; \
  203. __asm__ ("ftst%.x %1\n" \
  204. "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
  205. return (__fpsr & (3 << 24)) == 0; \
  206. } \
  207. \
  208. __m81_defun (float_type, __CONCAT(__scalbn,s), \
  209. (float_type __x, int __n)) \
  210. { \
  211. float_type __result; \
  212. __asm__ ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x)); \
  213. return __result; \
  214. }
  215. __inline_functions(double,)
  216. __inline_functions(float,f)
  217. __inline_functions(long double,l)
  218. # undef __inline_functions
  219. #endif /* Use misc. */
  220. #if defined __USE_MISC || defined __USE_XOPEN
  221. # define __inline_functions(float_type, s) \
  222. __m81_defun (int, __CONCAT(__isnan,s), (float_type __value)) \
  223. { \
  224. char __result; \
  225. __asm__("ftst%.x %1\n" \
  226. "fsun %0" : "=dm" (__result) : "f" (__value)); \
  227. return __result; \
  228. }
  229. __inline_functions(double,)
  230. # ifdef __USE_MISC
  231. __inline_functions(float,f)
  232. __inline_functions(long double,l)
  233. # endif
  234. # undef __inline_functions
  235. #endif
  236. #ifdef __USE_ISOC99
  237. # define __inline_functions(float_type, s) \
  238. __m81_defun (int, __CONCAT(__signbit,s), (float_type __value)) \
  239. { \
  240. /* There is no branch-condition for the sign bit, so we must extract \
  241. and examine the condition codes manually. */ \
  242. unsigned long int __fpsr; \
  243. __asm__ ("ftst%.x %1\n" \
  244. "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
  245. return (__fpsr >> 27) & 1; \
  246. } \
  247. \
  248. __m81_defun (float_type, __CONCAT(__scalbln,s), \
  249. (float_type __x, long int __n)) \
  250. { \
  251. return __CONCAT(__scalbn,s) (__x, __n); \
  252. } \
  253. \
  254. __m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) \
  255. { \
  256. float_type __result; \
  257. unsigned long int __ctrl_reg; \
  258. __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
  259. /* Temporarily disable the inexact exception. */ \
  260. __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
  261. : "dmi" (__ctrl_reg & ~0x200)); \
  262. __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
  263. __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
  264. : "dmi" (__ctrl_reg)); \
  265. return __result; \
  266. } \
  267. \
  268. __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) \
  269. { \
  270. long int __result; \
  271. __asm__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
  272. return __result; \
  273. } \
  274. \
  275. __m81_inline float_type \
  276. __m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y, \
  277. float_type __z) \
  278. { \
  279. return (__x * __y) + __z; \
  280. }
  281. __inline_functions (double,)
  282. __inline_functions (float,f)
  283. __inline_functions (long double,l)
  284. # undef __inline_functions
  285. #endif /* Use ISO C9x */
  286. #ifdef __USE_GNU
  287. # define __inline_functions(float_type, s) \
  288. __m81_inline void \
  289. __m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx, \
  290. float_type *__cosx) \
  291. { \
  292. __asm__ ("fsincos%.x %2,%1:%0" \
  293. : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \
  294. }
  295. __inline_functions (double,)
  296. __inline_functions (float,f)
  297. __inline_functions (long double,l)
  298. # undef __inline_functions
  299. #endif
  300. #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
  301. /* Define inline versions of the user visible functions. */
  302. /* Note that there must be no whitespace before the argument passed for
  303. NAME, to make token pasting work correctly with -traditional. */
  304. # define __inline_forward_c(rettype, name, args1, args2) \
  305. extern __inline rettype __attribute__((__const__)) \
  306. name args1 \
  307. { \
  308. return __CONCAT(__,name) args2; \
  309. }
  310. # define __inline_forward(rettype, name, args1, args2) \
  311. extern __inline rettype name args1 \
  312. { \
  313. return __CONCAT(__,name) args2; \
  314. }
  315. __inline_forward_c(double,floor, (double __x), (__x))
  316. __inline_forward_c(double,ceil, (double __x), (__x))
  317. # ifdef __USE_MISC
  318. # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
  319. __inline_forward_c(int,isinf, (double __value), (__value))
  320. # endif
  321. __inline_forward_c(int,finite, (double __value), (__value))
  322. __inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
  323. # endif
  324. # if defined __USE_MISC || defined __USE_XOPEN
  325. # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
  326. __inline_forward_c(int,isnan, (double __value), (__value))
  327. # endif
  328. # endif
  329. # ifdef __USE_ISOC99
  330. __inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
  331. __inline_forward_c(double,nearbyint, (double __value), (__value))
  332. __inline_forward_c(long int,lrint, (double __value), (__value))
  333. __inline_forward_c(double,fma, (double __x, double __y, double __z),
  334. (__x, __y, __z))
  335. # endif
  336. # ifdef __USE_GNU
  337. __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
  338. (__x, __sinx, __cosx))
  339. # endif
  340. # if defined __USE_MISC || defined __USE_ISOC99
  341. __inline_forward_c(float,floorf, (float __x), (__x))
  342. __inline_forward_c(float,ceilf, (float __x), (__x))
  343. # ifdef __USE_MISC
  344. __inline_forward_c(int,isinff, (float __value), (__value))
  345. __inline_forward_c(int,finitef, (float __value), (__value))
  346. __inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
  347. __inline_forward_c(int,isnanf, (float __value), (__value))
  348. # endif
  349. # ifdef __USE_ISOC99
  350. __inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
  351. __inline_forward_c(float,nearbyintf, (float __value), (__value))
  352. __inline_forward_c(long int,lrintf, (float __value), (__value))
  353. __inline_forward_c(float,fmaf, (float __x, float __y, float __z),
  354. (__x, __y, __z))
  355. # endif
  356. # ifdef __USE_GNU
  357. __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
  358. (__x, __sinx, __cosx))
  359. # endif
  360. __inline_forward_c(long double,floorl, (long double __x), (__x))
  361. __inline_forward_c(long double,ceill, (long double __x), (__x))
  362. # ifdef __USE_MISC
  363. __inline_forward_c(int,isinfl, (long double __value), (__value))
  364. __inline_forward_c(int,finitel, (long double __value), (__value))
  365. __inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n))
  366. __inline_forward_c(int,isnanl, (long double __value), (__value))
  367. # endif
  368. # ifdef __USE_ISOC99
  369. __inline_forward_c(long double,scalblnl, (long double __x, long int __n),
  370. (__x, __n))
  371. __inline_forward_c(long double,nearbyintl, (long double __value), (__value))
  372. __inline_forward_c(long int,lrintl, (long double __value), (__value))
  373. __inline_forward_c(long double,fmal,
  374. (long double __x, long double __y, long double __z),
  375. (__x, __y, __z))
  376. # endif
  377. # ifdef __USE_GNU
  378. __inline_forward(void,sincosl,
  379. (long double __x, long double *__sinx, long double *__cosx),
  380. (__x, __sinx, __cosx))
  381. # endif
  382. #endif /* Use misc or ISO C99 */
  383. #undef __inline_forward
  384. #undef __inline_forward_c
  385. #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
  386. #endif
  387. #endif /* GCC. */