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