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