bid_flag_operations.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /* Copyright (C) 2007-2022 Free Software Foundation, Inc.
  2. This file is part of GCC.
  3. GCC is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free
  5. Software Foundation; either version 3, or (at your option) any later
  6. version.
  7. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  8. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  9. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  10. for more details.
  11. Under Section 7 of GPL version 3, you are granted additional
  12. permissions described in the GCC Runtime Library Exception, version
  13. 3.1, as published by the Free Software Foundation.
  14. You should have received a copy of the GNU General Public License and
  15. a copy of the GCC Runtime Library Exception along with this program;
  16. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  17. <http://www.gnu.org/licenses/>. */
  18. /*****************************************************************************
  19. * Non-computational Operations on Flags:
  20. ****************************************************************************/
  21. #include "bid_internal.h"
  22. // Note the following definitions from bid_conf.h: if the status flags are
  23. // global, they have a fixed name recognized by the library functions:
  24. // _IDEC_glbflags; pfpsf, defined as &_IDEC_glbflags, can be used instead; no
  25. // argument is passed for the status flags to the library functions; if the
  26. // status flags are local then they are passed as an arument, always by
  27. // reference, to the library functions
  28. //
  29. // #if !DECIMAL_GLOBAL_EXCEPTION_FLAGS
  30. // #define _EXC_FLAGS_PARAM , _IDEC_flags *pfpsf
  31. // #else
  32. // extern _IDEC_flags _IDEC_glbflags;
  33. // #define _EXC_FLAGS_PARAM
  34. // #define pfpsf &_IDEC_glbflags
  35. // #endif
  36. #if DECIMAL_CALL_BY_REFERENCE
  37. void
  38. signalException (_IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
  39. // *pflagsmask is the logical OR of the flags to be set, e.g.
  40. // *pflagsmask =INVALID_EXCEPTION | ZERO_DIVIDE_EXCEPTION | OVERFLOW_EXCEPTION
  41. // UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION to set all five IEEE 754R
  42. // exception flags
  43. *pfpsf = *pfpsf | (*pflagsmask & BID_IEEE_FLAGS);
  44. }
  45. #else
  46. void
  47. signalException (_IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
  48. // flagsmask is the logical OR of the flags to be set, e.g.
  49. // flagsmask = INVALID_EXCEPTION | ZERO_DIVIDE_EXCEPTION | OVERFLOW_EXCEPTION
  50. // UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION to set all five IEEE 754R
  51. // exception flags
  52. *pfpsf = *pfpsf | (flagsmask & BID_IEEE_FLAGS);
  53. }
  54. #endif
  55. #if DECIMAL_CALL_BY_REFERENCE
  56. void
  57. lowerFlags (_IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
  58. // *pflagsmask is the logical OR of the flags to be cleared, e.g.
  59. // *pflagsmask =INVALID_EXCEPTION | ZERO_DIVIDE_EXCEPTION | OVERFLOW_EXCEPTION
  60. // UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION to clear all five IEEE 754R
  61. // exception flags
  62. *pfpsf = *pfpsf & ~(*pflagsmask & BID_IEEE_FLAGS);
  63. }
  64. #else
  65. void
  66. lowerFlags (_IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
  67. // flagsmask is the logical OR of the flags to be cleared, e.g.
  68. // flagsmask = INVALID_EXCEPTION | ZERO_DIVIDE_EXCEPTION | OVERFLOW_EXCEPTION
  69. // UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION to clear all five IEEE 754R
  70. // exception flags
  71. *pfpsf = *pfpsf & ~(flagsmask & BID_IEEE_FLAGS);
  72. }
  73. #endif
  74. #if DECIMAL_CALL_BY_REFERENCE
  75. void
  76. testFlags (_IDEC_flags * praised,
  77. _IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
  78. // *praised is a pointer to the result, i.e. the logical OR of the flags
  79. // selected by *pflagsmask that are set; e.g. if
  80. // *pflagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
  81. // and only the invalid and inexact flags are raised (set) then upon return
  82. // *praised = INVALID_EXCEPTION | INEXACT_EXCEPTION
  83. *praised = *pfpsf & (*pflagsmask & BID_IEEE_FLAGS);
  84. }
  85. #else
  86. _IDEC_flags
  87. testFlags (_IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
  88. _IDEC_flags raised;
  89. // the raturn value raised is the logical OR of the flags
  90. // selected by flagsmask, that are set; e.g. if
  91. // flagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION and
  92. // only the invalid and inexact flags are raised (set) then the return value
  93. // is raised = INVALID_EXCEPTION | INEXACT_EXCEPTION
  94. raised = *pfpsf & (flagsmask & BID_IEEE_FLAGS);
  95. return (raised);
  96. }
  97. #endif
  98. #if DECIMAL_CALL_BY_REFERENCE
  99. void
  100. testSavedFlags (_IDEC_flags * praised, _IDEC_flags * psavedflags,
  101. _IDEC_flags * pflagsmask) {
  102. // *praised is a pointer to the result, i.e. the logical OR of the flags
  103. // selected by *pflagsmask that are set in *psavedflags; e.g. if
  104. // *pflagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
  105. // and only the invalid and inexact flags are raised (set) in *psavedflags
  106. // then upon return *praised = INVALID_EXCEPTION | INEXACT_EXCEPTION
  107. // Note that the flags could be saved in a global variable, but this function
  108. // would still expect that value as an argument passed by reference
  109. *praised = *psavedflags & (*pflagsmask & BID_IEEE_FLAGS);
  110. }
  111. #else
  112. _IDEC_flags
  113. testSavedFlags (_IDEC_flags savedflags, _IDEC_flags flagsmask) {
  114. _IDEC_flags raised;
  115. // the raturn value raised is the logical OR of the flags
  116. // selected by flagsmask, that are set in savedflags; e.g. if
  117. // flagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION and
  118. // only the invalid and inexact flags are raised (set) in savedflags
  119. // then the return value is raised = INVALID_EXCEPTION | INEXACT_EXCEPTION
  120. // Note that the flags could be saved in a global variable, but this function
  121. // would still expect that value as an argument passed by value
  122. raised = savedflags & (flagsmask & BID_IEEE_FLAGS);
  123. return (raised);
  124. }
  125. #endif
  126. #if DECIMAL_CALL_BY_REFERENCE
  127. void
  128. restoreFlags (_IDEC_flags * pflagsvalues,
  129. _IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
  130. // restore the status flags selected by *pflagsmask to the values speciafied
  131. // (as a logical OR) in *pflagsvalues; e.g. if
  132. // *pflagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
  133. // and only the invalid and inexact flags are raised (set) in *pflagsvalues
  134. // then upon return the invalid status flag will be set, the underflow status
  135. // flag will be clear, and the inexact status flag will be set
  136. *pfpsf = *pfpsf & ~(*pflagsmask & BID_IEEE_FLAGS);
  137. // clear flags that have to be restored
  138. *pfpsf = *pfpsf | (*pflagsvalues & (*pflagsmask & BID_IEEE_FLAGS));
  139. // restore flags
  140. }
  141. #else
  142. void
  143. restoreFlags (_IDEC_flags flagsvalues,
  144. _IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
  145. // restore the status flags selected by flagsmask to the values speciafied
  146. // (as a logical OR) in flagsvalues; e.g. if
  147. // flagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
  148. // and only the invalid and inexact flags are raised (set) in flagsvalues
  149. // then upon return the invalid status flag will be set, the underflow status
  150. // flag will be clear, and the inexact status flag will be set
  151. *pfpsf = *pfpsf & ~(flagsmask & BID_IEEE_FLAGS);
  152. // clear flags that have to be restored
  153. *pfpsf = *pfpsf | (flagsvalues & (flagsmask & BID_IEEE_FLAGS));
  154. // restore flags
  155. }
  156. #endif
  157. #if DECIMAL_CALL_BY_REFERENCE
  158. void
  159. saveFlags (_IDEC_flags * pflagsvalues,
  160. _IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
  161. // return in *pflagsvalues the status flags specified (as a logical OR) in
  162. // *pflagsmask; e.g. if
  163. // *pflagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
  164. // and only the invalid and inexact flags are raised (set) in the status word,
  165. // then upon return the value in *pflagsvalues will have the invalid status
  166. // flag set, the underflow status flag clear, and the inexact status flag set
  167. *pflagsvalues = *pfpsf & (*pflagsmask & BID_IEEE_FLAGS);
  168. }
  169. #else
  170. _IDEC_flags
  171. saveFlags (_IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
  172. _IDEC_flags flagsvalues;
  173. // return the status flags specified (as a logical OR) in flagsmask; e.g. if
  174. // flagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
  175. // and only the invalid and inexact flags are raised (set) in the status word,
  176. // then the return value will have the invalid status flag set, the
  177. // underflow status flag clear, and the inexact status flag set
  178. flagsvalues = *pfpsf & (flagsmask & BID_IEEE_FLAGS);
  179. return (flagsvalues);
  180. }
  181. #endif
  182. // Note the following definitions from bid_conf.h (rearranged): if the rounding
  183. // mode is global, it has a fixed name recognized by the library functions:
  184. // _IDEC_glbround; rnd_mode, defined as &_IDEC_glbround, can be used instead; no
  185. // argument is passed for the rounding mode to the library functions; if the
  186. // rounding mode is local then it is passed as an arument, by reference or by
  187. // value, to the library functions
  188. //
  189. // #if DECIMAL_CALL_BY_REFERENCE
  190. // #if !DECIMAL_GLOBAL_ROUNDING
  191. // #define _RND_MODE_PARAM , _IDEC_round *prnd_mode
  192. // #else
  193. // #define _RND_MODE_PARAM
  194. // #define rnd_mode _IDEC_glbround
  195. // #endif
  196. // #else
  197. // #if !DECIMAL_GLOBAL_ROUNDING
  198. // #define _RND_MODE_PARAM , _IDEC_round rnd_mode
  199. // #else
  200. // #define _RND_MODE_PARAM
  201. // #define rnd_mode _IDEC_glbround
  202. // #endif
  203. // #endif
  204. #if DECIMAL_CALL_BY_REFERENCE
  205. #if !DECIMAL_GLOBAL_ROUNDING
  206. // #define _RND_MODE_PARAM , _IDEC_round *prnd_mode
  207. void
  208. getDecimalRoundingDirection (_IDEC_round * rounding_mode
  209. _RND_MODE_PARAM) {
  210. // returns the current rounding mode
  211. *rounding_mode = *prnd_mode;
  212. }
  213. #else
  214. // #define _RND_MODE_PARAM
  215. // #define rnd_mode _IDEC_glbround
  216. void
  217. getDecimalRoundingDirection (_IDEC_round * rounding_mode
  218. _RND_MODE_PARAM) {
  219. // returns the current rounding mode
  220. *rounding_mode = rnd_mode;
  221. }
  222. #endif
  223. #else
  224. #if !DECIMAL_GLOBAL_ROUNDING
  225. // #define _RND_MODE_PARAM , _IDEC_round rnd_mode
  226. _IDEC_round
  227. getDecimalRoundingDirection (_IDEC_round rnd_mode) {
  228. // returns the current rounding mode
  229. return (rnd_mode);
  230. }
  231. #else
  232. // #define _RND_MODE_PARAM
  233. // #define rnd_mode _IDEC_glbround
  234. _IDEC_round
  235. getDecimalRoundingDirection (void) {
  236. // returns the current rounding mode
  237. return (rnd_mode);
  238. }
  239. #endif
  240. #endif
  241. #if DECIMAL_CALL_BY_REFERENCE
  242. #if !DECIMAL_GLOBAL_ROUNDING
  243. // #define _RND_MODE_PARAM , _IDEC_round *prnd_mode
  244. void
  245. setDecimalRoundingDirection (_IDEC_round * rounding_mode
  246. _RND_MODE_PARAM) {
  247. // sets the current rounding mode to the value in *rounding_mode, if valid
  248. if (*rounding_mode == ROUNDING_TO_NEAREST ||
  249. *rounding_mode == ROUNDING_DOWN ||
  250. *rounding_mode == ROUNDING_UP ||
  251. *rounding_mode == ROUNDING_TO_ZERO ||
  252. *rounding_mode == ROUNDING_TIES_AWAY) {
  253. *prnd_mode = *rounding_mode;
  254. }
  255. }
  256. #else
  257. // #define _RND_MODE_PARAM
  258. // #define rnd_mode _IDEC_glbround
  259. void
  260. setDecimalRoundingDirection (_IDEC_round * rounding_mode
  261. ) {
  262. // sets the global rounding mode to the value in *rounding_mode, if valid
  263. if (*rounding_mode == ROUNDING_TO_NEAREST ||
  264. *rounding_mode == ROUNDING_DOWN ||
  265. *rounding_mode == ROUNDING_UP ||
  266. *rounding_mode == ROUNDING_TO_ZERO ||
  267. *rounding_mode == ROUNDING_TIES_AWAY) {
  268. rnd_mode = *rounding_mode;
  269. }
  270. }
  271. #endif
  272. #else
  273. #if !DECIMAL_GLOBAL_ROUNDING
  274. // #define _RND_MODE_PARAM , _IDEC_round rnd_mode
  275. _IDEC_round
  276. setDecimalRoundingDirection (_IDEC_round rounding_mode _RND_MODE_PARAM) {
  277. // sets the current rounding mode to the value in rounding_mode;
  278. // however, when arguments are passed by value and the rounding mode
  279. // is a local variable, this is not of any use
  280. if (rounding_mode == ROUNDING_TO_NEAREST ||
  281. rounding_mode == ROUNDING_DOWN ||
  282. rounding_mode == ROUNDING_UP ||
  283. rounding_mode == ROUNDING_TO_ZERO ||
  284. rounding_mode == ROUNDING_TIES_AWAY) {
  285. return (rounding_mode);
  286. }
  287. return (rnd_mode);
  288. }
  289. #else
  290. // #define _RND_MODE_PARAM
  291. // #define rnd_mode _IDEC_glbround
  292. void
  293. setDecimalRoundingDirection (_IDEC_round rounding_mode) {
  294. // sets the current rounding mode to the value in rounding_mode, if valid;
  295. if (rounding_mode == ROUNDING_TO_NEAREST ||
  296. rounding_mode == ROUNDING_DOWN ||
  297. rounding_mode == ROUNDING_UP ||
  298. rounding_mode == ROUNDING_TO_ZERO ||
  299. rounding_mode == ROUNDING_TIES_AWAY) {
  300. rnd_mode = rounding_mode;
  301. }
  302. }
  303. #endif
  304. #endif
  305. #if DECIMAL_CALL_BY_REFERENCE
  306. void
  307. is754 (int *retval) {
  308. *retval = 0;
  309. }
  310. #else
  311. int
  312. is754 (void) {
  313. return 0;
  314. }
  315. #endif
  316. #if DECIMAL_CALL_BY_REFERENCE
  317. void
  318. is754R (int *retval) {
  319. *retval = 1;
  320. }
  321. #else
  322. int
  323. is754R (void) {
  324. return 1;
  325. }
  326. #endif