1 /******************************************************************************
2   Copyright (c) 2007-2011, Intel Corp.
3   All rights reserved.
4 
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions are met:
7 
8     * Redistributions of source code must retain the above copyright notice,
9       this list of conditions and the following disclaimer.
10     * Redistributions in binary form must reproduce the above copyright
11       notice, this list of conditions and the following disclaimer in the
12       documentation and/or other materials provided with the distribution.
13     * Neither the name of Intel Corporation nor the names of its contributors
14       may be used to endorse or promote products derived from this software
15       without specific prior written permission.
16 
17   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27   THE POSSIBILITY OF SUCH DAMAGE.
28 ******************************************************************************/
29 
30 # ifndef DPML_EXCEPTION_H
31 # define DPML_EXCEPTION_H
32 
33 /*									    */
34 /*  Standardize the definition of COMPATIBILITY_MODE, a macro used to aid   */
35 /*  the transition from the "old" style exception record interface to the   */
36 /*  exception dispatcher to the "new" style interface.  It is used on	    */
37 /*  platforms where both interfaces may co-exist.  It will not be needed    */
38 /*  when the old interface is no longer used.				    */
39 /*									    */
40 /*  If COMPATIBILITY_MODE is TRUE when compiling a DPML procedure, both the */
41 /*  old and new record interfaces are available to the procedure.  The	    */
42 /*  interface actually used is determined by the macros which the procedure */
43 /*  uses to invoke the exception dispatcher.  The GET_EXCEPTION_RESULT_n    */
44 /*  macros use the old interface while the RETURN_EXCEPTION_RESULT_n macros */
45 /*  use the new interface.  If COMPATIBILITY_MODE is FALSE, only the new    */
46 /*  interface is supported.						    */
47 /*									    */
48 /*  When compiling the exception dispatcher, if COMPATIBILITY_MODE is TRUE, */
49 /*  both the old and new record interfaces are supported by the dispatcher. */
50 /*  However, if COMPATIBILITY_MODE is FALSE, only the new interface is	    */
51 /*  supported.								    */
52 /*									    */
53 /*  Since all DPML procedures initially use the old interface, the default  */
54 /*  is that both interfaces are available.  Thus, if COMPATIBILITY_MODE is  */
55 /*  not defined or is TRUE, it is (re)defined to be TRUE.  However, if it   */
56 /*  is defined and is FALSE, it is redefined to be FALSE.		    */
57 /*									    */
58 /*  When most procedures have been modified to use the new interface, the   */
59 /*  default should be changed to cause only the new interface to be	    */
60 /*  provided.								    */
61 /*									    */
62 /*  Note that the use of COMPATIBILITY_MODE impacts makefiles.  DPML	    */
63 /*  procedures which use the new interface while the old is the default	    */
64 /*  must be compiled with COMPATIBILITY_MODE=0.  Conversely, when the new   */
65 /*  interface is the default, procedures continuing to use the old must be  */
66 /*  compiled with COMPATIBILITY_MODE=1.  As long as there are DPML	    */
67 /*  procedures using each style of interface, the exception dispatcher must */
68 /*  be compiled with COMPATIBILITY_MODE set to TRUE, either explicitly via  */
69 /*  COMPATIBILITY_MODE=1 or implicitly through the default value given to   */
70 /*  COMPATIBILITY_MODE.							    */
71 /*									    */
72 
73 # if defined COMPATIBILITY_MODE
74 #    if COMPATIBILITY_MODE
75 #	undef COMPATIBILITY_MODE
76 #	define COMPATIBILITY_MODE 1
77 #    else
78 #	undef COMPATIBILITY_MODE
79 #	define COMPATIBILITY_MODE 0
80 #   endif
81 # else
82 #   define COMPATIBILITY_MODE 1
83 # endif
84 
85 /*									    */
86 /*  Once the "old" style interface is no longer supported, all use of	    */
87 /*  ERROR_WORD_COMPATIBILITY_MODE_FLAG should be removed.		    */
88 /*									    */
89 
90 # define ERROR_WORD_COMPATIBILITY_MODE_FLAG		\
91     ( U_WORD )( ( U_WORD )1 << ( BITS_PER_WORD - 1 ) )
92 
93 /*									    */
94 /*  If IEEE data types are used, default to IEEE behavior.		    */
95 /*									    */
96 
97 # if !defined IEEE_EXCEPTION_BEHAVIOR
98 #   if FLOAT_TYPES && IEEE_TYPES && !defined(MINIMAL_SILENT_MODE_EXCEPTION_HANDLER)
99 #      define IEEE_EXCEPTION_BEHAVIOR 1
100 #   else
101 #      define IEEE_EXCEPTION_BEHAVIOR 0
102 #      define DPML_UPDATE_STICKY_BITS( e )
103 #   endif
104 # else
105 #   undef  IEEE_EXCEPTION_BEHAVIOR
106 #   define IEEE_EXCEPTION_BEHAVIOR 1
107 # endif
108 
109 # if COMPATIBILITY_MODE
110 
111 /*									    */
112 /*  All of the DPML static exception behavior is encoded in an array of	    */
113 /*  structures.  The array is is indexed by error code (see		    */
114 /*  dpml_error_code.c) Each entry in the array contains an indication of    */
115 /*  which function generated the error code and a set of default responses  */
116 /*  to the error.  For discussion purposes, a response is an ordered pair   */
117 /*  of integers:  The first integer defines the DPML and the second defines */
118 /*  a return values (see dpml_error_code.c for details).  Currently, there  */
119 /*  are two responses associated with each error code: one for IEEE mode    */
120 /*  and one for fast mode.  While some platforms do not require all this    */
121 /*  information, currently it is always generated, regardless of platform   */
122 /*									    */
123 /*	NOTE: the function information is not currently used within the	    */
124 /*	DPML.  It is included for historic purposes and to allow other	    */
125 /*	users of the exception routines to generated function information   */
126 /*									    */
127 
128 typedef struct {
129     U_INT_32 func;
130     U_INT_8 fast_err;
131     U_INT_8 fast_val;
132     U_INT_8 ieee_err;
133     U_INT_8 ieee_val;
134     } DPML_EXCEPTION_RESPONSE;
135 
136 #define	GET_IEEE_VALUE(n)	RESPONSE_TABLE[n].ieee_val
137 #define	GET_IEEE_ERROR(n)	RESPONSE_TABLE[n].ieee_err
138 #define	GET_FAST_VALUE(n)	RESPONSE_TABLE[n].fast_val
139 #define	GET_FAST_ERROR(n)	RESPONSE_TABLE[n].fast_err
140 #define GET_ERR_CODE_FUNC(c)	RESPONSE_TABLE[c].func
141 
142 # endif
143 
144 /*									    */
145 /*  There are five generic error codes that are processed by DPML exception */
146 /*  handler: underflow, overflow, singularity, invalid and lost		    */
147 /*  significance.  These corrospond roughly to the IEEE exceptions	    */
148 /*  underflow, overflow, divide by zero, invalid argument and inexact.  In  */
149 /*  addition there are two pseudo errors: NO_ERROR, which allows platform   */
150 /*  specific function returns and ENV_INFO, which allow DPML routines to    */
151 /*  determine what environment they are functioning in.			    */
152 /*									    */
153 /*  When the exception handler is invoked, it determines the environment it */
154 /*  is executing in.  The environment is encoded in a bit vector that	    */
155 /*  indicates: Which of the five DPML exceptions should cause signals to be */
156 /*  generated; Whether denormalized numbers should be flushed to zero and;  */
157 /*  Whether IEEE mode is enabled.					    */
158 /*									    */
159 /*  The following defines indicate the bit positions used to encode the	    */
160 /*  environment and the masks used to query the environment.  The ordinal   */
161 /*  values of the error codes are important only in they correspond to the  */
162 /*  logic in the exception handler and the macro ERRNO_VALUE maps the	    */
163 /*  UNDER/OVERFLOW and SINGULARITY/INVALID onto ERANGE and EDOM		    */
164 /*  repectively.							    */
165 /*									    */
166 /*  Many assumptions are made about the order (both relative and absolute)  */
167 /*  of these values.							    */
168 /*									    */
169 
170 # define DPML_ENV_INFO	       -1
171 # define DPML_NO_ERROR		0
172 # define DPML_INVALID		1
173 # define DPML_SINGULARITY	2
174 # define DPML_OVERFLOW		3
175 # define DPML_UNDERFLOW		4
176 # define DPML_LOST_SIGNIFICANCE	5
177 # define DPML_FLUSH_TO_ZERO	6
178 # define DPML_IEEE_MODE		7
179 
180 /*									    */
181 /*  It is required that the ENABLE_xxx symbols be equal to 1 << DPML_xxx.   */
182 /*  Unfortunately, that cannot be checked during compilation.		    */
183 /*									    */
184 
185 # define ENABLE_NO_ERROR	  0x00
186 # define ENABLE_INVALID		  0x02
187 # define ENABLE_SINGULARITY	  0x04
188 # define ENABLE_OVERFLOW	  0x08
189 # define ENABLE_UNDERFLOW	  0x10
190 # define ENABLE_LOST_SIGNIFICANCE 0x20
191 # define ENABLE_FLUSH_TO_ZERO	  0x40
192 # define ENABLE_IEEE_MODE	  0x80
193 
194 # define EXCEPTION_ENABLE_MASK ( ENABLE_INVALID		  |	\
195 				 ENABLE_SINGULARITY	  |	\
196 				 ENABLE_OVERFLOW	  |	\
197 				 ENABLE_UNDERFLOW	  |	\
198 				 ENABLE_LOST_SIGNIFICANCE )
199 
200 # define STATUS_NO_ERROR	  ENABLE_NO_ERROR
201 # define STATUS_INVALID		  ENABLE_INVALID
202 # define STATUS_SINGULARITY	  ENABLE_SINGULARITY
203 # define STATUS_OVERFLOW	  ENABLE_OVERFLOW
204 # define STATUS_UNDERFLOW	  ENABLE_UNDERFLOW
205 # define STATUS_LOST_SIGNIFICANCE ENABLE_LOST_SIGNIFICANCE
206 # define STATUS_DENORM_PROCESSING ENABLE_FLUSH_TO_ZERO
207 
208 # define EXCEPTION_STATUS_MASK ( STATUS_INVALID		  |	\
209 				 STATUS_SINGULARITY	  |	\
210 				 STATUS_OVERFLOW	  |	\
211 				 STATUS_UNDERFLOW	  |	\
212 				 STATUS_LOST_SIGNIFICANCE )
213 
214 /*									    */
215 /*  These macros are used to determine the errno value associated with an   */
216 /*  error condition.  If the error is INVALID or SINGULARITY, errno is set  */
217 /*  to EDOM; if it is OVERFLOW or UNDERFLOW, it is set to ERANGE.  The	    */
218 /*  values DPML_EDOM and DPML_ERANGE are used internally in the DPML to	    */
219 /*  limit the need to include the system header file errno.h to the	    */
220 /*  exception dispatcher procedure itself.				    */
221 /*									    */
222 
223 # define ERRNO_TEST( error_code ) ( ( error_code ) < DPML_OVERFLOW )
224 # define DPML_ERRNO_VALUE( error_code )				\
225     ( ERRNO_TEST( error_code ) ? DPML_EDOM : DPML_ERANGE )
226 # define ERRNO_VALUE( error_code )				\
227     ( ERRNO_TEST( error_code ) ? EDOM : ERANGE )
228 
229 /*									    */
230 /*  In order to more easily encode the default return values for specific   */
231 /*  errors, the basic DPML errors are extended in some cases to include	    */
232 /*  positive and negative flavors.					    */
233 /*									    */
234 
235 #define	POS_ERR(e)	((e) << 1)
236 #define	NEG_ERR(e)	(POS_ERR(e) + 1)
237 #define UNSIGNED_ERR(e) ((e) >> 1)
238 
239 #define POS_UNDERFLOW_ERR	POS_ERR(DPML_UNDERFLOW)
240 #define NEG_UNDERFLOW_ERR	NEG_ERR(DPML_UNDERFLOW)
241 #define POS_OVERFLOW_ERR	POS_ERR(DPML_OVERFLOW)
242 #define NEG_OVERFLOW_ERR	NEG_ERR(DPML_OVERFLOW)
243 #define POS_SINGULARITY		POS_ERR(DPML_SINGULARITY)
244 #define NEG_SINGULARITY		NEG_ERR(DPML_SINGULARITY)
245 #define INVALID_ARGUMENT	POS_ERR(DPML_INVALID)
246 #define LOSS_OF_SIGNIFICANCE	POS_ERR(DPML_LOST_SIGNIFICANCE)
247 
248 # if COMPATIBILITY_MODE
249 
250 /*									    */
251 /*  The DPML exception handler is invoked with a type specific error code.  */
252 /*  The type information is given in the high five bits of the input.  The  */
253 /*  remaing bits are a type independent enumerated error code that is used  */
254 /*  to index into a table of default error responses.  The type		    */
255 /*  enumerations are defined in dpml_globals.c and the error codes in	    */
256 /*  dpml_error_codes.c.							    */
257 /*									    */
258 
259 #define TYPE_WIDTH	5
260 #define TYPE_POS	(BITS_PER_INT - TYPE_WIDTH)
261 
262 #define ADD_ERR_CODE_TYPE(e)            ((F_TYPE_ENUM << TYPE_POS) | (e))
263 #define GET_ERR_CODE_TYPE(c)            ((c) >> TYPE_POS)
264 #define GET_TYPELESS_ERR_CODE(c)        ((c) & ~MAKE_MASK(TYPE_WIDTH, TYPE_POS))
265 
266 # endif
267 
268 /*									    */
269 /*  Passing of data/value to subroutines and macros is done via a pointer   */
270 /*  to a structure rather than individual values.  The reason for this is   */
271 /*  that it simplifies macro definitions and subroutine interfaces.  The    */
272 /*  following structure definition is sufficiently general deal with all of */
273 /*  the currently supportted platforms.  Less general, platform specific    */
274 /*  data structures coulb be used.  However it does not appear the the	    */
275 /*  increase in efficency of platform specific structures justifies the	    */
276 /*  resulting complications.  If the platform we are dealing with requires  */
277 /*  reporting the actual arguments that cause an exception condition, use   */
278 /*  the follow union to pass them in.					    */
279 /*									    */
280 
281 # if ARCHITECTURE == alpha
282 
283 #   define EXCEPTION_INTERFACE_RECEIVE receive_exception_record
284 #   if defined MINIMAL_SILENT_MODE_EXCEPTION_HANDLER
285 #       define __PROCESS_DENORMS 0
286 #   endif
287 
288 #   if OP_SYSTEM == osf
289 #	include "alpha_unix_exception.h"
290 #	if defined dec_cc
291 #	    define EXCEPTION_INTERFACE_SEND ( send_error_code     |	\
292 					      send_return_address |	\
293 					      send_return_value )
294 #	else
295 #	    define EXCEPTION_INTERFACE_SEND ( send_error_code   |	\
296 					      send_return_value )
297 #	endif
298 
299 #   elif OP_SYSTEM == vms
300 #	include "alpha_vms_exception.h"
301 #	define EXCEPTION_INTERFACE_SEND ( send_error_code   |	\
302 					  send_return_value )
303 #	if VAX_FLOATING
304 #	    define __PROCESS_DENORMS 0
305 #	endif
306 
307 #   elif OP_SYSTEM == wnt
308 #	include "alpha_nt_exception.h"
309 #	define EXCEPTION_INTERFACE_SEND ( send_error_code     |	\
310 					  send_function_name  |	\
311 					  send_return_address |	\
312 					  send_arguments )
313 
314 #   elif OP_SYSTEM == linux
315 #	include "alpha_linux_exception.h"
316 #	define EXCEPTION_INTERFACE_SEND ( send_error_code   |	\
317 					  send_return_value )
318 #	define PLATFORM_SPECIFIC_HEADER_FILE "alpha_linux_exception.c"
319 
320 #   endif
321 
322 # else
323 
324 #   if ARCHITECTURE == mips
325 #	define PROCESS_DENORMS 1
326 #	define DPML_EXCEPTION_HANDLER DPML_EXCEPTION_NAME
327 #	define EXCEPTION_ARGUMENTS( error_code ) error_code
328 #	define PLATFORM_SPECIFIC_HEADER_FILE "mips_exception.c"
329 
330 #   elif ARCHITECTURE == hp_pa
331 #	define PROCESS_DENORMS 1
332 #	define DPML_EXCEPTION_HANDLER DPML_EXCEPTION_NAME
333 #	define EXCEPTION_ARGUMENTS( error_code ) error_code
334 #	define PLATFORM_SPECIFIC_HEADER_FILE "hppa_exception.c"
335 
336 #   elif ARCHITECTURE == ix86
337 #	define PROCESS_DENORMS 1
338 #	define DPML_EXCEPTION_HANDLER DPML_EXCEPTION_NAME
339 #	define EXCEPTION_ARGUMENTS( error_code ) error_code
340 //#	define PLATFORM_SPECIFIC_HEADER_FILE "intel_exception.c"
341 
342 #   elif ARCHITECTURE == merced
343 
344 #     if OP_SYSTEM == linux
345 //#	include "linux_exception.h"
346 /*#	define EXCEPTION_INTERFACE_SEND ( send_error_code   |	\
347 					  send_return_value )*/
348 #	define PROCESS_DENORMS 1
349 #	define DPML_EXCEPTION_HANDLER DPML_EXCEPTION_NAME
350 //#	define PLATFORM_SPECIFIC_HEADER_FILE "linux_exception.c"
351 
352 #     elif OP_SYSTEM == vms
353 #	include "ia64_vms_exception.h"
354 #	define EXCEPTION_INTERFACE_SEND ( send_error_code   |	\
355 					  send_return_value )
356 #	if VAX_FLOATING
357 #	    define __PROCESS_DENORMS 0
358 #	endif
359 
360 #     endif
361 
362 #   else
363 
364 #       if IEEE_FLOATING && !defined(MINIMAL_SILENT_MODE_EXCEPTION_HANDLER)
365 #          define PROCESS_DENORMS 1
366 #       else
367 #	   define PROCESS_DENORMS 0
368 #       endif
369 #       define DPML_EXCEPTION_HANDLER DPML_EXCEPTION_NAME
370 #   endif
371 
372 # endif
373 
374 /*									    */
375 /*	Provide default definitions of an exception value and the exception */
376 /*	record.								    */
377 /*									    */
378 
379 #if !defined(EXCEPTION_ARG_LIST)
380 
381     typedef union {
382 	WORD	    w ;
383 	float	    f ;
384 	double	    d ;
385 	long double ld ;
386 	} DPML_EXCEPTION_VALUE ;
387 
388     typedef struct {
389 	WORD		     func_error_code ;
390 	void*		     context ;
391 	WORD		     platform_specific_err_code ;
392 	WORD		     environment ;
393 	void*		     ret_val_ptr ;
394 	char*		     name ;
395 	char		     data_type ;
396 	char		     dpml_error ;
397 	char		     mode ;
398 	DPML_EXCEPTION_VALUE ret_val ;
399 	DPML_EXCEPTION_VALUE args[ 4 ] ;
400 	} DPML_EXCEPTION_RECORD ;
401 
402 #   define EXCEPTION_ARG_LIST DPML_EXCEPTION_RECORD*
403 
404 #endif
405 
406 
407 #define G_EXCPT_REC_FUNC_ECODE(p)	p->func_error_code
408 #define G_EXCPT_REC_PLTFRM_ECODE(p)	p->platform_specific_err_code
409 #define G_EXCPT_REC_ENVIRONMENT(p)	p->environment
410 #define G_EXCPT_REC_RET_VAL_PTR(p)	p->ret_val_ptr
411 #define G_EXCPT_REC_CONTEXT(p)		((CONTEXT *) p->context)
412 #define G_EXCPT_REC_NAME(p)		p->name
413 #define G_EXCPT_REC_DATA_TYPE(p)	p->data_type
414 #define G_EXCPT_REC_DPML_ECODE(p)	p->dpml_error
415 #define G_EXCPT_REC_MODE(p)		p->mode
416 #define G_EXCPT_REC_ARG(p,i,type)	p->PASTE_3(args[i], ., type)
417 #define G_EXCPT_REC_RET_VAL(p,type)	p->PASTE_3(ret_val, ., type)
418 
419 #define P_EXCPT_REC_FUNC_ECODE(p,v)	p->func_error_code = (v)
420 #define P_EXCPT_REC_PLTFRM_ECODE(p,v)	p->platform_specific_err_code = (v)
421 #define P_EXCPT_REC_ENVIRONMENT(p,v)	p->environment = (v)
422 #define P_EXCPT_REC_RET_VAL_PTR(p,v)	p->ret_val_ptr = (void *)(v)
423 #define P_EXCPT_REC_CONTEXT(p,v)	p->context = (void *)(v)
424 #define P_EXCPT_REC_NAME(p,v)		p->name = (v)
425 #define P_EXCPT_REC_DATA_TYPE(p,v)	p->data_type = (v)
426 #define P_EXCPT_REC_DPML_ECODE(p,v)	p->dpml_error = (v)
427 #define P_EXCPT_REC_MODE(p,v)		p->mode = (v)
428 #define P_EXCPT_REC_ARG(p,i,type,v)	p->PASTE_3(args[i], ., type) = (v)
429 #define P_EXCPT_REC_RET_VAL(p,type,v)	p->PASTE_3(ret_val, ., type) = (v)
430 
431 #define P_EXCPTN_VALUE_w(x,v)    x.w = (v)
432 #define P_EXCPTN_VALUE_f(x,v)    x.f = (v)
433 #define P_EXCPTN_VALUE_g(x,v)    x.d = (v)
434 #define P_EXCPTN_VALUE_s(x,v)    x.f = (v)
435 #define P_EXCPTN_VALUE_t(x,v)    x.d = (v)
436 #define P_EXCPTN_VALUE_x(x,v)    x.ld = (v)
437 #define P_EXCPTN_VALUE_F	PASTE_3(P_EXCPTN_VALUE, _, F_CHAR)
438 
439 #define G_EXCPTN_VALUE_w(x)      x.w
440 #define G_EXCPTN_VALUE_f(x)      x.f
441 #define G_EXCPTN_VALUE_g(x)      x.d
442 #define G_EXCPTN_VALUE_s(x)      x.f
443 #define G_EXCPTN_VALUE_t(x)      x.d
444 #define G_EXCPTN_VALUE_x(x)      x.ld
445 #define G_EXCPTN_VALUE_F	PASTE_3(G_EXCPTN_VALUE, _, F_CHAR)
446 
447 /*									    */
448 /*  Define platform specific execption information that is required for	    */
449 /*  compilation of individual DPML routines.  At the same time define the   */
450 /*  name of the header files that determine the exception behavior for the  */
451 /*  platform.								    */
452 /*									    */
453 /*  One of the symbols that must be available for individual DPML	    */
454 /*  compilations is PROCESS_DENORMS.  On some of the alpha platforms,	    */
455 /*  PROCESS_DENORMS is an informational call to the exception handler.	    */
456 /*  However, on other platforms if defaults to TRUE for IEEE types and	    */
457 /*  FALSE otherwise.							    */
458 /*									    */
459 /*  Finally, define the calling conventions between dpml routines and the   */
460 /*  exception handler.  Since on some platforms, dpml routines call a	    */
461 /*  "capture context" routine which in turn calls dpml_exception, the	    */
462 /*  calling interface to "the exception handler" and the actual interface   */
463 /*  to dpml_exception may be different.  Consquently, we use two macros to  */
464 /*  define hook-up between DPML routines and dpml_exception		    */
465 /*									    */
466 /*  The information passed to the exception handler is defined by the	    */
467 /*  symbol EXCEPTION_INTERFACE_SEND.  Currently, there are 3 disjoint sets  */
468 /*  of data that can be passed: the error code, the function name and the   */
469 /*  arguments.								    */
470 /*									    */
471 /*  We assume that the error code will always be passed, so that is the.    */
472 /*  If more than information than the error code is passed, then it is	    */
473 /*  assumed that the information is passed in an exception record.	    */
474 /*  Otherwise it is simply passed as an integer.			    */
475 /*									    */
476 /*  The information received by dpml_exception is defined by the macro	    */
477 /*  EXCEPTION_INTERFACE_RECEIVE.  Currently, there are 2 methods of	    */
478 /*  receiving data in dpml_exception: a error code only or a pointer to an  */
479 /*  exception record.  The default is error code only.			    */
480 /*									    */
481 /*  Provide names for the actual exception dispatcher procedure and a	    */
482 /*  possible "capture context" procedure unless they already have been	    */
483 /*  given names.  Typically, one of these names will be used as the	    */
484 /*  definition of DPML_EXCEPTION_HANDLER.				    */
485 /*									    */
486 
487 # if !defined( DPML_EXCEPTION_NAME )
488 #   define DPML_EXCEPTION_NAME __INTERNAL_NAME( exception )
489 # endif
490 
491 # if !defined( DPML_CAPTURE_CONTEXT_NAME )
492 #   define DPML_CAPTURE_CONTEXT_NAME __INTERNAL_NAME( capture_context )
493 # endif
494 
495 # if !defined EXCEPTION_INTERFACE_SEND
496 #   define EXCEPTION_INTERFACE_SEND	send_error_code
497 # endif
498 
499 # if !defined EXCEPTION_INTERFACE_RECEIVE
500 #   define EXCEPTION_INTERFACE_RECEIVE	receive_error_code
501 # endif
502 
503 # define receive_error_code	  1
504 # define receive_exception_record 2
505 # define send_error_code	  1
506 # define send_function_name	  2
507 # define send_arguments		  4
508 # define send_exception_record    8
509 # define send_return_address     16
510 # define send_return_value       32
511 
512 # if EXCEPTION_INTERFACE_SEND & send_function_name
513 #   define INIT_NAME P_EXCPT_REC_NAME( ( &tmp_rec ), STR( F_ENTRY_NAME ) )
514 # else
515 #   define INIT_NAME
516 # endif
517 
518 # if EXCEPTION_INTERFACE_SEND & send_arguments
519 #   define P_F_ARG_VALUE( n, x ) P_EXCPTN_VALUE_F( tmp_rec.args[ n ], x )
520 #   define P_W_ARG_VALUE( n, x ) P_EXCPTN_VALUE_w( tmp_rec.args[ n ], x )
521 # else
522 #   define P_F_ARG_VALUE( n, x )
523 #   define P_W_ARG_VALUE( n, x )
524 # endif
525 
526 # if EXCEPTION_INTERFACE_SEND & send_return_address
527     /* NOTE THE TRAILING COMMA						    */
528 #   define INIT_RETURN_ADDRESS \
529 	P_EXCPT_REC_RET_VAL_PTR( ( &tmp_rec ), RET_ADDR ),
530 # else
531 #   define INIT_RETURN_ADDRESS
532 # endif
533 
534 # if EXCEPTION_INTERFACE_SEND & send_return_value
535 #   define INIT_RETURN_VALUE( v ) P_EXCPTN_VALUE_F( tmp_rec.ret_val, v )
536 # else
537 #   define INIT_RETURN_VALUE( v )
538 # endif
539 
540 # if EXCEPTION_INTERFACE_SEND > send_error_code
541 #   undef EXCEPTION_INTERFACE_SEND
542 #   define EXCEPTION_INTERFACE_SEND send_exception_record
543 # endif
544 
545 # if EXCEPTION_INTERFACE_SEND == send_exception_record
546 
547 #   define EXCEPTION_RECORD_DECLARATION	DPML_EXCEPTION_RECORD tmp_rec ;
548 
549 #   if !defined EXCEPTION_ARG
550 #	define EXCEPTION_ARG( e ) \
551 	    ( P_EXCPT_REC_FUNC_ECODE( (&tmp_rec), ADD_ERR_CODE_TYPE(e)), \
552 				       INIT_RETURN_ADDRESS \
553 				       (&tmp_rec) \
554 				       )
555 #   endif
556 
557 # else
558 
559 #   define EXCEPTION_ARG_TYPE WORD
560 #   define EXCEPTION_RECORD_DECLARATION
561 #   define EXCEPTION_ARG( e ) ADD_ERR_CODE_TYPE( e )
562 
563 # endif
564 
565 # define SIGNAL_INTOVF 1
566 # define SIGNAL_INTDIV 2
567 
568 # define DENORM_SCREEN  0
569 # define DENORM_UNSCALE 1
570 
571 # if !defined SIGNAL_LOGZERNEG
572 #   define SIGNAL_LOGZERNEG 0
573 # endif
574 # if !defined SIGNAL_UNDEXP
575 #   define SIGNAL_UNDEXP 0
576 # endif
577 # if !defined SIGNAL_SQUROONEG
578 #   define SIGNAL_SQUROONEG 0
579 # endif
580 
581 # if COMPATIBILITY_MODE
582 
583     /*									    */
584     /*	Define the "old" interface to the exception dispatcher.		    */
585     /*									    */
586 
587 #   if !defined GET_EXCEPTION_RESULT
588 #	define GET_EXCEPTION_RESULT INIT_NAME
589 #   endif
590 
591 
592 #   define GET_EXCEPTION_RESULT_1( error_code,				\
593 				   argument,				\
594 				   result ) {				\
595 	GET_EXCEPTION_RESULT ;						\
596 	P_F_ARG_VALUE( 0, argument ) ;					\
597 	result = *( F_TYPE* )						\
598 	    DPML_EXCEPTION_HANDLER( EXCEPTION_ARG( error_code ) ) ;	\
599 	}
600 
601 #   define GET_EXCEPTION_RESULT_2( error_code,				\
602 				   argument_0,				\
603 				   argument_1,				\
604 				   result ) {				\
605 	GET_EXCEPTION_RESULT ;						\
606 	P_F_ARG_VALUE( 0, argument_0 ) ;				\
607 	P_F_ARG_VALUE( 1, argument_1 ) ;				\
608 	result = *( F_TYPE* )						\
609 	    DPML_EXCEPTION_HANDLER( EXCEPTION_ARG( error_code ) ) ;	\
610 	}
611 
612 #   define GET_EXCEPTION_RESULT_4( error_code,				\
613 				   argument_0,				\
614 				   argument_1,				\
615 				   argument_2,				\
616 				   argument_3,				\
617 				   result ) {				\
618 	GET_EXCEPTION_RESULT ;						\
619 	P_F_ARG_VALUE( 0, argument_0 ) ;				\
620 	P_F_ARG_VALUE( 1, argument_1 ) ;				\
621 	P_F_ARG_VALUE( 2, argument_2 ) ;				\
622 	P_F_ARG_VALUE( 3, argument_3 ) ;				\
623 	result = *( F_TYPE* )						\
624 	    DPML_EXCEPTION_HANDLER( EXCEPTION_ARG( error_code ) ) ;	\
625 	}
626 
627 # else
628 
629     /*									    */
630     /*	Define the "new" style interface to the exception dispatcher.	    */
631     /*									    */
632 
633 #   define RETURN_EXCEPTION_RESULT_1( error_word,	\
634 				      argument,		\
635 				      signature,	\
636 				      operation ) {	\
637 	P_F_ARG_VALUE( 0, argument ) ;			\
638 	RETURN_EXCEPTION_RESULT( error_word,		\
639 				 signature,		\
640 				 operation )		\
641 	}
642 
643 #   define RETURN_EXCEPTION_RESULT_2( error_word,	\
644 				      argument_0,	\
645 				      argument_1,	\
646 				      signature,	\
647 				      operation ) {	\
648 	P_F_ARG_VALUE( 0, argument_0 ) ;		\
649 	P_F_ARG_VALUE( 1, argument_1 ) ;		\
650 	RETURN_EXCEPTION_RESULT( error_word,		\
651 				 signature,		\
652 				 operation )		\
653 	}
654 
655 #   define RETURN_EXCEPTION_RESULT_4( error_word,	\
656 				      argument_0,	\
657 				      argument_1,	\
658 				      argument_2,	\
659 				      argument_3,	\
660 				      signature,	\
661 				      operation ) {	\
662 	P_F_ARG_VALUE( 0, argument_0 ) ;		\
663 	P_F_ARG_VALUE( 1, argument_1 ) ;		\
664 	P_F_ARG_VALUE( 2, argument_2 ) ;		\
665 	P_F_ARG_VALUE( 3, argument_3 ) ;		\
666 	RETURN_EXCEPTION_RESULT( error_word,		\
667 				 signature,		\
668 				 operation )		\
669 	}
670 
671 # endif
672 
673 /*									    */
674 /*  DPML_GET_ENVIRONMENT(p) is a macro that fills the envrionment field of  */
675 /*  the exception record pointed to by p with a bit vector that describes   */
676 /*  the enviroment the exception handler is operating in.  The specific bit */
677 /*  interpretations are defined by the ENABLE_<error> macros defined above. */
678 /*  If __DPML_EXCPT_ENVIRONMENT is defined at this point, then it is	    */
679 /*  assumed that the exception behavior of the library is determined at	    */
680 /*  compile time as indicated by the value of __DPML_EXCPT_ENVIRONMENT.	    */
681 /*  Otherwise, the exception behavior is assumed to be determined at	    */
682 /*  runtime.  In the latter case, the macro DPML_GET_ENVIRONMENT must	    */
683 /*  eventually be defined to be some code sequence that fills in the	    */
684 /*  environment field.							    */
685 /*									    */
686 /*  In order to facilitate efficient code generation, if the exception	    */
687 /*  behavior is static, then PROCESS_DENORMS is  defined to be a compile    */
688 /*  time constant.  If the exception behavior is dynamic, and		    */
689 /*  PROCESS_DENORMS is not already defined, set it up to probe the	    */
690 /*  environment via the exception handler				    */
691 /*									    */
692 
693 #if defined(__DPML_EXCPT_ENVIRONMENT)
694 #   define DPML_GET_ENVIRONMENT(p) \
695 		 P_EXCPT_REC_ENVIRONMENT(p, __DPML_EXCPT_ENVIRONMENT)
696 #else
697 #   define __DPML_EXCPT_ENVIRONMENT \
698 		((WORD) DPML_EXCEPTION_HANDLER(EXCEPTION_ARG(DPML_ENV_INFO)))
699 #endif
700 
701 #if !defined(__PROCESS_DENORMS)
702 #   define __PROCESS_DENORMS	\
703 			((__DPML_EXCPT_ENVIRONMENT & ENABLE_FLUSH_TO_ZERO) == 0)
704 #endif
705 
706 # if ARCHITECTURE == alpha
707 #   if OP_SYSTEM == osf
708 #   elif OP_SYSTEM == vms
709 #   elif OP_SYSTEM == wnt
710 #   elif OP_SYSTEM == linux
711 #   else
712 	typedef void* EXCEPTION_RETURN_TYPE ;
713 #   endif
714 # elif ARCHITECTURE == merced
715 #   if OP_SYSTEM == vms
716 #   else
717 	typedef void* EXCEPTION_RETURN_TYPE ;
718 #   endif
719 # else	/*  The hardware architecture is not Alpha or Merced		    */
720     typedef void* EXCEPTION_RETURN_TYPE ;
721 # endif
722 
723 extern EXCEPTION_RETURN_TYPE DPML_EXCEPTION_HANDLER( EXCEPTION_ARG_LIST ) ;
724 
725 /*									    */
726 /*  After including the operating-system header files, use default	    */
727 /*  definitions for those required macros which are not defined.	    */
728 /*									    */
729 
730 # if !defined GET_CONTEXT_INFO
731 #   define GET_CONTEXT_INFO
732 # endif
733 
734 # if !defined GET_FUNCTION_INFO
735 #   define GET_FUNCTION_INFO( signature, operation )
736 # endif
737 
738 # if !defined INIT_NAME
739 #   define INIT_NAME
740 # endif
741 
742 # if COMPATIBILITY_MODE
743 
744 #   if !defined PROCESS_DENORMS
745 #	define PROCESS_DENORMS (						\
746 	    ( ( U_WORD )DPML_EXCEPTION_HANDLER(					\
747 		EXCEPTION_ARGUMENTS( ( U_WORD )( WORD )DPML_ENV_INFO ) )	\
748 	    & ( ENABLE_FLUSH_TO_ZERO ) ) == 0					\
749 	    )
750 #   endif
751 # endif
752 
753 /*									    */
754 /*  The structure of ERROR_WORD if only IEEE data types are used is:	    */
755 /*									    */
756 /*     7     6	   5	 4     3     2	   1	 0			    */
757 /*  +-----+-----+-----+-----+-----+-----+-----+-----+			    */
758 /*  | MBZ |	    exception_cause	      |errno|			    */
759 /*  +-----+-----+-----+-----+-----+-----+-----+-----+			    */
760 /*									    */
761 /*     17    16	   15	 14    13    12	   11	 10    9     8		    */
762 /*  +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+	    */
763 /*  |	    IEEE_value	    |	    fast_value	    | data_type |	    */
764 /*  +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+	    */
765 /*									    */
766 /*     63    62    61    60    59             22    21    20    19    18    */
767 /*  +-----+-----+-----+-----+-----+--/////--+-----+-----+-----+-----+-----+ */
768 /*  | flag|                   exception_extension                         | */
769 /*  +-----+-----+-----+-----+-----+--/////--+-----+-----+-----+-----+-----+ */
770 /*									    */
771 /*									    */
772 /*  A possible record structure for ERROR_WORD is			    */
773 /*									    */
774 /*  struct {								    */
775 /*	unsigned int errno : 1 ;					    */
776 /*	unsigned int exception_cause : 6 ;				    */
777 /*	unsigned int : 1 ;						    */
778 /*	unsigned int data_type : 2 ;					    */
779 /*	unsigned int fast_value : 4 ;					    */
780 /*	unsigned int IEEE_value : 4 ;					    */
781 /*	unsigned int exception_extension : 45 ;				    */
782 /*	unsigned int flag : 1 ;						    */
783 /*	} ERROR_WORD ;							    */
784 /*									    */
785 /*									    */
786 /*  However, if both IEEE and VAX data types are supported, the format of   */
787 /*  ERROR_WORD is							    */
788 /*									    */
789 /*     7     6	   5	 4     3     2	   1	 0			    */
790 /*  +-----+-----+-----+-----+-----+-----+-----+-----+			    */
791 /*  | MBZ |	    exception_cause	      |errno|			    */
792 /*  +-----+-----+-----+-----+-----+-----+-----+-----+			    */
793 /*									    */
794 /*     18    17    16	 15    14    13    12	 11    10    9     8	    */
795 /*  +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+	    */
796 /*  |	    IEEE_value	    |	    fast_value	    |    data_type    |	    */
797 /*  +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+	    */
798 /*									    */
799 /*     63    62    61    60    59             23    22    21    20    19    */
800 /*  +-----+-----+-----+-----+-----+--/////--+-----+-----+-----+-----+-----+ */
801 /*  | flag|                   exception_extension                         | */
802 /*  +-----+-----+-----+-----+-----+--/////--+-----+-----+-----+-----+-----+ */
803 /*									    */
804 /*									    */
805 /*  A possible record structure for ERROR_WORD is then			    */
806 /*									    */
807 /*  struct {								    */
808 /*	unsigned int errno : 1 ;					    */
809 /*	unsigned int exception_cause : 6 ;				    */
810 /*	unsigned int : 1 ;						    */
811 /*	unsigned int data_type : 3 ;					    */
812 /*	unsigned int fast_value : 4 ;					    */
813 /*	unsigned int IEEE_value : 4 ;					    */
814 /*	unsigned int exception_extension : 44 ;				    */
815 /*	unsigned int flag : 1 ;						    */
816 /*	} ERROR_WORD ;							    */
817 /*									    */
818 
819 # define DPML_EDOM 0
820 # define DPML_ERANGE 1
821 # define ERROR_WORD_ERRNO_FLAG( errno )		\
822     ( ( ( errno ) == DPML_EDOM ) ? 0 : 1 )
823 # if OP_SYSTEM == vms
824 #   define ERROR_WORD_DATA_TYPE_SIZE 3
825 # else
826 #   define ERROR_WORD_DATA_TYPE_SIZE 2
827 # endif
828 # define ERROR_WORD_VALUE_SIZE 4
829 # define ERROR_EXTENSION_SIZE (					\
830     ( 8 * sizeof( U_WORD ) - 1 ) -				\
831     ( ERROR_WORD_DATA_TYPE_POS + ERROR_WORD_DATA_TYPE_SIZE +	\
832     2 * ERROR_WORD_VALUE_SIZE )					\
833     )
834 
835 # define ERROR_WORD_DATA_TYPE_POS 8
836 # define ERROR_WORD_FAST_VALUE_POS				\
837     ( ERROR_WORD_DATA_TYPE_POS + ERROR_WORD_DATA_TYPE_SIZE )
838 # define ERROR_WORD_IEEE_VALUE_POS				\
839     ( ERROR_WORD_FAST_VALUE_POS + ERROR_WORD_VALUE_SIZE )
840 # define ERROR_WORD_EXTRA_INFO_POS				\
841     ( ERROR_WORD_IEEE_VALUE_POS + ERROR_WORD_VALUE_SIZE )
842 
843 # define ERROR_WORD( exception_cause,				\
844 		     fast_value,				\
845 		     IEEE_value,				\
846 		     data_type,					\
847 		     errno,					\
848 		     exception_extension )			\
849     ( ERROR_WORD_ERRNO_FLAG( errno ) |				\
850     ( exception_cause ) |					\
851     ( ( data_type ) << ERROR_WORD_DATA_TYPE_POS ) |		\
852     ( ( fast_value ) << ERROR_WORD_FAST_VALUE_POS ) |		\
853     ( ( ( IEEE_value ) ^ ( fast_value ) )			\
854 	<< ERROR_WORD_IEEE_VALUE_POS ) |			\
855     ( ( exception_extension ) << ERROR_WORD_EXTRA_INFO_POS ) |	\
856     ( ERROR_WORD_COMPATIBILITY_MODE_FLAG ) )
857 
858 /*									    */
859 /*  Some of the definitions in this file are used in generating		    */
860 /*  dpml_globals.h and dpml_error_codes_enum.h.  If this is the case, don't */
861 /*  include those files now.						    */
862 /*									    */
863 
864 # ifndef MAKE_DPML_ERROR_CODES_ENUM
865 #   include "dpml_globals.h"	      /*  Include type specifiers and type  */
866 #   include "dpml_error_codes_enum.h" /*  independent error codes.	    */
867 # endif
868 
869 # endif	/*  ifndef DPML_EXCEPTION_H					    */
870