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