fperr.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:7k
源码类别:

DVD

开发平台:

Others

  1. /*
  2.  *      Paradigm C/C++ Run-Time Library - Version 5.0
  3.  *
  4.  *      Copyright (c) 1998 Paradigm Systems.  All rights reserved.
  5.  *      Portions Copyright (c) 1996 Borland International.
  6.  *
  7.  *      $Revision: 4 $
  8.  *      $Workfile: fperr.c $
  9.  *
  10.  *      Floating point exception handler code.
  11.  */
  12. #include "Config.h" // Global Configuration - do not remove!
  13. #include "IncludeSysdefs.h" // Global Configuration - do not remove!
  14. #include <stdio.h>
  15. #include <math.h>       /* for _mexcep */
  16. #include <stdlib.h>
  17. #include <signal.h>
  18. #include <float.h>      /* for FPE types */
  19. /* No denormal signal are caught here, but treat it for completeness. */
  20. #define FPE_DENORMAL            130     /* 80x87 denormalized operand   */
  21. typedef void cdecl (* CatcherPTR)(); /* Cleaner signal catcher declaration */
  22. extern  CatcherPTR (* cdecl __SignalPtr)();
  23. /*
  24.         The only exceptions routed through this code are GENUINE floating
  25.         point ones.  The explicitly raised SIGFPE and the integer related
  26.         SIGFPE types DO NOT come this way.
  27. */
  28. static const
  29.         struct f_errors
  30.         {
  31.                 int     FPEtype;
  32.                 char    *string;
  33.         }
  34.         fp_errors[] =
  35.         {
  36.                 { FPE_INVALID,          "Domain" },
  37.                 { FPE_DENORMAL,         "Denormal" },
  38.                 { FPE_ZERODIVIDE,       "Divide by 0" },
  39.                 { FPE_OVERFLOW,         "Overflow" },
  40.                 { FPE_UNDERFLOW,        "Underflow" },
  41.                 { FPE_INEXACT,          "Partial loss of precision" },
  42.                 { FPE_STACKFAULT,       "Stack fault" },
  43.         };
  44. /*
  45. This is an fp exception structure.  It describes the info passed
  46. to _fperror, the purpose of which is to give a C interface to
  47. trapping fp exceptions in a style similar to matherr().
  48. _fperror() is called directly from the NMI handler.  Portable fp
  49. exception handlers should call signal() instead, as that is an
  50. ANSI function.  _fperror() is for lower level control over the
  51. exception.
  52. The default _fperror() only uses the type and subtype fields of
  53. struct fpexcep.  The other fields are correctly filled in if the
  54. coprocessor is present, but not otherwise.  They can be used to
  55. help track down the source of the error, and the circumstances
  56. causing the error.
  57. _fperror() is not called for denormal exceptions, as these are
  58. handled by the NMI handler.  The NMI handler also attempts to
  59. correct some invalid operation exceptions, and only calls
  60. _fperror() if it is unsuccessful in curing the problem.
  61. _fperror() is also not called for certain Invalid Operation
  62. exceptions.  Some of these are recoverable stack faults.
  63. The subtype is always 1.  Future implementations may use this
  64. field to pass more info, such as whether an INVALID exception
  65. came from a FSQRT instruction.
  66. Here are the reasonable alternatives for an fp exception handler.
  67. 1. Print a suitable message and exit.  This is what the default
  68. handler does.  A program that wants to do the same may still wish
  69. to replace the handler as it may have some additional cleaning up
  70. to do, or may want to print a more informative message.
  71. 2. Do a long jump to safe place in the program.  If so, the
  72. program must pay attention to all of the usual hazards of long
  73. jumps, and in addition,
  74.         It should call _fpreset() to reset the coprocessor or emulator.
  75.         Since interrupts occur asynchronously, there is more danger than
  76.         usual that the code will be left in an inconsistent state.
  77. 3. Ignore the exception.  In most cases the coprocessor will
  78. generate infinities and NANs which are likely to cause additional
  79. exceptions. These exceptions can be ignored more efficiently by
  80. using _control87() to mask them.  This option does not work if
  81. the coprocessor is being emulated, as the emulator does not support
  82. all of the exception handling that the 8087 does.
  83. 4. Set a flag and continue.  As with case 3 above, most programs
  84. may prefer the simpler strategy of masking the exceptions.  The
  85. occurrence of the exception can still be detected by examining
  86. the status word with _status87() and can be cleared with
  87. _clear87().  This option does not work if the coprocessor is being
  88. emulated.
  89. 5. Attempt to analyze the damage and repair it. This is nearly
  90. impossible as the 8087 is a very complex chip with many
  91. instructions, data types, registers, and special cases.  Some
  92. info is provided at the _fperror() level for programs to try.
  93. Caution: _fperror() is a huge function in all memory models.
  94. Bugs:
  95. Currently, only the 'type' field of the struct fpexcep is supported.
  96. Do NOT use any of the others.
  97. */
  98. #ifdef I49FP_ERROR
  99. struct fpexcep
  100. {
  101.         _mexcep type;
  102.         int subtype;
  103.         unsigned int opcode;    /* offending instruction */
  104.         void huge *datap;       /* ptr to bad mem operand, if any */
  105.         void (huge *codep)();   /* ptr to bad instruction */
  106. };
  107. #endif
  108. /*
  109. void huge cdecl _fperror(void)
  110. */
  111. void near cdecl _fperror(void)
  112. {
  113. tr_printf (("FP errorn"));
  114. while (1);
  115. #ifdef I49FP_ERROR
  116.         struct fpexcep far *a = (struct fpexcep _ss *) _BX;
  117.         /*
  118.         If signal() functions are installed, use them. signal() makes
  119.         it's presence known by filling the '__SignalPtr' function pointer
  120.         the first time it's called.
  121.         */
  122.         if (__SignalPtr != NULL)                /* signals installed    */
  123.         {
  124.                 CatcherPTR      func;
  125. #pragma warn -pro
  126.                 func = (*__SignalPtr)(SIGFPE, SIG_DFL); /* get current  */
  127.                 (*__SignalPtr)(SIGFPE, func);           /* restore it   */
  128.                 if (func != SIG_IGN)
  129.                 {
  130.                         if (func == SIG_DFL)
  131.                                 goto default_actions;
  132.                         /*
  133.                                 Set a default handler and call the users
  134.                                 handler.  The user handler is responsible for
  135.                                 reenabling itself if it needs to.
  136.                         */
  137.                         (*__SignalPtr)(SIGFPE, SIG_DFL);
  138.                         (* func)(SIGFPE, fp_errors[a->type-1].FPEtype);
  139.                 }
  140.         }
  141. #pragma warn .pro
  142.         else    /* Default actions if signals aren't present    */
  143.         {       /* or are defaulted.                            */
  144. default_actions :
  145. /*
  146. // Default handler treats all exceptions as fatal.
  147. // Some won't occur unless the user enables them.
  148. */
  149. #if defined(__USE_STREAMS)
  150. fprintf(stderr, "Floating point error: %s.n", fp_errors[a->type-1].string);
  151. #endif
  152.                 /*
  153.                         Now abort the program.  The exit sequence will
  154.                         clean off the chip and restore interrupts.
  155.                 */
  156.                 abort();
  157.                 /* not reached */
  158.         }
  159. #endif        
  160. }